[zb4osgi-changeset] [scm] ZigBee 4 OSGi repository change: r534 - in /projects/zb4osgi/sandbox/telecomItalia/initialContribution: ./ GAL/ GAL/curl-7.27.0/ GAL/iniparser/ GAL/libupnp-1.6.15/ GAL/linuxgal/ GAL/shttpd/ GAL/tinyxml/ GAL/zigbee/ GAL/zigbee/doc/ GAL/zigbee/examples/ GAL/zigbee/include/ GAL/zigbee/scripts/ GAL/zigbee/src/ jGAL/

scm-notify at zb4osgi.aaloa.org scm-notify at zb4osgi.aaloa.org
Fri Oct 19 18:37:43 CEST 2012


Author: andrea.ranali
Date: Fri Oct 19 18:37:43 2012
New Revision: 534

Log:
Inizial commit made by Telecom Italia to setup the GAL project for the ZB4OSGi group.

Added:
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/Makefile
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/Makefile.rules
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/Notice.license
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/curl-7.27.0/
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/curl-7.27.0/Makefile.cross
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/iniparser/
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/iniparser/Makefile.cross
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/libupnp-1.6.15/
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/libupnp-1.6.15/Makefile.cross
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ACL.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ACL.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/Agents.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/Agents.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDebug.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDebug.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDiscoveryAgent.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDiscoveryAgent.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDummyZigBeeDataSource.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDummyZigBeeDataSource.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CHTTPClient.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CHTTPClient.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CHTTPServer.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CHTTPServer.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CLocalNode.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CLocalNode.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CLogStorage.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CLogStorage.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CManagementAgent.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CManagementAgent.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CMessage.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CMessage.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CQueryParser.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CQueryParser.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTBroker.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTBroker.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTClient.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTClient.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTServer.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTServer.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CResource.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CResource.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CServiceAgent.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CServiceAgent.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CTrustCenterAgent.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CTrustCenterAgent.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ConfigurationRepository.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ConfigurationRepository.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/Doxyfile
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/GWManagement.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/GWManagement.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/GalZbIf.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/GalZbIf.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/Makefile.am
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/Makefile.cross
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/MakefileDebug.cross
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/NodeMap.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/NodeMap.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/RESTErrors.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/StaticACLLoader.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/StaticACLLoader.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/XMLProcessor.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/XMLProcessor.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ZbNetDb.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ZbNetDb.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/acl.txt
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/config-trial.ini
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/config.ini
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/configure.ac
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/cscope.files
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/doxy.conf
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/main.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/mainconf.txt
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/pwdfile
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/run.sh
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/shttpd.conf
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/shttpd.pem
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/start_gal.sh
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/start_gal_valgrind.sh
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/winport.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/readme.rtf
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/readme.txt
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/setup.bash
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/setup.csh
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/shttpd/
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/shttpd/Makefile.cross
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/tinyxml/
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/tinyxml/Makefile.cross
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/Makefile
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/Makefile.cross
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/README
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/doc/
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/doc/doxy.conf
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/examples/
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/examples/Makefile
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/examples/lightswitch.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/examples/moon.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/examples/zbpcapsniffer.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/examples/zperf.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/fragment.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/hdlc_dl.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/hdlc_net.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/hdlc_proto.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/hdlc_ser.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/winport.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/zb_conn.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/zigbee.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/zigbee_log.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/zigbee_ser.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/zigbee_utils.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/scripts/
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/scripts/sdiodriver
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/Makefile
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_if.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_if.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_ser.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_ser.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_utils.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_utils.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/README
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/SDIO.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/SDIO.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/SerialProtocolGlobalDefine.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/SerialProtocolInner.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/SerialProtocolTypes.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/bisync.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/bisync.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/bisync_tokens.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_common.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_config.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_if.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_if.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_ser.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_ser.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/fragment.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/freescale_if.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/freescale_if.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/freescale_ser.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/freescale_ser.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/hdlc_net.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/hdlc_proto.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/hdlc_ser.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/integration_if.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/integration_if.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/stdafx.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/time_CE.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/time_ce.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zb_conn.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zigbee.cpp
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zigbee_c.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zigbee_local.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zigbee_log.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zigbee_utils.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zsdio_if.c
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zsdio_if.h
    projects/zb4osgi/sandbox/telecomItalia/initialContribution/jGAL/

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/Makefile
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/Makefile (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/Makefile Fri Oct 19 18:37:43 2012
@@ -1,0 +1,110 @@
+include Makefile.rules
+
+SUBDIRS = libupnp-1.6.15
+SUBDIRS += iniparser
+SUBDIRS += shttpd
+SUBDIRS += zigbee
+SUBDIRS += tinyxml
+#ifneq ($(strip $(TARGET_PLATFORM)),cygwin)
+#SUBDIRS += curl
+SUBDIRS += curl-7.27.0
+#endif
+SUBDIRS += linuxgal
+
+#export EMBER_STACK_PROFILE=1
+
+SUBDIRS_ALL = \
+	libupnp-1.6.15 \
+	iniparser \
+	zigbee \
+	tinyxml \
+	shttpd \
+	curl-7.27.0 \
+	linuxgal
+
+all:
+	@list='$(SUBDIRS)'; \
+	for subdir in $$list; do \
+		if [ -f $$subdir/Makefile.cross ] ; then \
+			if [ -f $$subdir/configure ] ; then \
+				(cd $$subdir && [ ! -f Makefile ] && $(MAKE) -f Makefile.cross config) \
+			fi ;\
+			(cd $$subdir && \
+			echo [CC] $$subdir && ($(MAKE) -f Makefile.cross $@) && \
+			echo [I] $$subdir && ($(MAKE) -f Makefile.cross install )); \
+			if test $$? != 0 ; then \
+				exit 1 ; \
+			fi  \
+		else \
+			echo 2222 ;\
+			if [ -f $$subdir/configure ] ; then \
+				(cd $$subdir && [ -f Makefile ] && ./configure --prefix=$(PREFIX) --host=$(HOSTARCH) --build=$(BUILDARCH) ) \
+			fi ;\
+			(cd $$subdir && \
+			echo [CC] $$subdir && $(MAKE) $@ && \
+			echo [I] $$subdir && ($(MAKE) install >& $(SOURCES_ROOT)/make.log)); \
+			if test $$? != 0 ; then \
+				exit 1 ; \
+			fi  \
+		fi \
+	done
+
+config:
+	list='$(SUBDIRS)'; \
+	for subdir in $$list; do \
+		if [ -f $$subdir/Makefile.cross ] ; then \
+			if [ -f $$subdir/configure ] ; then \
+				(cd $$subdir && $(MAKE) -f Makefile.cross config) \
+			fi \
+		else \
+			if [ -f $$subdir/configure ] ; then \
+				(cd $$subdir && ./configure --prefix=$(PREFIX) --host=$(HOSTARCH) --build=$(BUILDARCH) ) \
+			fi \
+		fi \
+	done
+
+clean:
+	@list='$(SUBDIRS_ALL)'; \
+	for subdir in $$list; do \
+		if [ -f $$subdir/Makefile.cross ] ; then \
+			(cd $$subdir && $(MAKE) -f Makefile.cross $@) \
+		else \
+			if [ -f $$subdir/Makefile ] ; then \
+				(cd $$subdir && $(MAKE) $@) \
+			fi \
+		fi \
+	done
+	rm -rf *~
+
+uninstall:
+	list='$(SUBDIRS_ALL)'; \
+	for subdir in $$list; do \
+		if [ -f $$subdir/Makefile.cross ] ; then \
+			(cd $$subdir && $(MAKE) -f Makefile.cross $@) \
+		else \
+			if [ -f $$subdir/Makefile ] ; then \
+				(cd $$subdir && $(MAKE) $@) \
+			fi \
+		fi \
+	done
+	rm -rf *~
+
+distclean:
+	list='$(SUBDIRS_ALL)'; \
+	for subdir in $$list; do \
+		if [ -f $$subdir/Makefile.cross ] ; then \
+			if [ -f $$subdir/configure ] ; then \
+				(cd $$subdir && $(MAKE) -f Makefile.cross $@) \
+			fi \
+		else \
+			if [ -f $$subdir/Makefile ] ; then \
+				if [ -f $$subdir/configure ] ; then \
+					(cd $$subdir && $(MAKE) $@) \
+				fi \
+			fi \
+		fi \
+	done
+	rm -rf *~
+
+ctags:
+	ctags-exuberant --recurse .

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/Makefile.rules
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/Makefile.rules (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/Makefile.rules Fri Oct 19 18:37:43 2012
@@ -1,0 +1,154 @@
+export LINUX_HEADERS = $(SOURCES_ROOT)/software/platform/kernel_include
+export KERNEL_DIR = $(SOURCES_ROOT)/software/platform/lvp_kernel_all
+export KERNEL_INCLUDE = $(KERNEL_DIR)/include
+
+export TELECOMITALIA_DIR = $(SOURCES_ROOT)/software/telecomitalia
+
+export VERSION_FULL	= TI_3.0.1
+export VERSION_HW	= 2.0
+export VERSION_SW	= TI_3.0.1
+
+export EXTRA		= ti
+
+ifeq ($(strip $(PROFILE)),)
+$(error set the PROFILE environment variable))
+endif
+
+ifeq ($(strip $(TARGET_PLATFORM)),)
+$(error environment variable TARGET_PLATFORM must be initialized to a valid value representing the target device (linux or lgvp))
+endif
+
+export TARGETS_DIR	=	$(SOURCES_ROOT)/targets
+export PREFIX		=	$(TARGETS_DIR)/$(PROFILE)/fs
+export PREFIX_SRC	=	$(SOURCES_ROOT)/targets/fs.src
+export PREFIX_TMP	=	$(PREFIX)/install
+export FREETYPE_CONFIG = $(PREFIX)/bin/freetype-config
+
+# Linux (Kubuntu or Debian, on intel platforms)
+ifeq ($(strip $(TARGET_PLATFORM)),linux)
+export CROSS_PATH		= 
+export HOSTARCH			= i686-pc-linux-gnu
+export BUILDARCH		= i686-pc-linux-gnu
+export PYTHON_COMPILE	= $(SOURCES_ROOT)/script/pycompile-lgvp.sh 
+export DEVPATH			= /usr
+export PYTHON			= python2.4
+export CFLAGS			=
+export EXE				=
+export LIB_EXT			= .so
+endif
+
+# SheevaPlug (Ubuntu 9.04)
+ifeq ($(strip $(TARGET_PLATFORM)),sheeva)
+export CROSS_PATH		=
+export HOSTARCH			= arm-linux-gnueabi
+export BUILDARCH		= arm-linux-gnueabi
+export PYTHON_COMPILE	= $(SOURCES_ROOT)/script/pycompile-lgvp.sh 
+export DEVPATH			= /usr
+export PYTHON			= python2.4
+export CFLAGS			=
+export EXE				=
+export LIB_EXT			= .so
+endif
+
+# Native Win32
+ifeq ($(strip $(TARGET_PLATFORM)),win32)
+export CROSS_PATH		=
+export HOSTARCH			= i686-pc-linux-gnu
+export BUILDARCH		= i686-pc-linux-gnu
+export PYTHON_COMPILE	= $(SOURCES_ROOT)/script/pycompile-lgvp-win32.sh 
+export DEVPATH			= /usr
+export PYTHON			= python2.5
+export CFLAGS			=
+export EXE				= .exe
+export LIB_EXT			= .dll
+endif
+
+# CYGWIN on Windows 
+ifeq ($(strip $(TARGET_PLATFORM)),cygwin)
+export CROSS_PATH		=
+export HOSTARCH			= i686-pc-linux-gnu
+export BUILDARCH		= i686-pc-linux-gnu
+export PYTHON_COMPILE	= $(SOURCES_ROOT)/script/pycompile-lgvp-cywin.sh 
+export DEVPATH			= /usr
+export PYTHON			= python2.5
+export CFLAGS			=
+export EXE				= .exe
+export LIB_EXT			= .dll
+endif
+
+# Teldat 
+ifeq ($(strip $(TARGET_PLATFORM)),teldat)
+export CROSS_PATH		=	/root/teldat/arm-2006q3/bin/arm-none-linux-gnueabi-
+export HOSTARCH			=	arm-none-linux
+export BUILDARCH		=	i686-pc-linux-gnu
+export PYTHON_COMPILE	=	/opt/dev/pycompile-lgvp.sh 
+export DEVPATH			=	/opt/dev/iwmmxt
+export PKG_CONFIG_PATH	= 	$(DEVPATH)/lib/pkgconfig:$(PREFIX_TMP)/lib/pkgconfig
+export CFLAGS			= -Os
+export CXXFLAGS			= -Os
+export PYTHON			= python2.4
+export EXE				=
+export LIB_EXT			= .so
+endif
+
+# Freescale CEDAC Board
+ifeq ($(strip $(TARGET_PLATFORM)),freescale)
+export CROSS_PATH		=	/opt/freescale/usr/local/gcc-4.4.4-glibc-2.11.1-multilib-1.0/arm-fsl-linux-gnueabi/bin/arm-none-linux-gnueabi-
+export HOSTARCH			=	arm-none-linux
+export BUILDARCH		=	i686-pc-linux-gnu
+export DEVPATH			=	
+export PKG_CONFIG_PATH	= 	$(DEVPATH)/lib/pkgconfig:$(PREFIX_TMP)/lib/pkgconfig
+export CFLAGS			= -Os
+export CXXFLAGS			= -Os
+export PYTHON			= python2.4
+export EXE				=
+export LIB_EXT			= .so
+endif
+
+# VDT 
+ifeq ($(strip $(TARGET_PLATFORM)),lgvp)
+export CROSS_PATH		=	/opt/host/lgvp/bin/armv5-softvfp-linux-gnu-
+export HOSTARCH			=	armv5-softvfp-linux-gnu
+export BUILDARCH		=	i686-pc-linux-gnu
+export PYTHON_COMPILE	=	/opt/dev/pycompile-lgvp.sh 
+export DEVPATH			=	/opt/dev/iwmmxt
+export PKG_CONFIG_PATH	= 	$(DEVPATH)/lib/pkgconfig:$(PREFIX_TMP)/lib/pkgconfig
+export CFLAGS			= -Os
+export CXXFLAGS			= -Os
+export PYTHON			= python2.4
+export EXE				=
+export LIB_EXT			= .so
+endif
+
+export CC	=	$(CROSS_PATH)gcc
+export CXX	=	$(CROSS_PATH)g++
+export AS	=	$(CROSS_PATH)as
+export AR	=	$(CROSS_PATH)ar
+export AR2	=	$(CROSS_PATH)ranlib
+export RANLIB=	$(CROSS_PATH)ranlib
+export LD	=	$(CROSS_PATH)ld
+export NM	=	$(CROSS_PATH)nm
+export STRIP=	$(CROSS_PATH)strip
+export OBJCOPY=	$(CROSS_PATH)objcopy
+
+
+# set the following macro to 'y' to install the new 2007 layout
+
+BUILD_MINI_HTTPD=
+BUILD_UPNP=
+BUILD_ASTERISK=
+BUILD_MICROWINDOWS=
+
+export BUILD_INET=y
+
+BUILD_ZIGBEE=
+BUILD_STEEPLE3=
+
+$(TARGETS_DIR)/$(PROFILE)/$(PROFILE):
+	mkdir -p $(SOURCES_ROOT)/targets/$(PROFILE)/distribute
+	mkdir -p $(SOURCES_ROOT)/targets/$(PROFILE)/fs
+	touch $(TARGETS_DIR)/$(PROFILE)/$(PROFILE)
+
+ifneq ($(strip $(PROFILE)),)
+include $(TARGETS_DIR)/$(PROFILE)/$(PROFILE)
+endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/Notice.license
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/Notice.license (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/Notice.license Fri Oct 19 18:37:43 2012
@@ -1,0 +1,21 @@
+Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ 
+I. 3rd parties Software
+This software does use open source software developed by 3rd parties:
+-	libupnp (current release 1.6.15). This product uses software downloaded at Sourceforge (http://sourceforge.net/projects/pupnp/files/pupnp/libUPnP%201.6.15/libupnp-1.6.15.tar.bz2/download)licensed under the BSD License.
+-	curl (current release 7.27.0). This product uses software developed Sourceforge (http://curl.haxx.se/download/curl-7.27.0.tar.gz) licensed under the MIT License.
+-	Shttpd (release 1.42) This product uses software developed Sourceforge (http://sourceforge.net/projects/shttpd/files/shttpd/1.42/shttpd-1.42.tar.gz/download ) licensed under the Public Domain License. This project has been ported to a new project called mongoose (current release 3.1), licensed under the MIT License (but not used by GAL)
+-	tinyxml (release 2.5.3). This product uses software developed at Sourceforge (http://sourceforge.net/projects/tinyxml/files/tinyxml/2.5.3/tinyxml_2_5_3.tar.gz/download) licensed under the zlib/libpng License.
+
+
+
+II. Specification used
+Part of this software is based on the specification provided by the ZigBee Alliance (http://www.zigbee.org). 
+Licensed under ZigBee specific license for non-member of the ZigBee Alliance.
+
+
+III. License Summary
+- Apache License 2.0
+- ZigBee Non-Member License

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/curl-7.27.0/Makefile.cross
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/curl-7.27.0/Makefile.cross (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/curl-7.27.0/Makefile.cross Fri Oct 19 18:37:43 2012
@@ -1,0 +1,53 @@
+include ../Makefile.rules
+
+all:
+	$(MAKE) all
+
+clean:
+	rm -f *~
+	$(MAKE) clean
+
+distclean:
+	$(MAKE) distclean
+
+config:
+	./configure \
+	--prefix=$(PREFIX_TMP) \
+	--host=$(HOSTARCH) \
+	--build=$(BUILDARCH) \
+	--disable-verbose \
+	--disable-manual \
+	--disable-debug \
+	--disable-ftp \
+	--disable-smtp \
+	--disable-file \
+	--disable-ldap \
+	--disable-ldaps \
+	--disable-dict \
+	--disable-tftp \
+	--disable-imap \
+	--disable-pop3 \
+	--disable-smtp \
+	--disable-rtsp \
+	--disable-telnet \
+	--disable-gopher \
+	--disable-proxy \
+	--disable-cookies \
+	--without-libssh2
+	
+
+install:
+	$(MAKE) $@
+	mkdir -p $(PREFIX)/usr/$(EXTRA)/lib
+	mkdir -p $(PREFIX)/usr/$(EXTRA)/bin
+	install -m 644 $(PREFIX_TMP)/lib/libcurl.so.4.2.0 $(PREFIX)/usr/$(EXTRA)/lib
+	ln -sfn libcurl.so.4.2.0 $(PREFIX)/usr/$(EXTRA)/lib/libcurl.so
+	ln -sfn libcurl.so.4.2.0 $(PREFIX)/usr/$(EXTRA)/lib/libcurl.so.4
+	$(STRIP) $(PREFIX)/usr/$(EXTRA)/lib/libcurl.so.4.2.0
+
+uninstall:
+	rm -f $(PREFIX)/usr/$(EXTRA)/lib/libcurl.so
+	rm -f $(PREFIX)/usr/$(EXTRA)/lib/libcurl.so.4
+	rm -f $(PREFIX)/usr/$(EXTRA)/bin/curl
+	$(MAKE) $@
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/iniparser/Makefile.cross
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/iniparser/Makefile.cross (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/iniparser/Makefile.cross Fri Oct 19 18:37:43 2012
@@ -1,0 +1,41 @@
+include ../Makefile.rules
+
+CLAGS += -Wall -Wno-format -g -DDEBUG -O2
+
+SRC = tinystr.cpp  tinyxml.cpp  tinyxmlerror.cpp  tinyxmlparser.cpp
+
+TARGETS = libtinyxml.a
+
+.PHONY: all install clean distclean
+
+all: 
+	$(MAKE) $<
+
+libtinyxml.a: tinystr.o  tinyxml.o  tinyxmlerror.o  tinyxmlparser.o 
+	@echo AR $@
+	@$(AR) r $@ $?
+
+
+clean:
+	$(MAKE) clean
+	rm -f *.a *.so* *~ src/*~
+
+distclean:
+	$(MAKE) $<
+
+config:
+	echo Nothing to config
+
+install:
+	mkdir -p $(PREFIX_TMP)/lib
+	mkdir -p $(PREFIX_TMP)/include
+	install -m 644 libiniparser.a  $(PREFIX_TMP)/lib
+	install -m 644 libiniparser.so.0  $(PREFIX_TMP)/lib
+	install -m 644 src/iniparser.h  $(PREFIX_TMP)/include
+	install -m 644 src/dictionary.h  $(PREFIX_TMP)/include
+
+uninstall:
+	rm -f $(PREFIX_TMP)/lib/libiniparser.a
+	rm -f $(PREFIX_TMP)/include/iniparser.h
+	rm -f $(PREFIX_TMP)/include/dictionary.h
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/libupnp-1.6.15/Makefile.cross
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/libupnp-1.6.15/Makefile.cross (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/libupnp-1.6.15/Makefile.cross Fri Oct 19 18:37:43 2012
@@ -1,0 +1,41 @@
+include ../Makefile.rules
+
+.PHONY: install clean all distclean config 
+
+export CFLAGS		+= -I$(PREFIX_TMP)/include -I/opt/dev/iwmmxt/include
+export LDFLAGS		= -L/opt/dev/iwmmxt/lib -L$(PREFIX)/usr/$(EXTRA)/lib -L$(PREFIX)/usr/local/lib
+
+all:
+	$(MAKE) all
+
+clean:
+	rm -rf *~
+	$(MAKE) clean
+
+distclean: clean
+	$(MAKE) distclean
+
+config:
+	./configure \
+	--prefix=$(PREFIX_TMP) \
+	--host=$(HOSTARCH) \
+	--build=$(BUILDARCH)
+
+install:
+	$(MAKE) $@
+	mkdir -p $(PREFIX)/usr/$(EXTRA)/lib
+	cp $(PREFIX_TMP)/lib/libthreadutil.so.6.0.0 $(PREFIX)/usr/$(EXTRA)/lib
+	ln -sfn libthreadutil.so.6.0.0 $(PREFIX)/usr/$(EXTRA)/lib/libthreadutil.so
+	ln -sfn libthreadutil.so.6.0.0 $(PREFIX)/usr/$(EXTRA)/lib/libthreadutil.so.6
+
+uninstall:
+	rm -f $(PREFIX)/usr/$(EXTRA)/lib/libixml.so
+	rm -f $(PREFIX)/usr/$(EXTRA)/lib/libixml.so.2
+	rm -f $(PREFIX)/usr/$(EXTRA)/lib/libixml.so.2.0.3
+	rm -f $(PREFIX)/usr/$(EXTRA)/lib/libupnp.so
+	rm -f $(PREFIX)/usr/$(EXTRA)/lib/libupnp.so.2
+	rm -f $(PREFIX)/usr/$(EXTRA)/lib/libupnp.so.2.0.3
+	rm -f $(PREFIX)/usr/$(EXTRA)/lib/libthreadutil.so
+	rm -f $(PREFIX)/usr/$(EXTRA)/lib/libthreadutil.so.6
+	rm -f $(PREFIX)/usr/$(EXTRA)/lib/libthreadutil.so.6.0.0
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ACL.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ACL.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ACL.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,19 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "ACL.h"
+
+/*
+ This class does not override any method so far.
+ */
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ACL.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ACL.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ACL.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,25 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef ACL_H_INCLUDED_
+#define ACL_H_INCLUDED_
+
+#include "NodeMap.h"
+
+#define ACL_MAX_ENTRIES NodeMap_MAX_ENTRIES
+
+/**
+ ACL Class - Access Control List
+ */
+class ACL: public NodeMap {
+
+};
+
+#endif
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/Agents.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/Agents.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/Agents.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,617 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include "Agents.h"
+
+//**************************************************************************
+//*************  RPCContext  ***********************************************
+//**************************************************************************
+
+/**
+ Constructor
+
+ @param void Void.
+ @return Void.
+ */
+
+template<class T, typename resf, typename notf>
+RPCContext<T, resf, notf>::RPCContext(int sessionId, T *handler,
+		resf rpcResponseCb, notf rpcNotifyCb) {
+	pLogger = new Debug("RPCContext");
+	pLogger->setDebugMode(DBG_ENABLED);
+	//pLogger->setDebugMode(DBG_DISABLED);
+	pLogger->setDebugLevel(DEBUGGING);
+	pLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+	pLogger->enableDebugOuput(DBG_SCREEN);
+	//pLogger->enableDebugOuput(DBG_LOGFILE);		
+
+#ifdef DEBUG_ACTIVE_RPCC
+	pLogger->debug("Constructor - sessionId = %d", sessionId);
+#endif
+
+	this->setSessionId(sessionId);
+	this->setHandler(handler);
+	this->setRPCResponseCb(rpcResponseCb);
+	this->setRPCNotifyCb(rpcNotifyCb);
+}
+
+template<class T, typename resf, typename notf>
+RPCContext<T, resf, notf>::RPCContext(const RPCContext<T, resf, notf> &ctxt) {
+	pLogger = new Debug("RPCContext");
+	pLogger->setDebugMode(DBG_ENABLED);
+	//pLogger->setDebugMode(DBG_DISABLED);
+	pLogger->setDebugLevel(DEBUGGING);
+	pLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+	pLogger->enableDebugOuput(DBG_SCREEN);
+	//pLogger->enableDebugOuput(DBG_LOGFILE);		
+
+#ifdef DEBUG_ACTIVE_RPCC
+	pLogger->debug("Constructor - sessionId = %d", sessionId);
+#endif
+
+	this->setSessionId(ctxt.sessionId);
+	this->setHandler(ctxt.handler);
+	this->setRPCResponseCb(ctxt.rpcResponseCb);
+	this->setRPCNotifyCb(ctxt.rpcNotifyCb);
+}
+
+template<class T, typename resf, typename notf>
+RPCContext<T, resf, notf> &RPCContext<T, resf, notf>::operator =(
+		const RPCContext<T, resf, notf> &ctxt) {
+	this->setSessionId(ctxt.sessionId);
+	this->setHandler(ctxt.handler);
+	this->setRPCResponseCb(ctxt.rpcResponseCb);
+	this->setRPCNotifyCb(ctxt.rpcNotifyCb);
+
+	return *this;
+}
+
+template<class T, typename resf, typename notf>
+RPCContext<T, resf, notf>::RPCContext() {
+	pLogger = new Debug("RPCContext");
+	pLogger->setDebugMode(DBG_ENABLED);
+	//pLogger->setDebugMode(DBG_DISABLED);
+	pLogger->setDebugLevel(DEBUGGING);
+	pLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+	pLogger->enableDebugOuput(DBG_SCREEN);
+	//pLogger->enableDebugOuput(DBG_LOGFILE);		
+
+#ifdef DEBUG_ACTIVE_RPCC
+	pLogger->debug("Constructor - sessionId = %d", sessionId);
+#endif
+
+	this->setSessionId(0);
+	this->setHandler(NULL);
+	this->setRPCResponseCb(NULL);
+	this->setRPCNotifyCb(NULL);
+}
+
+/**
+ Destructor
+
+ @param void Void.
+ @return Void.
+ */
+template<class T, typename resf, typename notf>
+RPCContext<T, resf, notf>::~RPCContext() {
+#ifdef DEBUG_ACTIVE_RPCC
+	pLogger->debug("Destructor");
+#endif
+
+	if (pLogger != NULL) {
+		delete pLogger;
+		pLogger = NULL;
+	}
+}
+
+template<class T, typename resf, typename notf>
+T *RPCContext<T, resf, notf>::getHandler() {
+	return handler;
+}
+
+template<class T, typename resf, typename notf>
+void RPCContext<T, resf, notf>::setHandler(T *handler) {
+	this->handler = handler;
+}
+
+/**
+ Public method RPCContext setRPCResponseCb
+ It is a modifier method: it allows setting rpcResponseCb.
+
+ @param value Pointer to the RPC Response Callback.
+ @return Void.
+ */
+template<class T, typename resf, typename notf>
+void RPCContext<T, resf, notf>::setRPCResponseCb(resf method) {
+#ifdef DEBUG_ACTIVE_RPCC
+	pLogger->debug("setRPCResponseCb");
+#endif
+	this->rpcResponseCb = method;
+}
+
+/**
+ Public method RPCContext getRPCResponseCb
+ It is a selector method: it allows retrieving rpcResponseCb value.
+
+ @param void Void.
+ @return Pointer to the registered RPC Response Callback.
+ */
+template<class T, typename resf, typename notf>
+resf RPCContext<T, resf, notf>::getRPCResponseCb() {
+#ifdef DEBUG_ACTIVE_RPCC
+	pLogger->debug("getRPCResponseCb");
+#endif
+	return this->rpcResponseCb;
+}
+
+/**
+ Public method RPCContext setRPCNotifyCb
+ It is a modifier method: it allows setting rpcNotifyCb.
+
+ @param method Pointer to the RPC Notify Callback.
+ @return Void.
+ */
+template<class T, typename resf, typename notf>
+void RPCContext<T, resf, notf>::setRPCNotifyCb(notf method) {
+#ifdef DEBUG_ACTIVE_RPCC
+	pLogger->debug("setRPCNotifyCb");
+#endif
+	this->rpcNotifyCb = method;
+}
+
+/**
+ Public method RPCContext getRPCNotifyCb
+ It is a selector method: it allows retrieving rpcNotifyCb value.
+
+ @param void Void.
+ @return Pointer to the registered RPC Notify Callback.
+ */
+template<class T, typename resf, typename notf>
+notf RPCContext<T, resf, notf>::getRPCNotifyCb() {
+#ifdef DEBUG_ACTIVE_RPCC
+	pLogger->debug("getRPCNotifyCb");
+#endif
+	return this->rpcNotifyCb;
+}
+
+/**
+ Public method RPCContext setSessionId
+ It is a modifier method: it allows setting sessionId.
+
+ @param value Session identifier value.
+ @return Void.
+ */
+template<class T, typename resf, typename notf>
+void RPCContext<T, resf, notf>::setSessionId(int value) {
+#ifdef DEBUG_ACTIVE_RPCC
+	pLogger->debug("setSessionId - sessionId = %d", value);
+#endif
+	this->sessionId = value;
+}
+
+/**
+ Public method RPCContext getSessionId
+ It is a selector method: it allows retrieving sessionId value.
+
+ @param void Void.
+ @return Registered session identifier value..
+ */
+template<class T, typename resf, typename notf>
+int RPCContext<T, resf, notf>::getSessionId() {
+#ifdef DEBUG_ACTIVE_RPCC
+	pLogger->debug("getSessionId - sessionId = %d",this->sessionId);
+#endif
+	return this->sessionId;
+}
+
+//**************************************************************************
+//*************  fContext  *************************************************
+//**************************************************************************
+template<class AT>
+static void *timer_CbW(void *input) {
+	//TODO: This part could be edit in order to fix the bug coming when a very short timeout is inserted (the GAL crash on killTimer() ).
+	timer_data_t<AT> *data;
+
+	data = (timer_data_t<AT> *) input;
+
+	((data->agentPtr)->*(data->callback))();
+
+	delete data;
+
+	return NULL;
+}
+
+template<class T, class AT, typename resf, typename notf>
+fContext<T, AT, resf, notf>::fContext(GalZbIf::FeatureControl *fc,
+		unsigned long features) {
+	this->fc = fc;
+	this->features = features;
+	fstate = Idle;
+
+	//2010-11-14
+	this->timerData = NULL;
+
+}
+
+template<class T, class AT, typename resf, typename notf>
+bool fContext<T, AT, resf, notf>::lock() {
+	if (fstate == Running)
+		return false;
+
+	if (!fc->lock(features))
+		return false;
+
+	fstate = Running;
+
+	return true;
+}
+
+template<class T, class AT, typename resf, typename notf>
+bool fContext<T, AT, resf, notf>::unlock(fState_t state) {
+	if (fstate != Running)
+		return false;
+
+	fc->unlock(features);
+
+	fstate = state;
+
+	return true;
+}
+
+template<class T, class AT, typename resf, typename notf>
+bool fContext<T, AT, resf, notf>::isLocked() {
+	return fstate == Running;
+}
+
+template<class T, class AT, typename resf, typename notf>
+bool fContext<T, AT, resf, notf>::setTimer(TimerThread *timerThread,
+		AT *agentPtr, void (AT::*callback)(void)) {
+	ThreadPoolJob job;
+	int res;
+
+	timerData = new timer_data_t<AT>;
+
+	timerData->callback = callback;
+	timerData->agentPtr = agentPtr;
+	timerData->tthread = timerThread;
+
+	TPJobInit(&job, timer_CbW<AT>, timerData);
+	TPJobSetFreeFunction(&job, NULL);
+	TPJobSetPriority(&job, MED_PRIORITY);
+
+	res = TimerThreadSchedule(timerThread, fTimeout, REL_SEC, &job, SHORT_TERM,
+			&timerData->eventId);
+	if (res != 0) {
+		delete timerData;
+		//--------2010-11-13
+		timerData = NULL;
+		return false;
+	}
+
+	return true;
+}
+
+template<class T, class AT, typename resf, typename notf>
+int fContext<T, AT, resf, notf>::killTimer() {
+	ThreadPoolJob tempJob;
+
+	// Check whether timer was created
+	if (timerData == NULL) {
+		return -1;
+	}
+	if (!TimerThreadRemove(timerData->tthread, timerData->eventId, &tempJob)) {
+		delete timerData;
+		timerData = NULL;
+	} else {
+		delete timerData;
+		timerData = NULL;
+		return -1;
+	}
+	return 0;
+}
+
+template<class T, class AT, typename resf, typename notf>
+int fContext<T, AT, resf, notf>::resetTimerEnv() {
+	this->timerData = NULL;
+	return 0;
+}
+
+#ifndef AGENTS_TEMPLATES
+
+//**************************************************************************
+//*************  RPCReqStatus  *********************************************
+//**************************************************************************
+
+/**
+ Constructor
+
+ @param void Void.
+ @return Void.
+ */
+
+RPCReqStatus::RPCReqStatus(fState_t fState, int fResult, AgentError returnValue //bool asynchReq
+		) {
+	pLogger = new Debug("RPCReqStatus");
+	pLogger->setDebugMode(DBG_ENABLED);
+	//pLogger->setDebugMode(DBG_DISABLED);
+	//TODO Remove DEBUGGING MODE!
+
+	pLogger->setDebugLevel(DEBUGGING);
+	pLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+	pLogger->enableDebugOuput(DBG_SCREEN);
+	//pLogger->enableDebugOuput(DBG_LOGFILE);		
+
+#ifdef DEBUG_ACTIVE_RPCR
+	pLogger->debug("Constructor");
+#endif
+
+	this->setFState(fState);
+	this->setFResult(fResult);
+	this->setReturnValue(returnValue);
+	this->setAsynchReq(false);
+}
+
+RPCReqStatus::RPCReqStatus(fState_t fState, int fResult, AgentError returnValue,
+		bool asynchReq) {
+	pLogger = new Debug("RPCReqStatus");
+	pLogger->setDebugMode(DBG_ENABLED);
+	//pLogger->setDebugMode(DBG_DISABLED);
+	//TODO Remove DEBUGGING MODE!
+
+	pLogger->setDebugLevel(DEBUGGING);
+	pLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+	pLogger->enableDebugOuput(DBG_SCREEN);
+	//pLogger->enableDebugOuput(DBG_LOGFILE);
+
+#ifdef DEBUG_ACTIVE_RPCR
+	pLogger->debug("Constructor");
+#endif
+
+	this->setFState(fState);
+	this->setFResult(fResult);
+	this->setReturnValue(returnValue);
+	this->setAsynchReq(asynchReq);
+
+}
+
+#endif
+
+template<class T, class AT, class resf, class notf>
+RPCReqStatus::RPCReqStatus(struct fContext<T, AT, resf, notf> &ctxt,
+		AgentError returnValue) {
+	pLogger = new Debug("RPCReqStatus");
+
+	pLogger->setDebugMode(DBG_ENABLED);
+	//pLogger->setDebugMode(DBG_DISABLED);
+	//TODO Remove DEBUGGING MODE!
+
+	pLogger->setDebugLevel(DEBUGGING);
+	pLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+	pLogger->enableDebugOuput(DBG_SCREEN);
+	//pLogger->enableDebugOuput(DBG_LOGFILE);		
+
+#ifdef DEBUG_ACTIVE_RPCR
+	pLogger->debug("Constructor");
+#endif
+
+	this->setFState(ctxt.fstate);
+	this->setFResult(ctxt.result);
+	this->setReturnValue(returnValue);
+	this->setAsynchReq(ctxt.rpcContext.getRPCNotifyCb() != NULL);
+
+}
+
+#ifndef AGENTS_TEMPLATES
+
+/**
+ Destructor
+
+ @param void Void.
+ @return Void.
+ */
+
+RPCReqStatus::~RPCReqStatus() {
+#ifdef DEBUG_ACTIVE_RPCR
+	pLogger->debug("Destructor");
+#endif
+	delete pLogger;
+}
+
+/**
+ Public method RPCReqStatus setFState
+ It is a modifier method: it allows setting fState (i.e. macrofunction state). The allowed values are defined in fState_t (refer to Agents.h)
+
+ @param value Macrofunction state value.
+ @return Void.
+ */
+
+void RPCReqStatus::setFState(fState_t value) {
+#ifdef DEBUG_ACTIVE_RPCR
+	pLogger->debug("setFState - fState = %d",value);
+#endif
+	this->fState = value;
+}
+
+/**
+ Public method RPCReqStatus getFState
+ It is a selector method: it allows retrieving fState value.
+
+ @param void Void.
+ @return Macrofunction state value.
+ */
+
+fState_t RPCReqStatus::getFState() {
+#ifdef DEBUG_ACTIVE_RPCR
+	pLogger->debug("getFState - fState = %d",this->fState);
+#endif
+	return this->fState;
+}
+
+/**
+ Public method RPCReqStatus setFResult
+ It is a modifier method: it allows setting fResult (i.e. macrofunction result). The allowed values are FSUCCESS, FFAILED and
+ FNOT_STARTED (refer to Agents.h)
+
+ @param value Macrofunction result value.
+ @return Void.
+ */
+
+void RPCReqStatus::setFResult(int value) {
+#ifdef DEBUG_ACTIVE_RPCR
+	pLogger->debug("setFResult - fResult = %d",value);
+#endif
+	this->fResult = value;
+}
+
+/**
+ Public method RPCReqStatus getFResult
+ It is a selector method: it allows retrieving fResult value.
+
+ @param void Void.
+ @return Macrofunction result value.
+ */
+
+int RPCReqStatus::getFResult() {
+#ifdef DEBUG_ACTIVE_RPCR
+	pLogger->debug("getFResult - fResult = %d",this->fResult);
+#endif
+	return this->fResult;
+}
+
+/**
+ Public method RPCReqStatus setReturnValue
+ It is a modifier method: it allows setting returnValue (i.e. return code). The allowed values are the "Agents Return Codes" defined in Agents.h.
+
+ @param value Function return value.
+ @return Void.
+ */
+
+void RPCReqStatus::setReturnValue(AgentError value) {
+#ifdef DEBUG_ACTIVE_RPCR
+	pLogger->debug("setFReturnValue - returnValue = %d",value);
+#endif
+	this->returnValue = value;
+}
+
+/**
+ Public method RPCReqStatus getFReturnValue
+ It is a selector method: it allows retrieving returnValue value.
+
+ @param void Void.
+ @return Function return value.
+ */
+
+AgentError RPCReqStatus::getReturnValue() {
+#ifdef DEBUG_ACTIVE_RPCR
+	pLogger->debug("getReturnValue - returnValue = %d",this->returnValue);
+#endif
+	return this->returnValue;
+}
+
+void RPCReqStatus::setAsynchReq(bool asynchReqValue) {
+	this->asynchReq = asynchReqValue;
+#ifdef DEBUG_ACTIVE_RPCR
+	pLogger->debug("setAsynchReq - asynchReq = %d", this->asynchReq);
+#endif
+}
+
+bool RPCReqStatus::isReqAsynch() {
+#ifdef DEBUG_ACTIVE_RPCR
+	pLogger->debug("isReqAsynch - asynchReq = %d", this->asynchReq);
+#endif
+	return this->asynchReq;
+}
+
+//**************************************************************************
+//*************  AgentErrorMessages  ***************************************
+//**************************************************************************
+
+static struct {
+	enum RESTError code;
+	const char *msg;
+} mapping[] = { { /*AGENT_SUCCESS*/
+NO_ERROR, "" },
+
+{ /*AGENT_ERROR*/
+GENERIC_REST_ERROR, "Generic Agent error" }, { /*UNKNOWN_AGENT_ERROR*/
+GENERIC_REST_ERROR, "Unknown Agent error" }, { /*GAL_NOT_RUNNING*/
+GENERIC_REST_ERROR, "GAL not running" }, { /*AGENT_BUSY*/
+GENERIC_REST_ERROR, "Agent Busy" }, { /*TIMER_ERROR*/
+GENERIC_REST_ERROR, "ERROR creating timer" }, { /*TIMER_EXPIRED*/
+TIMEOUT, "Timer expired" },
+
+{ /*INQUIRY_ERROR*/
+GENERIC_REST_ERROR, "ERROR returned by ZDO_IEEE_ADDR_confirm" }, { /*INQUIRY_CACHE_EMPTY*/
+GENERIC_REST_ERROR, "Inquiry cache empty" }, { /*INQUIRY_NOT_RUNNING*/
+GENERIC_REST_ERROR, "Inquiry not running" }, { /*INQUIRY_NONEXISTENTENT_NODE*/
+GENERIC_REST_ERROR, "A ZDO IEEE Addr confirm for a nonexistent "
+		"node has been received" }, { /*NODE_DESCRIPTOR_ERROR*/
+GENERIC_REST_ERROR, "ERROR returned by ZDO_NODE_DESC_confirm" }, { /*NONEXISTENTENT_NODE*/
+GENERIC_REST_ERROR, "A ZDO confirm for a nonexistent node has been received" },
+		{ /*POWER_DESCRIPTOR_ERROR*/
+		GENERIC_REST_ERROR, "ERROR returned by ZDO_POWER_DESC_confirm" }, { /*ANNCE_MODE_ALREADY_RUNNING*/
+		GENERIC_REST_ERROR, "AnnouncementsMode already running" }, { /*ANNCE_MODE_NOT_RUNNING*/
+		GENERIC_REST_ERROR, "AnnouncementsMode not running" }, { /*ACTIVE_EP_ERROR*/
+		GENERIC_REST_ERROR, "ERROR returned by ZDO_ACTIVE_EP_DESC_confirm" }, { /*SERVICE_DESCRIPTOR_ERROR*/
+		GENERIC_REST_ERROR, "ERROR returned by ZDO_SIMPLE_DESC_confirm" }, { /*GETNODEBINDING_ERROR*/
+		GENERIC_REST_ERROR, "ERROR returned by ZDP_MGMT_BIND_Response" }, { /*BIND_ERROR*/
+		GENERIC_REST_ERROR, "ERROR returned by ZDP_BIND_Response" }, { /*UNBIND_ERROR*/
+		GENERIC_REST_ERROR, "ERROR returned by ZDP_UNBIND_response" }, { /*NO_AVAILABLE_ENDPOINT*/
+		GENERIC_REST_ERROR,
+				"No available endpoint - service registration failed" }, { /*ENDPOINT_NOT_REGISTERED*/
+		GENERIC_REST_ERROR, "Endpoint not registered" }, { /*NO_ACTIVE_WSN_CONNECTIONS*/
+		GENERIC_REST_ERROR, "No active WSN Connection" }, { /*NO_CUSTOMIZED_FILTER_FOUND*/
+		GENERIC_REST_ERROR, "No customized callback registered" },
+
+		{ /*MSG_CACHE_EMPTY*/
+		GENERIC_REST_ERROR, "Message Cache Empty" }, { /*SENDING_MSG_ERROR*/
+		GENERIC_REST_ERROR, "ERROR sending message" },
+
+		{ /*WSNC_AUTH_FOR_NONEXISTENTENT_NODE*/
+		GENERIC_REST_ERROR,
+				"A WSN-C authorization response for a nonexistent node "
+						"has been received" }, { /*PENDING_NODES_NUMBER_OVERFLOW*/
+		GENERIC_REST_ERROR,
+				"The maximum number of pending nodes has been reached" },
+
+		{ /*GW_STARTUP_ALREADY_CALLED*/
+		GENERIC_REST_ERROR, "GW startup already invoked" }, { /*INVALID_GW_STATUS*/
+		METHOD_NOT_ALLOWED, "Invalid GW Status" }, { /*GW_STARTUP_FORMING_NETWORK_FAILED*/
+		ZB_NWK_FAILURE, "GW startup Forming ZigBee network failed" }, { /*GW_STARTUP_JOINING_NETWORK_FAILED*/
+		ZB_NWK_FAILURE, "GW startup Joining ZigBee network failed" }
+
+};
+
+/**
+ Public method AgentErrorMessages getErrorMessage
+ It is a selector method: it allows retrieving the error description related to a specific return code.
+
+ @param errorId Return code whose description is required.
+ @return Error description.
+ */
+
+const char * AgentErrorMessages::getErrorMessage(AgentError errorId) {
+	return mapping[errorId].msg;
+}
+
+enum RESTError AgentErrorMessages::getRESTError(AgentError errorId) {
+	return mapping[errorId].code;
+}
+
+#endif
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/Agents.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/Agents.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/Agents.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,309 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef AGENTS_H
+#define AGENTS_H
+
+#include "CDebug.h"
+#include "RESTErrors.h"
+#include "GalZbIf.h"
+
+/**
+ PACETIME is the delay added between two subsequents ZigBee messages sent over the air. 
+ This time interval is expressed in microseconds and is used by all the agents.
+ */
+#define PACETIME					800000
+
+/**
+ Each macrofunction (defined in a specific agent) has three possible results: FSUCCESS (if all expected responses have been properly received),
+ FFAILED (in case of any error) and FNOT_STARTED (if the related macrofunction has not been executed because of some issues, e.g. GAL is not running).
+ Please refer to the variable "result" included in the macrofunction context (struct fContext) defined in each specific agent.
+ */
+#define FSUCCESS					0
+#define FFAILED						1
+#define FNOT_STARTED					-1	
+
+/**
+ Agents Return Codes	
+ */
+enum AgentError {
+// Generic Agent Success
+	AGENT_SUCCESS,
+
+// Generic Agent Error codes
+	AGENT_ERROR, // Generic Agent error
+	UNKNOWN_AGENT_ERROR, // Unknown Agent error
+	GAL_NOT_RUNNING, // The GW is not in GW_RUNNING state
+	AGENT_BUSY, // The specific Agent is currently doing some other operations
+	TIMER_ERROR, // ERROR creating timer
+	TIMER_EXPIRED, // Timer expired
+
+// Discovery Agent Error codes
+	INQUIRY_ERROR, // ERROR returned by ZDO_IEEE_ADDR_confirm
+	INQUIRY_CACHE_EMPTY, // Inquiry cache is empty - no inquiry previously performed
+	INQUIRY_NOT_RUNNING, // When cancelInquiry is requested and no inquiry is running
+	INQUIRY_NONEXISTENTENT_NODE, // A ZDO_IEEE_ADDR_confirm is received concerning a non existentent node (node not already discovered)
+	NODE_DESCRIPTOR_ERROR, // ERROR returned by ZDO_NODE_DESC_confirm
+	NONEXISTENTENT_NODE, // INTERNAL ERROR: a NODE DESCRIPTOR or POWER DESCRIPTOR confirm for a nonexistent node has been received
+	POWER_DESCRIPTOR_ERROR, // ERROR returned by ZDO_POWER_DESC_confirm
+	ANNCE_MODE_ALREADY_RUNNING, // When startAnnouncementsMode is requested and AnnoucementsMode is already running	
+	ANNCE_MODE_NOT_RUNNING, // When cancelAnnouncementsMode is requested and AnnoucementsMode is not running
+
+// Service Agent Error codes
+	ACTIVE_EP_ERROR, // ERROR returned by ZDO_ACTIVE_EP_DESC_confirm
+	SERVICE_DESCRIPTOR_ERROR, // ERROR returned by ZDO_SIMPLE_DESC_confirm
+	GETNODEBINDING_ERROR, // ERROR returned by ZDP_MGMT_BIND_Response
+	BIND_ERROR, // ERROR returned by ZDP_BIND_Response
+	UNBIND_ERROR, // ERROR returned by ZDP_UNBIND_response
+
+	NO_AVAILABLE_ENDPOINT, // No available endpoint when adding service in ServiceAgent
+	ENDPOINT_NOT_REGISTERED, // Endpoint not registered
+	NO_ACTIVE_WSN_CONNECTIONS, // No active WSN Connection
+	NO_CUSTOMIZED_FILTER_FOUND, // No customized callback registered
+
+	MSG_CACHE_EMPTY, // Message Cache Empty
+	SENDING_MSG_ERROR, // ERROR sending message
+
+// TrustCenter Agent Error codes
+	WSNC_AUTH_FOR_NONEXISTENTENT_NODE, // A WSN-C authorization response for a nonexistent node has been received
+	PENDING_NODES_NUMBER_OVERFLOW, // The maximum number of pending nodes has been reached
+
+// LocalNolde Error codes
+	GW_STARTUP_ALREADY_CALLED, // GW startup already invoked
+	INVALID_GW_STATUS, // Invalid GW Status
+	GW_STARTUP_FORMING_NETWORK_FAILED,
+	GW_STARTUP_JOINING_NETWORK_FAILED
+
+};
+
+/**
+ Dummy Session ID used when internally calling Agents' methods 
+ e.g. when DiscoveryAgent startInquiry method is invoked by a method implemented in ServiceAgent
+ */
+#define INTERNAL_AGENT_REQUEST_SESSION_ID			-1
+
+enum fState_t {
+	NotAvailable, Idle, Running, Canceled, End
+};
+
+typedef struct {
+	void *rpcResponseCb;
+	void *rpcNotifyCb;
+	int sessionId;
+} rpcContext_t;
+
+typedef struct {
+	int returnValue;
+	fState_t fState;
+	int result;
+} rpcReqStatus_t;
+
+//**************************************************************************
+//*************  RPCContext  ***********************************************
+//**************************************************************************
+
+/**
+ RPCContext and RPCReqStatus classes define the interface between an agent and a generic RPC layer.
+ RPCContext is used by a RPC layer to register a response and a notify callback function to be used within a specific
+ session. In particular, sessionId is used to uniquely identify a RPC session and properly manage the agent response.
+ RPCReqStatus is used by a generic agent to share the results of a specific macrofunction with the upper RPC layer.
+ The class AgentErrorMessages is, in fact, a "error messages" dictionary. In particular, this class stores all the
+ return codes used by agents (i.e. Discovery Agent, Service Agent, Management Agent and TrustCenter Agent) along with
+ a brief human readable description for each return code.
+ */
+
+#define CALL_RESPONSE(ctxt)\
+ (((ctxt) -> getHandler ()) ->* ((ctxt) -> getRPCResponseCb ()))
+#define CALL_NOTIFY(ctxt)\
+ (((ctxt) -> getHandler ()) ->* ((ctxt) -> getRPCNotifyCb ()))
+
+template<class T, typename resf = void *, typename notf = void *>
+class RPCContext {
+
+public:
+	///	Constructors:
+	RPCContext(int sessionId, T *handler, resf rpcResponseCb, notf rpcNotifyCb);
+
+	RPCContext(const RPCContext &ctxt);
+
+	RPCContext &operator =(const RPCContext &ctxt);
+
+	RPCContext();
+
+	///	Destructor:
+	~RPCContext();
+
+	// Functions: modifiers (set), selectors (get)
+	void init();
+
+	///	rpcResponseCb modifier and selector 
+	void setRPCResponseCb(resf method);
+
+	resf getRPCResponseCb();
+
+	///	rpcNotifyCb modifier and selector 
+	void setRPCNotifyCb(notf method);
+
+	notf getRPCNotifyCb();
+
+	///	sessionId modifier and selector 
+	void setSessionId(int value);
+
+	int getSessionId();
+
+	///	handler modifier and selector 
+	void setHandler(T *handler);
+
+	T *getHandler();
+
+	// itterators:
+	// Attributes visible by scope of instantiation and use
+
+protected:
+
+	// Attributes visible to descendents
+
+	///	Pointer to a Debug object -> logger
+	Debug *pLogger;
+
+private:
+	// Local attributes
+	T *handler;
+	resf rpcResponseCb;
+	notf rpcNotifyCb;
+	int sessionId;
+
+};
+
+#define FCALL_RESPONSE(fctxt) 	CALL_RESPONSE(&fctxt.rpcContext)
+#define FCALL_NOTIFY(fctxt) 	CALL_NOTIFY (&fctxt.rpcContext)
+
+template<class AT>
+struct timer_data_t {
+	int eventId;
+	AT *agentPtr;
+	TimerThread *tthread;
+	void (AT::*callback)(void);
+};
+
+template<class T, class AT, typename resf = void *, typename notf = void *>
+struct fContext {
+
+	GalZbIf::FeatureControl *fc;
+	unsigned long features;
+
+	fState_t fstate;
+	int result; // Fcontext - result -> allowed values: FSUCCESS, FFAILED and FNOT_STARTED (refer to Agents.h)
+	int numExpectedMsgs;
+	int fTimeout; // Fcontext - fTimeout -> function timeout value (please refer to the method setTimer)
+
+	int data;
+
+	timer_data_t<AT> *timerData;
+	RPCContext<T, resf, notf> rpcContext; // Fcontext - rpcContext -> object containing information to manage RPC sessions
+
+	fContext(GalZbIf::FeatureControl *fc, unsigned long features);
+
+	bool lock();
+	bool unlock(fState_t state = End);
+	bool isLocked();
+
+	bool setTimer(TimerThread *tthread, AT *agentPtr,
+			void (AT::*callback)(void));
+
+	int killTimer();
+	int resetTimerEnv();
+};
+
+//**************************************************************************
+//*************  RPCReqStatus  *********************************************
+//**************************************************************************
+
+class RPCReqStatus {
+
+public:
+	///	Constructors:
+	RPCReqStatus(fState_t fState, int fResult, AgentError returnValue);
+
+	RPCReqStatus(fState_t fState, int fResult, AgentError returnValue,
+			bool asynchReq);
+
+	///	Constructors:
+	template<class T, class AT, class resf, class notf>
+	RPCReqStatus(struct fContext<T, AT, resf, notf> &ctxt,
+			AgentError returnValue);
+
+	///	Destructor:
+	~RPCReqStatus();
+
+	// Functions: modifiers (set), selectors (get)
+	void init();
+
+	///	fstate modifier and selector 
+	void setFState(fState_t value);
+
+	fState_t getFState();
+
+	///	fResult modifier and selector 
+	void setFResult(int value);
+
+	int getFResult();
+
+	///	returnValue modifier and selector 
+	void setReturnValue(AgentError value);
+
+	AgentError getReturnValue();
+
+	bool isReqAsynch();
+
+	// itterators:
+	// Attributes visible by scope of instantiation and use
+
+protected:
+
+	// Attributes visible to descendents
+
+	///	Pointer to a Debug object -> logger
+	Debug *pLogger;
+
+private:
+	// Local attributes
+
+	fState_t fState;
+	int fResult;
+	AgentError returnValue;
+
+	// It specifies whether request asynchronous
+	bool asynchReq;
+
+	void setAsynchReq(bool asynchReqValue);
+
+};
+
+//**************************************************************************
+//*************  AgentErrorMessages  ***************************************
+//**************************************************************************
+
+class AgentErrorMessages {
+
+private:
+	AgentErrorMessages() {
+	}
+
+public:
+	static const char *getErrorMessage(AgentError errorId);
+
+	static RESTError getRESTError(AgentError errorId);
+};
+
+#define AGENTS_TEMPLATES
+#import "Agents.cpp"
+#undef AGENTS_TEMPLATES
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDebug.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDebug.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDebug.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,259 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include "CDebug.h"
+
+#include "CLogStorage.h"
+
+/**
+ Constructor
+
+ @param void Void.
+ @return Void.
+ */
+
+Debug::Debug(const char *name) {
+	if (name != NULL) {
+		this->className = std::string(name);
+	} else {
+		// Default value
+		this->className = std::string("className");
+	}
+
+	///	Init debug output
+	outputs[DBG_SCREEN] = DBG_OUTPUT_DISABLED;
+	outputs[DBG_LOGFILE] = DBG_OUTPUT_DISABLED;
+
+	///	Init debug message format
+	_debugmsgformat = DBGMSGFORMAT_DEFAULT;
+}
+
+/**
+ Destructor
+
+ @param void Void.
+ @return Void.
+ */
+
+Debug::~Debug() {
+	//printf ( "Debug Destructor" );
+}
+
+/**
+ Public method Debug getDebugMode
+
+ @param void Void.
+ @return Current debug mode.
+ */
+
+int Debug::getDebugMode() {
+	//printf ( "Debug::getDebugMode - _debugMode = %d \n", this->_debugMode );
+	return this->_debugMode;
+}
+
+/**
+ Public method Debug setDebugMode
+
+ @param value Debug mode value.
+ @return Current debug mode.
+ */
+
+void Debug::setDebugMode(int value) {
+	this->_debugMode = value;
+	//printf ( "Debug::setDebugMode - _debugMode = %d \n", this->_debugMode );
+}
+
+/**
+ Public method Debug enableDebugOuput
+
+ @param type Output type.
+ @return Void.
+ */
+
+void Debug::enableDebugOuput(int type) {
+	if (this->_debugMode == DBG_ENABLED && type < DBG_OUTPUTS) {
+		if (outputs[type] == DBG_OUTPUT_DISABLED) {
+			outputs[type] = DBG_OUTPUT_ENABLED;
+			if (type == DBG_LOGFILE) {
+				this->logStorage = LogStorage::Instance();
+			}
+		}
+	}
+	//printf ( "Debug::enableDebugOuput - _debugMode = %d - enabled output %d\n", this->_debugMode, type );
+}
+
+/**
+ Public method Debug disableDebugOuput
+
+ @param type Output type.
+ @return Void.
+ */
+
+void Debug::disableDebugOuput(int type) {
+	if (this->_debugMode == DBG_ENABLED && type < DBG_OUTPUTS) {
+		outputs[type] = DBG_OUTPUT_DISABLED;
+	}
+	//printf ( "Debug::disableDebugOuput - _debugMode = %d - disabled output %d\n", this->_debugMode, type );
+}
+
+/**
+ Public method Debug getDebugLevel
+
+ @param void Void.
+ @return Current debug level.
+ */
+
+int Debug::getDebugLevel() {
+	//printf ( "Debug::getDebugLevel - _debugLevel = %d \n", this->_debugLevel );
+	return this->_debugLevel;
+}
+
+/**
+ Public method Debug setDebugLevel
+
+ @param value Debug level value.
+ @return Void.
+ */
+
+void Debug::setDebugLevel(int value) {
+	this->_debugLevel = value;
+	//printf ( "Debug::setDebugLevel - _debugLevel = %d \n", this->_debugLevel );
+}
+
+/**
+ Public method Debug setDebugMsgFormat
+
+ @param type Debug message format type.
+ @return Void.
+ */
+
+void Debug::setDebugMsgFormat(int type) {
+
+	switch (type) {
+	case DBGMSGFORMAT_XML:
+		_debugmsgformat = type;
+		break;
+	case DBGMSGFORMAT_SIMPLE:
+		_debugmsgformat = type;
+		break;
+	default:
+		// invalid value, I don't do anything
+		break;
+	}
+}
+
+/**
+ Public method Debug logDebugMsg
+ This method builds the core debug message and calls Debug::log.
+
+ @param filename Filename of interest (the file in which debug method has been invoked).
+ @param line Line number from which debug method has been invoked.
+ @param msgSeverity Debug message severity.
+ @param logMsg Log message.
+ @param ... Other parameters used for building the core debug message (variable argument list is used).
+ @return Status.
+ */
+
+int Debug::logDebugMsg(const char *filename, const int line,
+		const int msgSeverity, const char *logMsg, ...) {
+	if (this->_debugMode == DBG_DISABLED) {
+		///	If DebugMode is set to DBG_DISABLED, the method exits.
+		return -1;
+	}
+
+	va_list ap;
+	va_start(ap, logMsg);
+
+	char msg[MAX_DBGMSG_SIZE];
+	memset(msg, 0, MAX_DBGMSG_SIZE - 1);
+	vsnprintf(msg, MAX_DBGMSG_SIZE - 1, logMsg, ap);
+
+	va_end(ap);
+
+	if (msgSeverity >= this->_debugLevel) {
+		log(filename, line, msgSeverity, msg);
+	}
+
+	return 0;
+}
+
+/**
+ Protected method Debug log
+ This method sends a formatted debug message to the outputs enabled. In case, the debug message has to be stored into a file, logStorage is used.
+
+ @param filename Filename of interest (the file in which debug method has been invoked).
+ @param line Line number from which debug method has been invoked.
+ @param msgSeverity Debug message severity.
+ @param logMsg Log message.
+ @return Status.
+ */
+
+int Debug::log(const char *filename, const int line, const int msgSeverity,
+		const char *logMsg) {
+	char tempStr[STR_BUF_SIZE];
+	std::string xmlDbgMsg;
+
+	if (_debugmsgformat == DBGMSGFORMAT_XML) {
+		xmlDbgMsg = std::string("");
+		xmlDbgMsg.append("<DebugMsg ");
+
+		snprintf(tempStr, STR_BUF_SIZE - 1, "Type=\"%d\" ClassName=\"%s\" ",
+				msgSeverity, this->className.c_str());
+		xmlDbgMsg.append(tempStr);
+		snprintf(tempStr, STR_BUF_SIZE - 1,
+				"Filename=\"%s\" LineNumber=\"%d\" >", filename, line);
+		xmlDbgMsg.append(tempStr);
+
+		xmlDbgMsg.append("<Log>");
+		xmlDbgMsg.append(logMsg);
+		xmlDbgMsg.append("</Log>");
+
+		xmlDbgMsg.append("</DebugMsg>");
+	} else if (_debugmsgformat == DBGMSGFORMAT_SIMPLE) {
+		xmlDbgMsg = std::string("");
+
+		snprintf(tempStr, STR_BUF_SIZE - 1, "%s:%d - ", filename, line);
+		xmlDbgMsg.append(tempStr);
+
+		xmlDbgMsg.append(logMsg);
+
+	} else {
+		//FIXME how should I manage such errors ?
+		printf("Weird dbg format! This code should be unreachable");
+		exit(0);
+	}
+
+	if (outputs[DBG_SCREEN] == DBG_OUTPUT_ENABLED) {
+		fflush (stdout);
+		fputs(xmlDbgMsg.c_str(), stdout);
+		fputs("\n", stdout);
+		fflush(stdout);
+	}
+
+	if (outputs[DBG_LOGFILE] == DBG_OUTPUT_ENABLED) {
+		this->logStorage->print(xmlDbgMsg.c_str());
+	}
+
+	///	In case msgSeverity is FATAL, the programme exits.
+	if (msgSeverity == FATAL) {
+		exit(-1);
+	}
+
+	return 0;
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDebug.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDebug.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDebug.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,160 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef DEBUG_H
+#define DEBUG_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <stdarg.h>
+#include <syslog.h>
+#include <string>
+#include <errno.h>
+
+#include "ThreadPool.h"
+#include "TimerThread.h"
+
+#include "CLogStorage.h"
+
+/**
+ * If the LOCAL_LOGGER variable is defined, a set of shorthand logging
+ * macros is defined (L_DEBUG, L_INFO, L_WARN, L_ERROR, L_FATAL).
+ * They will use LOCAL_LOGGER as a reference to an instance of the 
+ * Debug class, and expand to the corresponding logging functions,
+ * unless LOCAL_DEBUG_ENABLED is #undefined. In that case they
+ * will expand to nothing and won't generate any code.
+ */
+#ifdef LOCAL_LOGGER
+#ifdef LOCAL_DEBUG_ENABLED
+#define L_LOG(level, what...) do { (LOCAL_LOGGER) -> level (what); } while (0)
+#else
+#define L_LOG(level, what...)
+#endif
+
+#define L_DEBUG(what...) L_LOG (debug, what) 
+#define L_INFO(what...) L_LOG (info, what) 
+#define L_WARN(what...) L_LOG (warn, what) 
+#define L_ERROR(what...) L_LOG (error, what) 
+#define L_FATAL(what...) L_LOG (fatal, what) 
+#endif
+
+/**
+ There are different levels of message severity: FATAL, ERROR, WARN, INFO, DEBUG
+ */
+enum {
+	DEBUG, INFO, WARN, ERROR, FATAL
+};
+
+/**
+ There are different debug levels: PRODUCTION, TEST and DEBUGGING
+ */
+#define PRODUCTION					3
+#define TEST						1
+#define DEBUGGING					0
+
+/**
+ There are two debug modes: 
+ */
+#define DBG_DISABLED					0
+#define DBG_ENABLED					1
+
+/**
+ Debug Outputs: 
+ */
+#define DBG_OUTPUTS					2
+#define DBG_SCREEN					0
+#define DBG_LOGFILE					1
+
+#define DBG_OUTPUT_DISABLED				0
+#define DBG_OUTPUT_ENABLED				1
+
+#define DBGMSGFORMAT_SIMPLE				0
+#define DBGMSGFORMAT_XML				1
+#define DBGMSGFORMAT_DEFAULT				DBGMSGFORMAT_XML
+
+/**
+ Maximum debug message length
+ */
+#define MAX_DBGMSG_SIZE					500
+#define MAX_DBGXMLMSG_SIZE				1000
+
+/**
+ Set of constants used in Debug class.
+ */
+#define STR_BUF_SIZE					100
+
+/**
+ Macro used in Debug class.
+ */
+#define fatal(logMsg,...) logDebugMsg(__FILE__,__LINE__,FATAL,logMsg,##__VA_ARGS__)
+#define error(logMsg,...) logDebugMsg(__FILE__,__LINE__,ERROR,logMsg,##__VA_ARGS__)
+#define warn(logMsg,...) logDebugMsg(__FILE__,__LINE__,WARN,logMsg,##__VA_ARGS__)
+#define info(logMsg,...) logDebugMsg(__FILE__,__LINE__,INFO,logMsg,##__VA_ARGS__)
+#define debug(logMsg,...) logDebugMsg(__FILE__,__LINE__,DEBUG,logMsg,##__VA_ARGS__)
+#define mytodo(...) logDebugMsg(__FILE__,__LINE__,DEBUG,"undeveloped stub reached",##__VA_ARGS__);exit(0);
+#define myfailure(...) logDebugMsg(__FILE__,__LINE__,DEBUG,"Critical failure",##__VA_ARGS__);exit(0);
+
+class Debug {
+
+public:
+	// Constructors
+	Debug(const char *name);
+
+	// Destructor
+	~Debug();
+
+	// Functions: modifiers (set), selectors (get)
+
+	///	DebugMode modifier and selector
+	int getDebugMode();
+	void setDebugMode(int value);
+
+	///	Debug Output enabler and disabler
+	void enableDebugOuput(int type);
+
+	void disableDebugOuput(int type);
+
+	///	Debug message format modifier
+	void setDebugMsgFormat(int type);
+
+	///	DebugLevel modifier and selector
+	int getDebugLevel();
+	void setDebugLevel(int value);
+
+	///	Debug method
+	int logDebugMsg(const char *filename, const int line, const int msgSeverity,
+			const char *logMsg, ...);
+
+	// itterators:
+	// Attributes visible by scope of instantiation and use
+
+protected:
+	// Attributes visible to descendents
+
+	int log(const char *filename, const int line, const int msgSeverity,
+			const char *logMsg);
+
+	LogStorage *logStorage;
+
+private:
+	// Local attributes
+
+	int _debugMode;
+	int _debugLevel;
+	int _debugmsgformat;
+
+	std::string className;
+
+	int outputs[DBG_OUTPUTS];
+
+};
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDiscoveryAgent.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDiscoveryAgent.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDiscoveryAgent.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,3394 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include "CDiscoveryAgent.h"
+
+template<class T>
+DiscoveryAgent<T> DiscoveryAgent<T>::instance;
+
+/**
+ Constructor
+ DiscoveryAgent constructor. It is a protected method (pattern Singleton)
+
+ @param void Void.
+ @return Void.
+ */
+template<class T>
+DiscoveryAgent<T>::DiscoveryAgent() :
+		functionsContext(GalZbIf::Instance()->getFeatureControl()) {
+	pthread_mutexattr_t attrs;
+
+	pthread_mutexattr_init(&attrs);
+	pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_RECURSIVE);
+	pthread_mutex_init(&mux, &attrs);
+	initTimers();
+
+	pGalZb = GalZbIf::Instance();
+
+	functionsContext.getNodeDescriptor.fTimeout =
+			DA_GET_NODE_DESCRIPTOR_TIMEOUT_IA;
+	functionsContext.getPowerDescriptor.fTimeout =
+			DA_GET_POWER_DESCRIPTOR_TIMEOUT_IA;
+	functionsContext.superDiscovery.fTimeout = DA_SUPER_DISCOVERY_TIMEOUT_IA;
+}
+
+/**
+ Destructor
+ DiscoveryAgent destructor.
+
+ @param void Void.
+ @return Void.
+ */
+template<class T>
+DiscoveryAgent<T>::~DiscoveryAgent() {
+	if (deadingNodeListCounter != 0)
+		free(deadingNodeList);
+	TimerThreadShutdown(&timerThread);
+	ThreadPoolShutdown(&threadPool);
+	if (tasks.keepAliveTask.taskStarted)
+		pthread_cancel(tasks.keepAliveTask.tid);
+	delete (pLogger);
+}
+
+/**
+ Public method DiscoveryAgent *Instance(void)
+ (pattern Singleton)
+
+ @param void Void.
+ @return Instance of DiscoveryAgent class.
+ */
+template<class T>
+DiscoveryAgent<T> *DiscoveryAgent<T>::Instance(void) {
+	return &instance;
+}
+
+/**
+ Public method DiscoveryAgent init
+ DiscoveryAgent initialization: macrofunction context is initialized.
+
+
+ @param void Void.
+ @return Void.
+ */
+template<class T>
+void DiscoveryAgent<T>::init() {
+	ConfigurationRepository *_conf = ConfigurationRepository::instance();
+	// We load the configuration from the ConfigurationManager
+	this->debugEnabled = _conf->getint("main:debugEnabled", false);
+	this->debugLevel = _conf->getint("Debug:DiscoveryAgentDL", TEST);
+
+	// Debug
+	pLogger = new Debug("DiscoveryAgent");
+	pLogger->setDebugMode(this->debugEnabled);
+	pLogger->setDebugLevel(this->debugLevel);
+
+	pLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+	pLogger->enableDebugOuput(DBG_SCREEN);
+
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("init");
+#endif
+
+	this->pGalDb = pGalZb->getDb();
+
+	assert(this->pGalDb != NULL);
+
+	//Initialize the Freshness checker timer parameter and its thread
+	this->KAthreshold = _conf->getint("main:keepAliveThreshold", 60);
+	this->KAnumOfPings = _conf->getint("main:keepAliveNumberOfAttempt", 3);
+	this->forceLQIPingTimer = _conf->getint("main:forcePingTimeout", 240);
+}
+
+template<class T>
+void DiscoveryAgent<T>::initDAListeners() {
+
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("initListeners");
+#endif
+
+	pGalZb->registerListener(ZB_ZDO_DEVICE_ANNCE_INDICATION,
+			(void *) (&Announce_CbW));
+
+	pGalZb->registerListener(ZB_ZDO_IEEE_ADDR_CONFIRM,
+			(void *) (&IeeeAddrConfirm_CbW));
+
+}
+
+template<class T>
+void DiscoveryAgent<T>::runKeepAliveAlgorithm() {
+	pthread_mutex_lock(&mux);
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("runKeepAliveAlgorithm");
+#endif
+	int startResult;
+	if (!tasks.keepAliveTask.taskStarted) {
+		startResult = tasks.keepAliveTask.start(startKATask_SW);
+		if (startResult)
+			pLogger->error("init - Error - task keepAliveTask failure (result = %d)", startResult);
+	}
+	pthread_mutex_unlock(&mux);
+}
+
+/**
+ Public method DiscoveryAgent startInquiry
+ Inquiry macrofunction is invoked.
+
+ @param rpcContextData RPC context.
+ @return Status.
+ */
+template<class T>
+AgentError DiscoveryAgent<T>::startInquiry(unsigned long int timeout,
+		RPCContext<T, inquiryResponseCb, inquiryNotifyCb> *rpcContextData) {
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("startInquiry");
+#endif
+
+	if (pGalZb->getGWStatus() != GW_RUNNING) {
+		pLogger->debug("startInquiry - Error GAL_NOT_RUNNING");
+
+		// RPC response Callback
+		// Check whether rpcContextData != NULL
+		if (rpcContextData != NULL) {
+			// Check whether RPCResponseCb != NULL
+			if (rpcContextData->getRPCResponseCb() != NULL) {
+				RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED,
+						GAL_NOT_RUNNING);
+				CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+						&rpcReqStatus);
+			} else {
+				// Warning!
+				pLogger->warn("startInquiry - (A) - RPCResponseCb == NULL");
+			}
+		}
+
+		// Return Error Code
+		return GAL_NOT_RUNNING;
+	}
+
+	pthread_mutex_lock(&mux);
+	if (functionsContext.inquiry.lock()) {
+
+		// Timer creation management
+		if (timeout > 0x00000000 && timeout != 0xffffffff) {
+			// Convert timeout from milliseconds to seconds (ceil)
+			timeout = timeout / 1000 + ((timeout % 1000) ? 1 : 0);
+
+			///	Set the timer for stopping the startGatewayDevice process
+			functionsContext.inquiry.fTimeout = (int) timeout;
+			pLogger->debug("startInquiry - timeout value = %d (sec)", functionsContext.inquiry.fTimeout);
+
+			if (!functionsContext.inquiry.setTimer(&timerThread, this,
+					&DiscoveryAgent::onInquiry)) {
+				pLogger->fatal("startInquiry - ERROR creating timer!");
+				pthread_mutex_unlock(&mux);
+				return TIMER_ERROR;
+			}
+		} else {
+			/// If timeout value is 0xffffffff (infinite amount of time) or 0x00000000 do not use timer
+			pLogger->debug("startInquiry - timeout value infinite or zero - timer disabled");
+		}
+
+		// Inquiry is not running: start Inquiry 
+
+		this->pGalDb = pGalZb->getDb();
+		assert(pGalDb != NULL);
+
+		///	Reset Inquiry result
+		functionsContext.inquiry.result = FSUCCESS;
+		///	Reset Inquiry numExpectedMsgs
+		functionsContext.inquiry.numExpectedMsgs = 0;
+		///	Register RPC Context Data (containing RPC SessionId and RPC callbacks for response and notification) related to the specific request.
+		functionsContext.inquiry.rpcContext = *rpcContextData;
+
+		///	Register a DiscoveryAgent listener on event ZB_ZDO_IEEE_ADDR_CONFIRM in GalZbIf.
+		///	On ZB_ZDO_IEEE_ADDR_CONFIRM, Inquiry_CbW will be called.			
+		pGalZb->registerListener(ZB_ZDO_IEEE_ADDR_CONFIRM,
+				(void *) (&Inquiry_CbW));
+
+		// RPC response Callback
+		// Check whether rpcContextData != NULL
+		if (rpcContextData != NULL) {
+			// Check whether RPCResponseCb != NULL
+			if (rpcContextData->getRPCResponseCb() != NULL) {
+				RPCReqStatus rpcReqStatus(Running, FSUCCESS, AGENT_SUCCESS);
+				CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+						&rpcReqStatus);
+			} else {
+				// Warning!
+#ifdef DEBUG_ACTIVE_SA
+				pLogger->warn("startInquiry - (B) - RPCResponseCb == NULL");
+#endif
+			}
+		}
+#ifdef DEBUG_ACTIVE_DA
+		pLogger->debug("startInquiry - Started");
+#endif
+		///	If a discovery has been already made the data structures must be cleaned up
+		pGalDb->clearAllButRoot();
+		this->clearDeadingNodeList();
+		///	An IEEE_ADDR_request to the local node is performed.
+		pGalZb->ZDO_IEEE_ADDR_request(pGalDb->root->get_nwk_addr(),
+				ZDO_REQ_TYPE_EX_RES, 0);
+		functionsContext.inquiry.numExpectedMsgs++;
+	} else {
+		pthread_mutex_unlock(&mux);
+		pLogger->debug("startInquiry - An Inquiry is already running");
+		// RPC response Callback
+		// Check whether rpcContextData != NULL
+		if (rpcContextData != NULL) {
+			// Check whether RPCResponseCb != NULL
+			if (rpcContextData->getRPCResponseCb() != NULL) {
+				RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED,
+						AGENT_BUSY);
+				CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+						&rpcReqStatus);
+			} else {
+				// Warning!
+				pLogger->warn("startInquiry - (C) - RPCResponseCb == NULL");
+			}
+		}
+		return AGENT_BUSY;
+	}
+	pthread_mutex_unlock(&mux);
+	return AGENT_SUCCESS;
+}
+
+template<class T>
+AgentError DiscoveryAgent<T>::MgmtLQI_Req(unsigned long int timeout,
+		RPCContext<T, MgmtLQIResponseCb, MgmtLQINotifyCb> *rpcContextData) {
+	Node *node;
+
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("MgmtLQI_Req");
+#endif
+
+	if (pGalZb->getGWStatus() != GW_RUNNING) {
+		pLogger->debug("MgmtLQI_Req - Error GAL_NOT_RUNNING");
+
+		// RPC response Callback - Check whether rpcContextData != NULL
+		if (rpcContextData != NULL) {
+			// Check whether RPCResponseCb != NULL
+			if (rpcContextData->getRPCResponseCb() != NULL) {
+				RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED,
+						GAL_NOT_RUNNING);
+				CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+						&rpcReqStatus);
+			} else {
+				// Warning!
+				pLogger->warn("MgmtLQI_Req - RPCResponseCb == NULL");
+			}
+		}
+		// Return Error Code
+		return GAL_NOT_RUNNING;
+	}
+	if (!functionsContext.MgmtLQI.lock()) {
+		pLogger->debug("MgmtLQI_Req - WARNING: A MGMT_LQI inquiry is already running!");
+		// RPC response Callback - Check whether rpcContextData != NULL
+		if (rpcContextData != NULL) {
+			// Check whether RPCResponseCb != NULL
+			if (rpcContextData->getRPCResponseCb() != NULL) {
+				RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED,
+						AGENT_BUSY);
+				CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+						&rpcReqStatus);
+			} else {
+				// Warning!
+				pLogger->warn("MgmtLQI_Req - RPCResponseCb is equals to NULL");
+			}
+		}
+		return AGENT_BUSY;
+	}
+	// Timer creation management
+	if (timeout > 0x00000000 && timeout != 0xffffffff) {
+		// Convert timeout from milliseconds to seconds (ceil)
+		timeout = timeout / 1000 + ((timeout % 1000) ? 1 : 0);
+		///	Set the timer for stopping the LQI process
+		functionsContext.MgmtLQI.fTimeout = (int) timeout;
+		pLogger->debug("MgmtLQI_Req - timeout value = %d (sec)", functionsContext.MgmtLQI.fTimeout);
+		if (!functionsContext.MgmtLQI.setTimer(&timerThread, this,
+				&DiscoveryAgent::onMgmtLQIRequest)) {
+			pLogger->fatal("MgmtLQI_Req - ERROR creating timer!");
+			return TIMER_ERROR;
+		}
+	} else {
+		/// If timeout value is 0xffffffff (infinite amount of time) or 0x00000000 do not use timer
+		pLogger->debug("MgmtLQI_Req - timeout value infinite or zero - timer disabled");
+	}
+	pthread_mutex_lock(&mux);
+	pGalDb = pGalZb->getDb();
+	assert(pGalDb != NULL);
+	///	Reset Inquiry result
+	functionsContext.MgmtLQI.result = FSUCCESS;
+	///	Reset Inquiry numExpectedMsgs
+	functionsContext.MgmtLQI.numExpectedMsgs = 0;
+	///	Register RPC Context Data (containing RPC SessionId and RPC callbacks for response and notification) related to the specific request.
+	functionsContext.MgmtLQI.rpcContext = *rpcContextData;
+	// If a discovery has been already made the data structures must be cleaned up: disable all the nodes so that they have to be announced again!
+	for (node = pGalDb->getFirstNode(); node != NULL;) {
+		node->setIsActive(false); //Force it to be discovered again!
+		//node->setKANodeTimer(this->KAthreshold - 2);
+		node = pGalDb->getNextNode(node);
+	}
+	// Also, delete any items that could be present in the deadNodeList of the KeepAlive algorithm!
+	clearDeadingNodeList();
+	// Added to enable the discovery notification of root Node as well!
+	this->rootNodeDiscovered = false;
+	functionsContext.MgmtLQI.numExpectedMsgs = 1;
+	pthread_mutex_unlock(&mux);
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("MgmtLQI_Req - Started");
+#endif
+	//	An Mgmt_LQI_Req to the root local node is performed. The ZigBee message is sent over the air, the reply is asynchronous.
+	pGalZb->ZB_MGMT_LQI_request(pGalDb->root->get_nwk_addr(), 0);
+	usleep(PACETIME);
+	// RPC response Callback
+	if (rpcContextData != NULL) {
+		if (rpcContextData->getRPCResponseCb() != NULL) {
+			RPCReqStatus rpcReqStatus(Running, FSUCCESS, AGENT_SUCCESS);
+			CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+					&rpcReqStatus);
+		}
+	}
+	return AGENT_SUCCESS;
+}
+
+/**
+ Public method DiscoveryAgent cancelInquiry
+ DiscoveryAgent cancelInquiry: stops macrofunction Inquiry, unregisters listener for IEEE Address confirm event
+ and detects ghost nodes.
+
+ @param rpcContextData RPC context.
+ @return Status.
+ */
+template<class T>
+AgentError DiscoveryAgent<T>::cancelInquiry(CancelInquiryCtxt *rpcContextData) {
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("cancelInquiry");
+#endif
+
+	pthread_mutex_lock(&mux);
+
+	if (functionsContext.inquiry.unlock(Canceled)) {
+		// Unregister listener
+		pGalZb->unregisterListener(ZB_ZDO_IEEE_ADDR_CONFIRM,
+				(void *) (&Inquiry_CbW));
+		///	A clearGhostNodes is performed to detect ghost nodes (nodes not responding) and remove them from node dictionary and neighbor list.
+		clearGhostNodes();
+		pthread_mutex_unlock(&mux);
+		pLogger->debug("cancelInquiry - Inquiry canceled");
+		// Check whether RPCResponseCb != NULL
+		if (rpcContextData->getRPCResponseCb() != NULL) {
+			RPCReqStatus rpcReqStatus(End, FSUCCESS, AGENT_SUCCESS);
+			CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+					&rpcReqStatus);
+		} else {
+			// Warning!
+			pLogger->warn("cancelInquiry - (A) - RPCResponseCb == NULL");
+		}
+		return AGENT_SUCCESS;
+	} else {
+		pthread_mutex_unlock(&mux);
+		pLogger->debug("cancelInquiry - Inquiry not running");
+		// Check whether RPCResponseCb != NULL
+		if (rpcContextData->getRPCResponseCb() != NULL) {
+			RPCReqStatus rpcReqStatus(End, FFAILED, INQUIRY_NOT_RUNNING);
+			CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+					&rpcReqStatus);
+		} else {
+			pLogger->warn("cancelInquiry - (B) - RPCResponseCb == NULL");
+		}
+		return INQUIRY_NOT_RUNNING;
+	}
+}
+
+template<class T>
+AgentError DiscoveryAgent<T>::cancelMgmtLQI_Req(
+		CancelMgmtLQICtxt *rpcContextData) {
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("cancelMgmtLQI_Req");
+#endif
+
+	pthread_mutex_lock(&mux);
+
+	if (functionsContext.MgmtLQI.unlock(Canceled)) {
+		// Unregister listener
+		//pGalZb->unregisterListener(ZB_MGMT_LQI_RESPONSE,(void *) (&Mgmt_LQI_CbW));
+		///	A clearGhostNodes is performed to detect ghost nodes (nodes not responding) and remove them from node dictionary and neighbor list.
+		clearGhostNodes();
+		pthread_mutex_unlock(&mux);
+		pLogger->debug("cancelMgmtLQI_Req - Inquiry canceled");
+		// Check whether RPCResponseCb != NULL
+		if (rpcContextData->getRPCResponseCb() != NULL) {
+			RPCReqStatus rpcReqStatus(End, FSUCCESS, AGENT_SUCCESS);
+			CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+					&rpcReqStatus);
+		} else {
+			pLogger->warn("cancelMgmtLQI_Req - RPCResponseCb == NULL");
+		}
+		return AGENT_SUCCESS;
+	} else {
+		pthread_mutex_unlock(&mux);
+		pLogger->debug("cancelMgmtLQI_Req - Inquiry not running");
+		// Check whether RPCResponseCb != NULL
+		if (rpcContextData->getRPCResponseCb() != NULL) {
+			RPCReqStatus rpcReqStatus(End, FFAILED, INQUIRY_NOT_RUNNING);
+			CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+					&rpcReqStatus);
+		} else {
+			pLogger->warn("cancelMgmtLQI_Req - RPCResponseCb is NULL");
+		}
+		return INQUIRY_NOT_RUNNING;
+	}
+}
+
+template<class T>
+void DiscoveryAgent<T>::IeeeAddrConfirm_CbW(uchar status, uchar *ieee_addr,
+		ushort nwk_addr, uchar num_assoc_dev, uchar start_index,
+		ushort *nwk_addr_assoc_dev_list) {
+	DiscoveryAgent* dAgent = DiscoveryAgent<T>::Instance();
+	dAgent->IeeeAddrConfirm_Cb(status, ieee_addr, nwk_addr, num_assoc_dev,
+			start_index, nwk_addr_assoc_dev_list);
+}
+
+template<class T>
+void DiscoveryAgent<T>::IeeeAddrConfirm_Cb(uchar status, uchar *ieee_addr,
+		ushort nwk_addr, uchar num_assoc_dev, uchar start_index,
+		ushort *nwk_addr_assoc_dev_list) {
+	Node *mainNode;
+	//DiscoveryAgent* dAgent = DiscoveryAgent<T>::Instance();
+
+	pthread_mutex_lock(&mux);
+#ifdef DEBUG_ACTIVE_DA
+	if (this->debugEnabled == true)
+	pLogger->debug("IeeeAddrConfirm_Cb");
+#endif
+
+	if (status != 0x00) {
+#ifdef DEBUG_ACTIVE_DA
+		if (this->debugEnabled == true)
+		pLogger->debug("IeeeAddrConfirm_Cb - WARNING: IEEEAddrConfirm not success: 0x%02x",status);
+#endif
+		if (status == 0x81 && nwk_addr != pGalDb->root->get_nwk_addr()) {
+			// Node not reachable anymore!
+			mainNode = pGalDb->findNodeByNwkAddr(nwk_addr); // Note: In Freescale the nwk_addr comes already in the correct address (swapped and ready to be used)
+			if (mainNode != NULL) {
+				// Node not reachable anymore in the network but still present in GAL's DB --> remove it!
+				mainNode->setKANodeTimer((long) 0xFFFFFFFC);
+			}
+		} else if (status == 0x81 && nwk_addr == pGalDb->root->get_nwk_addr()) {
+			//Note: GAL returned a ZDO_IEEE_ADDR_confirm with the local node not found...but the IEEEAddress is correct!!!!
+			printf(
+					"IeeeAddrConfirm_Cb - ERROR (firmware issue): Coordinator does not recognized its IEEEAddr!\n");
+		}
+		pthread_mutex_unlock(&mux);
+		return;
+	}
+	mainNode = pGalDb->findNodeByNwkAddr(nwk_addr); // Note: In Freescale the nwk_addr comes already in the correct address (swapped and ready to be used)
+	if (mainNode == NULL) {
+		// New node found!
+		if (this->debugEnabled == true)
+			pLogger->debug("IeeeAddrConfirm_Cb - Received an IEEEAddrConfirm - Creating a new entry for node (0x%04x)",nwk_addr);
+		//Create a new node entry and announce it!
+		Announce_Cb(nwk_addr, ieee_addr, 0x08); //0x08 corresponds to set receiveronwhenidle = true
+		// Find the just new inserted node and set its KeepAlive timer to be ping soon!!
+		mainNode = pGalDb->findNodeByNwkAddr(nwk_addr);
+		mainNode->setKANodeTimer(this->KAthreshold - 1);
+	} else {
+		//Node already present in the table, update its IEEEAddress and announce it (if different from the previous one)
+		if (memcmp(mainNode->get_ieee_addr(), ieee_addr, 8) != 0) {
+			// We worngly stored a wrong IEEE Address, so now we set the correct one and we announce it
+			if (this->debugEnabled == true)
+				pLogger->debug("IeeeAddrConfirm_Cb - Update IEEEAddrress of the existing node %04x",nwk_addr);
+			//Node already present, just update its IEEE and
+			mainNode->set_ieee_addr(ieee_addr);
+			// Add entry in translation table
+			pGalDb->addTranslationEntry(nwk_addr, ieee_addr);
+			// Announce it since it has a new IEEEAddress
+			Announce_Cb(nwk_addr, ieee_addr, 0x08); //0x08 corresponds to set receiveronwhenidle = true
+		} else {
+			// The IEEEAddress stored is correct, so just announce the node if needed!
+			if (mainNode->getIsActive() == false) {
+				Announce_Cb(nwk_addr, ieee_addr, 0x08); //0x08 corresponds to set receiveronwhenidle = true
+			}
+		}
+	}
+	pthread_mutex_unlock(&mux);
+	return;
+}
+
+/**
+ Public method DiscoveryAgent Inquiry_CbW
+ This is a static member function, used as a wrapper to callback to the non-static member Inquiry_Cb.
+ This function is called by GalZbIf::ZDO_IEEE_ADDR_confirm protected method.
+
+ @param status Success or Error status related to the request.
+ @param ieee_addr IEEE address of the device of interest.
+ @param nwk_addr Short address of the device of interest.
+ @param num_assoc_dev Number of associated devices to the remote device of interest.
+ @param start_index Starting index into the list of associated devices.
+ @param nwk_addr_assoc_dev_list The list of short addresses related to the associated devices.
+ @return Void.
+ */
+template<class T>
+void DiscoveryAgent<T>::Inquiry_CbW(uchar status, uchar *ieee_addr,
+		ushort nwk_addr, uchar num_assoc_dev, uchar start_index,
+		ushort *nwk_addr_assoc_dev_list) {
+	DiscoveryAgent* dAgent = DiscoveryAgent<T>::Instance();
+
+#ifdef DEBUG_ACTIVE_DA
+	if (dAgent->debugEnabled == true)
+	printf("DiscoveryAgent::Inquiry_CbW");
+#endif
+
+	dAgent->Inquiry_Cb(status, ieee_addr, nwk_addr, num_assoc_dev, start_index,
+			nwk_addr_assoc_dev_list);
+}
+
+/**
+ Public method DiscoveryAgent Inquiry_Cb
+ Implements Inquiry Callback
+
+ @param status Success or Error status related to the request.
+ @param ieee_addr IEEE address of the device of interest.
+ @param nwk_addr Short address of the device of interest.
+ @param num_assoc_dev Number of associated devices to the remote device of interest.
+ @param start_index Starting index into the list of associated devices.
+ @param nwk_addr_assoc_dev_list The list of short addresses related to the associated devices.
+ @return Void.
+ */
+template<class T>
+void DiscoveryAgent<T>::Inquiry_Cb(uchar status, uchar *ieee_addr,
+		ushort nwk_addr, uchar num_assoc_dev, uchar start_index,
+		ushort *nwk_addr_assoc_dev_list) {
+	Node *mainNode, *neighbor;
+
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("Inquiry_Cb");
+#endif
+
+	assert(pGalDb != NULL);
+
+	// Update number of expected messages
+	functionsContext.inquiry.numExpectedMsgs--;
+
+	if (status != ZB_ZDO_SUCCESS) {
+		pLogger->error("Inquiry_Cb - ERROR returned by ZDO_IEEE_ADDR_confirm");
+
+		functionsContext.inquiry.result = FFAILED;
+
+		if (functionsContext.inquiry.numExpectedMsgs == 0) {
+			pLogger->debug("Inquiry_Cb - Inquiry completed");
+
+			// The Inquiry is completed so we can delete the timer
+			if (!functionsContext.inquiry.killTimer()) {
+#ifdef DEBUG_ACTIVE_DA
+				pLogger->debug("Inquiry_Cb - Timer removed (b)");
+#endif
+			} else {
+#ifdef DEBUG_ACTIVE_DA
+				pLogger->debug("Inquiry_Cb - Timer was already removed (b)");
+#endif
+			}
+
+			// Unregister listener
+			pGalZb->unregisterListener(ZB_ZDO_IEEE_ADDR_CONFIRM,
+					(void *) (&Inquiry_CbW));
+
+			///	On completion of Inquiry, a clearGhostNodes is performed to detect ghost nodes (nodes not responding) and remove them from node dictionary and neighbor list.
+			clearGhostNodes();
+
+			// Inquiry Completed
+			functionsContext.inquiry.unlock();
+		}
+
+		// RPC notify Callback
+		if (functionsContext.inquiry.rpcContext.getRPCNotifyCb() != NULL) {
+			RPCReqStatus rpcReqStatus(functionsContext.inquiry, INQUIRY_ERROR);
+
+			FCALL_NOTIFY (functionsContext.inquiry)(NULL, &rpcReqStatus);
+		}
+
+		return;
+	}
+
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("Inquiry_Cb - ieee_addr = %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", (int)(ieee_addr[0]), (int)(ieee_addr[1]), (int)(ieee_addr[2]),
+			(int)(ieee_addr[3]), (int)(ieee_addr[4]), (int)(ieee_addr[5]), (int)(ieee_addr[6]), (int)(ieee_addr[7]) );
+#endif
+
+	pthread_mutex_lock(&mux);
+
+	// Lookup the node itself to add sons
+	mainNode = pGalDb->findNodeByNwkAddr(nwk_addr); // To be considered before if statement related to num_assoc_dev
+
+	///	Moreover, the reception of a IEEE address confirm related to a nonexistent node is considered. The received confirm could be related to a previous inquiry and has not to be considered in the current inquiry.
+	if (mainNode == NULL) // No entries found for node identified by network address "nwk_addr"
+			{
+		// Update number of expected messages
+		functionsContext.inquiry.numExpectedMsgs++;
+		pthread_mutex_unlock(&mux);
+		pLogger->error("Inquiry_Cb - Error: Nonexistent node %04x has been received",nwk_addr);
+		// RPC notify Callback
+		if (functionsContext.inquiry.rpcContext.getRPCNotifyCb() != NULL) {
+			RPCReqStatus rpcReqStatus(functionsContext.inquiry,
+					INQUIRY_NONEXISTENTENT_NODE);
+			FCALL_NOTIFY (functionsContext.inquiry)(NULL, &rpcReqStatus);
+		}
+		return;
+	} else {
+		mainNode->set_ieee_addr(ieee_addr);
+	}
+	if (!num_assoc_dev) {
+		// No associated devices
+#ifdef DEBUG_ACTIVE_DA
+		pLogger->debug("Inquiry_Cb - Node 0x%04X doesn't have any neighbor", nwk_addr);
+#endif
+	} else {
+#ifdef DEBUG_ACTIVE_DA
+		pLogger->debug("Inquiry_Cb - Node 0x%04X has neighbor", nwk_addr);
+#endif
+	}
+
+	ushort neighbor_nwk_addr;
+
+	///	The number of expected messages is increased by the number of neighbor (an IEEE Address request is sent
+	///	to every neighbor node; responses are expected).
+	functionsContext.inquiry.numExpectedMsgs =
+			functionsContext.inquiry.numExpectedMsgs + num_assoc_dev;
+
+	for (int i = 0; i < num_assoc_dev; i++) {
+
+		neighbor_nwk_addr = nwk_addr_assoc_dev_list[i];
+#ifdef DEBUG_ACTIVE_DA
+		pLogger->debug("Inquiry_Cb - mainNode = 0x%04X - neighbor = 0x%04X", nwk_addr, neighbor_nwk_addr);
+#endif
+
+		// Son added to the pointer array
+		neighbor = pGalDb->findNodeByNwkAddr(neighbor_nwk_addr);
+
+		// Error: Node already discovered -> continue
+		if (neighbor != NULL) {
+			pLogger->error("Inquiry_Cb - ATTENTION: node already discovered!");
+
+			functionsContext.inquiry.result = FFAILED;
+			functionsContext.inquiry.numExpectedMsgs =
+					functionsContext.inquiry.numExpectedMsgs - 1;
+			continue;
+		}
+		neighbor = new Node(neighbor_nwk_addr);
+		// By default we consider all nodes on (that is no sleepyEndDevice!), but we shall be more clear with a Node Descriptor request
+		neighbor->node_desc.receiveronwhenidle = true;
+		// Neighbor added to the mainNode
+		pGalDb->addNeighbor(mainNode, neighbor);
+		// Add entry in translation table
+		pGalDb->addTranslationEntry(nwk_addr, ieee_addr);
+		// ZDO_IEEE_ADDR_request on the neighbor. The ZigBee message is sent over the air, the reply is asynchronous
+		pGalZb->ZDO_IEEE_ADDR_request(neighbor_nwk_addr, ZDO_REQ_TYPE_EX_RES,
+				0);
+		usleep(PACETIME);
+	}
+
+	if (functionsContext.inquiry.numExpectedMsgs == 0) {
+
+#ifdef DEBUG_ACTIVE_DA
+		pLogger->debug("DiscoveryAgent<T>::Inquiry_Cb - Inquiry completed");
+#endif
+
+		// The Inquiry is completed so we can delete the timer
+		if (!functionsContext.inquiry.killTimer()) {
+#ifdef DEBUG_ACTIVE_DA
+			pLogger->debug("Inquiry_Cb - Timer removed (b)");
+#endif
+		} else {
+#ifdef DEBUG_ACTIVE_DA
+			pLogger->debug("Inquiry_Cb - Timer was already removed (b)");
+#endif
+		}
+
+		// Unregister listener
+		pGalZb->unregisterListener(ZB_ZDO_IEEE_ADDR_CONFIRM,
+				(void *) (&Inquiry_CbW));
+
+		// Detect ghost nodes (nodes not responding) and remove them from node dictionary and neighbor list.
+		clearGhostNodes();
+
+		// Inquiry Completed
+		functionsContext.inquiry.unlock();
+	}
+	pthread_mutex_unlock(&mux);
+	// RPC notify Callback
+	if (functionsContext.inquiry.rpcContext.getRPCNotifyCb() != NULL) {
+		RPCReqStatus rpcReqStatus(functionsContext.inquiry, AGENT_SUCCESS);
+		FCALL_NOTIFY (functionsContext.inquiry)(mainNode, &rpcReqStatus);
+	}
+}
+
+template<class T>
+void DiscoveryAgent<T>::Mgmt_LQI_CbW(uchar scrAddrMode, uchar *src_addr,
+		uchar status, uchar NeighborTableEntries, uchar StartIndex,
+		uchar NeighborTableListCount, ZB_NEIGHBOR_TABLE_LIST *NeighborTableList //ZB_NEIGHBOR_TABLE_LIST defined in Table 2.127
+		) {
+	DiscoveryAgent* dAgent = DiscoveryAgent<T>::Instance();
+	dAgent->Mgmt_LQI_Cb(scrAddrMode, src_addr, status, NeighborTableEntries,
+			StartIndex, NeighborTableListCount, NeighborTableList);
+}
+
+template<class T>
+void DiscoveryAgent<T>::Mgmt_LQI_Cb(uchar scrAddrMode, uchar * src_addr,
+		uchar status, uchar NeighborTableEntries, uchar StartIndex,
+		uchar NeighborTableListCount, ZB_NEIGHBOR_TABLE_LIST *NeighborTableList //ZB_NEIGHBOR_TABLE_LIST defined in Table 2.127
+		) {
+	Node * mainNode, *neighbor;
+	ushort mainNodeNwkAddr;
+	int i = 0;
+	uchar devType = 0x00;
+	struct timeval tv;
+	uchar allZeros[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+	uchar allFF[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+	uchar tempIEEEAddr[8];
+
+	assert(pGalDb != NULL);
+//#ifdef DEBUG_ACTIVE_DA
+	if (this->debugEnabled == true) {
+		if (scrAddrMode == ZB_AM_DIRECT_EX) {
+			pLogger->debug("Mgmt_LQI_Cb - Received message from %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+					src_addr[0],src_addr[1],src_addr[2],src_addr[3],src_addr[4],src_addr[5],src_addr[6],src_addr[7]);
+		} else {
+			pLogger->debug("Mgmt_LQI_Cb - Received message from 0x%04x", (src_addr[1] << 8)+src_addr[0] );
+		}
+	}
+//#endif
+	pthread_mutex_lock(&mux);
+	//Note: The addresses comes from Freescale without any conversion little/big endian, so it shall be made here!
+	mainNodeNwkAddr = (src_addr[1] << 8) + src_addr[0];
+	if (scrAddrMode == ZB_AM_DIRECT_EX) {
+		tempIEEEAddr[7] = src_addr[0];
+		tempIEEEAddr[6] = src_addr[1];
+		tempIEEEAddr[5] = src_addr[2];
+		tempIEEEAddr[4] = src_addr[3];
+		tempIEEEAddr[3] = src_addr[4];
+		tempIEEEAddr[2] = src_addr[5];
+		tempIEEEAddr[1] = src_addr[6];
+		tempIEEEAddr[0] = src_addr[7];
+		mainNode = pGalDb->findNodeByIEEEAddr(tempIEEEAddr);
+	} else {
+		mainNode = pGalDb->findNodeByNwkAddr(mainNodeNwkAddr);
+	}
+	if (mainNode == NULL) {
+		// Case we receive a node that wasn't present in any neighbor's table - WE SHALL NEVER ENTER HERE (unless there is a MGMT_LQI_Req made in CServiceAgent...)
+		// Probably the coordinator could get in here since it doesn't get yet the correct IEEEAddr
+		if (scrAddrMode == ZB_AM_DIRECT_EX) {
+			// No much we can do since we don't have an associated shortAddress!
+			if (this->debugEnabled == true)
+				printf(
+						"Mgmt_LQI_Cb - WARNING: node %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x not in DB. Nothing that we can do!",
+						tempIEEEAddr[0], tempIEEEAddr[1], tempIEEEAddr[2],
+						tempIEEEAddr[3], tempIEEEAddr[4], tempIEEEAddr[5],
+						tempIEEEAddr[6], tempIEEEAddr[7]);
+		} else {
+			// We can request an IEEE_Addr_Req!
+			if (debugEnabled == true)
+				pLogger->debug("Mgmt_LQI_Cb - WARNING: Found a node not in DB (0x%04x) - Send a ZDO_IEEE_ADDR_request!",mainNodeNwkAddr);
+			//	Register a DiscoveryAgent listener on event ZB_IEEE_ADDR_CONFIRM_X_DISCOVERY in GalZbIf
+			//pGalZb->registerListener(ZB_ZDO_IEEE_ADDR_CONFIRM,(void *) (&IeeeAddrConfirm_CbW));
+			pGalZb->ZDO_IEEE_ADDR_request(mainNodeNwkAddr, ZDO_REQ_TYPE_EX_RES,
+					0);
+		}
+		pthread_mutex_unlock(&mux);
+		return;
+	}
+	if ((memcmp(mainNode->get_ieee_addr(), allZeros, 8) == 0)
+			|| (memcmp(mainNode->get_ieee_addr(), allFF, 8) == 0)) {
+		// Case of a node present but without knowing yet its IEEEAddress, so we need to request it!
+#ifdef DEBUG_ACTIVE_DA
+		pLogger->debug("Mgmt_LQI_Cb - WARNING: Node 0x%04x without IEEEAddr - Send a ZDO_IEEE_ADDR_request!",mainNode->get_nwk_addr());
+#endif
+		///	Register a DiscoveryAgent listener on event ZB_IEEE_ADDR_CONFIRM_X_DISCOVERY in GalZbIf
+		//pGalZb->registerListener(ZB_ZDO_IEEE_ADDR_CONFIRM,(void *) (&IeeeAddrConfirm_CbW));
+		pGalZb->ZDO_IEEE_ADDR_request(mainNode->get_nwk_addr(),
+				ZDO_REQ_TYPE_EX_RES, 0);
+		usleep(PACETIME);
+		// Let's continue since the message is valid!
+	}
+	//Only for the local node, update its timestamp since any incoming messages doesn't comes from the call APSDE_DATA_indication
+	if (mainNode->get_nwk_addr() == pGalDb->root->get_nwk_addr())
+		pGalZb->manageNodeTimeouts(0x03, mainNode->get_ieee_addr());
+	// Announce the node if is hasn't been anounced yet!
+	if ((mainNode->getIsActive() == false)
+			&& ((memcmp(mainNode->get_ieee_addr(), allZeros, 8) != 0)
+					&& (memcmp(mainNode->get_ieee_addr(), allFF, 8) != 0))) {
+		if (debugEnabled == true) {
+			memcpy(tempIEEEAddr, mainNode->get_ieee_addr(), 8);
+			pLogger->debug("Mgmt_LQI_Cb - Announce node 0x%04x - %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",mainNode->get_nwk_addr(),
+					tempIEEEAddr[0],tempIEEEAddr[1],tempIEEEAddr[2],tempIEEEAddr[3],tempIEEEAddr[4],tempIEEEAddr[5],tempIEEEAddr[6],tempIEEEAddr[7]);
+		}
+		// The node from now on is active!
+		Announce_Cb(mainNode->get_nwk_addr(), mainNode->get_ieee_addr(), 0x08); //0x08 corresponds to set receiveronwhenidle = true
+	}
+	// Verify if there has been an error in the incoming message
+	if (status != ZB_ZDO_SUCCESS) {
+#ifdef DEBUG_ACTIVE_DA
+		pLogger->debug("Mgmt_LQI_Cb - Node 0x%04x returned MGMT_LQI_Rsp with an error: 0x%02x",mainNode->get_nwk_addr(),status);
+#endif
+		functionsContext.MgmtLQI.result = FFAILED;
+		// Delete the timer, the discovery is concluded due to an error
+		functionsContext.MgmtLQI.killTimer();
+		// Unregister listener
+		//pGalZb->unregisterListener(ZB_MGMT_LQI_RESPONSE,(void *) (&Mgmt_LQI_CbW));
+		// Detect ghost nodes (nodes not responding) and remove them from node dictionary and neighbor list.
+		clearGhostNodes();
+		// Inquiry Completed
+		functionsContext.MgmtLQI.unlock();
+		pthread_mutex_unlock(&mux);
+		// Notify that the LQI is ended due to an error
+		if (functionsContext.MgmtLQI.rpcContext.getRPCNotifyCb() != NULL) {
+			RPCReqStatus rpcReqStatus(functionsContext.MgmtLQI, INQUIRY_ERROR);
+			FCALL_NOTIFY (functionsContext.MgmtLQI)(NULL, &rpcReqStatus);
+		}
+		return;
+	}
+	// No error found in the incoming MGMT_LQI_Response so far...
+	//functionsContext.MgmtLQI.numExpectedMsgs--;	// update number of expected messages
+	// Verify if we received all the neighbor's entries for this selected node!
+	if (StartIndex + NeighborTableListCount < NeighborTableEntries) {
+		// There are more entries to request to the same node! Do it
+		//patch that correct a 4noks bug - 07-12-2011
+		if (NeighborTableListCount == 0x00) {
+			printf(
+					"Mgmt_LQI_Cb - ERROR (4Noks issue): StartIndex (%d) + NeighborTableListCount (%d) < NeighborTableEntries (%d)!\n",
+					StartIndex, NeighborTableListCount, NeighborTableEntries);
+		} else {
+			//end patch
+			pGalZb->ZB_MGMT_LQI_request(mainNode->get_nwk_addr(),
+					StartIndex + NeighborTableListCount);
+			usleep(PACETIME);
+			//Increase the counter related to the number of expected message
+			functionsContext.MgmtLQI.numExpectedMsgs++;
+		}
+	}
+#ifdef DEBUG_ACTIVE_DA
+	if (NeighborTableListCount != 0) {
+		pLogger->debug("Mgmt_LQI_Cb - Node 0x%04x contains 0x%02x neighbors",mainNode->get_nwk_addr(),NeighborTableListCount);
+	}
+#endif
+	// And now for each neighbor present in the current MGMT_LQI_Req insert a new entry (avoiding node already discovered & the sleepy device)
+	for (i = 0; i < NeighborTableListCount; i++) {
+		neighbor = pGalDb->findNodeByNwkAddr(
+				NeighborTableList[i].NetworkAddress);
+		if (neighbor == NULL) {
+			// Insert a new entry for this node
+			neighbor = new Node(NeighborTableList[i].NetworkAddress);
+			// neighbor added as mainNode's neighbor
+			pGalDb->addNeighbor(mainNode, neighbor);
+			// Set IEEE address of the neighbor node
+			neighbor->set_ieee_addr(NeighborTableList[i].ExtendedAddress); //Note: No need to swap, GalZbIf have done it!
+			// Set the Capability information
+			if ((NeighborTableList[i].devTypeRxOnRelation & 0x04) == 0x04) {
+				neighbor->node_desc.receiveronwhenidle = true;
+			} else {
+				neighbor->node_desc.receiveronwhenidle = false;
+			}
+			// Add entry in translation table
+			pGalDb->addTranslationEntry(NeighborTableList[i].NetworkAddress,
+					NeighborTableList[i].ExtendedAddress);
+#ifdef DEBUG_ACTIVE_DA
+			memcpy(tempIEEEAddr,neighbor->get_ieee_addr(),8);
+			pLogger->debug("Mgmt_LQI_Cb - Created a new entry for neighbor 0x%04x - %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",NeighborTableList[i].NetworkAddress,
+					tempIEEEAddr[0],tempIEEEAddr[1],tempIEEEAddr[2],tempIEEEAddr[3],
+					tempIEEEAddr[4],tempIEEEAddr[5],tempIEEEAddr[6],tempIEEEAddr[7]);
+#endif
+			if (devType != 0x00 && devType != 0x01
+					&& ((NeighborTableList[i].devTypeRxOnRelation & 0x04)
+							!= 0x04)) {
+				// Announce the node if it is a sleepy end device (otherwise it will be announced when GAL receives a response)
+				gettimeofday(&tv, NULL);
+				mainNode->setKANodeTimer((long) tv.tv_sec); //We imagine to have received a message from this node now!
+				Announce_Cb(neighbor->get_nwk_addr(), neighbor->get_ieee_addr(),
+						0x08); //0x08 corresponds to set receiveronwhenidle = true
+			} else
+				neighbor->setIsActive(false);
+		} else {
+			// This node is already in the DB, check if the IEEE address is correct!
+			if (memcmp(NeighborTableList[i].ExtendedAddress,
+					neighbor->get_ieee_addr(), 8) != 0) {
+				if (debugEnabled == true) {
+					memcpy(tempIEEEAddr, neighbor->get_ieee_addr(), 8);
+					pLogger->debug("Mgmt_LQI_Cb - ERROR: Found a node (0x%04x) with a wrong IEEEAddress (%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x instead of the stored %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x)! Send ZDO_IEEE_ADDR_request!\n",
+							NeighborTableList[i].ExtendedAddress[0],NeighborTableList[i].ExtendedAddress[1],NeighborTableList[i].ExtendedAddress[2],NeighborTableList[i].ExtendedAddress[3],
+							NeighborTableList[i].ExtendedAddress[4],NeighborTableList[i].ExtendedAddress[5],NeighborTableList[i].ExtendedAddress[6],NeighborTableList[i].ExtendedAddress[7],
+							tempIEEEAddr[0],tempIEEEAddr[1],tempIEEEAddr[2],tempIEEEAddr[3],
+							tempIEEEAddr[4],tempIEEEAddr[5],tempIEEEAddr[6],tempIEEEAddr[7],
+							NeighborTableList[i].NetworkAddress);
+				}
+				// Send an IEEEAddressRequest to find out the correct value!
+				//pGalZb->registerListener(ZB_ZDO_IEEE_ADDR_CONFIRM,(void *) (&IeeeAddrConfirm_CbW));
+				pGalZb->ZDO_IEEE_ADDR_request(
+						NeighborTableList[i].NetworkAddress,
+						ZDO_REQ_TYPE_EX_RES, 0);
+				usleep(PACETIME);
+			}
+		}
+	}
+	// Update the LQI related information
+	pGalDb->updateLQIDetails(mainNode, NeighborTableList,
+			NeighborTableListCount);
+	pthread_mutex_unlock(&mux);
+	// Finally verify if the algorithm is concluded
+	if (functionsContext.MgmtLQI.isLocked()
+			&& (functionsContext.MgmtLQI.numExpectedMsgs <= 0)) {
+#ifdef DEBUG_ACTIVE_DA
+		if (debugEnabled == true)
+		pLogger->debug("Mgmt_LQI_Cb - No more MGMT_LQI pending");
+#endif
+		// The Inquiry is completed so we can delete the timer
+		functionsContext.MgmtLQI.killTimer();
+		// Unregister listener
+		//pGalZb->unregisterListener(ZB_MGMT_LQI_RESPONSE,(void *) (&Mgmt_LQI_CbW));
+		// Detect ghost nodes (nodes not responding) and remove them from node dictionary and neighbor list.
+		clearGhostNodes();
+		// Inquiry Completed
+		functionsContext.MgmtLQI.unlock();
+		// Notify that the LQI is ended
+		if (functionsContext.MgmtLQI.rpcContext.getRPCNotifyCb() != NULL) {
+			RPCReqStatus rpcReqStatus(functionsContext.MgmtLQI, AGENT_SUCCESS);
+			FCALL_NOTIFY (functionsContext.MgmtLQI)(NULL, &rpcReqStatus);
+		}
+	}
+}
+
+/**
+ Public method DiscoveryAgent startAnnouncementsMode
+ DiscoveryAgent
+
+
+ @param listener Description of second function argument.
+ @return Void.
+ */
+template<class T>
+int DiscoveryAgent<T>::startAnnouncementsMode(
+		StartAnnouncementsModeCtxt *rpcContextData) {
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("startAnnouncementsMode");
+#endif
+
+	pthread_mutex_lock(&mux);
+	if (!functionsContext.announce.lock()) {
+		//if (debugEnabled == true)
+		//printf("startAnnouncementsMode - AnnouncementsMode is already running (overwrite the RPC context)\n");
+#ifdef DEBUG_ACTIVE_DA
+		pLogger->debug("startAnnouncementsMode - AnnouncementsMode is already running (overwrite the RPC context)");
+#endif
+		//	functionsContext.announce.unlock(Canceled);	//!!
+	}
+
+	//	Register RPC Context Data (containing RPC SessionId and RPC callbacks for response and notification) related to the specific request.
+	functionsContext.announce.rpcContext = *rpcContextData;
+
+	if (debugEnabled == true) {
+		if (functionsContext.announce.rpcContext.getRPCNotifyCb() == NULL)
+			printf(
+					"startAnnouncementsMode - WARNING: announcement with getRPCNotifyCb NULL!\n");
+		else
+			printf(
+					"startAnnouncementsMode - From now on the announcement is ON!\n");
+	}
+	// RPC response Callback
+	RPCReqStatus rpcReqStatus(Running, FSUCCESS, AGENT_SUCCESS);
+	CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+			&rpcReqStatus);
+	pthread_mutex_unlock(&mux);
+	return AGENT_SUCCESS;
+}
+
+/**
+ Public method DiscoveryAgent cancelAnnouncementsMode
+ DiscoveryAgent
+
+
+ @param listener Description of second function argument.
+ @return Void.
+ */
+template<class T>
+int DiscoveryAgent<T>::cancelAnnouncementsMode(
+		CancelAnnouncementsModeCtxt *rpcContextData) {
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("cancelAnnouncementsMode");
+#endif
+
+	if (rpcContextData == NULL) {
+#ifdef DEBUG_ACTIVE_DA
+		pLogger->debug("rpcContextData is null");
+#endif
+		return ANNCE_MODE_NOT_RUNNING;
+	}
+	pthread_mutex_lock(&mux);
+	if (functionsContext.announce.unlock(Canceled)) {
+#ifdef DEBUG_ACTIVE_DA
+		pLogger->debug("cancelAnnouncementsMode - AnnouncementsMode canceled");
+#endif
+		if (functionsContext.announce.rpcContext.getRPCResponseCb() == NULL) {
+#ifdef DEBUG_ACTIVE_DA
+			pLogger->debug("getRPCResponseCb return null");
+#endif
+			return ANNCE_MODE_NOT_RUNNING;
+		}
+		// RPC response Callback
+		RPCReqStatus rpcReqStatus(End, FSUCCESS, AGENT_SUCCESS);
+		CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+				&rpcReqStatus);
+		pthread_mutex_unlock(&mux);
+		return AGENT_SUCCESS;
+	} else {
+#ifdef DEBUG_ACTIVE_DA
+		pLogger->debug("cancelAnnouncementsMode - AnnouncementsMode not running");
+#endif
+		if (functionsContext.announce.rpcContext.getRPCResponseCb() == NULL) {
+#ifdef DEBUG_ACTIVE_DA
+			pLogger->debug("getRPCResponseCb return null");
+#endif
+			pthread_mutex_unlock(&mux);
+			return ANNCE_MODE_NOT_RUNNING;
+		}
+		// RPC response Callback
+		RPCReqStatus rpcReqStatus(End, FFAILED, ANNCE_MODE_NOT_RUNNING);
+		CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+				&rpcReqStatus);
+		pthread_mutex_unlock(&mux);
+		return ANNCE_MODE_NOT_RUNNING;
+	}
+	// We shall never arrive here (for the moment)
+}
+
+/**
+ Public method DiscoveryAgent Announce_CbW
+ This is a static member function, used as a wrapper to callback to the non-static member Inquiry_Cb.
+ This function is called by GalZbIf::ZDO_DEVICE_ANNCE_indication protected method.
+
+ @param status Success or Error status related to the request.
+ @param ieee_addr IEEE address of the device of interest.
+ @param nwk_addr Short address of the device of interest.
+ @param num_assoc_dev Number of associated devices to the remote device of interest.
+ @param start_index Starting index into the list of associated devices.
+ @param nwk_addr_assoc_dev_list The list of short addresses related to the associated devices.
+ @return Void.
+ */
+template<class T>
+void DiscoveryAgent<T>::Announce_CbW(ushort nwk_addr, uchar *ieee_addr,
+		uchar capability) {
+	DiscoveryAgent* dAgent = DiscoveryAgent<T>::Instance();
+	dAgent->Announce_Cb(nwk_addr, ieee_addr, capability);
+}
+
+/**
+ Public method DiscoveryAgent Announce_Cb
+ Implements Inquiry Callback
+
+ @param status Success or Error status related to the request.
+ @param ieee_addr IEEE address of the device of interest.
+ @param nwk_addr Short address of the device of interest.
+ @param num_assoc_dev Number of associated devices to the remote device of interest.
+ @return Void.
+ */
+template<class T>
+void DiscoveryAgent<T>::Announce_Cb(ushort nwk_addr, uchar *ieee_addr,
+		uchar capability) {
+	unsigned long long ieeeDec = 0;
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("Announce_Cb");
+#endif
+
+	pthread_mutex_lock(&mux);
+	Node *node = pGalDb->nodeAnnounce(nwk_addr, ieee_addr, capability);
+	if (functionsContext.announce.rpcContext.getRPCNotifyCb() == NULL) {
+		//if (debugEnabled == true)
+		printf("Announce_Cb - No callback registered to announce 0x%04x!\n",
+				nwk_addr);
+		// The returned node cannot be announce yet!
+		node->setIsActive(false);
+		pthread_mutex_unlock(&mux);
+		return;
+	}
+	node->setIsActive(true);
+	for (int i = 0; i <= 7; i++)
+		ieeeDec += (ieeeDec * 255) + ieee_addr[i];
+	printf(
+			"Announce_Cb - Discovered new node: 0x%04x - 0x%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x (%lld)!\n",
+			nwk_addr, ieee_addr[0], ieee_addr[1], ieee_addr[2], ieee_addr[3],
+			ieee_addr[4], ieee_addr[5], ieee_addr[6], ieee_addr[7], ieeeDec);
+	RPCReqStatus rpcReqStatus(functionsContext.announce, AGENT_SUCCESS);
+	FCALL_NOTIFY (functionsContext.announce)(node, &rpcReqStatus);
+	pthread_mutex_unlock(&mux);
+}
+
+template<class T>
+int DiscoveryAgent<T>::startFreshnessMode(
+		StartFreshnessModeCtxt *rpcContextData) {
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("startFreshnessMode");
+#endif
+	pthread_mutex_lock(&mux);
+	if (!functionsContext.freshness.lock()) {
+#ifdef DEBUG_ACTIVE_DA
+		pLogger->debug("startFreshnessMode - FreshnessMode is already running - overwrite the RPC context");
+#endif
+	}
+	if (debugEnabled == true)
+		printf("startFreshnessMode - From now on the freshness is ON!\n");
+	///	Register RPC Context Data (containing RPC SessionId and RPC callbacks for response and notification) related to the specific request.
+	functionsContext.freshness.rpcContext = *rpcContextData;
+	// RPC response Callback
+	RPCReqStatus rpcReqStatus(Running, FSUCCESS, AGENT_SUCCESS);
+	CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+			&rpcReqStatus);
+	pthread_mutex_unlock(&mux);
+	return AGENT_SUCCESS;
+}
+
+template<class T>
+int DiscoveryAgent<T>::cancelFreshnessMode(
+		CancelFreshnessModeCtxt *rpcContextData) {
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("cancelFreshnessMode");
+#endif
+
+	pthread_mutex_lock(&mux);
+	if (functionsContext.freshness.unlock(Canceled)) {
+#ifdef DEBUG_ACTIVE_DA
+		pLogger->debug("cancelFreshnessMode - FreshnessMode canceled");
+#endif
+		pthread_mutex_unlock(&mux);
+		// RPC response Callback
+		if (functionsContext.freshness.rpcContext.getRPCResponseCb() != NULL) {
+			RPCReqStatus rpcReqStatus(End, FSUCCESS, AGENT_SUCCESS);
+			CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+					&rpcReqStatus);
+		}
+		return AGENT_SUCCESS;
+	} else {
+#ifdef DEBUG_ACTIVE_DA
+		pLogger->debug("cancelFreshnessMode - FreshnessMode not running");
+#endif
+		pthread_mutex_unlock(&mux);
+		if (functionsContext.freshness.rpcContext.getRPCResponseCb() != NULL) {
+			// RPC response Callback
+			RPCReqStatus rpcReqStatus(End, FFAILED, ANNCE_MODE_NOT_RUNNING);
+			CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+					&rpcReqStatus);
+		}
+		return ANNCE_MODE_NOT_RUNNING;
+	}
+}
+
+template<class T>
+int DiscoveryAgent<T>::retrieveNodes(
+		RPCContext<T, retrieveNodesResponseCb> *rpcContextData) {
+	int ans;
+
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("retrieveNodes");
+#endif
+
+	pthread_mutex_lock(&mux);
+
+	if (pGalDb->getNodesCount() == 0) {
+		// Inquiry cache empty
+		pLogger->debug("retrieveNodes - Inquiry cache empty.");
+		RPCReqStatus rpcReqStatus(End, FFAILED, INQUIRY_CACHE_EMPTY);
+		CALL_RESPONSE (rpcContextData)(pGalDb, rpcContextData->getSessionId(),
+				&rpcReqStatus);
+		ans = INQUIRY_CACHE_EMPTY;
+	} else {
+		RPCReqStatus rpcReqStatus(End, FSUCCESS, AGENT_SUCCESS);
+		CALL_RESPONSE (rpcContextData)(pGalDb, rpcContextData->getSessionId(),
+				&rpcReqStatus);
+		ans = AGENT_SUCCESS;
+	}
+	functionsContext.inquiry.unlock();
+	pthread_mutex_unlock(&mux);
+	return ans;
+}
+
+/**
+ Protected method DiscoveryAgent clearGhostNodes
+ This method removes the nodes who have not answered an IEEE Address Request from node dictionary and from the neighbor list
+ of the related parent.
+
+ @param void Void.
+ @return Void.
+ */
+template<class T>
+void DiscoveryAgent<T>::clearGhostNodes() {
+	Node* node;
+	Node* tmpNode;
+	ushort nwk_addr;
+	int index, ghostMask;
+	uchar * ieeeAddr;
+
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("clearGhostNodes");
+#endif
+
+	for (node = pGalDb->getFirstNode(); node != NULL;) {
+#ifdef DEBUG_ACTIVE_DA
+		node->dump();
+#endif
+		ghostMask = 0;
+		nwk_addr = node->get_nwk_addr();
+		for (index = 0; index < IEEE_ADDR_LEN; index++) {
+			if ((node->get_ieee_addr())[index] == 0)
+				ghostMask++;
+		}
+
+		tmpNode = node;
+		node = pGalDb->getNextNode(node);
+
+		///	If the IEEE address is 00 00 00 00 00 00 00 00, the related node has not answered an IEEE Address Request -> A ghost node has been detected.
+		if (ghostMask == IEEE_ADDR_LEN) {
+
+			ieeeAddr = pGalDb->translateAddress(nwk_addr);
+			if (ieeeAddr == NULL) {
+
+				///	The ghost node is therefore removed from node dictionary and deleted.
+				pGalDb->removeNodeByNwkAddr(nwk_addr);
+				pLogger->debug("clearGhostNodes() - Ghost node %04X has been detected.", nwk_addr);
+			} else {
+				tmpNode->set_ieee_addr(ieeeAddr);
+			}
+		}
+	}
+}
+
+/**
+ Public method DiscoveryAgent getNodeDescriptor
+ getNodeDescriptor macrofunction is invoked.
+
+ @param nwk_addr Short address of the device of interest.
+ @param rpcContextData RPC context.
+ @return Status.
+ */
+template<class T>
+int DiscoveryAgent<T>::getNodeDescriptor(unsigned long int timeout,
+		ushort nwk_addr,
+		RPCContext<T, nodeDescriptorResponseCb, nodeDescriptorNotifyCb> *rpcContextData) {
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("getNodeDescriptor - node %04X", nwk_addr);
+#endif
+
+	//if (pGalZb->getGalStatus() != GAL_SS_RUNNING){
+	if (pGalZb->getGWStatus() != GW_RUNNING) {
+		pLogger->debug("getNodeDescriptor - Error GAL_NOT_RUNNING");
+
+		// RPC response Callback
+		RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED, GAL_NOT_RUNNING);
+
+		CALL_RESPONSE (rpcContextData)(nwk_addr, NULL, NULL,
+				rpcContextData->getSessionId(), &rpcReqStatus);
+
+		// Return Error Code
+		return GAL_NOT_RUNNING;
+	}
+
+	pthread_mutex_lock(&mux);
+
+	if (functionsContext.getNodeDescriptor.lock()) {
+		// getNodeDescriptor is not running: call getNodeDescriptor
+		assert(pGalDb != NULL);
+		///	Set the timer for stopping the discovery process
+		if (timeout > 0x00000000 && timeout != 0xffffffff) {
+			// Convert timeout from milliseconds to seconds (ceil)
+			timeout = timeout / 1000 + ((timeout % 1000) ? 1 : 0);
+			///	Set the timer for stopping the startGatewayDevice process
+			functionsContext.getNodeDescriptor.fTimeout = (int) timeout;
+#ifdef DEBUG_ACTIVE_DA
+			if (this->debugEnabled == true)
+			pLogger->debug("getNodeDescriptor - timeout value = %d (sec)", functionsContext.getNodeDescriptor.fTimeout);
+#endif
+			if (!functionsContext.getNodeDescriptor.setTimer(&timerThread, this,
+					&DiscoveryAgent::onGetNodeDescriptor)) {
+				pLogger->error("getNodeDescriptor - ERROR creating timer!");
+				functionsContext.getNodeDescriptor.unlock(Canceled);
+				pthread_mutex_unlock(&mux);
+				// RPC response Callback
+				RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED,
+						TIMER_ERROR);
+				CALL_RESPONSE (rpcContextData)(nwk_addr, NULL, NULL,
+						rpcContextData->getSessionId(), &rpcReqStatus);
+				return TIMER_ERROR;
+			}
+		} else {
+			/// If timeout value is 0xffffffff (infinite amount of time) or 0x00000000 do not use timer
+			pLogger->debug("getNodeDescriptor - timeout value infinite or zero - timer disabled");
+		}
+		///	Reset getNodeDescriptor result
+		functionsContext.getNodeDescriptor.result = FSUCCESS;
+		///	Reset getNodeDescriptor numExpectedMsgs
+		functionsContext.getNodeDescriptor.numExpectedMsgs = 0;
+		///	Register RPC Context Data (containing RPC SessionId and RPC callbacks for response and notification) related to the specific request.
+		functionsContext.getNodeDescriptor.rpcContext = *rpcContextData;
+#ifdef DEBUG_ACTIVE_DA
+		pLogger->debug("getNodeDescriptor started");
+#endif
+		///	Register a DiscoveryAgent listener on event ZB_ZDO_NODE_DESC_CONFIRM in GalZbIf
+		pGalZb->registerListener(ZB_ZDO_NODE_DESC_CONFIRM,
+				(void *) (&getNodeDescriptor_CbW));
+		// Increase number of expected messages
+		functionsContext.getNodeDescriptor.numExpectedMsgs++;
+		// Node Descriptor request on node identified by nwk_addr	
+		pGalZb->ZDO_NODE_DESC_request(nwk_addr, nwk_addr);
+		// In case an asynch request is considered, RPC response Callback has to be invoked
+		if (functionsContext.getNodeDescriptor.rpcContext.getRPCNotifyCb()
+				!= NULL) {
+#ifdef DEBUG_ACTIVE_DA
+			pLogger->debug("getNodeDescriptor - started the asynch request");
+#endif
+			RPCReqStatus rpcReqStatus(End, FSUCCESS, AGENT_SUCCESS, true);
+			CALL_RESPONSE (rpcContextData)(nwk_addr, NULL, NULL,
+					rpcContextData->getSessionId(), &rpcReqStatus);
+		}
+	} else {
+		pLogger->debug("getNodeDescriptor - A getNodeDescriptor is already running");
+		pthread_mutex_unlock(&mux);
+		RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED, AGENT_BUSY);
+		CALL_RESPONSE (rpcContextData)(nwk_addr, NULL, NULL,
+				rpcContextData->getSessionId(), &rpcReqStatus);
+		return AGENT_BUSY;
+	}
+	pthread_mutex_unlock(&mux);
+	return AGENT_SUCCESS;
+}
+
+/**
+ Public method DiscoveryAgent getNodeDescriptor_CbW
+ This is a static member function, used as a wrapper to callback to the non-static member getNodeDescriptor_Cb.
+ This function can be called by a method in GalZbIf.
+
+
+ @param status Success or Error status related to the request.
+ @param nwk_addr Short address of the device of interest.
+ @param node_descr  Pointer to the returned node descriptor data structure.
+ @return Void.
+ */
+template<class T>
+void DiscoveryAgent<T>::getNodeDescriptor_CbW(uchar status, ushort nwk_addr,
+		ZB_NODE_DESC *node_descr) {
+	DiscoveryAgent* dAgent = DiscoveryAgent<T>::Instance();
+
+#ifdef DEBUG_ACTIVE_DA
+	if (dAgent->debugEnabled == true)
+	printf("\nDiscoveryAgent::getNodeDescriptor_CbW\n");
+#endif
+	dAgent->getNodeDescriptor_Cb(status, nwk_addr, node_descr);
+}
+
+/**
+ Public method DiscoveryAgent getNodeDescriptor_Cb
+ Implements getNodeDescriptor Callback.
+
+ @param status Success or Error status related to the request.
+ @param nwk_addr Short address of the device of interest.
+ @param node_descr  Pointer to the returned node descriptor data structure.
+ @return Void.
+ */
+template<class T>
+void DiscoveryAgent<T>::getNodeDescriptor_Cb(uchar status, ushort nwk_addr,
+		ZB_NODE_DESC *node_descr) {
+	Node *node;
+
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("getNodeDescriptor_Cb - Node %04X", nwk_addr);
+#endif
+
+	assert(pGalDb != NULL);
+
+	functionsContext.getNodeDescriptor.numExpectedMsgs--;
+
+	if (status != ZB_ZDO_SUCCESS) {
+		pLogger->error("getNodeDescriptor_Cb - ERROR returned by ZDO_NODE_DESC_confirm");
+
+		functionsContext.getNodeDescriptor.result = FFAILED;
+
+		if (functionsContext.getNodeDescriptor.numExpectedMsgs == 0) {
+			pLogger->debug("getNodeDescriptor_Cb - getNodeDescriptor failed");
+
+			// Unregister listener
+			pGalZb->unregisterListener(ZB_ZDO_NODE_DESC_CONFIRM,
+					(void *) (&getNodeDescriptor_CbW));
+
+			// Remove timer related to getNodeDescriptor
+			functionsContext.getNodeDescriptor.killTimer();
+
+			// getNodedescriptor Completed
+			functionsContext.getNodeDescriptor.unlock();
+		}
+
+		if (functionsContext.getNodeDescriptor.rpcContext.getRPCNotifyCb()
+				!= NULL) {
+			RPCReqStatus rpcReqStatus(functionsContext.getNodeDescriptor,
+					NODE_DESCRIPTOR_ERROR);
+
+			FCALL_NOTIFY (functionsContext.getNodeDescriptor)(NULL,
+					&rpcReqStatus);
+		} else {
+			// RPC response Callback
+			RPCReqStatus rpcReqStatus(functionsContext.getNodeDescriptor,
+					NODE_DESCRIPTOR_ERROR);
+			FCALL_RESPONSE (functionsContext.getNodeDescriptor)(nwk_addr, NULL,
+					NULL,
+					functionsContext.getNodeDescriptor.rpcContext.getSessionId(),
+					&rpcReqStatus);
+		}
+		return;
+	}
+
+	// Lookup the node
+	node = pGalDb->findNodeByNwkAddr(nwk_addr);
+	if (node == NULL) {
+		pLogger->error("getNodeDescriptor_Cb - ERROR: arrived a node desc confirm for a unexistent node %04X", (int)nwk_addr);
+
+		functionsContext.getNodeDescriptor.result = FFAILED;
+
+		if (functionsContext.getNodeDescriptor.numExpectedMsgs == 0) {
+			pLogger->debug("getNodeDescriptor_Cb - getNodeDescriptor failed");
+
+			// Unregister listener
+			pGalZb->unregisterListener(ZB_ZDO_NODE_DESC_CONFIRM,
+					(void *) (&getNodeDescriptor_CbW));
+
+			// Remove timer related to getNodeDescriptor
+			functionsContext.getNodeDescriptor.killTimer();
+
+			// getNodedescriptor Completed
+			functionsContext.getNodeDescriptor.unlock();
+		}
+
+		if (functionsContext.getNodeDescriptor.rpcContext.getRPCNotifyCb()
+				!= NULL) {
+			RPCReqStatus rpcReqStatus(functionsContext.getNodeDescriptor,
+					NONEXISTENTENT_NODE);
+			FCALL_NOTIFY (functionsContext.getNodeDescriptor)(NULL,
+					&rpcReqStatus);
+		} else {
+			// RPC response Callback
+			RPCReqStatus rpcReqStatus(functionsContext.getNodeDescriptor,
+					NONEXISTENTENT_NODE);
+
+			FCALL_RESPONSE (functionsContext.getNodeDescriptor)(nwk_addr, NULL,
+					NULL,
+					functionsContext.getNodeDescriptor.rpcContext.getSessionId(),
+					&rpcReqStatus);
+		}
+		return;
+	}
+	// Node found!
+	switch (node_descr->logical_type) {
+	case COORDINATOR:
+		node->node_desc.logicaltype = COORDINATOR;
+		break;
+
+	case ROUTER:
+		node->node_desc.logicaltype = ROUTER;
+		break;
+
+	case ENDDEVICE:
+		node->node_desc.logicaltype = ENDDEVICE;
+		break;
+
+	default: {
+		pLogger->warn("getNodeDescriptor_Cb - logicaltype unknown %d", node_descr->logical_type);
+		node->node_desc.logicaltype = UNKNOWN_LOGICALTYPE;
+		break;
+	}
+	}
+	switch (node_descr->freq_band) {
+	case ZB_FREQ_BAND_868:
+		node->node_desc.frequencyband = F868_868D6;
+		break;
+
+	case ZB_FREQ_BAND_902:
+		node->node_desc.frequencyband = F902_928;
+		break;
+
+	case ZB_FREQ_BAND_2400:
+		node->node_desc.frequencyband = F2400_2483D5;
+		break;
+
+	default: {
+		node->node_desc.frequencyband = UNKNOWN_VALUE;
+		pLogger->warn("getNodeDescriptor_Cb - frequency unknown %d", node_descr->freq_band);
+		break;
+	}
+	}
+	/*
+	 #ifdef DEBUG_ACTIVE_DA
+	 pLogger->debug("getNodeDescriptor_Cb - frequency band: %d",node->node_desc.frequencyband);
+	 #endif
+	 */
+	uchar mac_cap = node_descr->mac_cap;
+	node->node_desc.mac_cap = node_descr->mac_cap;
+	node->node_desc.alternatePANcoordinator = GET_BIT(mac_cap, 0);
+	node->node_desc.devicetype = GET_BIT(mac_cap, 1);
+	node->node_desc.powersource = GET_BIT(mac_cap, 2);
+	node->node_desc.receiveronwhenidle = GET_BIT(mac_cap, 3);
+	node->node_desc.securytycapability = GET_BIT(mac_cap, 6);
+	node->node_desc.manufacturecode = node_descr->manifact_code;
+	node->node_desc.maximumbuffersize = node_descr->max_buf_size;
+	node->node_desc.maximumtransfersize = node_descr->max_transf_size;
+	node->node_desc.server_mask = node_descr->server_mask;
+	// Set filled to true = NodeDescriptor structure has been filled out
+	node->node_desc.filled = true;
+
+	if (functionsContext.getNodeDescriptor.numExpectedMsgs == 0) {
+		/*
+		 #ifdef DEBUG_ACTIVE_DA
+		 pLogger->debug("getNodeDescriptor_Cb - getNodeDescriptor completed (node %04X)",(int)nwk_addr);
+		 #endif
+		 */
+		// Unregister listener
+		pGalZb->unregisterListener(ZB_ZDO_NODE_DESC_CONFIRM,
+				(void *) (&getNodeDescriptor_CbW));
+		// Remove timer related to getNodeDescriptor
+		functionsContext.getNodeDescriptor.killTimer();
+	}
+
+	RPCReqStatus rpcReqStatus(functionsContext.getNodeDescriptor,
+			AGENT_SUCCESS);
+	if (functionsContext.getNodeDescriptor.rpcContext.getRPCNotifyCb()
+			!= NULL) {
+		FCALL_NOTIFY (functionsContext.getNodeDescriptor)(node, &rpcReqStatus);
+	} else if (functionsContext.getNodeDescriptor.rpcContext.getRPCResponseCb()
+			!= NULL) {
+		FCALL_RESPONSE (functionsContext.getNodeDescriptor)(nwk_addr,
+				node->get_ieee_addr(), &node->node_desc,
+				functionsContext.getNodeDescriptor.rpcContext.getSessionId(),
+				&rpcReqStatus);
+	} else {
+#ifdef DEBUG_ACTIVE_DA
+		pLogger->debug("getNodeDescriptor_Cb - Both getRPCNotifyCb and getRPCResponseCb are NULL");
+#endif
+	}
+	// getNodedescriptor Completed
+	functionsContext.getNodeDescriptor.unlock();
+}
+
+/**
+ Public method DiscoveryAgent getPowerDescriptor
+ getPowerDescriptor macrofunction is invoked.
+
+
+ @param nwk_addr Short address of the device of interest.
+ @param rpcContextData RPC context.
+ @return Status.
+ */
+template<class T>
+int DiscoveryAgent<T>::getPowerDescriptor(ushort nwk_addr,
+		RPCContext<T, powerDescriptorResponseCb> *rpcContextData) {
+
+	pthread_mutex_lock(&mux);
+	if (pGalZb->getGWStatus() != GW_RUNNING) {
+		pLogger->error("getPowerDescriptor - Error GAL_NOT_RUNNING");
+		pthread_mutex_unlock(&mux);
+		// RPC response Callback
+		RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED, GAL_NOT_RUNNING);
+		CALL_RESPONSE (rpcContextData)(nwk_addr, NULL, NULL,
+				rpcContextData->getSessionId(), &rpcReqStatus);
+		return GAL_NOT_RUNNING;
+	}
+	if (functionsContext.getPowerDescriptor.lock()) {
+		// getPowerDescriptor is not running: call getPowerDescriptor
+		assert(pGalDb != NULL);
+		/// Set the timer for stopping the discovery process 
+		if (!functionsContext.getPowerDescriptor.setTimer(&timerThread, this,
+				&DiscoveryAgent::onGetPowerDescriptor)) {
+			pLogger->error("getPowerDescriptor - ERROR creating timer!");
+			functionsContext.getPowerDescriptor.unlock(Canceled);
+			pthread_mutex_unlock(&mux);
+			RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED, TIMER_ERROR);
+			CALL_RESPONSE (rpcContextData)(nwk_addr, NULL, NULL,
+					rpcContextData->getSessionId(), &rpcReqStatus);
+			return TIMER_ERROR;
+		}
+		///	Reset getPowerDescriptor result
+		functionsContext.getPowerDescriptor.result = FSUCCESS;
+		///	Reset getPowerDescriptor numExpectedMsgs
+		functionsContext.getPowerDescriptor.numExpectedMsgs = 0;
+		///	Register RPC Context Data (containing RPC SessionId and RPC callbacks for response and notification) related to the specific request.
+		functionsContext.getPowerDescriptor.rpcContext = *rpcContextData;
+		// Register a DiscoveryAgent listener on event ZB_ZDO_POWER_DESC_CONFIRM in GalZbIf
+		pGalZb->registerListener(ZB_ZDO_POWER_DESC_CONFIRM,
+				(void *) (&getPowerDescriptor_CbW));
+
+#ifdef DEBUG_ACTIVE_DA
+		pLogger->debug("getPowerDescriptor started");
+#endif
+		// Power Descriptor request on node identified by nwk_addr	
+		pGalZb->ZDO_POWER_DESC_request(nwk_addr, nwk_addr);
+		// Increase number of expected messages 
+		functionsContext.getPowerDescriptor.numExpectedMsgs++;
+		pthread_mutex_unlock(&mux);
+		return AGENT_SUCCESS;
+	} else {
+		pLogger->debug("getPowerDescriptor - A getPowerDescriptor is already running");
+		pthread_mutex_unlock(&mux);
+		RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED, AGENT_BUSY);
+		CALL_RESPONSE (rpcContextData)(nwk_addr, NULL, NULL,
+				rpcContextData->getSessionId(), &rpcReqStatus);
+		return AGENT_BUSY;
+	}
+}
+
+/**
+ Public method DiscoveryAgent getPowerDescriptor_CbW
+ This is a static member function, used as a wrapper to callback to the non-static member getPowerDescriptor_Cb.
+ This function can be called by a method in GalZbIf.
+
+ @param status Success or Error status related to the request.
+ @param nwk_addr Short address of the device of interest.
+ @param power_descr  Pointer to the returned power descriptor data structure.
+ @return Void.
+ */
+template<class T>
+void DiscoveryAgent<T>::getPowerDescriptor_CbW(uchar status, ushort nwk_addr,
+		ZB_POWER_DESC *power_descr) {
+	DiscoveryAgent* dAgent = DiscoveryAgent<T>::Instance();
+
+#ifdef DEBUG_ACTIVE_DA
+	if (dAgent->debugEnabled == true)
+	printf("\nDiscoveryAgent::getPowerDescriptor_CbW\n");
+#endif
+
+	dAgent->getPowerDescriptor_Cb(status, nwk_addr, power_descr);
+}
+
+/**
+ Public method DiscoveryAgent getPowerDescriptor_Cb
+ Implements getPowerDescriptor Callback.
+
+ @param status Success or Error status related to the request.
+ @param nwk_addr Short address of the device of interest.
+ @param power_descr  Pointer to the returned power descriptor data structure.
+ @return Void.
+ */
+template<class T>
+void DiscoveryAgent<T>::getPowerDescriptor_Cb(uchar status, ushort nwk_addr,
+		ZB_POWER_DESC *power_descr) {
+	Node *node;
+
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("getPowerDescriptor_Cb");
+#endif
+
+	assert(pGalDb != NULL);
+
+	functionsContext.getPowerDescriptor.numExpectedMsgs--;
+
+	if (status != ZB_ZDO_SUCCESS) {
+		pLogger->error("getPowerDescriptor_Cb - ERROR returned by ZDO_POWER_DESC_confirm");
+
+		functionsContext.getPowerDescriptor.result = FFAILED;
+
+		if (functionsContext.getPowerDescriptor.numExpectedMsgs == 0) {
+			pLogger->debug("getPowerDescriptor_Cb - getPowerDescriptor failed");
+
+			// Unregister listener
+			pGalZb->unregisterListener(ZB_ZDO_POWER_DESC_CONFIRM,
+					(void *) (&getPowerDescriptor_CbW));
+
+			// Remove timer related to getPowerDescriptor
+			functionsContext.getPowerDescriptor.killTimer();
+
+			// getPowerdescriptor completed
+			functionsContext.getPowerDescriptor.unlock();
+		}
+
+		// RPC response Callback		
+		RPCReqStatus rpcReqStatus(functionsContext.getPowerDescriptor,
+				POWER_DESCRIPTOR_ERROR);
+
+		FCALL_RESPONSE (functionsContext.getPowerDescriptor)(nwk_addr, NULL,
+				NULL,
+				functionsContext.getPowerDescriptor.rpcContext.getSessionId(),
+				&rpcReqStatus);
+
+		return;
+	}
+
+	// Lookup the node
+	node = pGalDb->findNodeByNwkAddr(nwk_addr);
+
+	if (node == NULL) {
+		pLogger->error("getNodeDescriptor_Cb - INTERNAL ERROR: arrived a power desc confirm for a unexistent node %04X", (int)nwk_addr);
+
+		functionsContext.getPowerDescriptor.result = FFAILED;
+
+		if (functionsContext.getPowerDescriptor.numExpectedMsgs == 0) {
+			pLogger->debug("getPowerDescriptor_Cb - getPowerDescriptor failed");
+
+			// Unregister listener
+			pGalZb->unregisterListener(ZB_ZDO_POWER_DESC_CONFIRM,
+					(void *) (&getPowerDescriptor_CbW));
+
+			// Remove timer related to getPowerDescriptor
+			functionsContext.getPowerDescriptor.killTimer();
+
+			// getPowerdescriptor completed
+			functionsContext.getPowerDescriptor.unlock();
+		}
+
+		// RPC response Callback	
+		RPCReqStatus rpcReqStatus(functionsContext.getPowerDescriptor,
+				NONEXISTENTENT_NODE);
+
+		FCALL_RESPONSE (functionsContext.getPowerDescriptor)(nwk_addr, NULL,
+				NULL,
+				functionsContext.getPowerDescriptor.rpcContext.getSessionId(),
+				&rpcReqStatus);
+
+		return;
+	}
+
+	// Set currentpowermode
+	switch (power_descr->curr_pw_mode) {
+	case SYNCHRONIZED_WITH_RECEIVERONWHENIDLE:
+		node->power_desc.currentpowermode =
+				SYNCHRONIZED_WITH_RECEIVERONWHENIDLE;
+		break;
+
+	case PERIODICALLYON:
+		node->power_desc.currentpowermode = PERIODICALLYON;
+		break;
+
+	case WHENSTIMULATED:
+		node->power_desc.currentpowermode = WHENSTIMULATED;
+		break;
+
+	default: {
+		pLogger->warn("getPowerDescriptor_Cb - Currentpowermode unknown %d", power_descr->curr_pw_mode);
+		node->power_desc.currentpowermode = UNKNOWN_POWERMODE;
+		break;
+	}
+	}
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("getNodeDescriptor_Cb - Currentpowermode: %d", node->power_desc.currentpowermode);
+#endif
+
+	/*
+	 // TODO They need to be fixed!
+	 //set avaiablepowersource
+	 node->->power_desc.avaiablepowersource[MAINPOWER] = (msg[5]>>4)&0x01;
+	 node->->power_desc.avaiablepowersource[RECHARGEABLE] = (msg[5]>>5)&0x01;
+	 node->->power_desc.avaiablepowersource[DISPOSABLE] = (msg[5]>>6)&0x01;
+	 //set currentpowersource
+	 node->->power_desc.currentpowersource[MAINPOWER] = msg[6]&0x01;
+	 node->->power_desc.currentpowersource[RECHARGEABLE] = (msg[6]>>1)&0x01;
+	 node->->power_desc.currentpowersource[DISPOSABLE] = (msg[6]>>2)&0x01;
+	 */
+
+	//set currentpowersourcelevel
+	switch (power_descr->curr_pw_src_level) {
+	case CRITICAL:
+		node->power_desc.currentpowersourcelevel = CRITICAL;
+		break;
+
+	case P33:
+		node->power_desc.currentpowersourcelevel = P33;
+		break;
+
+	case P66:
+		node->power_desc.currentpowersourcelevel = P66;
+		break;
+
+	case P100:
+		node->power_desc.currentpowersourcelevel = P100;
+		break;
+
+	default: {
+		pLogger->warn("getPowerDescriptor_Cb - Currentpowersourcelevel unknown %d", power_descr->curr_pw_src_level);
+		node->power_desc.currentpowersourcelevel = UNKNOWN_PSLEVEL;
+		break;
+	}
+	}
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("getPowerDescriptor_Cb - Currentpowersourcelevel: %d", node->power_desc.currentpowersourcelevel);
+#endif
+
+	// Set filled to true = PowerDescriptor structure has been filled out
+	node->power_desc.filled = true;
+
+	if (functionsContext.getPowerDescriptor.numExpectedMsgs == 0) {
+		pLogger->debug("getPowerDescriptor_Cb - getPowerDescriptor completed (node %04X)",(int)nwk_addr);
+
+		// Unregister listener
+		pGalZb->unregisterListener(ZB_ZDO_POWER_DESC_CONFIRM,
+				(void *) (&getPowerDescriptor_CbW));
+
+		// Remove timer related to getPowerDescriptor
+		functionsContext.getPowerDescriptor.killTimer();
+
+		// getPowerdescriptor Completed
+		functionsContext.getPowerDescriptor.unlock();
+
+		// RPC response Callback	
+		RPCReqStatus rpcReqStatus(functionsContext.getPowerDescriptor,
+				AGENT_SUCCESS);
+
+		FCALL_RESPONSE (functionsContext.getPowerDescriptor)(nwk_addr,
+				node->get_ieee_addr(), &node->power_desc,
+				functionsContext.getPowerDescriptor.rpcContext.getSessionId(),
+				&rpcReqStatus);
+	} else
+		pLogger->fatal("getPowerDescriptor_Cb - getPowerDescriptor NOT completed.");
+
+	return;
+}
+
+/**
+ Public method DiscoveryAgent superDiscovery
+ superDiscovery macrofunction is invoked.
+
+ @param rpcContextData RPC context.
+ @return Status.
+ */
+template<class T>
+int DiscoveryAgent<T>::superDiscovery(
+		RPCContext<T, superDiscoveryResponseCb> *rpcContextData) {
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("superDiscovery");
+#endif
+
+	//if (pGalZb->getGalStatus() != GAL_SS_RUNNING){
+	if (pGalZb->getGWStatus() != GW_RUNNING) {
+		pLogger->debug("superDiscovery - Error GAL_NOT_RUNNING");
+
+		// RPC response Callback
+		RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED, GAL_NOT_RUNNING);
+
+		CALL_RESPONSE (rpcContextData)(NULL, rpcContextData->getSessionId(),
+				&rpcReqStatus);
+
+		// Return Error Code
+		return GAL_NOT_RUNNING;
+	}
+
+	pthread_mutex_lock(&mux);
+
+	if (functionsContext.superDiscovery.lock()) {
+		///	If superDiscovery is not already running: start superDiscovery 
+		assert(pGalDb != NULL);
+
+		///	Set the timer for stopping the discovery process
+		if (!functionsContext.superDiscovery.setTimer(&timerThread, this,
+				&DiscoveryAgent::onSuperDiscovery)) {
+			pLogger->error("superDiscovery - ERROR creating timer!");
+			functionsContext.superDiscovery.unlock(Canceled);
+			pthread_mutex_unlock(&mux);
+			RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED, TIMER_ERROR);
+			CALL_RESPONSE (rpcContextData)(NULL, rpcContextData->getSessionId(),
+					&rpcReqStatus);
+			return TIMER_ERROR;
+		}
+		/// Reset superDiscovery result
+		functionsContext.superDiscovery.result = FSUCCESS;
+
+		/// Reset superDiscovery numExpectedMsgs
+		functionsContext.superDiscovery.numExpectedMsgs = 0;
+
+		/// Register RPC Context Data (containing RPC SessionId and RPC callbacks for response and notification) related to the specific request.
+		functionsContext.superDiscovery.rpcContext = *rpcContextData;
+
+		/// Register a DiscoveryAgent listener on event ZB_ZDO_IEEE_ADDR_CONFIRM in GalZbIf.
+		/// On ZB_ZDO_IEEE_ADDR_CONFIRM, superDiscovery_CbW will be called.		
+		pGalZb->registerListener(ZB_ZDO_IEEE_ADDR_CONFIRM,
+				(void *) (&superDiscovery_CbW));
+
+		/// Register a DiscoveryAgent listener on event ZB_ZDO_NODE_DESC_CONFIRM in GalZbIf
+		/// On ZB_ZDO_NODE_DESC_CONFIRM, superDiscovery_ND_CbW will be called.	
+		pGalZb->registerListener(ZB_ZDO_NODE_DESC_CONFIRM,
+				(void *) (&superDiscovery_ND_CbW));
+
+		/// Register a DiscoveryAgent listener on event ZB_ZDO_POWER_DESC_CONFIRM in GalZbIf
+		/// On ZB_ZDO_POWER_DESC_CONFIRM, superDiscovery_PD_CbW will be called.		
+		pGalZb->registerListener(ZB_ZDO_POWER_DESC_CONFIRM,
+				(void *) (&superDiscovery_PD_CbW));
+
+#ifdef DEBUG_ACTIVE_DA
+		pLogger->debug("superDiscovery started");
+#endif
+
+		//Node *root;
+		ushort nwk_addr = pGalDb->root->get_nwk_addr();
+
+		/// If a discovery has been already made the data structures must be cleaned up 	
+		pGalDb->clearAllButRoot();
+		this->clearDeadingNodeList();
+
+		/// The number of expected messages is increased by 3 (an IEEE Address request, a Node Descriptor
+		/// request and a Power Descriptor request are sent to the root node; responses are expected)	
+		functionsContext.superDiscovery.numExpectedMsgs += 3;
+
+		/// IEEE_ADDR_request on the root. The ZigBee message is sent over the air, the reply is asynchronous
+		pGalZb->ZDO_IEEE_ADDR_request(nwk_addr, ZDO_REQ_TYPE_EX_RES, 0);
+		usleep(PACETIME);
+
+		/// Node Descriptor request on the root	
+		pGalZb->ZDO_NODE_DESC_request(nwk_addr, nwk_addr);
+		usleep(PACETIME);
+
+		/// Power Descriptor request on the root	
+		pGalZb->ZDO_POWER_DESC_request(nwk_addr, nwk_addr);
+		usleep(PACETIME);
+	} else {
+		pLogger->debug("superDiscovery - A superDiscovery is already running");
+		pthread_mutex_unlock(&mux);
+		RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED, AGENT_BUSY);
+		CALL_RESPONSE (rpcContextData)(NULL, rpcContextData->getSessionId(),
+				&rpcReqStatus);
+		return AGENT_BUSY;
+	}
+	pthread_mutex_unlock(&mux);
+	return AGENT_SUCCESS;
+}
+
+/**
+ Public method DiscoveryAgent superDiscovery_CbW
+ superDiscovery Callback Wrapper: this is a static member fucntion, used as a wrapper to callback to the non-static member superDiscovery_Cb.
+ This function can be called by a method in GalZbIf.
+
+ @param status Success or Error status related to the request.
+ @param ieee_addr IEEE address of the device of interest.
+ @param nwk_addr Short address of the device of interest.
+ @param num_assoc_dev Number of associated devices to the remote device of interest.
+ @param start_index Starting index into the list of associated devices.
+ @param nwk_addr_assoc_dev_list The list of short addresses related to the associated devices.
+ @return Void.
+ */
+template<class T>
+void DiscoveryAgent<T>::superDiscovery_CbW(uchar status, uchar *ieee_addr,
+		ushort nwk_addr, uchar num_assoc_dev, uchar start_index,
+		ushort *nwk_addr_assoc_dev_list) {
+	DiscoveryAgent* dAgent = DiscoveryAgent<T>::Instance();
+
+#ifdef DEBUG_ACTIVE_DA
+	if (dAgent->debugEnabled == true)
+	printf("\nDiscoveryAgent::superDiscovery_CbW\n");
+#endif
+
+	dAgent->superDiscovery_Cb(status, ieee_addr, nwk_addr, num_assoc_dev,
+			start_index, nwk_addr_assoc_dev_list);
+
+}
+
+/**
+ Public method DiscoveryAgent superDiscovery_Cb
+ Implements superDiscovery Callback.
+
+ @param status Success or Error status related to the request.
+ @param ieee_addr IEEE address of the device of interest.
+ @param nwk_addr Short address of the device of interest.
+ @param num_assoc_dev Number of associated devices to the remote device of interest.
+ @param start_index Starting index into the list of associated devices.
+ @param nwk_addr_assoc_dev_list The list of short addresses related to the associated devices.
+ @return Void.
+ */
+template<class T>
+void DiscoveryAgent<T>::superDiscovery_Cb(uchar status, uchar *ieee_addr,
+		ushort nwk_addr, uchar num_assoc_dev, uchar start_index,
+		ushort *nwk_addr_assoc_dev_list) {
+	Node *mainNode, *neighbor;
+
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("superDiscovery_Cb");
+#endif
+
+	assert(pGalDb != NULL);
+
+	pthread_mutex_lock(&mux);
+
+	// Update number of expected messages
+	functionsContext.superDiscovery.numExpectedMsgs--;
+
+	if (status != ZB_ZDO_SUCCESS) {
+		pLogger->error("superDiscovery_Cb - ERROR returned by ZDO_IEEE_ADDR_confirm");
+
+		functionsContext.superDiscovery.result = FFAILED;
+
+		if (functionsContext.superDiscovery.numExpectedMsgs == 0) {
+			pLogger->warn("superDiscovery_Cb - numExpectedMsgs = 0  (superDiscovery completed in superDiscovery_Cb) -> WARNING");
+
+			// Unregister listeners
+			pGalZb->unregisterListener(ZB_ZDO_IEEE_ADDR_CONFIRM,
+					(void *) (&superDiscovery_CbW));
+			pGalZb->unregisterListener(ZB_ZDO_NODE_DESC_CONFIRM,
+					(void *) (&superDiscovery_ND_CbW));
+			pGalZb->unregisterListener(ZB_ZDO_POWER_DESC_CONFIRM,
+					(void *) (&superDiscovery_PD_CbW));
+
+			// Remove timer related to superDiscovery
+			functionsContext.superDiscovery.killTimer();
+
+			///	On abnormal completion of superDiscovery in superDiscovery_Cb, a clearGhostNodes is performed to detect ghost nodes (nodes not responding) and remove them from node dictionary and neighbor list.
+			clearGhostNodes();
+
+			// superDiscovery Completed
+			functionsContext.superDiscovery.unlock();
+
+			// RPC response Callback			
+			RPCReqStatus rpcReqStatus(functionsContext.superDiscovery,
+					AGENT_SUCCESS);
+			FCALL_RESPONSE (functionsContext.superDiscovery)(this->pGalDb,
+					functionsContext.superDiscovery.rpcContext.getSessionId(),
+					&rpcReqStatus);
+
+		}
+		pthread_mutex_unlock(&mux);
+		return;
+	}
+
+	// Debug
+	pLogger->debug("superDiscovery_Cb - ieee_addr = %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X - nwk_addr = %04X", (int)(ieee_addr[0]), (int)(ieee_addr[1]),
+			(int)(ieee_addr[2]), (int)(ieee_addr[3]), (int)(ieee_addr[4]), (int)(ieee_addr[5]), (int)(ieee_addr[6]), (int)(ieee_addr[7]), nwk_addr );
+
+	// Lookup the node itself to add sons
+	mainNode = pGalDb->findNodeByNwkAddr(nwk_addr); // To be considered before if statement related to num_assoc_dev
+	mainNode->set_ieee_addr(ieee_addr);
+
+	if (!num_assoc_dev) {
+		// No associated devices
+		pLogger->debug("superDiscovery_Cb - Node 0x%04X doesn't have any neighbor", (int)nwk_addr);
+	} else
+		pLogger->debug("superDiscovery_Cb - Node 0x%04X has neighbor", (int)nwk_addr);
+
+	ushort neighbor_nwk_addr;
+
+	///	The number of expected messages is increased by 3 times the number of neighbor (an IEEE Address request, a Node Descriptor
+	///	request and a Power Descriptor request are sent to every neighbor node; responses are expected).
+	functionsContext.superDiscovery.numExpectedMsgs += 3 * num_assoc_dev;
+
+	for (int i = 0; i < num_assoc_dev; i++) {
+
+		neighbor_nwk_addr = nwk_addr_assoc_dev_list[i];
+
+		pLogger->debug("superDiscovery_Cb - mainNode = 0x%04X - neighbor = 0x%04X", nwk_addr, neighbor_nwk_addr);
+
+		// Son added to the pointer array
+		neighbor = pGalDb->findNodeByNwkAddr(neighbor_nwk_addr);
+
+		// Error: Node already discovered -> continue
+		if (neighbor != NULL) {
+			pLogger->error("superDiscovery_Cb - ATTENTION: node already discovered!");
+			pthread_mutex_lock(&mux);
+			functionsContext.superDiscovery.result = FFAILED;
+			functionsContext.superDiscovery.numExpectedMsgs -= 3;
+			continue;
+		}
+		neighbor = new Node(neighbor_nwk_addr);
+
+		///	neighbor added to mainNode. The IEEE Address of the neighbor node is set to 00 00 00 00 00 00 00 00
+		pGalDb->addNeighbor(mainNode, neighbor);
+
+		///	ZDO_IEEE_ADDR_request on the neighbor. The ZigBee message is sent over the air, the reply is asynchronous
+		pGalZb->ZDO_IEEE_ADDR_request(neighbor_nwk_addr, ZDO_REQ_TYPE_EX_RES,
+				0);
+		usleep(PACETIME);
+
+		///	Node Descriptor request on node identified by nwk_addr	
+		pGalZb->ZDO_NODE_DESC_request(neighbor_nwk_addr, neighbor_nwk_addr);
+		usleep(PACETIME);
+
+		///	Power Descriptor request on node identified by nwk_addr	
+		pGalZb->ZDO_POWER_DESC_request(neighbor_nwk_addr, neighbor_nwk_addr);
+		usleep(PACETIME);
+	}
+
+	if (functionsContext.superDiscovery.numExpectedMsgs == 0) {
+		pLogger->warn("superDiscovery_Cb - numExpectedMsgs = 0  (superDiscovery completed in superDiscovery_Cb) -> WARNING");
+
+		// Unregister listeners
+		pGalZb->unregisterListener(ZB_ZDO_IEEE_ADDR_CONFIRM,
+				(void *) (&superDiscovery_CbW));
+		pGalZb->unregisterListener(ZB_ZDO_NODE_DESC_CONFIRM,
+				(void *) (&superDiscovery_ND_CbW));
+		pGalZb->unregisterListener(ZB_ZDO_POWER_DESC_CONFIRM,
+				(void *) (&superDiscovery_PD_CbW));
+
+		// Remove timer related to superDiscovery
+		functionsContext.superDiscovery.killTimer();
+
+		///	On completion of superDiscovery, a clearGhostNodes is performed to detect ghost nodes (nodes not responding) and remove them from node dictionary and neighbor list.
+		clearGhostNodes();
+
+		// superDiscovery completed
+		functionsContext.superDiscovery.unlock();
+
+		// RPC response Callback			
+		RPCReqStatus rpcReqStatus(functionsContext.superDiscovery,
+				AGENT_SUCCESS);
+
+		FCALL_RESPONSE (functionsContext.superDiscovery)(this->pGalDb,
+				functionsContext.superDiscovery.rpcContext.getSessionId(),
+				&rpcReqStatus);
+	}
+	pthread_mutex_unlock(&mux);
+}
+
+/**
+ Public method DiscoveryAgent superDiscovery_ND_CbW
+ This is a static member function, used as a wrapper to callback to the non-static member superDiscovery_ND_Cb.
+ This function can be called by a method in GalZbIf.
+
+ @param status Success or Error status related to the request.
+ @param nwk_addr Short address of the device of interest.
+ @param node_descr  Pointer to the returned node descriptor data structure.
+ @return Void.
+ */
+template<class T>
+void DiscoveryAgent<T>::superDiscovery_ND_CbW(uchar status, ushort nwk_addr,
+		ZB_NODE_DESC *node_descr) {
+	DiscoveryAgent* dAgent = DiscoveryAgent<T>::Instance();
+
+#ifdef DEBUG_ACTIVE_DA
+	if (dAgent->debugEnabled == true)
+	printf("\nDiscoveryAgent::superDiscovery_ND_CbW\n");
+#endif
+
+	dAgent->superDiscovery_ND_Cb(status, nwk_addr, node_descr);
+
+}
+
+/**
+ Public method DiscoveryAgent superDiscovery_ND_Cb
+ Implements superDiscovery - Node Descriptor Callback.
+
+
+ @param status Success or Error status related to the request.
+ @param nwk_addr Short address of the device of interest.
+ @param node_descr  Pointer to the returned node descriptor data structure.
+ @return Void.
+ */
+template<class T>
+void DiscoveryAgent<T>::superDiscovery_ND_Cb(uchar status, ushort nwk_addr,
+		ZB_NODE_DESC *node_descr) {
+	Node *node;
+
+	pLogger->debug("superDiscovery_ND_Cb - Node Descriptor node %04X", nwk_addr);
+
+	assert(pGalDb != NULL);
+
+	pthread_mutex_lock(&mux);
+
+	// Update number of expected messages
+	functionsContext.superDiscovery.numExpectedMsgs--;
+
+	if (status != ZB_ZDO_SUCCESS) {
+		pLogger->error("superDiscovery_ND_Cb - ERROR returned by ZDO_NODE_DESC_confirm");
+
+		functionsContext.superDiscovery.result = FFAILED;
+
+		if (functionsContext.superDiscovery.numExpectedMsgs == 0) {
+			pLogger->debug("superDiscovery_ND_Cb - superDiscovery-ND failed");
+
+			// Unregister listeners
+			pGalZb->unregisterListener(ZB_ZDO_IEEE_ADDR_CONFIRM,
+					(void *) (&superDiscovery_CbW));
+			pGalZb->unregisterListener(ZB_ZDO_NODE_DESC_CONFIRM,
+					(void *) (&superDiscovery_ND_CbW));
+			pGalZb->unregisterListener(ZB_ZDO_POWER_DESC_CONFIRM,
+					(void *) (&superDiscovery_PD_CbW));
+
+			// Remove timer related to superDiscovery
+			functionsContext.superDiscovery.killTimer();
+			///	On completion of superDiscovery, a clearGhostNodes is performed to detect ghost nodes (nodes not responding) and remove them from node dictionary and neighbor list.
+			clearGhostNodes();
+
+			// superDiscovery completed
+			functionsContext.superDiscovery.unlock();
+
+			// RPC response Callback			
+			RPCReqStatus rpcReqStatus(functionsContext.superDiscovery,
+					AGENT_SUCCESS);
+
+			FCALL_RESPONSE (functionsContext.superDiscovery)(this->pGalDb,
+					functionsContext.superDiscovery.rpcContext.getSessionId(),
+					&rpcReqStatus);
+		}
+		pthread_mutex_unlock(&mux);
+		return;
+	}
+
+	// Lookup the node
+	node = pGalDb->findNodeByNwkAddr(nwk_addr);
+
+	if (node == NULL) {
+		pLogger->error("superDiscovery_ND_Cb - INTERNAL ERROR: arrived a node desc confirm for a unexistent node %04X", (int)nwk_addr);
+
+		functionsContext.superDiscovery.result = FFAILED;
+
+		if (functionsContext.superDiscovery.numExpectedMsgs == 0) {
+			pLogger->debug("superDiscovery_ND_Cb - superDiscovery-ND failed");
+
+			// Unregister listeners
+			pGalZb->unregisterListener(ZB_ZDO_IEEE_ADDR_CONFIRM,
+					(void *) (&superDiscovery_CbW));
+			pGalZb->unregisterListener(ZB_ZDO_NODE_DESC_CONFIRM,
+					(void *) (&superDiscovery_ND_CbW));
+			pGalZb->unregisterListener(ZB_ZDO_POWER_DESC_CONFIRM,
+					(void *) (&superDiscovery_PD_CbW));
+
+			// Remove timer related to superDiscovery
+			functionsContext.superDiscovery.killTimer();
+			///	On completion of superDiscovery, a clearGhostNodes is performed to detect ghost nodes (nodes not responding) and remove them from node dictionary and neighbor list.
+			clearGhostNodes();
+
+			// superDiscovery completed
+			functionsContext.superDiscovery.unlock();
+
+			// RPC response Callback		
+			RPCReqStatus rpcReqStatus(functionsContext.superDiscovery,
+					AGENT_SUCCESS);
+			FCALL_RESPONSE (functionsContext.superDiscovery)(this->pGalDb,
+					functionsContext.superDiscovery.rpcContext.getSessionId(),
+					&rpcReqStatus);
+
+		}
+		pthread_mutex_unlock(&mux);
+		return;
+	}
+
+	switch (node_descr->logical_type) {
+	case ZB_COORDINATOR:
+		node->node_desc.logicaltype = COORDINATOR;
+		break;
+
+	case ZB_ROUTER:
+		node->node_desc.logicaltype = ROUTER;
+		break;
+
+	case ZB_END_DEVICE:
+		node->node_desc.logicaltype = ENDDEVICE;
+		break;
+
+	default: {
+		pLogger->warn("superDiscovery_ND_Cb - logicaltype unknown %d", node_descr->logical_type);
+		node->node_desc.logicaltype = UNKNOWN_LOGICALTYPE;
+		break;
+	}
+	}
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("superDiscovery_ND_Cb - logicaltype: %d",node->node_desc.logicaltype);
+#endif
+
+	switch (node_descr->freq_band) {
+	case ZB_FREQ_BAND_868:
+		node->node_desc.frequencyband = F868_868D6;
+		break;
+
+	case ZB_FREQ_BAND_902:
+		node->node_desc.frequencyband = F902_928;
+		break;
+
+	case ZB_FREQ_BAND_2400:
+		node->node_desc.frequencyband = F2400_2483D5;
+		break;
+
+	default: {
+		node->node_desc.frequencyband = UNKNOWN_VALUE;
+		pLogger->warn("superDiscovery_ND_Cb - frequency unknown %d", node_descr->freq_band);
+		break;
+	}
+	}
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("superDiscovery_ND_Cb - frequency band: %d",node->node_desc.frequencyband);
+#endif
+
+	uchar mac_cap = node_descr->mac_cap;
+	node->node_desc.mac_cap = node_descr->mac_cap;
+
+	node->node_desc.alternatePANcoordinator = GET_BIT(mac_cap, 0);
+	node->node_desc.devicetype = GET_BIT(mac_cap, 1);
+	node->node_desc.powersource = GET_BIT(mac_cap, 2);
+	node->node_desc.receiveronwhenidle = GET_BIT(mac_cap, 3);
+	node->node_desc.securytycapability = GET_BIT(mac_cap, 6);
+	node->node_desc.manufacturecode = node_descr->manifact_code;
+	node->node_desc.maximumbuffersize = node_descr->max_buf_size;
+	node->node_desc.maximumtransfersize = node_descr->max_transf_size;
+	node->node_desc.server_mask = node_descr->server_mask;
+
+	// Set filled to true = NodeDescriptor structure has been filled out
+	node->node_desc.filled = true;
+
+	if (functionsContext.superDiscovery.numExpectedMsgs == 0) {
+		pLogger->debug("superDiscovery_ND_Cb - superDiscovery completed");
+
+		// Unregister listeners
+		pGalZb->unregisterListener(ZB_ZDO_IEEE_ADDR_CONFIRM,
+				(void *) (&superDiscovery_CbW));
+		pGalZb->unregisterListener(ZB_ZDO_NODE_DESC_CONFIRM,
+				(void *) (&superDiscovery_ND_CbW));
+		pGalZb->unregisterListener(ZB_ZDO_POWER_DESC_CONFIRM,
+				(void *) (&superDiscovery_PD_CbW));
+
+		// Remove timer related to superDiscovery
+		functionsContext.superDiscovery.killTimer();
+
+		// Detect ghost nodes (nodes not responding) and remove them from node dictionary and neighbor list.
+		clearGhostNodes();
+
+		// superDiscovery Completed
+		functionsContext.superDiscovery.unlock();
+
+		// RPC response Callback		
+		RPCReqStatus rpcReqStatus(functionsContext.superDiscovery,
+				AGENT_SUCCESS);
+		FCALL_RESPONSE (functionsContext.superDiscovery)(this->pGalDb,
+				functionsContext.superDiscovery.rpcContext.getSessionId(),
+				&rpcReqStatus);
+	}
+	pthread_mutex_unlock(&mux);
+	return;
+}
+
+/**
+ Public method DiscoveryAgent superDiscovery_PD_CbW
+ This is a static member function, used as a wrapper to callback to the non-static member superDiscovery_PD_Cb.
+ This function can be called by a method in GalZbIf.
+
+ @param status Success or Error status related to the request.
+ @param nwk_addr Short address of the device of interest.
+ @param power_descr  Pointer to the returned power descriptor data structure.
+ @return Void.
+ */
+template<class T>
+void DiscoveryAgent<T>::superDiscovery_PD_CbW(uchar status, ushort nwk_addr,
+		ZB_POWER_DESC *power_descr) {
+	DiscoveryAgent* dAgent = DiscoveryAgent<T>::Instance();
+
+#ifdef DEBUG_ACTIVE_DA
+	if (dAgent->debugEnabled == true)
+	printf("\nDiscoveryAgent::superDiscovery_PD_CbW\n");
+#endif
+
+	dAgent->superDiscovery_PD_Cb(status, nwk_addr, power_descr);
+}
+
+/**
+ Public method DiscoveryAgent superDiscovery_PD_Cb
+ Implements superDiscovery - Power Descriptor Callback.
+
+
+ @param status Success or Error status related to the request.
+ @param nwk_addr Short address of the device of interest.
+ @param power_descr  Pointer to the returned power descriptor data structure.
+ @return Void.
+ */
+template<class T>
+void DiscoveryAgent<T>::superDiscovery_PD_Cb(uchar status, ushort nwk_addr,
+		ZB_POWER_DESC *power_descr) {
+	Node *node;
+
+	pLogger->debug("superDiscovery_PD_Cb - Power Descriptor node %04X", nwk_addr);
+
+	assert(pGalDb != NULL);
+
+	pthread_mutex_lock(&mux);
+
+	// Update number of expected messages
+	functionsContext.superDiscovery.numExpectedMsgs--;
+
+	if (status != ZB_ZDO_SUCCESS) {
+		pLogger->error("superDiscovery_PD_Cb - ERROR returned by ZDO_POWER_DESC_confirm");
+
+		functionsContext.superDiscovery.result = FFAILED;
+
+		if (functionsContext.superDiscovery.numExpectedMsgs == 0) {
+			pLogger->debug("superDiscovery_PD_Cb - superDiscovery-PD failed");
+
+			// Unregister listeners
+			pGalZb->unregisterListener(ZB_ZDO_IEEE_ADDR_CONFIRM,
+					(void *) (&superDiscovery_CbW));
+			pGalZb->unregisterListener(ZB_ZDO_NODE_DESC_CONFIRM,
+					(void *) (&superDiscovery_ND_CbW));
+			pGalZb->unregisterListener(ZB_ZDO_POWER_DESC_CONFIRM,
+					(void *) (&superDiscovery_PD_CbW));
+
+			// Remove timer related to superDiscovery
+			functionsContext.superDiscovery.killTimer();
+
+			///	On completion of superDiscovery, a clearGhostNodes is performed to detect ghost nodes (nodes not responding) and remove them from node dictionary and neighbor list.
+			clearGhostNodes();
+
+			// superDiscovery Completed
+			functionsContext.superDiscovery.unlock();
+
+			// RPC response Callback		
+			RPCReqStatus rpcReqStatus(functionsContext.superDiscovery,
+					AGENT_SUCCESS);
+			FCALL_RESPONSE (functionsContext.superDiscovery)(this->pGalDb,
+					functionsContext.superDiscovery.rpcContext.getSessionId(),
+					&rpcReqStatus);
+
+		}
+		pthread_mutex_unlock(&mux);
+		return;
+	}
+	// Lookup the node
+	node = pGalDb->findNodeByNwkAddr(nwk_addr);
+
+	if (node == NULL) {
+		pLogger->error("superDiscovery_PD_Cb - INTERNAL ERROR: arrived a power desc confirm for a unexistent node %04X", (int)nwk_addr);
+
+		functionsContext.superDiscovery.result = FFAILED;
+
+		if (functionsContext.superDiscovery.numExpectedMsgs == 0) {
+			pLogger->debug("superDiscovery_PD_Cb - superDiscovery-PD failed");
+
+			// Unregister listener
+			pGalZb->unregisterListener(ZB_ZDO_IEEE_ADDR_CONFIRM,
+					(void *) (&superDiscovery_CbW));
+			pGalZb->unregisterListener(ZB_ZDO_NODE_DESC_CONFIRM,
+					(void *) (&superDiscovery_ND_CbW));
+			pGalZb->unregisterListener(ZB_ZDO_POWER_DESC_CONFIRM,
+					(void *) (&superDiscovery_PD_CbW));
+
+			// Remove timer related to superDiscovery
+			functionsContext.superDiscovery.killTimer();
+			///	On completion of superDiscovery, a clearGhostNodes is performed to detect ghost nodes (nodes not responding) and remove them from node dictionary and neighbor list.
+			clearGhostNodes();
+
+			// superDiscovery completed
+			functionsContext.superDiscovery.unlock();
+
+			// RPC response Callback		
+			RPCReqStatus rpcReqStatus(functionsContext.superDiscovery,
+					AGENT_SUCCESS);
+			FCALL_RESPONSE (functionsContext.superDiscovery)(this->pGalDb,
+					functionsContext.superDiscovery.rpcContext.getSessionId(),
+					&rpcReqStatus);
+		}
+		pthread_mutex_unlock(&mux);
+		return;
+	}
+
+	// Set currentpowermode
+	switch (power_descr->curr_pw_mode) {
+	case SYNCHRONIZED_WITH_RECEIVERONWHENIDLE:
+		node->power_desc.currentpowermode =
+				SYNCHRONIZED_WITH_RECEIVERONWHENIDLE;
+		break;
+
+	case PERIODICALLYON:
+		node->power_desc.currentpowermode = PERIODICALLYON;
+		break;
+
+	case WHENSTIMULATED:
+		node->power_desc.currentpowermode = WHENSTIMULATED;
+		break;
+
+	default: {
+		pLogger->warn("superDiscovery_PD_Cb - Currentpowermode unknown %d", power_descr->curr_pw_mode);
+		node->power_desc.currentpowermode = UNKNOWN_POWERMODE;
+		break;
+	}
+	}
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("superDiscovery_PD_Cb - Currentpowermode: %d", node->power_desc.currentpowermode);
+#endif
+
+	/*
+	 // TODO They need to be fixed!
+	 //set avaiablepowersource
+	 node->->power_desc.avaiablepowersource[MAINPOWER] = (msg[5]>>4)&0x01;
+	 node->->power_desc.avaiablepowersource[RECHARGEABLE] = (msg[5]>>5)&0x01;
+	 node->->power_desc.avaiablepowersource[DISPOSABLE] = (msg[5]>>6)&0x01;
+	 //set currentpowersource
+	 node->->power_desc.currentpowersource[MAINPOWER] = msg[6]&0x01;
+	 node->->power_desc.currentpowersource[RECHARGEABLE] = (msg[6]>>1)&0x01;
+	 node->->power_desc.currentpowersource[DISPOSABLE] = (msg[6]>>2)&0x01;
+	 */
+
+	//set currentpowersourcelevel
+	switch (power_descr->curr_pw_src_level) {
+	case CRITICAL:
+		node->power_desc.currentpowersourcelevel = CRITICAL;
+		break;
+
+	case P33:
+		node->power_desc.currentpowersourcelevel = P33;
+		break;
+
+	case P66:
+		node->power_desc.currentpowersourcelevel = P66;
+		break;
+
+	case P100:
+		node->power_desc.currentpowersourcelevel = P100;
+		break;
+
+	default: {
+		pLogger->warn("superDiscovery_PD_Cb - Currentpowersourcelevel unknown %d", power_descr->curr_pw_src_level);
+		node->power_desc.currentpowersourcelevel = UNKNOWN_PSLEVEL;
+		break;
+	}
+
+	}
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("superDiscovery_PD_Cb - Currentpowersourcelevel: %d", node->power_desc.currentpowersourcelevel);
+#endif
+
+	// Set filled to true = PowerDescriptor structure has been filled out
+	node->power_desc.filled = true;
+
+	pthread_mutex_lock(&mux);
+
+	if (functionsContext.superDiscovery.numExpectedMsgs == 0) {
+		pLogger->debug("superDiscovery_PD_Cb - superDiscovery completed");
+
+		// Unregister listener
+		pGalZb->unregisterListener(ZB_ZDO_IEEE_ADDR_CONFIRM,
+				(void *) (&superDiscovery_CbW));
+		pGalZb->unregisterListener(ZB_ZDO_NODE_DESC_CONFIRM,
+				(void *) (&superDiscovery_ND_CbW));
+		pGalZb->unregisterListener(ZB_ZDO_POWER_DESC_CONFIRM,
+				(void *) (&superDiscovery_PD_CbW));
+
+		// Remove timer related to superDiscovery
+		functionsContext.superDiscovery.killTimer();
+		// Detect ghost nodes (nodes not responding) and remove them from node dictionary and neighbor list.
+		clearGhostNodes();
+
+		// superDiscovery Completed
+		functionsContext.superDiscovery.unlock();
+
+		// RPC response Callback		
+		RPCReqStatus rpcReqStatus(functionsContext.superDiscovery,
+				AGENT_SUCCESS);
+		FCALL_RESPONSE (functionsContext.superDiscovery)(this->pGalDb,
+				functionsContext.superDiscovery.rpcContext.getSessionId(),
+				&rpcReqStatus);
+	}
+	pthread_mutex_unlock(&mux);
+	return;
+}
+
+template<class T>
+void DiscoveryAgent<T>::getIEEEAddress_CbW(uchar status, uchar *ieee_addr,
+		ushort nwk_addr, uchar num_assoc_dev, uchar start_index,
+		ushort *nwk_addr_assoc_dev_list) {
+	DiscoveryAgent* dAgent = DiscoveryAgent::Instance();
+#ifdef DEBUG_ACTIVE_DA
+	if (dAgent->debugEnabled == true)
+	printf("\nDiscoveryAgent::getIEEEAddress_CbW\n");
+#endif
+	dAgent->getIEEEAddress_Cb(status, ieee_addr, nwk_addr, num_assoc_dev,
+			start_index, nwk_addr_assoc_dev_list);
+}
+
+template<class T>
+void DiscoveryAgent<T>::getIEEEAddress_Cb(uchar status, uchar *ieee_addr,
+		ushort nwk_addr, uchar num_assoc_dev, uchar start_index,
+		ushort *nwk_addr_assoc_dev_list) {
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("getIEEEAddress_Cb");
+#endif
+
+	//Get pointer to GAL database
+	this->pGalDb = pGalZb->getDb();
+	assert(this->pGalDb != NULL);
+
+	pthread_mutex_lock(&mux);
+
+	// Update number of expected messages
+	functionsContext.inquiry.numExpectedMsgs--;
+
+	if (status != ZB_ZDO_SUCCESS) {
+		pLogger->error("getIEEEAddress - ERROR returned by ZDO_IEEE_ADDR_confirm");
+
+		functionsContext.inquiry.result = FFAILED;
+
+		if (functionsContext.inquiry.numExpectedMsgs == 0) {
+			pLogger->debug("getIEEEAddress - getIEEEAddress_Cb completed");
+
+			// Unregister listener
+			pGalZb->unregisterListener(ZB_ZDO_IEEE_ADDR_CONFIRM,
+					(void *) (&getIEEEAddress_CbW));
+
+			// getIEEEAddress_Cb Completed -> Change DA_INQUIRY macro function State
+			functionsContext.inquiry.unlock();
+		}
+		pthread_mutex_unlock(&mux);
+		if (functionsContext.inquiry.rpcContext.getRPCNotifyCb() != NULL) {
+			RPCReqStatus rpcReqStatus(functionsContext.inquiry, INQUIRY_ERROR);
+
+			FCALL_NOTIFY (functionsContext.inquiry)(NULL, &rpcReqStatus);
+		}
+		return;
+	}
+
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("getIEEEAddress_Cb - ieee_addr = %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", (int)(ieee_addr[0]), (int)(ieee_addr[1]), (int)(ieee_addr[2]),
+			(int)(ieee_addr[3]), (int)(ieee_addr[4]), (int)(ieee_addr[5]), (int)(ieee_addr[6]), (int)(ieee_addr[7]) );
+#endif
+
+	if (functionsContext.inquiry.numExpectedMsgs == 0) {
+
+#ifdef DEBUG_ACTIVE_DA
+		pLogger->debug("DiscoveryAgent::getIEEEAddress_Cb - Request completed");
+#endif
+
+		// Unregister listener
+		pGalZb->unregisterListener(ZB_ZDO_IEEE_ADDR_CONFIRM,
+				(void *) (&getIEEEAddress_CbW));
+
+		// Inquiry Completed
+		functionsContext.inquiry.unlock();
+	} else {
+		pLogger->warn("DiscoveryAgent::getIEEEAddress_Cb - Error -> numExpectedMsgs != 0 -> It should be an unreachable state!");
+		functionsContext.inquiry.result = FFAILED;
+
+		// Unregister listener
+		pGalZb->unregisterListener(ZB_ZDO_IEEE_ADDR_CONFIRM,
+				(void *) (&getIEEEAddress_CbW));
+		functionsContext.inquiry.unlock();
+		pthread_mutex_unlock(&mux);
+		if (functionsContext.inquiry.rpcContext.getRPCNotifyCb() != NULL) {
+			RPCReqStatus rpcReqStatusErr(functionsContext.inquiry,
+					INQUIRY_ERROR);
+
+			FCALL_NOTIFY (functionsContext.inquiry)(NULL, &rpcReqStatusErr);
+		}
+		return;
+	}
+
+	//**** Consider this response as an announce
+	if (debugEnabled == true)
+		pLogger->debug("getIEEEAddress_Cb - call nodeAnnounce");
+	//TODO Check if we shall really announce here the node (probably this was used for the old inquiry CB (so it still needs to be here)
+	uchar capability = 0x8C; // This is a fake capability bits since we don't know any real information!
+	Node *node = pGalDb->nodeAnnounce(nwk_addr, ieee_addr, capability);
+	// RPC notify Callback
+	if (functionsContext.inquiry.rpcContext.getRPCNotifyCb() != NULL) {
+		RPCReqStatus rpcReqStatus(functionsContext.inquiry, AGENT_SUCCESS);
+		FCALL_NOTIFY (functionsContext.inquiry)(node, &rpcReqStatus);
+	}
+	if (!functionsContext.announce.isLocked()) {
+#ifdef DEBUG_ACTIVE_DA
+		pLogger->debug("getIEEEAddress_Cb - Announcement disabled!");
+#endif
+		pthread_mutex_unlock(&mux);
+		return;
+	}
+
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("getIEEEAddress_Cb - DA_ANNCE is running");
+#endif
+
+	// RPC notify Callback
+	if (functionsContext.announce.rpcContext.getRPCNotifyCb() == NULL) {
+#ifdef DEBUG_ACTIVE_DA
+		pLogger->debug("getRPCNotifyCb return null");
+#endif
+		pthread_mutex_unlock(&mux);
+		return;
+	}
+	pthread_mutex_unlock(&mux);
+	RPCReqStatus rpcReqStatusAnn(functionsContext.announce, AGENT_SUCCESS);
+	FCALL_NOTIFY (functionsContext.announce)(node, &rpcReqStatusAnn);
+}
+
+template<class T>
+int DiscoveryAgent<T>::searchNodeFromDeadingNodeList(Node * node) {
+	// If the list is empty return a negative value (the index zero could be recognized as a valid value)
+	if (deadingNodeListCounter == 0)
+		return -1;
+
+	for (int i = 0; i < this->deadingNodeListCounter; i++) {
+		if (memcmp(deadingNodeList[i].ieee_addr, node->get_ieee_addr(), 8) == 0)
+			return i;
+	}
+	//Node not found, return the total number of item!
+	return deadingNodeListCounter;
+}
+
+template<class T>
+void DiscoveryAgent<T>::removeNodeFromDeadingNodeList(int index) {
+	deadingNode *tempListNodes;
+
+	pthread_mutex_lock(&mux);
+#ifdef DEBUG_ACTIVE_DA
+	if (this->debugEnabled == true)
+	pLogger->debug("removeNodeFromDeadingNodeList - Removing node %02x%02x%02x%02x%02x%02x%02x%02x (index %02x, size %02x)",
+			deadingNodeList[index].ieee_addr[0],deadingNodeList[index].ieee_addr[1],deadingNodeList[index].ieee_addr[2],deadingNodeList[index].ieee_addr[3],
+			deadingNodeList[index].ieee_addr[4],deadingNodeList[index].ieee_addr[5],deadingNodeList[index].ieee_addr[6],deadingNodeList[index].ieee_addr[7],
+			index,deadingNodeListCounter);
+#endif
+	if (this->deadingNodeListCounter <= 1) {
+		// Initialize the list!
+		deadingNodeListCounter = 0;
+		free(deadingNodeList);
+		deadingNodeList = NULL;
+		pthread_mutex_unlock(&mux);
+		return;
+	} else {
+		deadingNodeListCounter--;
+		tempListNodes = (deadingNode *) malloc(
+				sizeof(deadingNode) * this->deadingNodeListCounter);
+		//Copy all the items and then overwrite those one starting from the 'index' position
+		for (int i = 0; i < index; i++) {
+			tempListNodes[i] = deadingNodeList[i];
+		}
+		for (int i = index; i < this->deadingNodeListCounter; i++) {
+			tempListNodes[i] = deadingNodeList[i + 1];
+		}
+		free(deadingNodeList);
+		// Take the new list!
+		deadingNodeList = tempListNodes;
+	}
+	pthread_mutex_unlock(&mux);
+}
+
+template<class T>
+void DiscoveryAgent<T>::clearDeadingNodeList() {
+
+	pthread_mutex_lock(&mux);
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("clearDeadingNodeList (length %d)",this->deadingNodeListCounter);
+#endif
+	this->deadingNodeListCounter = 0;
+	free(deadingNodeList);
+	deadingNodeList = NULL;
+	pthread_mutex_unlock(&mux);
+}
+
+template<class T>
+void DiscoveryAgent<T>::insertNodeIntoDeadingNodeList(uchar *ieee, long time) {
+	deadingNode *tempListNodes;
+
+	pthread_mutex_lock(&mux);
+	//Before to insert check if the node has been already inserted (in case, this would be an error with the algorithm...)
+	for (int i = 0;
+			(i < this->deadingNodeListCounter) && (deadingNodeList != NULL);
+			i++) {
+		if (memcmp(deadingNodeList[i].ieee_addr, ieee, 8) == 0) {
+#ifdef DEBUG_ACTIVE_DA
+			pLogger->warn("insertNodeIntoDeadingNodeList - WARNING: Node already present in deadingNodeList");
+#endif
+			pthread_mutex_unlock(&mux);
+			return;
+		}
+	}
+	// update the counter
+	deadingNodeListCounter++;
+	// Create a new space for deadingNodeList
+	tempListNodes = (deadingNode *) malloc(
+			sizeof(deadingNode) * (this->deadingNodeListCounter));
+	// Create new node and insert in the last position
+	memcpy(tempListNodes[this->deadingNodeListCounter - 1].ieee_addr, ieee, 8);
+	tempListNodes[this->deadingNodeListCounter - 1].expiredTime = time;
+	//Update the other items
+	if (deadingNodeList == NULL) {
+		// This means also that deadingNodeListCounter was 0, so nothing else to do!
+		deadingNodeList = tempListNodes;
+	} else {
+		//Copy all the previous items
+		for (int i = 0; i < deadingNodeListCounter - 1; i++) {
+			tempListNodes[i] = deadingNodeList[i];
+		}
+		//Free the previous allocate memory
+		free(deadingNodeList);
+		// Set and use the new one
+		deadingNodeList = tempListNodes;
+	}
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("insertNodeIntoDeadingNodeList - List updated (counter: %02x)", deadingNodeListCounter);
+	for (int i = 0; (i < this ->deadingNodeListCounter) && (deadingNodeList!= NULL); i++) {
+		pLogger->debug("Pos %d - IEEE: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", i,deadingNodeList[i].ieee_addr[0],deadingNodeList[i].ieee_addr[1],
+				deadingNodeList[i].ieee_addr[2],deadingNodeList[i].ieee_addr[3],deadingNodeList[i].ieee_addr[4],deadingNodeList[i].ieee_addr[5],deadingNodeList[i].ieee_addr[6],deadingNodeList[i].ieee_addr[7]);
+	}
+#endif
+	pthread_mutex_unlock(&mux);
+}
+
+template<class T>
+void DiscoveryAgent<T>::setKAthreshold(int threshold) {
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("setKAthreshold - Storing the KeepAliveThreshold value: %x (sec)",threshold);
+#endif
+	if (threshold >= 0) {
+		this->KAthreshold = threshold;
+	}
+}
+
+//This function is responsible to announce the dead node to the upper layer (and update the database)
+template<class T>
+void DiscoveryAgent<T>::announceDeadNode(Node * node) {
+	// Maximum timer expired, notify this to the RPC layer (RESTBroker) if a callback is registered
+	//TODO: This is a well known problem: forcePingAlgorithm could set to false the "isActive" boolean, so the node can be deleted without a proper announcement!
+	//if ( (node->getIsActive() == true) && (functionsContext.freshness.rpcContext.getRPCNotifyCb() != NULL)) {
+	if (functionsContext.freshness.rpcContext.getRPCNotifyCb() != NULL) {
+#ifdef DEBUG_ACTIVE_DA
+		if (this->debugEnabled == true)
+		pLogger->debug("announceDeadNode: send notification!");
+#endif
+		RPCReqStatus rpcReqStatus(functionsContext.freshness, AGENT_SUCCESS);
+		// Return the currentNode that is dead (removeTranslationEntry and removeNodeByNwkAddr are called inside this callback!)
+		FCALL_NOTIFY (functionsContext.freshness)(node, &rpcReqStatus);
+	} else {
+#ifdef DEBUG_ACTIVE_DA
+		if (this->debugEnabled == true)
+		pLogger->debug("Node never activated, deleting without notify!");
+#endif
+	}
+}
+
+template<class T>
+void DiscoveryAgent<T>::forcePingAlgorithm(Node *currentNode) {
+	struct timeval tv;
+	time_t curTimeSec;
+
+	pthread_mutex_lock(&mux);
+	if (currentNode == NULL || this->forceLQIPingTimer == 0) {
+		//No node registered yet (or feature disabled), nothing to do!
+		pthread_mutex_unlock(&mux);
+		return;
+	}
+	gettimeofday(&tv, NULL);
+	curTimeSec = tv.tv_sec; //get the seconds
+	// If it has never been initialized let's do it now!
+	if (currentNode->getForcePingTimer() == 0x00000000) {
+		currentNode->setForcePingTimer(curTimeSec);
+		pthread_mutex_unlock(&mux);
+		return;
+	}
+	if ((currentNode->getIsActive() == true)
+			&& (currentNode->getForcePingTimer() + this->forceLQIPingTimer
+					<= curTimeSec)) {
+		if (currentNode->node_desc.receiveronwhenidle == false) {
+			//Case of a sleepy end device!
+			if (debugEnabled == true)
+				pLogger->debug("forcePingAlgorithm - Node 0x%04x is sleepyEndDevice (skipped)",currentNode->get_nwk_addr());
+			//Update the timer
+			currentNode->setForcePingTimer(curTimeSec);
+			pthread_mutex_unlock(&mux);
+			return;
+		}
+#ifdef DEBUG_ACTIVE_DA
+		if (this->debugEnabled == true)
+		pLogger->debug("forcePingAlgorithm - Node 0x%04x needs to be ping (forced ping)!", currentNode->get_nwk_addr());
+#endif
+		//TODO: If the node is already in the "discovery" phase (i.e. it is in "insertNodeIntoDeadingNodeList" list, then skip this test!)
+		// Force this node to be re-announced!
+		currentNode->setIsActive(false);
+		// Delete also the LQITable ionformation since it will get the new ones!
+		currentNode->removeOldLQIInformation(NULL, 0); //"0" will cause a reset for this table!
+		//Send a ping
+		//pGalZb->registerListener(ZB_MGMT_LQI_RESPONSE, (void *) (&Mgmt_LQI_CbW));
+		pGalZb->ZB_MGMT_LQI_request(currentNode->get_nwk_addr(), 0);
+		//functionsContext.MgmtLQI.numExpectedMsgs++;
+		usleep(PACETIME);
+		//Update the timer
+		currentNode->setForcePingTimer(curTimeSec);
+	}
+	pthread_mutex_unlock(&mux);
+}
+
+/**
+ Public method DiscoveryAgent keepAliveAlgorithm
+ This function is called periodically by startKATask_SW and checks the status of the currentNode.
+ If currentNode == NULL, then do nothing
+ Otherwise, manage the currentNode status
+
+ @param Node *currentNode
+ */
+template<class T>
+void DiscoveryAgent<T>::keepAliveAlgorithm(Node *currentNode) {
+	int i = 0;
+	struct timeval tv;
+	time_t curTimeSec;
+
+	pthread_mutex_lock(&mux);
+	pGalDb = pGalZb->getDb();
+	assert(pGalDb != NULL);
+	if (currentNode == NULL) {
+		//No node registered yet, nothing to do!
+		pthread_mutex_unlock(&mux);
+		return;
+	}
+	if (currentNode->getKANodeTimer() == (long) 0xFFFFFFFC) {
+		//GalZbIf set this value to indicate a MGMT_LEAVE_confirm, so announce that this node left and quit here!
+		announceDeadNode(currentNode);
+		pthread_mutex_unlock(&mux);
+		return;
+	}
+	if (currentNode->node_desc.receiveronwhenidle == false
+			&& currentNode->getIsActive() == true
+			&& currentNode->get_nwk_addr() != 0x0000) {
+		//Case of a sleepy end device already announced- nothing to do!!
+#ifdef DEBUG_ACTIVE_DA
+		if (this->debugEnabled == true)
+		printf("keepAliveAlgorithm - Node 0x%04x SLEEPY_DEVICE\n",currentNode->get_nwk_addr() );
+#endif
+		// In case the node was in the deadingNodeList, remove it...
+		i = searchNodeFromDeadingNodeList(currentNode);
+		if ((i == 0 && this->deadingNodeListCounter != 0)
+				|| (i >= 1 && i < this->deadingNodeListCounter)) {
+			// This node was inserte when it wasn't yet active!
+			removeNodeFromDeadingNodeList(i);
+		}
+		pthread_mutex_unlock(&mux);
+		return;
+	}
+	// Check if this node was present in one of the previous MGMT_LQI_Rsp (= in another neighbor's table)
+	if ((currentNode->getIsActive() == false)
+			&& (currentNode->getKANodeTimer() != 0x00000000)) {
+		// It never has been polled and it is not already in the deadList!
+#ifdef DEBUG_ACTIVE_DA
+		if (debugEnabled == true)
+		pLogger->debug("keepAliveAlgorithm - Set 0x%04x node in \"pinging\" mode", currentNode->get_nwk_addr());
+#endif
+		// Set the timer to a value that it will be polled for sure
+		currentNode->setKANodeTimer(this->KAthreshold - 1);
+	}
+	switch (currentNode->getKANodeTimer()) {
+	case (long) 0xFFFFFFFF:
+		//Node created but not set yet to any value
+		gettimeofday(&tv, NULL);
+		curTimeSec = tv.tv_sec; //get the seconds
+		currentNode->setKANodeTimer((long) curTimeSec);
+#ifdef DEBUG_ACTIVE_DA
+		pLogger->debug("keepAliveAlgorithm - Found node 0x%04x without timestamp, send a ping", currentNode->get_nwk_addr());
+#endif
+		///	Register a DiscoveryAgent listener on event ZB_MGMT_LQI_response in GalZbIf.
+		pGalZb->ZB_MGMT_LQI_request(currentNode->get_nwk_addr(), 0); //0=startIndex
+		usleep(PACETIME);
+		break;
+	case (long) 0x00000000:
+		// This node is in the deadingNodeList!
+#ifdef DEBUG_ACTIVE_DA
+		pLogger->debug("keepAliveAlgorithm - Node 0x%04x is in deadList (NumOfNodes: %d)",currentNode->get_nwk_addr(),this ->deadingNodeListCounter);
+#endif
+		i = searchNodeFromDeadingNodeList(currentNode);
+		if (!((i == 0 && this->deadingNodeListCounter != 0)
+				|| (i >= 1 && i < this->deadingNodeListCounter))) {
+			//If not found, enter here: but this is not possible, the node was supposed to be here!
+#ifdef DEBUG_ACTIVE_DA
+			pLogger->warn("keepAliveAlgorithm - Node 0x%04x not found in deadingNodeList, refreshing its values!",currentNode->get_nwk_addr());
+#endif
+			currentNode->setKANodeTimer(this->KAthreshold - 2); //This will force the node to enter in the pinging mode again!
+			pthread_mutex_unlock(&mux);
+			return;
+		}
+		// Node found and present on position i of the DeadingNodeList...
+		gettimeofday(&tv, NULL);
+		curTimeSec = tv.tv_sec; //get the seconds
+		// Verify if we have to send a "ping" again or if it is time to report its death!
+		if (currentNode->getnumOfPingsDone() >= this->KAnumOfPings) {
+			printf("++++++\nNODE 0x%04x IS NOT REACHABLE ANYMORE!\n++++++\n",
+					currentNode->get_nwk_addr());
+			//NB: This function announce to the upper layer that the node is DEAD!
+			announceDeadNode(currentNode);
+			// Remove the item from the list and free the memory allocated!
+			removeNodeFromDeadingNodeList(i);
+		} else {
+			// We keep the node in the DeadingNodeList and we send to it another ping!
+			// Update the number of retries!
+			currentNode->setnumOfPingsDone(
+					currentNode->getnumOfPingsDone() + 1);
+			if (debugEnabled == true)
+				pLogger->debug("keepAliveAlgorithm - SENDING a ping to 0x%04x (%0x times)",currentNode->get_nwk_addr(),currentNode->getnumOfPingsDone());
+			///	Register a DiscoveryAgent listener on event ZB_MGMT_LQI_response in GalZbIf.
+			//pGalZb->registerListener(ZB_MGMT_LQI_RESPONSE, (void *) (&Mgmt_LQI_CbW));
+			pGalZb->ZB_MGMT_LQI_request(currentNode->get_nwk_addr(), 0); //0=startIndex
+			usleep(PACETIME);
+		}
+		break;
+	default:
+		// Standard case: the node has a "normal" timeout, so it just need to be verified!
+		gettimeofday(&tv, NULL);
+		curTimeSec = tv.tv_sec; //get the seconds
+		// Verify if it is time to start polling!
+		if ((curTimeSec - currentNode->getKANodeTimer()) > this->KAthreshold) {
+			// The node shall be inserted in the deadingNodeList but delete it immediately if it has never replied to a ping since the beginning!
+			if ((currentNode->getIsActive() == false)
+					&& (currentNode->getKANodeTimer() != this->KAthreshold - 1)) {
+#ifdef DEBUG_ACTIVE_DA
+				pLogger->debug("keepAliveAlgorithm - Node 0x%04x never activated, delete it and remove listener (without announcing anything)!",currentNode->get_nwk_addr());
+#endif
+				pGalDb->removeTranslationEntry(currentNode->get_nwk_addr());
+				pGalDb->removeNodeByNwkAddr(currentNode->get_nwk_addr());
+				pthread_mutex_unlock(&mux);
+				return;
+			}
+			uchar tmpIEEE[8];
+			memcpy(tmpIEEE, currentNode->get_ieee_addr(), 8);
+#ifdef DEBUG_ACTIVE_DA
+			pLogger->debug("keepAliveAlgorithm - Inserting node 0x%04x (%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x) in DeadingNodeList (new size will be: %x)!",currentNode->get_nwk_addr(),
+					tmpIEEE[0],tmpIEEE[1],tmpIEEE[2],tmpIEEE[3],tmpIEEE[4],tmpIEEE[5],tmpIEEE[6],tmpIEEE[7],deadingNodeListCounter + 1);
+#endif
+			// This node has not sent message for a while, include it in the deadList and sent immediately a ping!
+			insertNodeIntoDeadingNodeList(currentNode->get_ieee_addr(),
+					curTimeSec);
+			// Reset the timer for this node (its original timer is not useful anymore)
+			currentNode->setKANodeTimer(0x00000000);
+			// Send immediately a ping to check if it is alive
+#ifdef DEBUG_ACTIVE_DA
+			if (this->debugEnabled == true)
+			pLogger->debug("keepAliveAlgorithm - Sending first ping to 0x%04x",currentNode->get_nwk_addr());
+#endif
+			currentNode->setnumOfPingsDone(1);
+			///	Register a DiscoveryAgent listener on event ZB_MGMT_LQI_response in GalZbIf.
+			//pGalZb->registerListener(ZB_MGMT_LQI_RESPONSE, (void *) (&Mgmt_LQI_CbW));
+			pGalZb->ZB_MGMT_LQI_request(currentNode->get_nwk_addr(), 0); //0=startIndex
+			//functionsContext.MgmtLQI.numExpectedMsgs++;
+			usleep(PACETIME);
+			pthread_mutex_unlock(&mux);
+			return;
+		}
+		// We arrive here if the node node is fine and there is no need to take any action
+		// Just verify if it is in  deadingNodeList (and in case remove it!)
+		if (currentNode->getIsActive() == true) { // Do not print information about non existing nodes...
+#ifdef DEBUG_ACTIVE_DA
+			if (this->debugEnabled == true)
+			printf("keepAliveAlgorithm - Node 0x%04x OK (%d sec)\n",
+					currentNode->get_nwk_addr(), (int) (curTimeSec - currentNode->getKANodeTimer() ) );
+#endif
+			// This is case when a node previously answered to a "ping" command
+			i = searchNodeFromDeadingNodeList(currentNode);
+			if ((i == 0 && this->deadingNodeListCounter != 0)
+					|| (i >= 1 && i < this->deadingNodeListCounter)) {
+				//Node found, then remove it from the deadingNodeList!
+				removeNodeFromDeadingNodeList(i);
+			}
+		}
+		break;
+	}
+	pthread_mutex_unlock(&mux);
+}
+
+/**
+ Protected method DiscoveryAgent initTimers
+ Timers initialization.
+
+ @param void Void.
+ @return Status.
+ */
+template<class T>
+int DiscoveryAgent<T>::initTimers(void) {
+	ThreadPoolAttr attr;
+
+	TPAttrInit(&attr);
+	TPAttrSetMaxThreads(&attr, DA_MAX_THREADS);
+	TPAttrSetMinThreads(&attr, DA_MIN_THREADS);
+	TPAttrSetJobsPerThread(&attr, DA_JOBS_PER_THREAD);
+	TPAttrSetIdleTime(&attr, DA_THREAD_IDLE_TIME);
+
+#ifdef NEW_VERSION
+	TPAttrSetMaxJobsTotal(&attr, DA_MAX_JOBS_TOTAL);
+#endif
+
+	if (ThreadPoolInit(&threadPool, &attr) != 0) {
+		return -1;
+	}
+	TimerThreadInit(&timerThread, &threadPool);
+	return 0;
+}
+
+template<class T>
+void DiscoveryAgent<T>::onGetNodeDescriptor() {
+	pthread_mutex_lock(&mux);
+
+	pLogger->debug("onGetNodeDescriptor - timer canceled (Failed)");
+	/// Set result
+	functionsContext.getNodeDescriptor.result = FFAILED;
+	/// Unregister listener
+	pGalZb->unregisterListener(ZB_ZDO_NODE_DESC_CONFIRM,
+			(void *) (&getNodeDescriptor_CbW));
+	RPCReqStatus rpcReqStatus(functionsContext.getNodeDescriptor,
+			TIMER_EXPIRED);
+	if (functionsContext.getNodeDescriptor.rpcContext.getRPCNotifyCb()
+			!= NULL) {
+		FCALL_NOTIFY (functionsContext.getNodeDescriptor)(NULL, &rpcReqStatus);
+	} else {
+		// RPC response Callback
+		FCALL_RESPONSE (functionsContext.getNodeDescriptor)(0, NULL, NULL,
+				functionsContext.getNodeDescriptor.rpcContext.getSessionId(),
+				&rpcReqStatus);
+	}
+	/// getNodedescriptor canceled
+	functionsContext.getNodeDescriptor.unlock(Canceled);
+	pthread_mutex_unlock(&mux);
+}
+
+template<class T>
+void DiscoveryAgent<T>::onGetPowerDescriptor() {
+	pthread_mutex_lock(&mux);
+
+	pLogger->debug("onTimer - getPowerDescriptor canceled (Failed)");
+
+	///	Set result
+	functionsContext.getPowerDescriptor.result = FFAILED;
+
+	///	Unregister listener
+	pGalZb->unregisterListener(ZB_ZDO_POWER_DESC_CONFIRM,
+			(void *) (&getPowerDescriptor_CbW));
+
+	///	getPowerdescriptor Canceled
+	functionsContext.getPowerDescriptor.unlock(Canceled);
+	pthread_mutex_unlock(&mux);
+	RPCReqStatus rpcReqStatus(functionsContext.getPowerDescriptor,
+			TIMER_EXPIRED);
+	FCALL_RESPONSE (functionsContext.getPowerDescriptor)(0, NULL, NULL,
+			functionsContext.getPowerDescriptor.rpcContext.getSessionId(),
+			&rpcReqStatus);
+}
+
+template<class T>
+void DiscoveryAgent<T>::onSuperDiscovery() {
+	pthread_mutex_lock(&mux);
+
+	pLogger->debug("onTimer - superDiscovery canceled (Failed)");
+
+	///	Set result
+	functionsContext.superDiscovery.result = FFAILED;
+
+	///	Unregister listener
+	pGalZb->unregisterListener(ZB_ZDO_IEEE_ADDR_CONFIRM,
+			(void *) (&superDiscovery_CbW));
+	pGalZb->unregisterListener(ZB_ZDO_NODE_DESC_CONFIRM,
+			(void *) (&superDiscovery_ND_CbW));
+	pGalZb->unregisterListener(ZB_ZDO_POWER_DESC_CONFIRM,
+			(void *) (&superDiscovery_PD_CbW));
+
+	///	Detect ghost nodes (nodes not responding) and remove them from node dictionary and neighbor list.
+	clearGhostNodes();
+
+	///	superDiscovery Canceled
+	functionsContext.superDiscovery.unlock(Canceled);
+	pthread_mutex_unlock(&mux);
+	RPCReqStatus rpcReqStatus(functionsContext.superDiscovery, AGENT_SUCCESS);
+	FCALL_RESPONSE (functionsContext.superDiscovery)(this->pGalDb,
+			functionsContext.superDiscovery.rpcContext.getSessionId(),
+			&rpcReqStatus);
+}
+
+template<class T>
+void DiscoveryAgent<T>::onInquiry() {
+	pthread_mutex_lock(&mux);
+
+	pLogger->debug("onInquiry - Inquiry canceled (timeout expired)");
+
+	functionsContext.inquiry.resetTimerEnv();
+
+	/// Set result
+	functionsContext.inquiry.result = FFAILED;
+
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("onInquiry - Discovery using LQI interrupted!");
+#endif
+
+	// Unregister listener
+	pGalZb->unregisterListener(ZB_ZDO_IEEE_ADDR_CONFIRM,
+			(void *) (&Inquiry_CbW));
+	//A clearGhostNodes is performed to detect ghost nodes (nodes not responding) and remove them from node dictionary and neighbor list.
+	clearGhostNodes();
+	// Inquiry Completed
+	functionsContext.inquiry.unlock(Canceled);
+	pthread_mutex_unlock(&mux);
+	// RPC notify Callback
+	if (functionsContext.inquiry.rpcContext.getRPCNotifyCb() != NULL) {
+		RPCReqStatus rpcReqStatus(functionsContext.inquiry, TIMER_EXPIRED);
+		FCALL_NOTIFY (functionsContext.inquiry)(NULL, &rpcReqStatus);
+	} else {
+		pLogger->warn("onInquiry - functionsContext.inquiry.rpcContext.getRPCNotifyCb() == NULL");
+	}
+}
+
+template<class T>
+void DiscoveryAgent<T>::onMgmtLQIRequest() {
+	pthread_mutex_lock(&mux);
+
+	pLogger->debug("onMgmtLQIRequest - MgmtLQI canceled (timeout expired)");
+
+	functionsContext.MgmtLQI.resetTimerEnv();
+
+	/// Set result
+	functionsContext.MgmtLQI.result = FFAILED;
+
+#ifdef DEBUG_ACTIVE_DA
+	pLogger->debug("onMgmtLQIRequest - Discovery using LQI interrupted!");
+#endif
+
+	// Unregister listener
+	//pGalZb->unregisterListener(ZB_MGMT_LQI_RESPONSE, (void *) (&Mgmt_LQI_CbW));
+	// Detect ghost nodes (nodes not responding) and remove them from node dictionary and neighbor list.
+	clearGhostNodes();
+	// Inquiry Completed
+	functionsContext.MgmtLQI.unlock(Canceled);
+	pthread_mutex_unlock(&mux);
+	// RPC notify Callback
+	if (functionsContext.MgmtLQI.rpcContext.getRPCNotifyCb() != NULL) {
+		RPCReqStatus rpcReqStatus(functionsContext.MgmtLQI, TIMER_EXPIRED);
+		FCALL_NOTIFY (functionsContext.MgmtLQI)(NULL, &rpcReqStatus);
+	} else {
+		pLogger->warn("onMgmtLQIRequest - functionsContext.MgmtLQI.rpcContext.getRPCNotifyCb() == NULL");
+	}
+}
+
+template<class T>
+DiscoveryAgent<T>::Task::Task(void) {
+	taskStarted = false;
+}
+
+template<class T>
+int DiscoveryAgent<T>::Task::start(void *(*invokedMethod)(void *)) {
+	DiscoveryAgent* pDAgent;
+	Debug *pLogger;
+	int returnValue = 0;
+	pDAgent = DiscoveryAgent<T>::Instance();
+	pLogger = pDAgent->pLogger;
+
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("Task::start");
+#endif
+	if (taskStarted) {
+		pLogger->error("Task::start - Thread already started (unreachable state)!");
+		return -1;
+	}
+	returnValue = pthread_create(&tid, NULL, invokedMethod, NULL);
+	if (returnValue) {
+		pLogger->error("Task::start - Error in creating thread");
+	}
+	taskStarted = true;
+	return returnValue;
+}
+
+template<class T>
+void DiscoveryAgent<T>::Task::stop(void) {
+	if (taskStarted) {
+		taskStarted = false;
+		pthread_join(tid, NULL);
+
+		DiscoveryAgent* pDAgent;
+		pDAgent = DiscoveryAgent<T>::Instance();
+		pDAgent->functionsContext.freshness.unlock(Canceled);
+	}
+}
+
+//keepAliveTask Static Wrapper
+template<class T>
+void* DiscoveryAgent<T>::startKATask_SW(void *arg) {
+	Node * currentNode = NULL;
+	//Node * nextNode = NULL;
+
+	ushort shortAddr;
+	DiscoveryAgent* pDAgent = DiscoveryAgent<T>::Instance();
+	GalZbIf *pGalZb = GalZbIf::Instance();
+	ZbNetDb *pGalDb = pGalZb->getDb();
+	assert(pGalDb != NULL);
+
+	while (pGalDb->getDBNodesSize() == 0) {
+		sleep(DA_KA_GAL_NOT_INITIALIZED_TIME); //Wait a couple of seconds, then try again!
+	}
+	// Register to any incoming MGMT_LQI_Req
+	pGalZb->registerListener(ZB_MGMT_LQI_RESPONSE, (void *) (&Mgmt_LQI_CbW));
+	// Wait 10 seconds and then start forever the algorithm
+	sleep(DA_KA_INITIAL_WAITING_TIME);
+	// Get the first node from the DB (the GAL)
+	currentNode = pGalDb->root;
+	if (currentNode == NULL) {
+		printf(
+				"startKATask_SW - ERROR: At least one node shall be present to the dictionary!\n");
+		exit(0);
+	}
+	currentNode->setKANodeTimer(0xFFFFFFFF); //This will force to do immediately a ping to find out info about this node
+	printf(
+			"\n************\nkeepAliveAlgorithm AND forcePingAlgorithm start now!\n************\n");
+	/*
+	 while (true) {
+	 //Every DA_KA_INTERVAL_SCANNING_TIME seconds checks for one entry in the DB (if GAL is running and if the feature is not disabled!)
+	 if ( (pGalZb->getGWStatus() == GW_RUNNING) && (pDAgent->KAthreshold > 0) ){
+	 //Get the next node before to call the keepAliveAlgorithm
+	 nextNode = pGalDb->getNextNode(currentNode);
+	 if (nextNode == NULL)
+	 {
+	 // We reached the end, start again with the first node!
+	 nextNode = pGalDb->getFirstNode();	//At least one shall always exists (the GAL's node)
+	 if (nextNode == NULL){
+	 printf("startKATask_SW - Error: node_dict cannot be null! Set root node as default...\n");
+	 nextNode = pGalDb->root;	//Forcing a node to be not null...
+	 }
+	 }
+	 // get the shortAddress of the current node that we're analyzing
+	 shortAddr = currentNode -> get_nwk_addr();
+	 // Manage the status of the current node
+	 pDAgent -> keepAliveAlgorithm(currentNode);
+	 //Check if the previous feature hasn't removed the currentNode...
+	 if (pGalDb->findNodeByNwkAddr(shortAddr) != NULL){
+	 // Check if it time to run a forced ping!
+	 pDAgent -> forcePingAlgorithm(currentNode);
+	 }
+	 // There is at least another node with the GAL, so take the next node avoiding GAL
+	 currentNode = nextNode;			//End of the list, move back to the first item
+	 } else if (pGalZb->getGWStatus() != GW_RUNNING){
+	 // Since we're waiting that the GAL starts again, just set as currentNode the root (the only one available)!
+	 currentNode = pGalDb->root;
+	 }
+	 // Decide here the frequency of the execution of this thread
+	 sleep(DA_KA_INTERVAL_SCANNING_TIME);
+	 }
+	 */
+	while (true) {
+		//Every DA_KA_INTERVAL_SCANNING_TIME seconds checks for one entry in the DB (if GAL is running and if the feature is not disabled!)
+		if ((pGalZb->getGWStatus() == GW_RUNNING)
+				&& (pDAgent->KAthreshold > 0)) {
+			// get the shortAddress of the current node
+			shortAddr = currentNode->get_nwk_addr();
+			// Run the KeepAlive algorithm
+			pDAgent->keepAliveAlgorithm(currentNode);
+			// Check if node is still present in the DB (KeepAlive could have delete it)
+			if (pGalDb->findNodeByNwkAddr(shortAddr) != NULL) {
+				// Run the ForcePing algorithm
+				pDAgent->forcePingAlgorithm(currentNode);
+			}
+			// Sleep!
+			sleep(DA_KA_INTERVAL_SCANNING_TIME);
+			// Get the next node!
+			if (pGalDb->findNodeByNwkAddr(shortAddr) != NULL) {
+				// Node still there, so it could have a next
+				currentNode = pGalDb->getNextNode(currentNode);
+			} else {
+				// Node not existing anymore, set it to NULL!
+				currentNode = NULL;
+			}
+			if (currentNode == NULL) {
+				// Node not present anymore in DB (or reached the end of the list), start from the beginning
+				currentNode = pGalDb->getFirstNode();
+				if (currentNode == NULL) {
+					//Forcing currentNode to be not NULL (however we should never enter here)
+					currentNode = pGalDb->root;
+				}
+			}
+		} else if (pGalZb->getGWStatus() != GW_RUNNING) {
+			// Since we're waiting that the GAL starts again, just set as currentNode the root (the only one available)!
+			currentNode = pGalDb->root;
+		}
+	}
+	return NULL;
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDiscoveryAgent.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDiscoveryAgent.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDiscoveryAgent.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,446 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef DISCOVERYAGENT_H
+#define DISCOVERYAGENT_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "ThreadPool.h"
+#include "TimerThread.h"
+
+#include "GalZbIf.h"
+#include "ZbNetDb.h"
+#include "CDebug.h"
+
+#include "Agents.h"
+
+#include "ConfigurationRepository.h"
+
+/**
+ Discovery Agent is organized in macrofunctions, i.e. Inquiry, getNodeDescriptor, getPowerDescriptor 
+ Each macrofunction is identified by a unique ID (please refer to the following ID list).
+ This unique ID is used as a key in associative arrays containing macrofunction context (e.g. the status
+ of the macrofunction, number of expected messages, ...) or the RPC listeners registered on the specific function.
+ */
+#define DA_INQUIRY						1
+#define DA_GET_NODE_DESCRIPTOR			2
+#define DA_GET_POWER_DESCRIPTOR			3
+#define DA_SUPER_DISCOVERY				4
+#define DA_ANNCE   						5
+
+/**
+ Allmost all macrofunctions ( GetNodeDescriptor, GetPowerDescriptor and SuperDiscovery ) use a timeout: once it has expired, the related function
+ is terminated with a failure result (i.e. function not properly ended).
+ Different values are used depending on ZigBee platform (Integration, TI-Chipcon,... ) used.
+ */
+///	Integration Associates (IA)
+//#define DA_GET_NODE_DESCRIPTOR_TIMEOUT_IA		15
+//#define DA_GET_POWER_DESCRIPTOR_TIMEOUT_IA		15
+//#define DA_SUPER_DISCOVERY_TIMEOUT_IA			50
+#define DA_GET_NODE_DESCRIPTOR_TIMEOUT_IA		6
+#define DA_GET_POWER_DESCRIPTOR_TIMEOUT_IA		6
+//#define DA_SUPER_DISCOVERY_TIMEOUT_IA			30
+#define DA_SUPER_DISCOVERY_TIMEOUT_IA			10
+
+///	Texas Instruments - Chipcon (TICC)
+#define DA_GET_NODE_DESCRIPTOR_TIMEOUT_TICC		6
+#define DA_GET_POWER_DESCRIPTOR_TIMEOUT_TICC		6
+#define DA_SUPER_DISCOVERY_TIMEOUT_TICC			30
+
+/**
+ Set of constants used in thread management.
+ */
+#define DA_MAX_THREADS					10
+#define DA_MIN_THREADS					10	
+#define DA_JOBS_PER_THREAD				10
+#define DA_THREAD_IDLE_TIME 				5000
+#define DA_MAX_JOBS_TOTAL 				10
+
+// Constants used in the KeepAlive Algorithm thread (startKATask_SW)
+#define DA_KA_GAL_NOT_INITIALIZED_TIME	2
+#define DA_KA_INITIAL_WAITING_TIME		10
+#define DA_KA_INTERVAL_SCANNING_TIME	3
+
+template<class T>
+class DiscoveryAgent {
+
+public:
+
+	//	function pointers types related to RPC callbacks (Macrofunction Inquiry)
+	typedef void *(T::*inquiryResponseCb)(int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void *(T::*inquiryNotifyCb)( //related to wnsnodesList_NtfCbW
+			Node *node, RPCReqStatus *rpcReqStatus);
+
+	typedef void *(T::*cancelInquiryResponseCb)(int sessionId,
+			RPCReqStatus *rpcReqStatus);
+	/*
+	 typedef	void *(T::*cancelMgmtLQI_Req) (
+	 int sessionId,
+	 RPCReqStatus *rpcContextData);
+	 */
+	typedef void *(T::*MgmtLQIResponseCb)(int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void *(T::*MgmtLQINotifyCb)(Node *node, RPCReqStatus *rpcReqStatus);
+
+	typedef void *(T::*cancelMgmtLQIResponseCb)(int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void *(T::*retrieveNodesResponseCb)(ZbNetDb* buffer, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void *(T::*getIEEEAddressResponseCb)(int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void *(T::*getIEEEAddressNotifyCb)(Node *node,
+			RPCReqStatus *rpcReqStatus);
+	/*
+	 typedef	void *(T::*cancelGetIEEEAddressResponseCb) (
+	 int sessionId,
+	 RPCReqStatus *rpcReqStatus
+	 );
+	 */
+	typedef void *(T::*startAnnouncementsModeResponseCb)(int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void *(T::*cancelAnnouncementsModeResponseCb)(int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void *(T::*announceNotifyCb)( //related to wnsnodeAnnce_NtfCbW
+			Node *node, RPCReqStatus *rpcReqStatus);
+
+	typedef void *(T::*startFreshnessModeResponseCb)(int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void *(T::*cancelFreshnessModeResponseCb)(int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void *(T::*freshnessNotifyCb)( //related to wnsnodeAnnce_NtfCbW
+			Node *node, RPCReqStatus *rpcReqStatus);
+
+	//	function pointers types related to RPC callbacks (Macrofunction getNodeDescriptor)
+	typedef void *(T::*nodeDescriptorResponseCb)(ushort nwk_addr,
+			uchar *ieee_addr, NodeDescriptor *nodeDesc, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void *(T::*nodeDescriptorNotifyCb)(Node *node,
+			RPCReqStatus *rpcReqStatus);
+
+	//	function pointers types related to RPC callbacks (Macrofunction getPowerDescriptor)
+	typedef void * (T::*powerDescriptorResponseCb)(ushort nwk_addr,
+			uchar *ieee_addr, PowerDescriptor *power_descr, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	//	function pointers types related to RPC callbacks (Macrofunction superDiscovery)
+	typedef void * (T::*superDiscoveryResponseCb)(ZbNetDb *dbNodes,
+			int sessionId, RPCReqStatus *rpcReqStatus);
+
+	typedef RPCContext<T, retrieveNodesResponseCb> RetrieveNodesCtxt;
+
+	typedef RPCContext<T, getIEEEAddressResponseCb, getIEEEAddressNotifyCb> GetIEEEAddressCtxt;
+	/*
+	 typedef RPCContext<T, cancelGetIEEEAddressResponseCb> 
+	 CancelGetIEEEAddressCtxt;
+	 */
+	typedef RPCContext<T, startAnnouncementsModeResponseCb, announceNotifyCb> StartAnnouncementsModeCtxt;
+
+	typedef RPCContext<T, cancelAnnouncementsModeResponseCb> CancelAnnouncementsModeCtxt;
+
+	typedef RPCContext<T, startAnnouncementsModeResponseCb, announceNotifyCb> StartFreshnessModeCtxt;
+	typedef RPCContext<T, cancelFreshnessModeResponseCb> CancelFreshnessModeCtxt;
+
+	typedef RPCContext<T, inquiryResponseCb, inquiryNotifyCb> InquiryCtxt;
+
+	typedef RPCContext<T, cancelInquiryResponseCb> CancelInquiryCtxt;
+
+	typedef RPCContext<T, MgmtLQIResponseCb, MgmtLQINotifyCb> MgmtLQICtxt;
+
+	typedef RPCContext<T, cancelMgmtLQIResponseCb> CancelMgmtLQICtxt;
+
+	typedef RPCContext<T, nodeDescriptorResponseCb, nodeDescriptorNotifyCb> NodeDescriptorCtxt;
+
+	typedef RPCContext<T, powerDescriptorResponseCb> PowerDescriptorCtxt;
+
+	typedef RPCContext<T, superDiscoveryResponseCb> SuperDiscoveryCtxt;
+
+	typedef struct {
+		uchar ieee_addr[8];
+		long expiredTime;
+	} deadingNode;
+
+	///	Macrofunction getNodeDescriptor -- protected method: getNodeDescriptor_Cb 
+	void getNodeDescriptor_Cb(uchar status, ushort nwk_addr,
+			ZB_NODE_DESC *node_descr);
+
+	///	Macrofunction getPowerDescriptor -- protected method: getPowerDescriptor_Cb 
+	void getPowerDescriptor_Cb(uchar status, ushort nwk_addr,
+			ZB_POWER_DESC *power_descr);
+
+public:
+	// Constructors
+
+	// Destructor
+	~DiscoveryAgent();
+
+	// Functions: modifiers (set), selectors (get)
+
+	// Pattern Singleton
+//	static DiscoveryAgent *Instance(void);
+	static DiscoveryAgent<T> *Instance(void);
+
+	void init();
+	void initDAListeners();
+
+	void runKeepAliveAlgorithm();
+
+	///	Macrofunction Inquiry -- public methods: startInquiry, cancelInquiry 
+	AgentError startInquiry(unsigned long int timeout,
+			InquiryCtxt *rpcContextData);
+
+	AgentError cancelInquiry(CancelInquiryCtxt *rpcContextData);
+
+	AgentError cancelMgmtLQI_Req(CancelMgmtLQICtxt *rpcContextData);
+
+	static void IeeeAddrConfirm_CbW(uchar status, uchar *ieee_addr,
+			ushort nwk_addr, uchar num_assoc_dev, uchar start_index,
+			ushort *nwk_addr_assoc_dev_list);
+
+	static void Inquiry_CbW(uchar status, uchar *ieee_addr, ushort nwk_addr,
+			uchar num_assoc_dev, uchar start_index,
+			ushort *nwk_addr_assoc_dev_list);
+
+	AgentError MgmtLQI_Req(unsigned long int timeout,
+			MgmtLQICtxt *rpcContextData);
+
+	static void Mgmt_LQI_CbW(uchar scrAddrMode, uchar * src_addr, uchar status,
+			uchar NeighborTableEntries, uchar StartIndex,
+			uchar NeighborTableListCount,
+			ZB_NEIGHBOR_TABLE_LIST *NeighborTableList);
+
+	int startAnnouncementsMode(StartAnnouncementsModeCtxt *rpcContextData);
+
+	int cancelAnnouncementsMode(CancelAnnouncementsModeCtxt *rpcContextData);
+
+	static void Announce_CbW(ushort nwk_addr, uchar *ieee_addr,
+			uchar capability);
+
+	int retrieveNodes(RPCContext<T, retrieveNodesResponseCb> *rpcContextData);
+
+	int startFreshnessMode(StartFreshnessModeCtxt *rpcContextData);
+
+	int cancelFreshnessMode(CancelFreshnessModeCtxt *rpcContextData);
+
+	static void getIEEEAddress_CbW(uchar status, uchar *ieee_addr,
+			ushort nwk_addr, uchar num_assoc_dev, uchar start_index,
+			ushort *nwk_addr_assoc_dev_list);
+
+	///	Macrofunction getNodeDescriptor -- public methods: getNodeDescriptor 
+	int getNodeDescriptor(unsigned long int timeout, ushort nwk_addr,
+			NodeDescriptorCtxt *rpcContextData);
+
+	static void getNodeDescriptor_CbW(uchar status, ushort nwk_addr,
+			ZB_NODE_DESC *node_descr);
+
+	///	Macrofunction getPowerDescriptor -- public methods: getPowerDescriptor 
+	int getPowerDescriptor(ushort nwk_addr,
+			PowerDescriptorCtxt *rpcContextData);
+
+	static void getPowerDescriptor_CbW(uchar status, ushort nwk_addr,
+			ZB_POWER_DESC *power_descr);
+
+	///	Macrofunction getNodeAllDescriptors -- public methods: getNodeAllDescriptors 
+	int getNodeAllDescriptors(ushort nwk_addr);
+
+	///	Macrofunction superDiscovery - public method: superDiscovery 
+	int superDiscovery(SuperDiscoveryCtxt *rpcContextData);
+
+	static void superDiscovery_CbW(uchar status, uchar *ieee_addr,
+			ushort nwk_addr, uchar num_assoc_dev, uchar start_index,
+			ushort *nwk_addr_assoc_dev_list);
+
+	static void superDiscovery_ND_CbW(uchar status, ushort nwk_addr,
+			ZB_NODE_DESC *node_descr);
+
+	static void superDiscovery_PD_CbW(uchar status, ushort nwk_addr,
+			ZB_POWER_DESC *power_descr);
+
+	// Start KeepAliveTask - static wrapper
+	static void *startKATask_SW(void *arg);
+
+	// iterators:
+	// Attributes visible by scope of instantiation and use
+
+	//mgmt Lqi Discovery
+	bool rootNodeDiscovered;
+
+	int searchNodeFromDeadingNodeList(Node * node);
+	void removeNodeFromDeadingNodeList(int index);
+	void insertNodeIntoDeadingNodeList(uchar *ieee, long time);
+	void clearDeadingNodeList();
+
+	void setKAthreshold(int threshold);
+	void announceDeadNode(Node * node);
+	void keepAliveAlgorithm(Node *currentNode);
+	void forcePingAlgorithm(Node *currentNode);
+
+protected:
+
+	///	Constructor (pattern Singleton)
+	DiscoveryAgent();
+
+	void Announce_Cb(ushort nwk_addr, uchar *ieee_addr, uchar capability);
+
+	void IeeeAddrConfirm_Cb(uchar status, uchar *ieee_addr, ushort nwk_addr,
+			uchar num_assoc_dev, uchar start_index,
+			ushort *nwk_addr_assoc_dev_list);
+
+	///	Macrofunction Inquiry -- protected method: Inquiry_Cb 
+	void Inquiry_Cb(uchar status, uchar *ieee_addr, ushort nwk_addr,
+			uchar num_assoc_dev, uchar start_index,
+			ushort *nwk_addr_assoc_dev_list);
+
+	void Mgmt_LQI_Cb(uchar scrAddrMode, uchar * src_addr, uchar status,
+			uchar NeighborTableEntries, uchar StartIndex,
+			uchar NeighborTableListCount,
+			ZB_NEIGHBOR_TABLE_LIST *NeighborTableList);
+
+	void getIEEEAddress_Cb(uchar status, uchar *ieee_addr, ushort nwk_addr,
+			uchar num_assoc_dev, uchar start_index,
+			ushort *nwk_addr_assoc_dev_list);
+
+	///	Macrofunction getNodeAllDescriptors -- public methods: getNodeAllDescriptors_PD_Cb 
+	void getNodeAllDescriptors_PD_Cb( //TODO
+			uchar status, ushort nwk_addr, ZB_POWER_DESC *power_descr);
+
+	//TODO	Define function pointers types related to RPC callbacks (Macrofunction getNodeAllDescriptors)
+
+	///	Macrofunction superDiscovery - protected methods: superDiscovery_Cb, superDiscovery_ND_Cb, superDiscovery_PD_Cb 
+	void superDiscovery_Cb(uchar status, uchar *ieee_addr, ushort nwk_addr,
+			uchar num_assoc_dev, uchar start_index,
+			ushort *nwk_addr_assoc_dev_list);
+
+	void superDiscovery_ND_Cb(uchar status, ushort nwk_addr,
+			ZB_NODE_DESC *node_descr);
+
+	void superDiscovery_PD_Cb(uchar status, ushort nwk_addr,
+			ZB_POWER_DESC *power_descr);
+
+	///	clearGhostNodes
+	void clearGhostNodes();
+
+	/// Timer handlers
+	void onGetNodeDescriptor();
+
+	void onGetPowerDescriptor();
+
+	void onSuperDiscovery();
+
+	void onMgmtLQIRequest();
+
+	void onInquiry();
+
+	typedef void *TIMERPROC;
+
+	int initTimers(void);
+
+	int KAthreshold;
+	int KAnumOfPings;
+	int forceLQIPingTimer;
+
+	struct Task {
+		bool taskStarted;
+		pthread_t tid;
+
+		int start(void *(*invokedMethod)(void *));
+
+		void stop();
+
+		Task();
+
+	};
+
+	struct {
+		Task keepAliveTask;
+	} tasks;
+
+	void *startFCTask(DiscoveryAgent<T>::Task *task);
+
+	// Attributes visible to descendents
+
+	///	Pointer to GalZbIf object
+	GalZbIf *pGalZb;
+
+	///	Pointer to Gal database (refer to ZbNetDb class)
+	ZbNetDb *pGalDb;
+
+	///	Pointer to a Debug object -> logger
+	Debug *pLogger;
+
+	///	To enable/disable Debug (default value is 0)
+	bool debugEnabled;
+	int debugLevel;
+
+private:
+	// Local attributes
+
+	// Pattern Singleton
+	static DiscoveryAgent<T> instance;
+
+	///	Mutex
+	pthread_mutex_t mux;
+
+	///	Thread management
+	ThreadPool threadPool;
+
+	TimerThread timerThread;
+
+	// This is a dynamic table that has a list of the node that doesn't respond since a while
+	deadingNode *deadingNodeList;
+	int deadingNodeListCounter;
+
+	///	Map containing functions context data
+	struct fContexts {
+		fContext<T, DiscoveryAgent, inquiryResponseCb, inquiryNotifyCb> inquiry;
+
+		fContext<T, DiscoveryAgent, MgmtLQIResponseCb, MgmtLQINotifyCb> MgmtLQI;
+
+		fContext<T, DiscoveryAgent, nodeDescriptorResponseCb,
+				nodeDescriptorNotifyCb> getNodeDescriptor;
+
+		fContext<T, DiscoveryAgent, powerDescriptorResponseCb> getPowerDescriptor;
+
+		fContext<T, DiscoveryAgent, superDiscoveryResponseCb> superDiscovery;
+
+		fContext<T, DiscoveryAgent, startAnnouncementsModeResponseCb,
+				announceNotifyCb> announce;
+
+		fContext<T, DiscoveryAgent, startFreshnessModeResponseCb,
+				freshnessNotifyCb> freshness;
+
+		fContexts(GalZbIf::FeatureControl *fc) :
+				inquiry(fc, AGO_INQUIRY), MgmtLQI(fc, AGO_INQUIRY), getNodeDescriptor(
+						fc, AGO_GET_NODE_DESC), getPowerDescriptor(fc,
+						AGO_GET_POWER_DESC), superDiscovery(fc,
+						AGO_GET_NODE_DESC | AGO_GET_POWER_DESC | AGO_INQUIRY), announce(
+						fc, AGO_GET_ANNOUNCEMENTS),
+				//freshness (fc, AGO_INQUIRY)
+				freshness(fc, AGO_GET_DEATH_NOTIFICATIONS) {
+		}
+
+	} functionsContext;
+};
+
+#import "CDiscoveryAgent.cpp"
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDummyZigBeeDataSource.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDummyZigBeeDataSource.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDummyZigBeeDataSource.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,247 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <winport.h>		
+
+#include "CDummyZigBeeDataSource.h"
+
+DummyZigBeeDataSource *DummyZigBeeDataSource::pInstance = NULL;
+
+/**
+ Constructor
+ DummyZigBeeDataSource constructor. It is a protected method (pattern Singleton)
+
+ @param void Void.
+ @return Void.
+ */
+
+DummyZigBeeDataSource::DummyZigBeeDataSource() {
+	pLogger = new Debug("DummyZigBeeDataSource");
+	pLogger->setDebugMode(DBG_ENABLED);
+	pLogger->setDebugLevel(DEBUGGING);
+	pLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+	pLogger->enableDebugOuput(DBG_SCREEN);
+
+	pthread_mutex_init(&mux, NULL);
+
+#ifdef DEBUG_ACTIVE_Dummy_ZIGBEE_DATA_SOURCE
+	pLogger->debug("Constructor");
+#endif
+
+}
+
+/**
+ Destructor
+ DummyZigBeeDataSource destructor.
+
+ @param void Void.
+ @return Void.
+ */
+
+DummyZigBeeDataSource::~DummyZigBeeDataSource() {
+#ifdef DEBUG_ACTIVE_DUMMY_ZIGBEE_DATA_SOURCE
+	pLogger->debug("Destructor");
+#endif
+
+	delete pLogger;
+}
+
+/**
+ Public method DummyZigBeeDataSource *Instance(void)
+ (pattern Singleton)
+
+ @param void Void.
+ @return Instance of DummyZigBeeDataSource class.
+ */
+
+DummyZigBeeDataSource *DummyZigBeeDataSource::getInstance(void) {
+	if (pInstance == NULL) {
+		pInstance = new DummyZigBeeDataSource;
+	}
+	return pInstance;
+}
+
+/**
+ Public method DummyZigBeeDataSource init
+ DummyZigBeeDataSource initialization: dispatchPostData thread is created.
+
+ @param void Void.
+ @return Void.
+ */
+
+void DummyZigBeeDataSource::init() {
+	int tcRet;
+#ifdef DEBUG_ACTIVE_DUMMY_ZIGBEE_DATA_SOURCE
+	pLogger->debug("init");
+#endif
+
+	pGalZb = GalZbIf::Instance();
+
+	if (pGalZb != NULL) {
+		pGalZb->registerListener(GW_STATUS_CHANGED_EVENT,
+				(void *) (&gwStatusChanged_Event_CbW));
+	} else {
+#ifdef DEBUG_ACTIVE_DUMMY_ZIGBEE_DATA_SOURCE
+		pLogger->error("init - ERROR - GalZbIf not initiated !");
+#endif
+	}
+}
+
+void DummyZigBeeDataSource::gwStatusChanged_Event_CbW(int gwStatus,
+		int errorCode) {
+#ifdef DEBUG_ACTIVE_DUMMY_ZIGBEE_DATA_SOURCE
+	printf("\ngwStatusChanged_Event_CbW\n");
+#endif
+
+	DummyZigBeeDataSource* dummyZigBeeDataSource =
+			DummyZigBeeDataSource::getInstance();
+
+	dummyZigBeeDataSource->gwStatusChanged_Event_Cb(gwStatus, errorCode);
+}
+
+void DummyZigBeeDataSource::gwStatusChanged_Event_Cb(int gwStatus,
+		int errorCode) {
+#ifdef DEBUG_ACTIVE_DUMMY_ZIGBEE_DATA_SOURCE
+	pLogger->debug("gwStatusChanged_Event_Cb");
+#endif
+
+#ifdef DEBUG_ACTIVE_DUMMY_ZIGBEE_DATA_SOURCE
+	pLogger->debug("gwStatusChanged_Event_Cb - gwStatus = %d -- errorCode = %d",gwStatus, errorCode);
+#endif
+
+	pthread_mutex_lock(&mux);
+
+	ConfigurationRepository *_conf = ConfigurationRepository::instance();
+
+	// We load the configuration from the ConfigurationManager
+	this->txPeriod = _conf->getint("PerfomanceTest:txPeriod", 1000000);
+
+#ifdef DEBUG_ACTIVE_RB
+	pLogger->debug("gwStatusChanged_Event_Cb - txPeriod = %d", this->txPeriod);
+#endif
+
+	pthread_mutex_unlock(&mux);
+
+	if (gwStatus == GW_RUNNING) {
+#ifdef DEBUG_ACTIVE_DUMMY_ZIGBEE_DATA_SOURCE
+		pLogger->info("gwStatusChanged_Event_Cb - GW Started -> start sending Data automatically");
+#endif
+		this->start();
+	}
+}
+
+void DummyZigBeeDataSource::start() {
+	int tcRet;
+#ifdef DEBUG_ACTIVE_DUMMY_ZIGBEE_DATA_SOURCE
+	pLogger->debug("start");
+#endif
+
+	///  thread is created.		
+	tcRet = pthread_create(&(this->tId), NULL, sendingData_SW, this);
+	if (tcRet) {
+		pLogger->error("start - Error in creating thread performanceTest");
+	}
+}
+
+/**
+ Public method DummyZigBeeDataSource startDataSource_SW
+ Static wrapper: DummyZigBeeDataSource dispatchPostData is called. In particular, this is used in dispatchPostData thread creation.
+
+ @param arg Pointer to the DummyZigBeeDataSource object.
+ @return Void.
+ */
+
+void* DummyZigBeeDataSource::sendingData_SW(void *arg) {
+	DummyZigBeeDataSource *pDummyZigBeeDataSource = NULL;
+#ifdef DEBUG_ACTIVE_DUMMY_ZIGBEE_DATA_SOURCE
+	printf("DummyZigBeeDataSource::sendingData_SW\n");
+#endif
+
+	pDummyZigBeeDataSource = (DummyZigBeeDataSource *) arg;
+	pDummyZigBeeDataSource->sendingData();
+	return 0;
+}
+
+/**
+ Public method DummyZigBeeDataSource performanceTest
+ This method works in a separate thread. 
+
+ @param void Void.
+ @return Void.
+ */
+
+void* DummyZigBeeDataSource::sendingData() {
+#ifdef DEBUG_ACTIVE_DUMMY_ZIGBEE_DATA_SOURCE
+	pLogger->debug("sendingData");
+#endif
+
+	uchar dst_addr_mode;
+	uchar *dst_addr;
+	uchar dst_ep;
+
+	uchar src_addr_mode;
+	uchar *src_addr;
+	uchar src_ep;
+	ushort profile_id;
+	ushort cluster_id;
+	uchar asdu_len;
+	uchar *asdu;
+	uchar was_broadcast;
+	uchar sec_status;
+
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("send");
+#endif
+
+	dst_addr_mode = 0x02;
+	dst_addr = (uchar *) malloc(2 * sizeof(uchar));
+	dst_addr[0] = 0x00;
+	dst_addr[1] = 0x00;
+	dst_ep = 0x01;
+
+	src_addr_mode = 0x02;
+	src_addr = (uchar *) malloc(2 * sizeof(uchar));
+	src_addr[0] = 0x01;
+	src_addr[1] = 0x00;
+	src_ep = 0x01;
+
+	profile_id = 0xC044;
+	cluster_id = 0x0006;
+
+	asdu_len = 0x04;
+	asdu = (uchar *) malloc(2 * sizeof(uchar));
+	asdu[0] = 0xAA;
+	asdu[1] = 0xBB;
+	asdu[2] = 0xCC;
+	asdu[3] = 0xDD;
+	was_broadcast = 0x00;
+	sec_status = 0xFF;
+
+	while (1) {
+
+#ifdef DEBUG_ACTIVE_DUMMY_ZIGBEE_DATA_SOURCE
+		pLogger->debug("sendingData - DATA ------------------------------------------------------");
+#endif
+
+		pGalZb->APSDE_DATA_indication_Dummy(dst_addr_mode, dst_addr, dst_ep,
+				src_addr_mode, src_addr, src_ep, profile_id, cluster_id,
+				asdu_len, asdu, was_broadcast, sec_status);
+
+		usleep(txPeriod);
+	}
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDummyZigBeeDataSource.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDummyZigBeeDataSource.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CDummyZigBeeDataSource.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,87 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef DUMMY_ZIGBEE_DATA_SOURCE_H
+#define DUMMY_ZIGBEE_DATA_SOURCE_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <string>
+
+#include "ThreadPool.h"
+#include "TimerThread.h"
+#include <pthread.h>
+
+#include "GalZbIf.h"
+#include "ZbNetDb.h"
+#include "GWManagement.h"
+
+#include "CDebug.h"
+
+#include "ConfigurationRepository.h"
+
+class DummyZigBeeDataSource {
+
+public:
+	// Constructors
+
+	// Destructor
+	~DummyZigBeeDataSource();
+
+	// Functions: modifiers (set), selectors (get)
+
+	// Pattern Singleton
+	static DummyZigBeeDataSource *getInstance(void);
+
+	void init();
+	void start();
+
+	static void *sendingData_SW(void *arg);
+
+	static void gwStatusChanged_Event_CbW(int gwStatus, int errorCode);
+
+	// iterators:
+	// Attributes visible by scope of instantiation and use
+
+protected:
+
+	///	Constructor (pattern Singleton)
+	DummyZigBeeDataSource();
+
+	///	Data management
+	void *sendingData();
+
+	void gwStatusChanged_Event_Cb(int gwStatus, int errorCode);
+
+	///	Pointer to GalZbIf object
+	GalZbIf *pGalZb;
+
+	///	Pointer to a Debug object -> logger
+	Debug *pLogger;
+
+	/// 
+	int txPeriod;
+
+private:
+	// Local attributes
+
+	// Pattern Singleton
+	static DummyZigBeeDataSource *pInstance;
+
+	///	Mutex
+	pthread_mutex_t mux;
+
+	///	Thread descriptor
+	pthread_t tId;
+
+};
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CHTTPClient.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CHTTPClient.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CHTTPClient.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,118 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include "CHTTPClient.h"
+
+/**
+ Constructor
+
+ @param void Void.
+ @return Void.
+ */
+
+HTTPClient::HTTPClient() {
+#ifdef DEBUG_ACTIVE_HTTPCLIENT
+	printf("HTTPClient Constructor\n");
+#endif
+
+	// CURLOPT_TIMEOUT default value = 3
+	this->setOptTimeout(3);
+}
+
+/**
+ Destructor
+
+ @param void Void.
+ @return Void.
+ */
+
+HTTPClient::~HTTPClient() {
+#ifdef DEBUG_ACTIVE_HTTPCLIENT
+	printf("HTTPClient Destructor\n");
+#endif
+
+	curl_global_cleanup();
+}
+
+void HTTPClient::setOptTimeout(int value) {
+	this->optTimeout = value;
+}
+
+/**
+ Public method HTTPClient postData.
+
+ @param URL Destination URL.
+ @param buffer Stl String containing the message to be sent.
+ @param listener Function pointer to the method invoked on HTTP response reception.
+ @return Status.
+ */
+
+int HTTPClient::postData(std::string *URL, std::string *buffer,
+		void *listener) {
+	CURL *curl;
+	CURLcode res, resultList;
+	struct curl_slist *headers = NULL;
+	char error_buffer[256];
+
+	curl = curl_easy_init();
+	if (curl) {
+		curl_easy_setopt(curl, CURLOPT_URL, URL->c_str());
+		//headers = curl_slist_append(headers, "Content-Type: text/xml");
+		headers = curl_slist_append(headers, "Expect:");
+		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
+		curl_easy_setopt(curl, CURLOPT_VERBOSE, CURLOPT_VERBOSE_DISABLED);
+		curl_easy_setopt(curl, CURLOPT_NOSIGNAL, CURLOPT_NOSIGNAL_ENABLED);
+		//Solution for managing umproper Application (using GAL) behaviour.
+		curl_easy_setopt(curl, CURLOPT_TIMEOUT, this->optTimeout);
+		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, buffer->c_str());
+		// If POSTFIELDSIZE is not set, libcurl will strlen() by itself
+		curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(buffer->c_str()));
+		if (listener != NULL) {
+			resultList = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
+					listener);
+			// This part works only with curl 7.18 or superior releases
+			if (resultList == CURL_WRITEFUNC_PAUSE) {
+				// SEE http://curl.haxx.se/libcurl/c/curl_easy_pause.html
+				//#ifdef DEBUG_ACTIVE_HTTPCLIENT
+				printf(
+						"postData -  ERROR: No possible to establish a listener to get the POST response");
+				//#endif
+				// Writing to this connection has been paused! Try to recovery it
+				curl_easy_pause(listener, CURLPAUSE_CONT); //CURLPAUSE_CONT: Convenience define that unpauses both directions
+			}
+			curl_easy_setopt(curl, CURLOPT_WRITEDATA, NULL);
+			curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_buffer); //Note:  If the CURLOPT_ERRORBUFFER was set with curl_easy_setopt there will be a readable error message in the error buffer when non-zero is returned.
+		}
+#ifdef DEBUG_ACTIVE_HTTPCLIENT
+		printf("postData - Sending POST to %s\n",URL->c_str());
+#endif
+		res = curl_easy_perform(curl);
+		if (res) {
+			//#ifdef DEBUG_ACTIVE_HTTPCLIENT
+			printf("WARNING: POST to %s returned an error: %d --> %s\n",
+					URL->c_str(), res, error_buffer);
+			//#endif
+		}
+		// Cleanup function (refer to libcurl library).
+		curl_easy_cleanup(curl); //End a libcurl easy session
+		// Free the header list (refer to libcurl library).
+		curl_slist_free_all(headers); //removes all traces of a previously built curl_slist linked list.
+		return res;
+	}
+	return -1;
+}

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CHTTPClient.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CHTTPClient.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CHTTPClient.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,55 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef HTTPCLIENT_H
+#define HTTPCLIENT_H
+
+#include "curl/curl.h"		// cURL library
+#include <string>
+#include "CDebug.h"
+
+/**
+ Set of constants used for libcurl
+ */
+#define CURLOPT_VERBOSE_DISABLED				0
+#define CURLOPT_VERBOSE_ENABLED					1
+#define CURLOPT_NOSIGNAL_DISABLED				0
+#define CURLOPT_NOSIGNAL_ENABLED				1
+
+class HTTPClient {
+
+public:
+	///	Constructors:
+	HTTPClient();
+	///	Destructor:
+	~HTTPClient();
+
+	///	Functions: modifiers (set), selectors (get)
+
+	int postData(std::string *URL, std::string *buffer, void *listener);
+
+	void setOptTimeout(int value);
+
+	// itterators:
+	// Attributes visible by scope of instantiation and use
+
+protected:
+	// Attributes visible to descendents
+
+	///	Pointer to a Debug object -> logger
+	Debug *pLogger;
+
+	int optTimeout;
+
+private:
+	// Local attributes
+
+};
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CHTTPServer.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CHTTPServer.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CHTTPServer.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,546 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef _WIN32
+#include <winsock.h>
+#define	snprintf			_snprintf
+
+#ifndef _WIN32_WCE
+#ifdef _MSC_VER /* pragmas not valid on MinGW */
+#pragma comment(lib,"ws2_32")
+#endif /* _MSC_VER */
+#define ALIAS_URI "/my_c"
+#define ALIAS_DIR "c:\\"
+
+#else /* _WIN32_WCE */
+/* Windows CE-specific definitions */
+#pragma comment(lib,"ws2")
+//#include "compat_wince.h"
+#define ALIAS_URI "/my_root"
+#define ALIAS_DIR "\\"
+#endif /* _WIN32_WCE */
+
+#else
+#include <sys/types.h>
+#include <sys/select.h>
+#define ALIAS_URI "/my_etc"
+#define ALIAS_DIR "/etc/"
+#endif
+
+#ifndef _WIN32_WCE /* Some ANSI #includes are not available on Windows CE */
+#include <time.h>
+#include <errno.h>
+#include <signal.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#define LOCAL_LOGGER pLogger
+#ifdef DEBUG_ACTIVE_HTTPSERVER
+#define LOCAL_DEBUG_ENABLED
+#endif
+
+#include "CHTTPServer.h"
+
+ResourceDescriptor HTTPServer::rootDesc("");
+
+HTTPSessionContext::HTTPSessionContext(shttpd_arg *context) :
+		context(context) {
+
+	ConfigurationRepository *_conf = ConfigurationRepository::instance();
+	//	We load the configuration from the ConfigurationManager
+	this->debugEnabled = _conf->getint("main:debugEnabled", false);
+	this->debugLevel = _conf->getint("Debug:HTTPSessionContextDL", TEST);
+
+	pLogger = new Debug("SessionContext");
+	//	Set Debug parameters
+	pLogger->setDebugMode(this->debugEnabled);
+	pLogger->setDebugLevel(this->debugLevel);
+	pLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+	pLogger->enableDebugOuput(DBG_SCREEN);
+	//pLogger->enableDebugOuput(DBG_LOGFILE);
+
+	rxDataBuffer = new std::string("");
+
+	L_DEBUG("new HTTPSessionContext");
+	numReadBytes = 0;
+
+	switch (getReqMethod()) {
+	case M_POST:
+	case M_PUT:
+		status = S_READING_BODY;
+		break;
+
+	default:
+		status = S_BODY_READ;
+		break;
+	}
+
+}
+
+void HTTPSessionContext::check() throw (HTTPException) {
+	const char *len;
+
+	len = getHeader("Content-Length");
+	if (len != NULL) {
+		L_DEBUG("createSessionContext - Content length = %s", len);
+		contentLen = strtoul(len, NULL, 10);
+	} else if (status == S_READING_BODY) {
+		L_DEBUG("createSessionContext - No content length!");
+		throw HTTPException(411, "Content-Length Required");
+	}
+
+}
+
+HTTPSessionContext::~HTTPSessionContext() {
+	L_DEBUG("HTTPSessionContext destructor");
+
+	delete pLogger;
+
+	/* Make sure we don't have dangling links */
+	context->state = NULL;
+
+	delete rxDataBuffer;
+}
+
+HTTPSessionStatus HTTPSessionContext::getSessionStatus() {
+	return status;
+}
+
+void HTTPSessionContext::setSessionStatus(HTTPSessionStatus status) {
+	L_DEBUG("setSessionStatus: %d", status);
+	this->status = status;
+}
+
+int HTTPSessionContext::getSessionId() {
+	return (int) this;
+}
+
+HTTPSessionContext *HTTPSessionContext::fromSessionId(int sessionId) {
+	return (HTTPSessionContext *) sessionId;
+}
+
+std::string *HTTPSessionContext::getRxDataBuffer() {
+	L_INFO("getRxDataBuffer rxDataBuffer = %s --", rxDataBuffer->c_str());
+
+	return rxDataBuffer;
+}
+
+const char *HTTPSessionContext::getHeader(const char *headerName) {
+	return shttpd_get_header(context, headerName);
+}
+
+Method HTTPSessionContext::getReqMethod() {
+	const char *requestMethod;
+	Method code;
+
+	requestMethod = shttpd_get_env(context, "REQUEST_METHOD");
+	if (strcmp(requestMethod, "GET") == 0)
+		code = M_GET;
+	else if (strcmp(requestMethod, "POST") == 0)
+		code = M_POST;
+	else if (strcmp(requestMethod, "PUT") == 0)
+		code = M_PUT;
+	else if (strcmp(requestMethod, "DELETE") == 0)
+		code = M_DELETE;
+	else
+		code = M_OTHER;
+
+	L_DEBUG("getReqMethod - reqMethod = %s - code = %d", requestMethod, code);
+
+	return code;
+}
+
+const char *HTTPSessionContext::getReqMethodStr() {
+	return shttpd_get_env(context, "REQUEST_METHOD");
+}
+
+const char *HTTPSessionContext::getReqURI() {
+	return shttpd_get_env(context, "REQUEST_URI");
+}
+
+const char *HTTPSessionContext::getQueryStr() {
+	return shttpd_get_env(context, "QUERY_STRING");
+}
+
+void HTTPSessionContext::setResponse(std::string body) {
+	L_DEBUG("setResponse");
+
+	this->body = body;
+}
+
+std::string HTTPSessionContext::getResponse() {
+	return body;
+}
+
+int HTTPSessionContext::printOut(const char *outputString) {
+	return shttpd_printf(context, "%s", outputString);
+}
+
+void HTTPSessionContext::closeStream() {
+	context->flags |= SHTTPD_END_OF_OUTPUT;
+}
+
+void HTTPSessionContext::sendResponse() {
+	L_DEBUG("sendResponse - response = %s", body.c_str());
+
+	printOut("HTTP/1.0 200 OK\r\nContent-Type: text/xml\r\n\r\n");
+
+	printOut(body.c_str());
+
+	closeStream();
+
+	status = S_TERM;
+}
+
+void HTTPSessionContext::reply(HTTPException &e) {
+	std::stringstream s;
+
+	L_DEBUG("reply - reponse = %d %s", e.code, e.msg);
+
+	s << "HTTP/1.0 " << e.code << " " << e.msg << "\r\n\r\n";
+
+	printOut(s.str().c_str());
+	closeStream();
+}
+
+void HTTPSessionContext::processPostData() throw (HTTPException) {
+	char *tmpBuf;
+
+	L_DEBUG("processPostData");
+
+	if (context->flags & SHTTPD_CONNECTION_ERROR) {
+		L_ERROR("processPostData - CONNECTION_ERROR");
+		// Connection broken prematurely: return ERROR value.
+		throw HTTPException(400, "Connection error");
+	}
+
+	if (status == S_READING_BODY) {
+
+		// A local temporary buffer is used to store the
+		// content of the SHTTPD library internal buffer
+
+		tmpBuf = new char[context->in.len + 1];
+		strncpy(tmpBuf, context->in.buf, context->in.len); //Note: in.buf cannot be resolved by Valgrind!
+		tmpBuf[context->in.len] = '\0';
+
+		L_DEBUG("processPostData - tmpBuf = [[%s]]", tmpBuf);
+
+		// The number of received bytes is updated.
+		numReadBytes += context->in.len;
+
+		// Set SHTTPD library parameter to state that all data
+		// has been processed
+		context->in.num_bytes = context->in.len;
+
+		// The received data is stored into the rxDataBuffer
+		// (session buffer).
+
+		rxDataBuffer->append(tmpBuf);
+		delete[] tmpBuf;
+
+		L_DEBUG("processPostData - rxDataBuffer = [[%s]] --",
+				rxDataBuffer->c_str());
+//			pContext -> rxDataBuffer -> c_str ());
+
+		// Check whether POST data stream is finished or not
+		if (numReadBytes >= contentLen) {
+			L_DEBUG("processPostData - COMPLETED");
+			L_INFO("processPostData - COMPLETED - "
+					"rxDataBuffer = [[%s]]", rxDataBuffer->c_str());
+//			       pContext -> rxDataBuffer -> c_str());
+			status = S_BODY_READ;
+		} else
+			L_DEBUG("processPostData - IN_PROGRESS");
+	}
+}
+
+ProtectedURIList::ProtectedURIList() {
+	/* empty */
+}
+
+ProtectedURIList::~ProtectedURIList() {
+	/* empty */
+}
+
+void ProtectedURIList::addAssociation(Resource *res, const char *fname) {
+	ht[res->uri] = fname;
+}
+
+void ProtectedURIList::removeAssociation(Resource *res) {
+	ht.erase(res->uri);
+}
+
+void ProtectedURIList::getProtectValue(std::string &s) {
+	map<std::string, std::string>::iterator i;
+	const char *comma;
+
+	s = "";
+	comma = "";
+	for (i = ht.begin(); i != ht.end(); i++) {
+		s += comma + (*i).first + "=" + (*i).second;
+		comma = ",";
+	}
+}
+
+HTTPServer::HTTPServer() :
+		root(rootDesc, NULL, this) {
+
+	ConfigurationRepository *_conf = ConfigurationRepository::instance();
+	//	We load the configuration from the ConfigurationManager
+	this->debugEnabled = _conf->getint("main:debugEnabled", false);
+	this->debugLevel = _conf->getint("Debug:HTTPServerDL", TEST);
+
+	pLogger = new Debug("HTTPServer");
+	pLogger->setDebugMode(this->debugEnabled);
+	pLogger->setDebugLevel(this->debugLevel);
+
+	pLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+	pLogger->enableDebugOuput(DBG_SCREEN);
+	//pLogger->enableDebugOuput(DBG_LOGFILE);	
+
+	L_DEBUG("Constructor");
+
+	///	Initialize SHTTPD context
+	serverContext = shttpd_init(0, NULL);
+
+	shttpd_register_uri(serverContext, "/", callback, &root);
+
+	///	Set Poll timeout
+	setPollTimeout(1000);
+}
+
+HTTPServer::~HTTPServer() {
+	L_DEBUG("Destructor");
+
+	clearResource(&root);
+
+	// Deallocate SHTTPD context
+	shttpd_fini(serverContext);
+	if (pLogger != NULL) {
+		delete pLogger;
+		pLogger = NULL;
+	}
+}
+
+void HTTPServer::start() {
+	L_INFO("start");
+	for (;;)
+		shttpd_poll(serverContext, pollTimeout);
+}
+
+Resource *HTTPServer::createResource(Resource *root,
+		const ResourceDescriptor &rd, ResourceHandler *handler, void *data) {
+	Resource *res;
+
+	res = new Resource(rd, handler, data);
+	registerResource(res, root);
+
+	return res;
+}
+
+Resource *HTTPServer::findResource(Resource *r, const char *name) {
+	std::list<Resource *>::iterator i;
+
+	if (r == NULL)
+		r = &root;
+
+	for (i = r->children.begin(); i != r->children.end(); i++) {
+		//L_DEBUG("findResource - PATH considered = %s\n", (*i) -> rd.path.c_str());
+		if ((*i)->rd.path == name)
+			return *i;
+	}
+	return NULL;
+}
+
+///Remove all the sub-resources included the root passed in input
+void HTTPServer::removeResource(Resource *r) {
+	list<Resource *>::iterator i;
+
+	clearResource(r);
+	unregisterResource(r);
+	if (r->parent != NULL)
+		r->parent->removeChild(r);
+
+	delete r;
+}
+
+///Remove all the sub-resources apart from the root passed in input
+void HTTPServer::clearResource(Resource *r) {
+	list<Resource *>::iterator i;
+	Resource *rp;
+
+	if (r == NULL)
+		return;
+
+	i = r->children.begin();
+	while (i != r->children.end()) {
+		rp = *i;
+		clearResource(rp);
+		i = r->children.erase(i);
+		unregisterResource(rp);
+		delete rp;
+	}
+}
+
+void HTTPServer::registerResource(Resource *res, Resource *root) {
+	if (root == NULL)
+		root = &this->root;
+
+	root->addChild(res);
+
+	shttpd_register_uri(serverContext, res->uri.c_str(), callback, res);
+}
+
+void HTTPServer::callback(shttpd_arg *arg) {
+	Resource *res, *root;
+	HTTPServer *server;
+	root = res = (Resource *) arg->user_data;
+	while (root->parent != NULL)
+		root = root->parent;
+
+	server = (HTTPServer *) root->data.p;
+
+	server->handle(res, arg);
+}
+
+void HTTPServer::handle(Resource *resource, shttpd_arg *arg) {
+	HTTPSessionContext *ctxt;
+
+	L_DEBUG("handle");
+	try {
+		ctxt = (HTTPSessionContext *) arg->state;
+		if (ctxt == NULL) {
+			ctxt = makeSessionContext(arg);
+			arg->state = ctxt;
+			L_DEBUG("Associated (new) sessiond Id %d", ctxt->getSessionId());
+			//Add the new session Id to the active HTTPSessions list
+			this->activeHTTPSessions.push_back(ctxt->getSessionId());
+		} else {
+			ctxt->context = arg;
+		}
+		ctxt->check();
+		L_DEBUG("dispatcher - reqMethod = %d -reqURI = %s - queryString = %s",
+				ctxt->getReqMethod(), ctxt->getReqURI(), ctxt->getQueryStr());
+		// Process POST data, if needed
+		ctxt->processPostData();
+		// Request has been processed -> serve the request
+		if (ctxt->getSessionStatus() == S_BODY_READ) {
+			L_INFO("dispatcher - REQUEST PROCESSED -> "
+					"call serveRequest");
+			ctxt->setSessionStatus(S_SERVING);
+			serveRequest(resource, ctxt);
+		}
+		// Request has been served
+		if (ctxt->getSessionStatus() == S_SERVING)
+			ctxt->setSessionStatus(S_SERVED);
+		if (ctxt->getSessionStatus() == S_READY) {
+			ctxt->sendResponse();
+			ctxt->setSessionStatus(S_TERM);
+		}
+		if (ctxt->getSessionStatus() == S_TERM) {
+			L_INFO("dispatcher - delete context");
+			//Remove the session Id from the active HTTPSessions list
+			activeHTTPSessions.remove(ctxt->getSessionId());
+			delete ctxt;
+		}
+	} catch (HTTPException &e) {
+		L_WARN("dispatcher -- exception driver HTTP response: %d %s", e.code,
+				e.msg);
+		ctxt->reply(e);
+		//Remove the session Id from the active HTTPSessions list
+		activeHTTPSessions.remove(ctxt->getSessionId());
+		delete ctxt;
+	}
+}
+
+HTTPSessionContext *HTTPServer::makeSessionContext(shttpd_arg *arg)
+		throw (HTTPException) {
+	return new HTTPSessionContext(arg);
+}
+
+void HTTPServer::serveRequest(Resource *resource, HTTPSessionContext *ctxt)
+		throw (HTTPException) {
+	throw HTTPException(403, "Forbidden");
+}
+
+int HTTPServer::unregisterResource(Resource *res) {
+	int returnValue = 1;
+	if (res == NULL)
+		return returnValue;
+	returnValue = shttpd_unregister_uri(serverContext, res->uri.c_str());
+	plist.removeAssociation(res);
+	updateAssociations();
+	return returnValue;
+}
+
+void HTTPServer::protectResource(Resource *res, const char *pwdfilename) {
+	plist.addAssociation(res, pwdfilename);
+	updateAssociations();
+}
+
+void HTTPServer::updateAssociations(void) {
+	std::string s;
+
+	plist.getProtectValue(s);
+	setOption("protect", s.c_str());
+}
+
+int HTTPServer::setOption(const char *option, const char *value) {
+	int returnValue = 0;
+
+	int shttpdRetValue = shttpd_set_option(serverContext, option, value);
+	if (!shttpdRetValue) {
+		returnValue = 1;
+		L_ERROR("setOption - Error setting option %s (value = %s)", option,
+				value);
+	}
+	return returnValue;
+}
+
+const char *HTTPServer::getOption(const char *option) {
+	return shttpd_get_option(serverContext, option);
+}
+
+void HTTPServer::setPollTimeout(int timeout) {
+	pollTimeout = timeout;
+}
+
+HTTPSessionContext *HTTPServer::getHTTPSessionContext(int sessionId) {
+	std::list<int>::iterator iter;
+
+	L_DEBUG("getHTTPSessionContext");
+
+	bool found = false;
+	for (iter = this->activeHTTPSessions.begin();
+			iter != this->activeHTTPSessions.end(); ++iter) {
+		L_DEBUG("getHTTPSessionContext - iter = %d\n", *iter);
+		if (*iter == sessionId) {
+			L_DEBUG("getHTTPSessionContext - iter = %d (FOUND)", *iter);
+			found = true;
+			break;
+		}
+	}
+
+	if (!found) {
+		pLogger->error("getHTTPSessionContext - ERROR - A HTTPSessionContext was request for a non-active Session Id");
+		return NULL;
+	} else {
+		return HTTPSessionContext::fromSessionId(sessionId);
+	}
+
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CHTTPServer.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CHTTPServer.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CHTTPServer.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,486 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef HTTPSERVER_H
+#define HTTPSERVER_H
+
+#include "shttpd.h"
+
+#include <string>
+#include <map>
+
+#include "ConfigurationRepository.h"
+#include "CDebug.h"
+#include "CResource.h"
+
+/**
+ * An exception thrown whenever the processing must stop and
+ * an HTTP error shall be generated. Though this exception won't
+ * mandate any behaviour on handlers, since there is no way
+ * to specify the response's body, it is expected that no
+ * body will be generated.
+ */
+class HTTPException: public std::exception {
+
+public:
+	/**
+	 * Constructor.
+	 *	@param code the HTTP code
+	 *	@param msg the reason phrase
+	 */
+	HTTPException(int code, const char *msg) :
+			code(code), msg(msg) {
+	}
+
+public:
+	/** The HTTP code */
+	int code;
+
+	/** The reason phrase */
+	const char *msg;
+};
+
+/**
+ * This class contains all the uri-pwdfile associations for the
+ * HTTP server. Of course it features the methods to add and
+ * remove associations and reconfigure the SHTTPD library
+ * accordingly.
+ */
+class ProtectedURIList {
+
+public:
+	/** Constructor */
+	ProtectedURIList();
+
+	/** Destructor */
+	virtual ~ProtectedURIList();
+
+	/**
+	 * Add an association between a resource and its password 
+	 * filename. If the same resource is associated twice, using
+	 * different filenames, the oldest one is replaced.
+	 *	@param res the resource to be protected
+	 *	@param fname the password filename 
+	 */
+	void addAssociation(Resource *res, const char *fname);
+
+	/**
+	 * Removes an association.
+	 *	@param res the resources to be deassociated
+	 */
+	void removeAssociation(Resource *res);
+
+	/**
+	 * Returns a configuration string that can be used to
+	 * update the configuration of the SHTTPD instance.
+	 * To do this, call <tt>shttpd_set_option</tt> using
+	 * the <tt>protect</tt> key.
+	 *	@param s a string that will be filled with
+	 *	 	that value
+	 */
+	void getProtectValue(std::string &s);
+
+private:
+	std::map<std::string, std::string> ht;
+};
+
+/** The states of the HTTP Session FSM */
+enum HTTPSessionStatus {
+	/** Reading the body, if present */
+	S_READING_BODY,
+
+	/** Body read, the resource handler can be invoked */
+	S_BODY_READ,
+
+	/** Handler invoked, no response ready */
+	S_SERVING,
+
+	/** Handler invoked, processing complete, response not set */
+	S_SERVED,
+
+	/** Handler invoked, processing complete, 
+	 response set, but not sent yet */
+	S_READY,
+
+	/** Transaction complete */
+	S_TERM
+};
+
+class HTTPServer;
+
+/**
+ * The conversation state of an HTTP transaction. This class
+ * contains a state machine that tracks the stage the transaction
+ * is at. It can also be used to obtain information about the
+ * original request and send the appropriate response.
+ */
+class HTTPSessionContext {
+
+public:
+
+	/** 
+	 * Constructor.
+	 *	@param context the shttpd context
+	 */
+	HTTPSessionContext(shttpd_arg *context);
+
+	/**
+	 * Desctructor. 
+	 */
+	virtual ~HTTPSessionContext();
+
+	/** 
+	 * Performs all the initialization checks, throwing an exception
+	 * if the request has something wrong.
+	 */
+	virtual void check() throw (HTTPException);
+
+	/**
+	 * Returns an unique transaction identifier. At any 
+	 * moment there can coexist no CHTTPServer instances
+	 * with the same session identifier.
+	 *	@return the session identifier
+	 */
+	int getSessionId();
+
+	/**
+	 * Returns an instance of this class, given its unique 
+	 * transaction identifier. 
+	 *	@param sessionId the session identifier
+	 *	@return the reference to that class
+	 */
+	static HTTPSessionContext *fromSessionId(int sessionId);
+
+	/**
+	 * Returns the current status of the transaction state machine.
+	 *	@return the status
+	 */
+	HTTPSessionStatus getSessionStatus();
+
+	/**
+	 * Updates the current status of the transaction state machine.
+	 *	@param value the new status
+	 */
+	void setSessionStatus(HTTPSessionStatus value);
+
+	/**
+	 * Returns the body of the request, as a string.
+	 *	@return a string containing the request body 
+	 */
+	std::string *getRxDataBuffer();
+
+	/**
+	 * Returns the contents of an header in the initial HTTP request.
+	 *	@param headerName the header name
+	 *	@return the header, or NULL
+	 */
+	const char *getHeader(const char *headerName);
+
+	/**
+	 * Returns the method of the request, as a Method enumeration.
+	 *	@return the method code 
+	 */
+	Method getReqMethod();
+
+	/**
+	 * Returns the method of the request, as a string.
+	 *	@return the method name
+	 */
+	const char *getReqMethodStr();
+
+	/**
+	 * Returns the Request-URI. The query string is stripped away
+	 * (see getQueryStr).
+	 *	@return the request URI
+	 */
+	const char *getReqURI();
+
+	/**
+	 * Returns the query string in the initial request.
+	 *	@return the query string
+	 */
+	const char *getQueryStr();
+
+	/**
+	 * Writes a string to the HTTP response socket.
+	 * The socket is not closed, so multiple calls to this method
+	 * are allowed.
+	 *	@param outputString the string to write
+	 *	@return the number of characters actually written,
+	 *		or -1 in case of permanent error
+	 */
+	int printOut(const char *outputString);
+
+	/**
+	 * Closes the stream
+	 */
+	void closeStream();
+
+	/**
+	 * Sets the response body. The status code is assumed to 
+	 * be 200 Ok,
+	 *	@param body the body
+	 */
+	virtual void setResponse(std::string body);
+
+	/**
+	 * Returns the response body. This string is meaningful only
+	 * if #setResponse has been called previously
+	 */
+	std::string getResponse();
+
+	/**
+	 * Sends a 200 Ok response, using the response body set by
+	 * #setResponse and moving to S_TERM state.
+	 */
+	void sendResponse();
+
+	/**
+	 * Collects the body of an HTTP request. 
+	 * This method is repeatedly called by HTTPServer::handle
+	 * to feed the reques body. As such, it only makes sense 
+	 * to call it while in processing state.
+	 */
+	virtual void processPostData() throw (HTTPException);
+
+	/**
+	 * Sends back an HTTP responses, and closes the stream.
+	 *	@param e the exception containing HTTP response info
+	 */
+	void reply(HTTPException &e);
+
+protected:
+
+	///	To enable/disable Debug (default value is 0)
+	bool debugEnabled;
+	int debugLevel;
+
+	/// Pointer to a Debug object -> logger
+	Debug *pLogger;
+
+private:
+	/** The SHTTPD session data */
+	shttpd_arg *context;
+
+	/** The expected length of the body. It is set to the
+	 *  value of the Content-Length header, or to -1 when
+	 *  this header is missing or invalid */
+	size_t contentLen;
+
+	/** Size in bytes of the fragment of HTTP request body
+	 *  received so far */
+
+	size_t numReadBytes;
+
+	/** Buffer containing the HTTP request body received so far */
+	std::string *rxDataBuffer;
+
+	/** The FSM status */
+	HTTPSessionStatus status;
+
+	/** The response body. It is set by #setResponse */
+	std::string body;
+
+	friend class HTTPServer;
+};
+
+/**
+ * A shttpd-based HTTP server. This object can be used to configure,
+ * start and stop the HTTP server. Resources can be dynamically added
+ * to the virtual path tree, by calling #createResource or the
+ * more low-level #registerURI method.
+ * Incoming transactions are handled by creating an instance
+ * of the HTTPSessionContext class, and handing it to the resource
+ * handler associated to the targeted resource. The HTTP server
+ * contains a default resource (#root), which is the root of
+ * the hierarchy.
+ */
+class HTTPServer {
+
+public:
+	/**
+	 * Constructor.
+	 */
+	HTTPServer();
+
+	/**
+	 * Destructor.
+	 */
+	virtual ~HTTPServer();
+
+	/**
+	 * Accepts connections from the HTTP server, 
+	 * blocking until #pollTimeout milliseconds have elapsed.
+	 */
+	virtual void start();
+
+	/**
+	 * Attaches a new resource to the web server hierarchy.
+	 * This is done by giving the ResourceDescriptor template,
+	 * the event handler and the resource-specific opaque data.
+	 * In practice, this method is equivalent to creating
+	 * the appropriate Resource object and calling the
+	 * #registerURI method.
+	 *	@param parent the parent resource. Set to NULL
+	 *	 	if the new resource shall be registered
+	 *		at the root of the server
+	 *	@param rd the resource descriptor
+	 *	@param handler pointer to the handler interface
+	 *	@param data the opaque data
+	 *	@return the new resource 
+	 */
+	virtual Resource *createResource(Resource *parent,
+			const ResourceDescriptor &rd, ResourceHandler *handler, void *data);
+	/**
+	 * Looks for a subresource, given its name and a pointer
+	 * to its parent.
+	 *	@param parent the parent resource, or NULL
+	 *	@param name the resource name
+	 *	@return the resource found, or NULL
+	 */
+	virtual Resource *findResource(Resource *parent, const char *name);
+
+	/**
+	 * Removes a resource from the web server hierarchy.
+	 * As this method is concevied as the dual of #createResource,
+	 * the object passed to it is also destroyed.
+	 */
+	virtual void removeResource(Resource *r);
+
+	/**
+	 * Removes all the subresources of a given resource 
+	 * from the web server hierarchy.
+	 */
+	virtual void clearResource(Resource *r);
+
+	/**
+	 * Registers a resource on the web server hierarchy.
+	 *	@param res the resource to attach
+	 *	@param parent the parent resource. Set to NULL
+	 *		if the new resource shall be registered
+	 *		at the root of the server
+	 */
+	void registerResource(Resource *res, Resource *parent);
+
+	/**
+	 * Unregisters a resource from the web server hierarchy.
+	 *	@param res the resource
+	 */
+	int unregisterResource(Resource *res);
+
+	/**
+	 * Protects a given resource, using a specific secret file
+	 *	@param res the resource file
+	 *	@param pwdfilename the filename
+	 */
+	void protectResource(Resource *res, const char *pwdfilename);
+
+	/**
+	 * Changes some SHTTPD setting.
+	 *	@param option the option name
+	 *	@param value the new value
+	 */
+	int setOption(const char *option, const char *value);
+
+	/**
+	 * Returns the current value of a SHTTPD setting.
+	 *	@param option the option name
+	 *	@return the current value
+	 */
+	const char *getOption(const char *option);
+
+	/**
+	 * Changes the poll timeout.
+	 *	@param the new value
+	 */
+	void setPollTimeout(int timeout);
+
+	//
+	HTTPSessionContext *getHTTPSessionContext(int sessionId);
+
+protected:
+	/**
+	 * This method is called when a new transaction, is accepted
+	 * by the HTTP server. By default, it creates an HTTPSessionContext
+	 * object, however derived classes may override this method
+	 * to specify objects with a different behaviour.
+	 *	@param arg the SHTTPD state
+	 *	@return a session context object
+	 */
+	virtual HTTPSessionContext *makeSessionContext(shttpd_arg *arg)
+			throw (HTTPException);
+
+	/**
+	 * The non-static callback entry point. This method gets called
+	 * by #callback after it has identified the correct HTTPResponse
+	 * associated to the resource being accessed.
+	 *	@param res the resource being accessed
+	 *	@param arg the SHTTPD state
+	 */
+	void handle(Resource *res, shttpd_arg *arg);
+
+	/**
+	 * This method is meant to be overridden by derived classes.
+	 * It is invoked by #handle after all the common processing
+	 * (e.g. context association and error handling) has been done.
+	 * The current implementation throws a 403/Forbidden exception
+	 *	@param resource the resource being accessed
+	 *	@param httpContext the context
+	 */
+	virtual void serveRequest(Resource *resource,
+			HTTPSessionContext *httpContext) throw (HTTPException);
+
+private:
+	/**
+	 * The callback method, invoked by SHTTPD to inform that
+	 * an HTTP request must be served. This method actually
+	 * looks for the correct instance of HTTPServer, and
+	 * invokes #handle.
+	 *	@param arg the SHTTPD state
+	 */
+	static void callback(shttpd_arg *arg);
+
+	/**
+	 * Updates the security settings of SHTTPD, using the 
+	 * information stored in the #plist object.
+	 */
+	void updateAssociations();
+
+	// itterators:
+	// Attributes visible by scope of instantiation and use
+
+protected:
+	// Attributes visible to descendents
+
+	///	HTTP Server context (refer to SHTTPD library)
+	struct shttpd_ctx *serverContext;
+
+	int pollTimeout;
+
+	///	To enable/disable Debug (default value is 0)
+	bool debugEnabled;
+	int debugLevel;
+
+	///	Pointer to a Debug object -> logger
+	Debug *pLogger;
+
+private:
+	// Local attributes
+	static ResourceDescriptor rootDesc;
+
+	Resource root;
+
+	ProtectedURIList plist;
+
+	// List of active HTTPSessionContext (each identified by a Session Id
+	std::list<int> activeHTTPSessions;
+
+};
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CLocalNode.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CLocalNode.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CLocalNode.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,1325 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include "tinyxml.h"		//needed for TiXmlDocument!
+#include "CLocalNode.h"
+
+template<class T>
+LocalNode<T> LocalNode<T>::instance;
+
+/**
+ Constructor
+ LocalNode constructor. It is a protected method (pattern Singleton)
+
+ @param void Void.
+ @return Void.
+ */
+template<class T>
+LocalNode<T>::LocalNode() :
+		functionsContext(GalZbIf::Instance()->getFeatureControl()) {
+#ifdef DEBUG_ACTIVE_GALZB
+	printf("LocalNode - Constructor\n"); //TODO: replace with pLogger->debug
+#endif
+
+	pthread_mutex_init(&mux, NULL);
+
+	//Timers initialization
+	initTimers();
+
+	pGalZb = GalZbIf::Instance();
+
+	pGalDb = pGalZb->getDb();
+
+	gwDescriptor = new GwDescriptor();
+
+	timerThreadResult = 1;
+	threadPoolResult = 1;
+}
+
+/**
+ Destructor
+ LocalNode destructor.
+
+ @param void Void.
+ @return Void.
+ */
+template<class T>
+LocalNode<T>::~LocalNode() {
+#ifdef DEBUG_ACTIVE_GALZB
+	printf("LocalNode - Destructor\n");
+#endif
+	// Kill the thread
+	if (tasks.startZNP.taskStarted)
+		pthread_cancel(tasks.startZNP.tid);
+	if (pLogger != NULL) {
+		delete (pLogger);
+		pLogger = NULL;
+	}
+	//Kill timers
+	if (timerThreadResult != 0) {
+		printf("LocalNode - Killing timerThread...\n");
+		timerThreadResult = TimerThreadShutdown(&timerThread);
+	}
+	if (threadPoolResult != 0) {
+		printf("LocalNode - Killing threadPool...\n");
+		threadPoolResult = ThreadPoolShutdown(&threadPool);
+	}
+
+	free(gwDescriptor);
+}
+
+/**
+ Public method LocalNode *getLocalNode(void)
+ (pattern Singleton)
+
+ @param void Void.
+ @return Instance of LocalNode class.
+ */
+template<class T>
+LocalNode<T> *LocalNode<T>::getLocalNode(void) {
+	return &instance;
+}
+
+/**
+ Public method LocalNode init
+ LocalNode initialization.
+
+
+ @param device String specifing the local device.
+ @return Void.
+ */
+template<class T>
+void LocalNode<T>::init(const char *device) {
+	ConfigurationRepository *_conf = ConfigurationRepository::instance();
+	// We load the configuration from the ConfigurationManager
+	this->debugEnabled = _conf->getint("main:debugEnabled", false);
+	this->debugLevel = _conf->getint("Debug:LocalNodeDL", TEST);
+
+	// Debug
+	pLogger = new Debug("LocalNode");
+	pLogger->setDebugMode(this->debugEnabled);
+	pLogger->setDebugLevel(this->debugLevel);
+
+	pLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+	pLogger->enableDebugOuput(DBG_SCREEN);
+
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("init");
+#endif
+
+	/// Set localDevice
+	this->localDevice = device;
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("init - localDevice = %s \n",localDevice);
+#endif
+
+	// Init pGalZb
+	pGalZb->init();
+
+	pGalZb->registerListener(GW_STATUS_CHANGED_EVENT,
+			(void *) (&gwStatusChanged_Event_CbW));
+
+	this->loadDefaultStartAttributeSet();
+
+	//TODO To be moved to TCAgent and invoked by RESTBroker
+	this->loadTCKeyTable();
+
+	pGalZb->LoadConfig(NULL);
+
+	gwDescriptor->setGwState(pGalZb->getGWStatus());
+	gwDescriptor->setErrorCode(0); //TODO  Complete
+
+	this->initZNP();
+}
+
+template<class T>
+void LocalNode<T>::setWSNId(const char *id) {
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("setWSNId - WSN Id = %s\n",id);
+#endif
+	gwDescriptor->setWSNId(id);
+}
+
+template<class T>
+GwDescriptor* LocalNode<T>::getGwDescriptor() {
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("getGwDescriptor - ");
+#endif
+
+	return this->gwDescriptor;
+}
+
+/*
+ template<class T>
+ uchar* LocalNode<T>::getLocalNodeNwkAddress() {
+ return pGalZb->getLocalNwkAddress_uc();
+ }
+
+ template<class T>
+ ushort LocalNode<T>::getLocalNodeNwkAddress_us() {
+ return pGalZb->getLocalNwkAddress_us();
+ }
+
+ template<class T>
+ uchar* LocalNode<T>::getLocalNodeIEEEAddress() {
+ return pGalZb->getLocalIEEEAddress_uc();
+ }
+ */
+
+template<class T>
+void LocalNode<T>::set_securityLevel(int sec) {
+	if (pGalZb != NULL) {
+		pGalZb->securityLevel = sec;
+	}
+}
+
+/**
+ Public method LocalNode startGatewayDevice
+ LocalNode initialization.
+
+
+ @param timeout	integer measured in milliseconds where the value of 0xffffffff
+ shall indicate an infinite amount of time
+ @param sai
+ @param rpcContextData
+ @return int
+ */
+
+template<class T>
+int LocalNode<T>::startGatewayDevice(unsigned long int timeout,
+		StartupAttributeInfo *sai, StartGatewayDeviceCtxt *rpcContextData) {
+	int gwStatus;
+
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("startGatewayDevice");
+#endif
+
+	unsigned long int restTimeout = timeout;
+
+	gwStatus = pGalZb->getGWStatus();
+
+	// Init result value
+	functionsContext.startGatewayDevice.result = FSUCCESS;
+
+	switch (gwStatus) {
+	//		case GW_STOPPED:
+	case GW_ZNP_SERIAL_INITIALIZED: {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("startup - current GW Status = %d -> call start", gwStatus);
+#endif
+
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("startGatewayDevice - configure startup attributes");
+#endif
+
+		if (sai != NULL) {
+			int setResult = pGalDb->setStartupAttributeInfo(1, sai); //TODO	Modify the first parameter
+			if (setResult) {
+				pLogger->info("startGatewayDevice - the provided StartupAttributeSet contains errors");
+
+				// RPC response Callback
+				RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED,
+						AGENT_ERROR);
+				//TODO Modify the error value - Actually, this error relates to a wrong config.
+
+				CALL_RESPONSE (rpcContextData)(NOT_A_VALUE,
+						rpcContextData->getSessionId(), &rpcReqStatus);
+
+				return AGENT_ERROR;
+				//TODO Modify the error value - Actually, this error relates to a wrong config.
+			}
+		}
+		// Register RPC Context Data (containing RPC SessionId and RPC callbacks for response and notification)
+		// related to the specific request.
+		functionsContext.startGatewayDevice.rpcContext = *rpcContextData;
+
+		// In case an asynch request is considered, RPC response Callback has to be invoked
+		if (functionsContext.startGatewayDevice.rpcContext.getRPCNotifyCb()
+				!= NULL) {
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->info("startGatewayDevice - asynch request");
+#endif
+			RPCReqStatus rpcReqStatus(End, FSUCCESS, AGENT_SUCCESS, true);
+
+			CALL_RESPONSE (rpcContextData)(NOT_A_VALUE,
+					rpcContextData->getSessionId(), &rpcReqStatus);
+		}
+		// Timer creation management
+		if (timeout > 0x00000000 && timeout != 0xffffffff) {
+			// Convert timeout from milliseconds to seconds (ceil)
+			timeout = timeout / 1000 + ((timeout % 1000) ? 1 : 0);
+
+			///	Set the timer for stopping the startGatewayDevice process
+			functionsContext.startGatewayDevice.fTimeout = (int) timeout;
+			pLogger->info("startGatewayDevice - timeout value = %d (sec)", functionsContext.startGatewayDevice.fTimeout);
+
+			if (!functionsContext.startGatewayDevice.setTimer(&timerThread,
+					this, &LocalNode::onStartGatewayDevice)) {
+
+				pLogger->fatal("startGatewayDevice - ERROR creating timer!");
+
+				//TODO Change! - in case of asynch request -> send a notify event otherwise send a response now!
+				/*
+
+				 // RPC response Callback
+				 RPCReqStatus rpcReqStatus (NotAvailable, FNOT_STARTED,
+				 TIMER_ERROR);
+				 CALL_RESPONSE (rpcContextData)
+				 (rpcContextData -> getSessionId (),
+				 &rpcReqStatus);
+				 */
+				return TIMER_ERROR;
+			}
+		} else {
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->info("startGatewayDevice - timer disabled");
+#endif
+		}
+
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("startGatewayDevice - call start");
+#endif
+
+		// In case the timeout specified at REST is too small (i.e. < 1 sec), do not do anything and
+		// leave the timer to expire
+		if ((int) restTimeout > 0 && (int) restTimeout < 1000)
+			return AGENT_SUCCESS;
+
+		int startResult;
+		if (!tasks.startZNP.taskStarted) {
+			startResult = tasks.startZNP.start(startZNPTask_SW);
+			if (startResult)
+				pLogger->error("startGatewayDevice - Error - task start failure (result = %d)", startResult);
+		}
+		return AGENT_SUCCESS;
+	}
+		break;
+
+		//MOD!!!!!!!!!!!!!!!!!!!!!!!!
+		/*
+		 case GW_ZNP_SERIAL_INITIALIZED:
+		 {
+		 #ifdef DEBUG_ACTIVE_GALZB
+		 pLogger->debug("startup - GW Status = %d -> Startup already called", gwStatus);
+		 #endif
+
+		 // RPC response Callback
+		 RPCReqStatus *rpcReqStatus = new RPCReqStatus( End, FFAILED, GW_STARTUP_ALREADY_CALLED);
+		 CALL_RESPONSE (rpcContextData)
+		 (rpcContextData -> getSessionId (), rpcReqStatus);
+		 delete(rpcReqStatus);
+
+		 return GW_STARTUP_ALREADY_CALLED;
+		 }
+		 break;
+		 */
+
+	case GW_STARTING: {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("startup - GW Status = %d -> Startup already called", gwStatus);
+#endif
+
+		// RPC response Callback
+		RPCReqStatus *rpcReqStatus = new RPCReqStatus(End, FFAILED,
+				GW_STARTUP_ALREADY_CALLED);
+		CALL_RESPONSE (rpcContextData)(NOT_A_VALUE,
+				rpcContextData->getSessionId(), rpcReqStatus);
+		delete (rpcReqStatus);
+
+		return GW_STARTUP_ALREADY_CALLED;
+	}
+		break;
+
+	case GW_RUNNING: {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("startup - GW Status = %d -> call restart", gwStatus);
+#endif
+
+		if (sai != NULL) {
+			int setResult = pGalDb->setStartupAttributeInfo(1, sai); //TODO	Modify the first parameter
+			if (setResult) {
+
+				pLogger->error("startGatewayDevice - the provided StartupAttributeSet contains errors");
+
+				// RPC response Callback
+				RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED,
+						AGENT_ERROR);
+				//TODO Modify the error value - Actually, this error relates to a wrong config.
+
+				CALL_RESPONSE (rpcContextData)(NOT_A_VALUE,
+						rpcContextData->getSessionId(), &rpcReqStatus);
+
+				return AGENT_ERROR;
+				//TODO Modify the error value - Actually, this error relates to a wrong config.
+			}
+		}
+
+		//Check the timeout value
+		if (timeout > 0x00000000 && timeout != 0xffffffff) {
+
+			// Convert timeout from milliseconds to seconds (ceil)
+			timeout = timeout / 1000 + ((timeout % 1000) ? 1 : 0);
+
+			///	Set the timer for stopping the startGatewayDevice process
+			functionsContext.startGatewayDevice.fTimeout = (int) timeout;
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->info("startGatewayDevice - timeout value = %d (sec)", functionsContext.startGatewayDevice.fTimeout);
+#endif
+			if (!functionsContext.startGatewayDevice.setTimer(&timerThread,
+					this, &LocalNode::onStartGatewayDevice)) {
+
+				pLogger->error("startGatewayDevice - ERROR creating timer!");
+
+				// RPC response Callback
+				RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED,
+						TIMER_ERROR);
+				CALL_RESPONSE (rpcContextData)(NOT_A_VALUE,
+						rpcContextData->getSessionId(), &rpcReqStatus);
+
+				return TIMER_ERROR;
+			}
+		} else {
+			/// If timeout value is 0xffffffff (infinite amount of time) or 0x00000000 do not use timer
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->info("startGatewayDevice - timeout value infinite or zero - timer disabled");
+#endif
+		}
+
+		///	Register RPC Context Data (containing RPC SessionId and RPC callbacks for response and notification) related to the specific request.
+		//TODO - Register in a safer way!
+		functionsContext.startGatewayDevice.rpcContext = *rpcContextData;
+
+		if (functionsContext.startGatewayDevice.rpcContext.getRPCNotifyCb()
+				!= NULL) {
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("startGatewayDevice - getRPCNotifyCb() != NULL = asynch request");
+#endif
+			// RPC response Callback
+			RPCReqStatus *rpcReqStatus = new RPCReqStatus(End, FSUCCESS,
+					AGENT_SUCCESS, true);
+
+			CALL_RESPONSE (rpcContextData)(NOT_A_VALUE,
+					rpcContextData->getSessionId(), rpcReqStatus);
+			delete (rpcReqStatus);
+		}
+
+		if ((int) restTimeout > 0 && (int) restTimeout < 1000)
+			return AGENT_SUCCESS;
+
+		this->start();
+
+		return AGENT_SUCCESS;
+	}
+		break;
+
+	case GW_ERROR: {
+		//Retry!
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("startup - GW Status = %d -> try to restart", gwStatus);
+#endif
+
+		if (sai != NULL) {
+			int setResult = pGalDb->setStartupAttributeInfo(1, sai); //TODO	Modify the first parameter
+			if (setResult) {
+				pLogger->info("startGatewayDevice - the provided StartupAttributeSet contains errors");
+
+				// RPC response Callback
+				RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED,
+						AGENT_ERROR);
+				//TODO Modify the error value - Actually, this error relates to a wrong config.
+
+				CALL_RESPONSE (rpcContextData)(NOT_A_VALUE,
+						rpcContextData->getSessionId(), &rpcReqStatus);
+
+				return AGENT_ERROR;
+				//TODO Modify the error value - Actually, this error relates to a wrong config.
+			}
+		}
+
+		// Timer creation management
+		if (timeout > 0x00000000 && timeout != 0xffffffff) {
+
+			// Convert timeout from milliseconds to seconds (ceil)
+			timeout = timeout / 1000 + ((timeout % 1000) ? 1 : 0);
+
+			///	Set the timer for stopping the startGatewayDevice process
+			functionsContext.startGatewayDevice.fTimeout = (int) timeout;
+			pLogger->info("startGatewayDevice - timeout value = %d (sec)", functionsContext.startGatewayDevice.fTimeout);
+
+			if (!functionsContext.startGatewayDevice.setTimer(&timerThread,
+					this, &LocalNode::onStartGatewayDevice)) {
+
+				pLogger->error("startGatewayDevice - ERROR creating timer!");
+
+				// RPC response Callback
+				RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED,
+						TIMER_ERROR);
+				CALL_RESPONSE (rpcContextData)(NOT_A_VALUE,
+						rpcContextData->getSessionId(), &rpcReqStatus);
+
+				return TIMER_ERROR;
+			}
+		} else {
+			/// If timeout value is 0xffffffff (infinite amount of time) or 0x00000000 do not use timer
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->info("startGatewayDevice - timeout value infinite or zero - timer disabled");
+#endif
+		}
+
+		///	Register RPC Context Data (containing RPC SessionId and RPC callbacks for response and notification) related to the specific request.
+		//TODO - Register in a safer way!
+		functionsContext.startGatewayDevice.rpcContext = *rpcContextData;
+
+		// RPC response Callback
+		if (functionsContext.startGatewayDevice.rpcContext.getRPCNotifyCb()
+				!= NULL) {
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->info("startGatewayDevice - getRPCNotifyCb() != NULL = asynch request");
+#endif
+			// RPC response Callback
+			RPCReqStatus *rpcReqStatus = new RPCReqStatus(End, FSUCCESS,
+					AGENT_SUCCESS, true);
+			CALL_RESPONSE (rpcContextData)(NOT_A_VALUE,
+					rpcContextData->getSessionId(), rpcReqStatus);
+			delete (rpcReqStatus);
+		}
+
+		if ((int) restTimeout > 0 && (int) restTimeout < 1000)
+			return AGENT_SUCCESS;
+
+		this->start();
+
+		return AGENT_SUCCESS;
+	}
+		break;
+
+	default: // This state should be unreachable
+	{
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->error(" - gwStatus value = %d unknown",gwStatus);
+#endif
+
+		// RPC response Callback
+		RPCReqStatus *rpcReqStatus = new RPCReqStatus(End, FFAILED,
+				INVALID_GW_STATUS);
+		CALL_RESPONSE (rpcContextData)(NOT_A_VALUE,
+				rpcContextData->getSessionId(), rpcReqStatus);
+		delete (rpcReqStatus);
+
+		return INVALID_GW_STATUS; // gwStatus value is unknown -> unreachable state
+	}
+	}
+}
+
+template<class T>
+
+int LocalNode<T>::createCallback(StatusChanged_Event_NotifyCtxt *listener,
+		CreateCallbackCtxt *rpcContextData) {
+	listeners.gwStatusChanged.push_back(*listener);
+
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("createCallback - listener registered");
+#endif
+
+	// RPC response Callback
+	RPCReqStatus rpcReqStatus(End, FSUCCESS, AGENT_SUCCESS);
+	CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+			&rpcReqStatus);
+
+	return AGENT_SUCCESS;
+}
+
+template<class T>
+int LocalNode<T>::resetRequest(unsigned char options,
+		ResetCommandCtxt *rpcContextData) {
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->info("resetRequest");
+#endif
+
+	pthread_mutex_lock(&mux);
+
+	if (functionsContext.resetCommand.lock()) {
+		if (pGalDb->getStartModeSetting() == 0x00) {
+			//0 - StartupSetMode=0x18 (CommissioningMode) AND StartupControlMode=0x00 (Association) --> To be used the first time, when the network is created
+			options += 0x02; //Use CommissioningMode
+		} else if (pGalDb->getStartModeSetting() == 0x01) {
+			//1 - StartupSetMode=0x00 (use NVM) AND StartupControlMode=0x04 (SilentStart) --> To be used at running time
+			options += 0x10; //use SilentStartMode
+		} else if (pGalDb->getStartModeSetting() == 0x02) {
+			//2 - StartupSetMode=0x18 (CommissioningMode) AND StartupControlMode=0x04 (SilentStart) --> To be used for TC Replacement
+			options += 0x02; //Use CommissioningMode
+			options += 0x10; //use SilentStartMode
+		}
+
+		// Register to a listener!
+#ifdef DEBUG_ACTIVE_MA
+		pLogger->info("resetRequest - Register a listener on event ZB_ZDO_RESET_CONFIRM");
+#endif
+		pGalZb->registerListener(ZB_ZDO_RESET_CONFIRM,
+				(void *) (&resetCommandNotify_CbW));
+		// Register RPC Context Data (containing RPC SessionId and RPC callbacks for response and notification)
+		// related to the specific request.
+		functionsContext.resetCommand.rpcContext = *rpcContextData;
+		// Cal the reset!
+		pGalZb->ZDO_RESET_request(options);
+		if (functionsContext.resetCommand.rpcContext.getRPCNotifyCb() != NULL) {
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->info("resetRequest - asynch request");
+#endif
+			// RPC response Callback
+			RPCReqStatus rpcReqStatus(Running, FSUCCESS, AGENT_SUCCESS);
+			CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+					&rpcReqStatus);
+		}
+	} else {
+		pthread_mutex_unlock(&mux);
+		pLogger->info("resetRequest - A reset is already running");
+		// RPC response Callback
+		RPCReqStatus rpcReqStatus(NotAvailable, FSUCCESS, AGENT_BUSY);
+		CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+				&rpcReqStatus);
+		return AGENT_BUSY;
+	}
+
+	pthread_mutex_unlock(&mux);
+	return AGENT_SUCCESS;
+}
+
+//This is just a wrapper to call a static function!
+template<class T>
+void LocalNode<T>::resetCommandNotify_CbW(uchar status) {
+	LocalNode* localNode = LocalNode<T>::getLocalNode();
+	localNode->resetCommandNotify_Cb(status);
+	return;
+}
+
+template<class T>
+void LocalNode<T>::resetCommandNotify_Cb(uchar status) {
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("resetCommandNotify_Cb");
+#endif
+	pthread_mutex_lock(&mux);
+
+	//Unlock
+	functionsContext.resetCommand.unlock();
+
+	// RPC notify Callback
+	if (functionsContext.resetCommand.rpcContext.getRPCNotifyCb() != NULL) {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("resetCommandNotify_Cb - Procedure completed send asynch notification");
+#endif
+		RPCReqStatus rpcReqStatus(Idle, FSUCCESS, AGENT_SUCCESS);
+		FCALL_NOTIFY (functionsContext.resetCommand)(status, &rpcReqStatus);
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("resetCommandNotify_Cb - Procedure completed send synch response");
+#endif
+
+		// RPC response Callback
+		RPCReqStatus rpcReqStatus(functionsContext.resetCommand, AGENT_SUCCESS);
+		FCALL_RESPONSE (functionsContext.resetCommand)(
+				functionsContext.resetCommand.rpcContext.getSessionId(),
+				&rpcReqStatus);
+	}
+	pGalZb->unregisterListener(ZB_ZDO_RESET_CONFIRM,
+			(void *) (&resetCommandNotify_CbW));
+	pthread_mutex_unlock(&mux);
+	return;
+}
+
+/**
+ Public method LocalNode start
+ Start
+
+
+ @param void Void.
+ @return Void.
+ */
+template<class T>
+int LocalNode<T>::initZNP() {
+	int gwStatus;
+
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("start");
+#endif
+	gwStatus = pGalZb->ZbIfConnect_W(localDevice);
+	if (gwStatus != GW_ZNP_SERIAL_INITIALIZED) {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->error("start - ERROR: ZNP serial initialization failed");
+#endif
+		return 1;
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("start - ZNP serial initialization completed");
+#endif
+	}
+	return 0;
+}
+
+/**
+ Public method LocalNode stop
+ Stop
+
+
+ @param void Void.
+ @return Void.
+ */
+template<class T>
+int LocalNode<T>::stop() {
+	int gwStatus;
+
+#ifdef DEBUG_ACTIVE_GALZB
+	printf("LocalNode<T>::stop\n");
+#endif
+
+	gwStatus = pGalZb->ZbIfDisconnect_W();
+
+	return gwStatus;
+}
+
+template<class T>
+int LocalNode<T>::start() {
+	DiscoveryAgent<LocalNode> *pDAgent;
+
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("start");
+#endif
+
+	// Get the current StartupAttributeSetIndex used
+	StartupAttributeInfo *sai;
+	int currentSASIndex = pGalDb->getCurrentStartupAttributeSetIndex();
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("start - currentSASIndex = %d",currentSASIndex);
+#endif
+	sai = pGalDb->getStartupAttributeInfo(currentSASIndex);
+	if (sai == NULL) {
+		pLogger->fatal("start - sai = NULL");
+	}
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("security level %d", sai->_securityLevel);
+#endif
+	// Init startupPhase
+	/*
+	 if (sai->_securityLevel == 5)
+	 startupPhase = 2;	//insert 2 in order to launch the network up only once
+	 else
+	 startupPhase = 0;	//insert 0 for a non secure network since we want to execute twice the startup phase (useful to send a leave command)
+	 */
+	// NVMSetting is not used -> the data structures must be cleaned up before
+	// restarting the ZigBee GatewayDevice
+	if (pGalDb->getStartModeSetting() != 0x01) {
+		pLogger->info("start - NVMSetting is not used");
+		pGalDb->clearAllButRoot();
+		pDAgent = DiscoveryAgent<LocalNode>::Instance();
+		pDAgent->init();
+		pDAgent->clearDeadingNodeList();
+	}
+	pGalZb->Start();
+	return pGalZb->getGWStatus();
+
+}
+
+/**
+ Public method LocalNode getDiscoveryAgent
+ This method allows getting the instance of DiscoveryAgent class.
+
+ @param void Void.
+ @return Instance of DiscoveryAgent class.
+ */
+template<class T>
+DiscoveryAgent<T>* LocalNode<T>::getDiscoveryAgent() {
+	return DiscoveryAgent<T>::Instance();
+}
+
+/**
+ Public method LocalNode getServiceAgent
+ This method allows getting the instance of ServiceAgent class.
+
+ @param void Void.
+ @return Instance of ServiceAgent class.
+ */
+template<class T>
+ServiceAgent<T>* LocalNode<T>::getServiceAgent() {
+	return ServiceAgent<T>::Instance();
+}
+
+/**
+ Public method LocalNode getManagementAgent
+ This method allows getting the instance of ManagementAgent class.
+
+ @param void Void.
+ @return Instance of ManagementAgent class.
+ */
+template<class T>
+ManagementAgent<T>* LocalNode<T>::getManagementAgent() {
+	return ManagementAgent<T>::Instance();
+}
+
+#if 0
+/**
+ Public method LocalNode getTrustCenterAgent
+ This method allows getting the instance of TrustCenterAgent class.
+
+ @param void Void.
+ @return Instance of TrustCenterAgent class.
+ */
+template<class T>
+TrustCenterAgent<T>* LocalNode<T>::getTrustCenterAgent(
+)
+{
+	return TrustCenterAgent<T>::Instance();
+}
+#endif
+
+template<class T>
+int LocalNode<T>::loadDefaultStartAttributeSet() {
+	int channelMask = 0;
+	// Load the StartupAttribute Set from the Configuration file
+	StartupAttributeInfo sai;
+	ConfigurationRepository *_conf = ConfigurationRepository::instance();
+
+	// StartupAttributeSetIndex set to 0 - default
+	sai.startupAttributeSetIndex = 0;
+	// Device Type - default value = Coordinator
+	sai.deviceType = _conf->getint("DefaultStartupAttributeSet:DeviceType",
+			ZB_COORDINATOR);
+	if (sai.deviceType < 0 || sai.deviceType > 3) {
+		printf(
+				"ERROR: Inserted a wrong deviceType value, coordinator will be selected instead!\n");
+		sai.deviceType = ZB_COORDINATOR;
+	}
+	sai.isDeviceTypeDefined = true;
+	// Set the channel mask (default value = 0x00100000 - 20)
+	channelMask = _conf->getint("DefaultStartupAttributeSet:ChannelMask",
+			0x00100000);
+	if (channelMask == 0) {
+		// All/any channel
+		sai.channelMask = 0x07FFF800;
+	} else if (channelMask >= 11 && channelMask <= 26) {
+		// Shift the bit 1 by "n" positions!
+		sai.channelMask = 1 << channelMask;
+	} else {
+		pLogger->error("loadDefaultStartAttributeSet - INVALID CHANNEL MASK: %x",channelMask);
+		exit(0);
+		return -1;
+	}
+	/*
+	 switch (channelMask) {
+	 case 26:
+	 sai.channelMask = 0x04000000;
+	 break;
+	 case 25:
+	 sai.channelMask = 0x02000000;
+	 break;
+	 case 24:
+	 sai.channelMask = 0x01000000;
+	 break;
+	 case 23:
+	 sai.channelMask = 0x00800000;
+	 break;
+	 case 22:
+	 sai.channelMask = 0x00400000;
+	 break;
+	 case 21:
+	 sai.channelMask = 0x00200000;
+	 break;
+	 case 20:
+	 sai.channelMask = 0x00100000;
+	 break;
+	 case 19:
+	 sai.channelMask = 0x00080000;
+	 break;
+	 case 18:
+	 sai.channelMask = 0x00040000;
+	 break;
+	 case 17:
+	 sai.channelMask = 0x00020000;
+	 break;
+	 case 16:
+	 sai.channelMask = 0x00010000;
+	 break;
+	 case 15:
+	 sai.channelMask = 0x00008000;
+	 break;
+	 case 14:
+	 sai.channelMask = 0x00004000;
+	 break;
+	 case 13:
+	 sai.channelMask = 0x00002000;
+	 break;
+	 case 12:
+	 sai.channelMask = 0x00001000;
+	 break;
+	 case 11:
+	 sai.channelMask = 0x00000800;
+	 break;
+	 case 0:
+	 // All/any channel
+	 sai.channelMask = 0x07FFF800;
+	 break;
+	 default:
+	 pLogger->error("loadDefaultStartAttributeSet - INVALID CHANNEL MASK: %x",channelMask);
+	 exit(0);
+	 break;
+	 }
+	 */
+	// PAN Id
+	sai.PANId = _conf->getint("DefaultStartupAttributeSet:PANId", 0xFFFF);
+	/*
+	 if (sai.PANId == 0xFFFF) {
+	 //generate a random PanId
+	 srand((unsigned) time(0));
+	 sai.PANId = rand() % 0xFFFE;
+	 }
+	 */
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("The PANId that will be used is %04x",sai.PANId);
+#endif
+	// ExtendedPANId
+	_conf->getHexArray("DefaultStartupAttributeSet:ExtendedPanId",
+			"0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00", sai.extendedPANId, 8);
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("loadDefaultStartAttributeSet - sai.extendedPANId = [%02x %02x %02x %02x %02x %02x %02x %02x]",sai.extendedPANId[0],sai.extendedPANId[1],sai.extendedPANId[2],
+			sai.extendedPANId[3], sai.extendedPANId[4], sai.extendedPANId[5],
+			sai.extendedPANId[6], sai.extendedPANId[7]);
+#endif
+	// StartUpControl
+	sai.StartupControl = _conf->getint(
+			"DefaultStartupAttributeSet:StartUpControl", 0x00);
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("loadDefaultStartAttributeSet - StartupControl = %d",sai.StartupControl);
+#endif
+	sai.isStartupControlDefined = true;
+	// Security level - non standard info
+	sai._securityLevel = _conf->getint(
+			"DefaultStartupAttributeSet:SecurityLevel", 0);
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("loadDefaultStartAttributeSet - securityLevel = %d",sai._securityLevel);
+#endif
+	// Network Key
+	_conf->getHexArray("DefaultStartupAttributeSet:networkKey",
+			"0x5a 0x69 0x67 0x42 0x65 0x65 0x41 0x6c 0x6c 0x69 0x61 0x6e 0x63 0x65 0x30 0x39",
+			sai.networkKey, 16);
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("loadDefaultStartAttributeSet - sai.networkKey = [%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x]",
+			sai.networkKey[0],sai.networkKey[1],sai.networkKey[2],sai.networkKey[3],
+			sai.networkKey[4],sai.networkKey[5],sai.networkKey[6],sai.networkKey[7],
+			sai.networkKey[8],sai.networkKey[9],sai.networkKey[10],sai.networkKey[11],
+			sai.networkKey[12],sai.networkKey[13],sai.networkKey[14],sai.networkKey[15]);
+#endif
+	// Preconfigured Link Key
+	_conf->getHexArray("DefaultStartupAttributeSet:preconfiguredLinkKey",
+			"0x5a 0x69 0x67 0x42 0x65 0x65 0x41 0x6c 0x6c 0x69 0x61 0x6e 0x63 0x65 0x30 0x39",
+			sai.preconfiguredLinkKey, 16);
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("loadDefaultStartAttributeSet - sai.preconfiguredLinkKey = [%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x]",
+			sai.preconfiguredLinkKey[0],sai.preconfiguredLinkKey[1],sai.preconfiguredLinkKey[2],sai.preconfiguredLinkKey[3],
+			sai.preconfiguredLinkKey[4],sai.preconfiguredLinkKey[5],sai.preconfiguredLinkKey[6],sai.preconfiguredLinkKey[7],
+			sai.preconfiguredLinkKey[8],sai.preconfiguredLinkKey[9],sai.preconfiguredLinkKey[10],sai.preconfiguredLinkKey[11],
+			sai.preconfiguredLinkKey[12],sai.preconfiguredLinkKey[13],sai.preconfiguredLinkKey[14],sai.preconfiguredLinkKey[15]);
+#endif
+
+	/*
+	 // is TrustCenter Key Table Defined - non standard info
+	 sai._isTCKeyTableDefined = _conf->getint("DefaultStartupAttributeSet:TCKeyTableSize", 0);
+	 pLogger->debug("loadDefaultStartAttributeSet - sai._isTCKeyTableDefined=%d",sai._isTCKeyTableDefined);
+	 */
+	if (pGalDb->setStartupAttributeInfo(0, &sai)) {
+		pLogger->warn("loadDefaultStartAttributeSet - wrong default configuration");
+		//TODO what's the next action?
+	}
+
+	return 0;
+}
+
+template<class T>
+int LocalNode<T>::configureStartupAttributeSet(int startupAttributeSetIndex,
+		StartupAttributeInfo *sai,
+		RPCContext<T, startupResponseCb> *rpcContextData) {
+	if (pGalDb->setStartupAttributeInfo(1, sai)) {
+		pLogger->info("configureStartAttributeSet - wrong default configuration");
+		//TODO what's the next action?
+	}
+	return 0;
+}
+
+template<class T>
+int LocalNode<T>::readStartupAttributeSet(int startupAttributeSetIndex,
+		RPCContext<T, startupResponseCb> *rpcContextData) {
+	pLogger->info("readStartupAttributeSet");
+	return 0;
+}
+
+template<class T>
+StartupAttributeInfo* LocalNode<T>::readStartupAttributeSet(
+		int startupAttributeSetIndex) {
+	pLogger->info("readStartupAttributeSet LOCAL");
+	return pGalDb->getStartupAttributeInfo(startupAttributeSetIndex);
+}
+
+//TODO To be moved to TrustCenter Agent
+template<class T>
+int LocalNode<T>::loadTCKeyTable() {
+	// Load the Trust Center Key Table from the Configuration file
+
+	int i = 0;
+	tcKeyTableEntry tableEntry;
+	ConfigurationRepository *_conf = ConfigurationRepository::instance();
+
+	std::string ieeeAddStr;
+	std::string tcKeyEntryStr;
+	std::stringstream counter;
+
+	int size = _conf->getint("TCKeyTable:TCKeyTableSize", 0);
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("loadTCKeyTable - TCKeyTableSize = %d",size);
+#endif
+	pGalDb->setTCKeyTableSize(size);
+
+	for (i = 0; i < size; i++) {
+		counter.str("");
+		counter.width(2);
+		counter.fill('0');
+		counter << i;
+		ieeeAddStr = string("TCKeyTable:IEEEAddress") + counter.str();
+		tcKeyEntryStr = string("TCKeyTable:TCLinkKey") + counter.str();
+
+		tableEntry.keyTableEntryIndex = i;
+
+		// IEEE Address
+		_conf->getHexArray(ieeeAddStr.c_str(),
+				"0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00",
+				tableEntry.ieeeAddress, 8);
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("loadTCKeyTable - tableEntry.ieeeAddress = [%02x %02x %02x %02x %02x %02x %02x %02x]",tableEntry.ieeeAddress[0],tableEntry.ieeeAddress[1],
+				tableEntry.ieeeAddress[2], tableEntry.ieeeAddress[3], tableEntry.ieeeAddress[4], tableEntry.ieeeAddress[5],
+				tableEntry.ieeeAddress[6], tableEntry.ieeeAddress[7]);
+#endif
+
+		// Preconfigured Link Key
+		_conf->getHexArray(tcKeyEntryStr.c_str(),
+				"0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00",
+				tableEntry.preconfiguredLinkKey, 16);
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("loadTCKeyTable - tableEntry.preconfiguredLinkKey = [%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x]",
+				tableEntry.preconfiguredLinkKey[0],tableEntry.preconfiguredLinkKey[1],tableEntry.preconfiguredLinkKey[2],tableEntry.preconfiguredLinkKey[3],
+				tableEntry.preconfiguredLinkKey[4],tableEntry.preconfiguredLinkKey[5],tableEntry.preconfiguredLinkKey[6],tableEntry.preconfiguredLinkKey[7],
+				tableEntry.preconfiguredLinkKey[8],tableEntry.preconfiguredLinkKey[9],tableEntry.preconfiguredLinkKey[10],tableEntry.preconfiguredLinkKey[11],
+				tableEntry.preconfiguredLinkKey[12],tableEntry.preconfiguredLinkKey[13],tableEntry.preconfiguredLinkKey[14],tableEntry.preconfiguredLinkKey[15]);
+#endif
+
+		if (pGalDb->setTCKeyTableEntry(&tableEntry)) {
+			pLogger->warn("setTCKeyTableEntry - something went wrong (index %d)", i);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+template<class T>
+void LocalNode<T>::gwStatusChanged_Event_CbW(int gwStatus, int errorCode,
+		uchar commandStatus) {
+	LocalNode* localNode = LocalNode<T>::getLocalNode();
+
+#ifdef DEBUG_ACTIVE_GALZB
+	if (localNode->debugEnabled == true)
+	printf("\ngwStatusChanged_Event_CbW\n");
+#endif
+
+	localNode->gwStatusChanged_Event_Cb(gwStatus, errorCode, commandStatus);
+
+}
+
+template<class T>
+void LocalNode<T>::gwStatusChanged_Event_Cb(int gwStatus, int errorCode,
+		uchar commandStatus) {
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->info("gwStatusChanged_Event_Cb - gwStatus = %d -- errorCode = %d -- commandStatus = 0x%x",gwStatus, errorCode, commandStatus);
+#endif
+
+	if (functionsContext.startGatewayDevice.result == FFAILED) {
+		pLogger->info("gwStatusChanged_Event_Cb - the procedure previously failed");
+		return;
+	}
+
+	//PATCH
+	if (gwStatus == GW_ERROR && errorCode == GW_ZNP_INITIALIZATION_FAILED) {
+		pLogger->error("gwStatusChanged_Event_Cb - GW_ZNP_INITIALIZATION_FAILED");
+		exit(1);
+	}
+
+	if (gwStatus == GW_ERROR && errorCode == 500) {
+		this->start();
+		return;
+	}
+
+	//Update GwDescriptor
+	gwDescriptor->setGwState(gwStatus);
+	gwDescriptor->setErrorCode(errorCode);
+
+	if (!listeners.gwStatusChanged.empty()) {
+		typename std::list<StatusChanged_Event_NotifyCtxt>::iterator iter;
+
+		// RPC notify Callback
+		RPCReqStatus rpcReqStatus(Running, FSUCCESS, AGENT_SUCCESS);
+
+		for (iter = listeners.gwStatusChanged.begin();
+				iter != listeners.gwStatusChanged.end(); iter++) {
+
+			CALL_NOTIFY (&(*iter))(gwDescriptor, &rpcReqStatus);
+		}
+
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("gwStatusChanged_Event_Cb - Map Listeners empty");
+#endif
+	}
+
+	if (gwStatus == GW_RUNNING) {
+		// The gateway is running so we can delete the timer
+		functionsContext.startGatewayDevice.killTimer();
+		//TODO Add here the update of Information Bases
+		if (functionsContext.startGatewayDevice.rpcContext.getRPCNotifyCb()
+				!= NULL) {
+			// startGatewayDevice was invoked as an asynchronous procedure
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("gwStatusChanged_Event_Cb - raise startGatewayDevice event (asynchronous)");
+#endif
+			RPCReqStatus rpcReqStatus(functionsContext.startGatewayDevice,
+					AGENT_SUCCESS);
+			FCALL_NOTIFY (functionsContext.startGatewayDevice)(commandStatus,
+					&rpcReqStatus);
+		} else {
+			//startGatewayDevice was invoked as a synchronous procedure
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("gwStatusChanged_Event_Cb - CALL_RESPONSE");
+#endif
+
+			if (functionsContext.startGatewayDevice.rpcContext.getRPCResponseCb()
+					!= NULL) {
+
+				// RPC notify Callback
+				RPCReqStatus rpcReqStatus(Running, FSUCCESS, AGENT_SUCCESS);
+				FCALL_RESPONSE (functionsContext.startGatewayDevice)(
+						commandStatus,
+						functionsContext.startGatewayDevice.rpcContext.getSessionId(),
+						&rpcReqStatus);
+			} else {
+				pLogger->warn("gwStatusChanged_Event_Cb - getRPCResponseCb() == NULL");
+			}
+		}
+
+	} else if (gwStatus == GW_ERROR) {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("gwStatusChanged_Event_Cb - (gwStatus != GW_RUNNING) raised startGatewayDevice event!");
+#endif
+		// If timer related to startGatewayDevice
+		if (!functionsContext.startGatewayDevice.killTimer()) {
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->info("gwStatusChanged_Event_Cb - Timer removed");
+#endif
+		} else
+			pLogger->warn("gwStatusChanged_Event_Cb - Timer was already removed");
+
+		//TODO Add here the update of Information Bases
+
+		// RPC notify Callback
+		if (functionsContext.startGatewayDevice.rpcContext.getRPCNotifyCb()
+				!= NULL) {
+
+			// startGatewayDevice was invoked as an asynchronous procedure
+			pLogger->info("gwStatusChanged_Event_Cb - startGatewayDevice procedure deleted!");
+			functionsContext.startGatewayDevice.fstate = Canceled;
+			pLogger->info("gwStatusChanged_Event_Cb - functionsContext.startGatewayDevice.fstate = Canceled");
+
+			AgentError ae = AGENT_SUCCESS;
+			if (errorCode == 11) {
+				pLogger->info("gwStatusChanged_Event_Cb - AgentError = GW_STARTUP_FORMING_NETWORK_FAILED");
+				ae = GW_STARTUP_FORMING_NETWORK_FAILED;
+			} else if (errorCode == 10) {
+				pLogger->info("gwStatusChanged_Event_Cb - AgentError = GW_STARTUP_JOINING_NETWORK_FAILED");
+				ae = GW_STARTUP_JOINING_NETWORK_FAILED;
+			} else {
+				pLogger->error("gwStatusChanged_Event_Cb - errorCode = %d - Unreachable status",errorCode);
+			}
+
+			RPCReqStatus rpcReqStatus(functionsContext.startGatewayDevice, ae);
+			FCALL_NOTIFY (functionsContext.startGatewayDevice)(commandStatus,
+					&rpcReqStatus);
+
+		} else {
+
+			//startGatewayDevice was invoked as a synchronous procedure
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->info("gwStatusChanged_Event_Cb - CALL_RESPONSE !!");
+#endif
+			// RPC Response Callback
+			fState_t fstatetmp;
+			fstatetmp = Canceled;
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->info("functionsContext.startGatewayDevice.fstate = Canceled");
+#endif
+			AgentError ae = AGENT_SUCCESS;
+			if (errorCode == 11) {
+				pLogger->info("gwStatusChanged_Event_Cb - AgentError = GW_STARTUP_FORMING_NETWORK_FAILED");
+				ae = GW_STARTUP_FORMING_NETWORK_FAILED;
+			} else if (errorCode == 10) {
+				pLogger->info("gwStatusChanged_Event_Cb - AgentError = GW_STARTUP_JOINING_NETWORK_FAILED");
+				ae = GW_STARTUP_JOINING_NETWORK_FAILED;
+			} else {
+				pLogger->error("gwStatusChanged_Event_Cb - errorCode = %d - Unreachable status",errorCode);
+			}
+
+			RPCReqStatus rpcReqStatus(fstatetmp, FFAILED, ae);
+
+			FCALL_RESPONSE (functionsContext.startGatewayDevice)(commandStatus,
+					functionsContext.startGatewayDevice.rpcContext.getSessionId(),
+					&rpcReqStatus);
+		}
+
+	}
+}
+
+/**
+ Protected method LocalNode initTimers
+ Timers initialization.
+
+ @param void Void.
+ @return Status.
+ */
+template<class T>
+int LocalNode<T>::initTimers(void) {
+	ThreadPoolAttr attr;
+
+	TPAttrInit(&attr);
+	TPAttrSetMaxThreads(&attr, DA_MAX_THREADS);
+	TPAttrSetMinThreads(&attr, DA_MIN_THREADS);
+	TPAttrSetJobsPerThread(&attr, DA_JOBS_PER_THREAD);
+	TPAttrSetIdleTime(&attr, DA_THREAD_IDLE_TIME);
+
+#ifdef NEW_VERSION
+	TPAttrSetMaxJobsTotal(&attr, DA_MAX_JOBS_TOTAL);
+#endif
+
+	if (ThreadPoolInit(&threadPool, &attr) != 0) {
+		//return GAL_E_ERROR;			//TODO		Define new error code
+		return -1;
+	}
+	//return GAL_SUCCESS;				//TODO		Define new error code
+
+	TimerThreadInit(&timerThread, &threadPool);
+
+	return 0;
+}
+
+template<class T>
+void LocalNode<T>::onStartGatewayDevice() {
+	pthread_mutex_lock(&mux);
+	pLogger->error("onTimer - startGatewayDevice canceled (timeout expired)");
+	functionsContext.startGatewayDevice.resetTimerEnv();
+	/// Set result
+	functionsContext.startGatewayDevice.result = FFAILED;
+	if (functionsContext.startGatewayDevice.rpcContext.getRPCNotifyCb()
+			!= NULL) {
+		// startGatewayDevice was invoked as an asynchronous procedure
+		pLogger->info("onStartGatewayDevice - raise startGatewayDevice event!");
+		RPCReqStatus rpcReqStatus(functionsContext.startGatewayDevice,
+				TIMER_EXPIRED);
+		FCALL_NOTIFY (functionsContext.startGatewayDevice)(NOT_A_VALUE,
+				&rpcReqStatus);
+	} else {
+		//startGatewayDevice was invoked as a synchronous procedure
+		pLogger->info("gwStatusChanged_Event_Cb - CALL_RESPONSE!");
+
+		if (functionsContext.startGatewayDevice.rpcContext.getRPCResponseCb()
+				!= NULL) {
+
+			// RPC response Callback
+			RPCReqStatus rpcReqStatus(functionsContext.startGatewayDevice,
+					TIMER_EXPIRED);
+
+			FCALL_RESPONSE (functionsContext.startGatewayDevice)(NOT_A_VALUE,
+					functionsContext.startGatewayDevice.rpcContext.getSessionId(),
+					&rpcReqStatus);
+		} else {
+			pLogger->warn("gwStatusChanged_Event_Cb - getRPCResponseCb() == NULL !");
+		}
+
+	}
+	pthread_mutex_unlock(&mux);
+}
+
+template<class T>
+LocalNode<T>::Task::Task(void) {
+	taskStarted = false;
+}
+
+template<class T>
+int LocalNode<T>::Task::start(void *(*invokedMethod)(void *)) {
+	LocalNode* pLocalNode;
+	Debug *pLogger;
+
+	int returnValue = 0;
+
+	pLocalNode = LocalNode<T>::getLocalNode();
+	pLogger = pLocalNode->pLogger;
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("Task::start");
+#endif
+	if (taskStarted) {
+		pLogger->error("Task::start - Thread already started!"
+				"(unreachable state)");
+		return -1;
+	}
+
+	taskStarted = true;
+
+	returnValue = pthread_create(&tid, NULL, invokedMethod, NULL);
+	if (returnValue) {
+		pLogger->error("Task::start - Error in creating thread");
+		taskStarted = false;
+	}
+
+	return returnValue;
+}
+
+template<class T>
+void LocalNode<T>::Task::stop(void) {
+	if (taskStarted) {
+		taskStarted = false;
+		pthread_join(tid, NULL);
+	}
+}
+
+template<class T>
+void* LocalNode<T>::startZNPTask_SW(void *arg) {
+	LocalNode* pLocalNode;
+	Debug *pLogger;
+
+	pLocalNode = LocalNode<T>::getLocalNode();
+	pLogger = pLocalNode->pLogger;
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("startZNPTask_SW");
+#endif
+	pLocalNode->start();
+
+	pLocalNode->tasks.startZNP.taskStarted = false;
+
+	return 0;
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CLocalNode.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CLocalNode.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CLocalNode.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,239 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef LOCALNODE_H
+#define LOCALNODE_H
+
+#include <list>	
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "ThreadPool.h"
+#include "TimerThread.h"
+
+#include "GalZbIf.h"
+#include "CDiscoveryAgent.h"
+#include "CServiceAgent.h"
+#include "CManagementAgent.h"
+#include "CTrustCenterAgent.h"
+#include "ConfigurationRepository.h"
+#include "XMLProcessor.h"
+
+/**
+ LocalNode exposes to upper layer some of its internal features. In particular, the considered features are organized as macrofunctions,
+ i.e. Startup, ...
+ Each macrofunction is identified by a unique ID (please refer to the following ID list).
+ This unique ID is used as a key in associative arrays containing macrofunction context (e.g. the status
+ of the macrofunction,  ...) or the RPC listeners registered on the specific function.
+ */
+#define LND_STARTUP					1
+
+#define	NOT_A_VALUE					0xFF
+
+template<class T>
+class LocalNode {
+
+public:
+	//	function pointers types related to RPC callbacks (Macrofunction Startup)
+	typedef void * (T::*startupResponseCb)(uchar status, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void * (T::*startupNotifyCb)(uchar status,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void *(T::*resetResponseCb)(int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void *(T::*resetNotifyCb)(uchar status, RPCReqStatus *rpcReqStatus);
+
+	typedef RPCContext<T, resetResponseCb, resetNotifyCb> ResetCommandCtxt;
+
+	typedef void * (T::*createCallbackResponseCb)(int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void * (T::*gwStatusChanged_Event_NotifyCb)(
+			GwDescriptor *gwDescriptor, RPCReqStatus *rpcReqStatus);
+
+	typedef RPCContext<T, startupResponseCb> StartupResponseCtxt;
+
+	typedef RPCContext<T, void *, gwStatusChanged_Event_NotifyCb> StatusChanged_Event_NotifyCtxt;
+
+	typedef RPCContext<T, createCallbackResponseCb> CreateCallbackCtxt;
+
+	typedef RPCContext<T, startupResponseCb, startupNotifyCb> StartGatewayDeviceCtxt;
+
+public:
+	// Constructors
+
+	// Destructor
+	~LocalNode();
+
+	// Functions: modifiers (set), selectors (get)
+
+	// Pattern Singleton
+	static LocalNode *getLocalNode(void);
+
+	void init(const char *device);
+	int initZNP();
+	int stop();
+	int start();
+
+	void set_securityLevel(int sec);
+
+	void setWSNId(const char *id);
+
+	GwDescriptor *getGwDescriptor();
+
+	/*
+	 uchar *getLocalNodeNwkAddress( );
+	 ushort getLocalNodeNwkAddress_us( );
+	 uchar *getLocalNodeIEEEAddress( );
+	 */
+
+	static DiscoveryAgent<T> *getDiscoveryAgent(void);
+
+	static ServiceAgent<T> *getServiceAgent(void);
+
+	static ManagementAgent<T> *getManagementAgent(void);
+
+#if 0
+	static TrustCenterAgent<T> *getTrustCenterAgent(void);
+#endif
+
+	static void gwStatusChanged_Event_CbW(int gwStatus, int errorCode,
+			uchar commandStatus);
+
+	int startGatewayDevice(
+			//int timeout,
+			unsigned long int timeout, StartupAttributeInfo *sai,
+			StartGatewayDeviceCtxt *rpcContextData);
+
+	int createCallback(StatusChanged_Event_NotifyCtxt *listener,
+			CreateCallbackCtxt *rpcContextData);
+
+	int resetRequest(unsigned char options, ResetCommandCtxt *rpcContextData);
+
+	static void resetCommandNotify_CbW(uchar status);
+
+	void resetCommandNotify_Cb(uchar status);
+
+	int readStartupAttributeSet(int startupAttributeSetIndex,
+			RPCContext<T, startupResponseCb> *rpcContextData);
+
+	StartupAttributeInfo* readStartupAttributeSet(int startupAttributeSetIndex);
+
+	// Start ZNP Task - static wrapper
+	static void *startZNPTask_SW(void *arg);
+
+	// iterators:
+	// Attributes visible by scope of instantiation and use
+
+protected:
+
+	///	Constructor (pattern Singleton)
+	LocalNode();
+
+	// Attributes visible to descendents
+
+	int loadDefaultStartAttributeSet();
+
+	int configureStartupAttributeSet(int startupAttributeSetIndex,
+			StartupAttributeInfo *sai,
+			RPCContext<T, startupResponseCb> *rpcContextData);
+
+	//TODO To be moved to TrustCenter Agent
+	int loadTCKeyTable();
+
+	void gwStatusChanged_Event_Cb(int gwStatus, int errorCode,
+			uchar commandStatus);
+
+	/// Timer handlers
+	void onStartGatewayDevice();
+
+	typedef void *TIMERPROC;
+
+	int initTimers(void);
+
+	struct Task {
+		bool taskStarted;
+		pthread_t tid;
+
+		int start(void *(*invokedMethod)(void *));
+
+		void stop();
+
+		Task();
+
+	};
+
+	struct {
+		Task startZNP;
+	} tasks;
+
+	///	Pointer to GalZbIf object
+	GalZbIf *pGalZb;
+
+	///	Pointer to Gal database (refer to ZbNetDb class)
+	ZbNetDb *pGalDb;
+
+	///	Pointer to a Debug object -> logger
+	Debug *pLogger;
+
+	/// To enable/disable Debug (default value is 0)
+	bool debugEnabled;
+	int debugLevel;
+
+	/// Parameter
+	bool automaticStartupLeaveMngmtEnabled;
+
+	// To manage automatic sending of Leave Mngmt @ startup
+	//int startupPhase;
+
+	GwDescriptor *gwDescriptor;
+
+	int timerThreadResult;
+	int threadPoolResult;
+
+private:
+	// Local attributes
+
+	// Pattern Singleton
+	static LocalNode instance;
+
+	const char *localDevice;
+
+	///	Mutex
+	pthread_mutex_t mux;
+
+	///	Thread management
+	ThreadPool threadPool;
+
+	TimerThread timerThread;
+
+	///	Map containing functions context data
+	struct fContexts {
+		fContext<T, LocalNode, startupResponseCb, startupNotifyCb> startGatewayDevice;
+
+		fContext<T, LocalNode, resetResponseCb, resetNotifyCb> resetCommand;
+
+		fContexts(GalZbIf::FeatureControl *fc) :
+				startGatewayDevice(fc, 1), resetCommand(fc, 1) {
+		}
+
+	} functionsContext;
+
+	struct {
+		std::list<StatusChanged_Event_NotifyCtxt> gwStatusChanged;
+	} listeners;
+};
+
+#import "CLocalNode.cpp"
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CLogStorage.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CLogStorage.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CLogStorage.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,103 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include "CLogStorage.h"
+
+LogStorage *LogStorage::pInstance = NULL;
+
+/**
+ Constructor
+ LogStorage constructor. It is a protected method (pattern Singleton)
+
+ @param void Void.
+ @return Void.
+ */
+
+LogStorage::LogStorage() {
+	printf("LogStorage Constructor\n");
+
+	this->init();
+
+	pthread_mutex_init(&mux, NULL);
+}
+
+/**
+ Destructor
+ LogStorage destructor.
+
+ @param void Void.
+ @return Void.
+ */
+
+LogStorage::~LogStorage() {
+	printf("LogStorage Destructor\n");
+}
+
+/**
+ Public method LogStorage *Instance(void)
+ (pattern Singleton)
+
+ @param void Void.
+ @return Instance of LogStorage class.
+ */
+
+LogStorage *LogStorage::Instance(void) {
+	if (pInstance == NULL) {
+		pInstance = new LogStorage;
+	}
+	return pInstance;
+}
+
+/**
+ Public method LogStorage init
+ (pattern Singleton)
+
+ @param void Void.
+ @return Void.
+ */
+
+void LogStorage::init(void) {
+	fstream logFile;
+
+	logFile.open(LOG_FILENAME, ios::out);
+	logFile << "<LogFile></LogFile>\n";
+	logFile.close();
+}
+
+/**
+ Public method LogStorage print
+ This method appends the debug message to the end of the considered debug file.
+
+ @param msg Message to be stored.
+ @return Status.
+ */
+
+int LogStorage::print(const char *msg) {
+	fstream logFile;
+
+	pthread_mutex_lock(&mux);
+	logFile.open(LOG_FILENAME);
+	logFile.seekp((streamoff)(-XMLTAG_OFFSET), ios::end);
+	logFile.write(msg, strlen(msg));
+	logFile << "</LogFile>\n";
+	logFile.close();
+	pthread_mutex_unlock(&mux);
+
+	return 0;
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CLogStorage.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CLogStorage.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CLogStorage.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,66 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef LOGSTORAGE_H
+#define LOGSTORAGE_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <iostream>
+#include <fstream>
+
+#include "ThreadPool.h"
+#include "TimerThread.h"
+
+using namespace std;
+
+#define LOG_FILENAME						"log.xml"
+
+#define XMLTAG_OFFSET						11
+
+class LogStorage {
+
+public:
+	// Constructors
+
+	// Destructor
+	~LogStorage();
+
+	// Functions: modifiers (set), selectors (get)
+
+	// Pattern Singleton
+	static LogStorage *Instance(void);
+
+	void init();
+
+	int print(const char *msg);
+
+	// iterators:
+	// Attributes visible by scope of instantiation and use
+
+protected:
+
+	///	Constructor (pattern Singleton)
+	LogStorage();
+
+	// Attributes visible to descendents
+
+private:
+	// Local attributes
+
+	// Pattern Singleton
+	static LogStorage *pInstance;
+
+	///	Mutex
+	pthread_mutex_t mux;
+
+};
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CManagementAgent.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CManagementAgent.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CManagementAgent.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,479 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include "CManagementAgent.h"
+
+template<class T>
+ManagementAgent<T> ManagementAgent<T>::instance;
+
+/**
+ Constructor
+ ManagementAgent constructor. It is a protected method (pattern Singleton)
+
+ @param void Void.
+ @return Void.
+ */
+template<class T>
+ManagementAgent<T>::ManagementAgent() :
+		functionsContext(GalZbIf::Instance()->getFeatureControl()) {
+	//Timers initialization
+	initTimers();
+
+	pthread_mutex_init(&mux, NULL);
+
+#ifdef DEBUG_ACTIVE_MA
+	pLogger->info("Constructor");
+#endif
+
+	pGalZb = GalZbIf::Instance();
+}
+
+/**
+ Destructor
+ ManagementAgent destructor.
+
+ @param void Void.
+ @return Void.
+ */
+template<class T>
+ManagementAgent<T>::~ManagementAgent() {
+#ifdef DEBUG_ACTIVE_MA
+	printf("ManagementAgent - Destructor\n");
+#endif
+
+	TimerThreadShutdown(&timerThread);
+	ThreadPoolShutdown(&threadPool);
+
+	delete pLogger;
+}
+
+/**
+ Public method ManagementAgent *Instance(void)
+ (pattern Singleton)
+
+ @param void Void.
+ @return Instance of ManagementAgent class.
+ */
+template<class T>
+ManagementAgent<T> *ManagementAgent<T>::Instance(void) {
+	return &instance;
+}
+
+/**
+ Public method ManagementAgent init
+ ManagementAgent initialization: macrofunction context is initialized.
+
+
+ @param void Void.
+ @return Void.
+ */
+template<class T>
+void ManagementAgent<T>::init() {
+	ConfigurationRepository *_conf = ConfigurationRepository::instance();
+	// We load the configuration from the ConfigurationManager
+	this->debugEnabled = _conf->getint("main:debugEnabled", false);
+	this->debugLevel = _conf->getint("Debug:ManagementAgentDL", TEST);
+
+	// Debug
+	pLogger = new Debug("ManagementAgent");
+	pLogger->setDebugMode(this->debugEnabled);
+	pLogger->setDebugLevel(this->debugLevel);
+
+	pLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+	pLogger->enableDebugOuput(DBG_SCREEN);
+
+#ifdef DEBUG_ACTIVE_MA
+	pLogger->debug("init");
+#endif
+
+	pGalDb = pGalZb->getDb();
+}
+
+/**
+ Public method ManagementAgent leaveRequest
+
+ @param nwk_addr The network address
+ @param removeChildren If present, the children will be removed as well from the network
+ @param rejoin True is it is requested to rejoin the network
+ @param rpcContextData RPC context.
+ */
+template<class T>
+int ManagementAgent<T>::leaveRequest(ushort nwk_addr, bool removeChildren,
+		bool rejoin,
+		RPCContext<T, leaveResponseCb, leaveNotifyCb> *rpcContextData) {
+	Node *node;
+	pLogger->info("leaveRequest - nwk_addr %04X", nwk_addr);
+
+	if (pGalZb->getGWStatus() != GW_RUNNING) {
+		pLogger->info("leaveRequest - Error GAL_NOT_RUNNING");
+
+		// RPC response Callback
+		RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED, GAL_NOT_RUNNING);
+
+		CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+				&rpcReqStatus);
+		// Return Error Code
+		return GAL_NOT_RUNNING;
+	}
+
+	pthread_mutex_lock(&mux);
+	functionsContext.leaveCommand.rpcContext = *rpcContextData;
+	// Register a Listener for a response
+#ifdef DEBUG_ACTIVE_MA
+	pLogger->info("createCallback - Register a listener on event ZB_MGMT_LEAVE_RESPONSE");
+#endif
+	pGalZb->registerListener(ZB_MGMT_LEAVE_RESPONSE,
+			(void *) (&leaveCommandNotify_CbW));
+	pLogger->debug("************* Send a LEAVE REQUEST *****************");
+	uchar dst_addr_mode;
+	uchar dst_addr[2];
+	uchar dst_ep;
+	ushort profile_id;
+	ushort cluster_id;
+	uchar src_ep;
+	ushort asdu_len;
+	uchar asdu[10];
+	uchar tx_options;
+	uchar radius;
+
+	dst_addr_mode = 0x02; //ZB_AM_DIRECT - direct address mode
+
+	dst_addr[0] = (nwk_addr) & 0xFF;
+	dst_addr[1] = ((nwk_addr) >> 8) & 0xFF;
+
+	dst_ep = 0x00;
+	profile_id = 0x0000;
+	cluster_id = 0x0034;
+
+	src_ep = 0x00;
+	asdu_len = 0x0A;
+
+	asdu[0] = 0x00;
+
+	node = pGalDb->findNodeByNwkAddr(nwk_addr);
+	if (node == NULL) {
+		// Could not find the IEEEAddress, send the leave with all zeros (it still works)
+		asdu[1] = 0x00;
+		asdu[2] = 0x00;
+		asdu[3] = 0x00;
+		asdu[4] = 0x00;
+		asdu[5] = 0x00;
+		asdu[6] = 0x00;
+		asdu[7] = 0x00;
+		asdu[8] = 0x00;
+	} else {
+		// Get the IEEE and store to the asdu array!
+		asdu[1] = node->get_ieee_addr()[7];
+		asdu[2] = node->get_ieee_addr()[6];
+		asdu[3] = node->get_ieee_addr()[5];
+		asdu[4] = node->get_ieee_addr()[4];
+		asdu[5] = node->get_ieee_addr()[3];
+		asdu[6] = node->get_ieee_addr()[2];
+		asdu[7] = node->get_ieee_addr()[1];
+		asdu[8] = node->get_ieee_addr()[0];
+	}
+
+	uchar leaveParameters = 0x00;
+	if (removeChildren) {
+		leaveParameters = leaveParameters | 0x40;
+	}
+	if (rejoin) {
+		leaveParameters = leaveParameters | 0x80;
+	}
+	pLogger->info("leaveRequest - %x",leaveParameters);
+	asdu[9] = leaveParameters; // 0xC0 - true for remove children and rejoin | 0x40 - true for remove children
+
+	tx_options = 0x00;
+	radius = 0xFF;
+	//#ifdef DEBUG_ACTIVE_SA
+	ManagementAgent* mAgent = ManagementAgent<T>::Instance();
+	if (mAgent->debugEnabled == true)
+		printf("send - APSDE_DATA_request to 0x%02x%02x\n", dst_addr[1],
+				dst_addr[0]);
+	//#endif
+	pGalZb->APSDE_DATA_request(dst_addr_mode, dst_addr, dst_ep, profile_id,
+			cluster_id, src_ep, asdu_len, asdu, tx_options, radius);
+	pthread_mutex_unlock(&mux);
+	// RPC response Callback
+	RPCReqStatus rpcReqStatus(Running, FSUCCESS, AGENT_SUCCESS);
+	CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+			&rpcReqStatus);
+	return AGENT_SUCCESS;
+}
+
+//This is just a wrapper to call a static function!
+template<class T>
+void ManagementAgent<T>::leaveCommandNotify_CbW(uchar status) {
+	ManagementAgent* mAgent = ManagementAgent<T>::Instance();
+
+#ifdef DEBUG_ACTIVE_MA
+	if (mAgent->debugEnabled == true)
+	printf("ManagementAgent::leaveCommandNotify_CbW\n");
+#endif
+
+	mAgent->leaveCommandNotify_Cb(status);
+	return;
+}
+
+template<class T>
+void ManagementAgent<T>::leaveCommandNotify_Cb(uchar status) {
+#ifdef DEBUG_ACTIVE_MA
+	pLogger->debug("leaveCommandNotify_Cb");
+#endif
+	// RPC notify Callback
+	if (functionsContext.leaveCommand.rpcContext.getRPCNotifyCb() != NULL) {
+#ifdef DEBUG_ACTIVE_MA
+		if (mAgent->debugEnabled == true)
+		printf("Calling the notify function\r\n");
+#endif
+		RPCReqStatus rpcReqStatus(Running, FSUCCESS, AGENT_SUCCESS);
+		FCALL_NOTIFY (functionsContext.leaveCommand)((uchar) NULL, status,
+				&rpcReqStatus);
+	} else
+		printf(
+				"WARNING: No notify function associated to MGMT_LEAVE_RESPONSE!!\r\n");
+	// Remove the listener!
+	pGalZb->unregisterListener(ZB_MGMT_LEAVE_RESPONSE,
+			(void *) (&leaveCommandNotify_CbW));
+	return;
+}
+
+/**
+ Public method ManagementAgent permitJoin
+
+ @param nwk_addr The network address
+ @param timer The timer value
+ @param rpcContextData RPC context.
+ */
+template<class T>
+int ManagementAgent<T>::permitJoin(ushort nwk_addr, ushort PermitDuration,
+		bool TCSignificance, unsigned long int timeout,
+		permitJoinCtxt *rpcContextData) {
+	uchar dst_addr_mode;
+	uchar dst_addr[2];
+	uchar dst_ep;
+	ushort profile_id;
+	ushort cluster_id;
+	uchar src_ep;
+	ushort asdu_len;
+	uchar asdu[4];
+	uchar tx_options;
+	uchar radius;
+
+	//ManagementAgent* mAgent=ManagementAgent<T>::Instance();
+	/*
+	 #ifdef DEBUG_ACTIVE_MA
+	 pLogger->info("permitJoin - set destAddr to 0x%04x", nwk_addr);
+	 pLogger->info("permitJoin - set timer to 0x%02x", PermitDuration);
+	 pLogger->info("permitJoin - set TCSignificance to 0x%02x", TCSignificance);
+	 #endif
+	 */
+	if (pGalZb->getGWStatus() != GW_RUNNING) {
+		pLogger->info("permitJoin - Error GAL_NOT_RUNNING");
+		// RPC response Callback
+		RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED, GAL_NOT_RUNNING);
+		CALL_RESPONSE (rpcContextData)(-1, rpcContextData->getSessionId(),
+				&rpcReqStatus);
+		// Return Error Code
+		return GAL_NOT_RUNNING;
+	}
+	pthread_mutex_lock(&mux);
+	if (functionsContext.permitJoin.isLocked()) {
+		pLogger->debug("\nWARNING at permitJoin: A previous PermitJoin has not concluded yet, overwrite it!!\n");
+	} else {
+		functionsContext.permitJoin.lock();
+		// Register to receive a response
+		pGalZb->registerListener(ZB_MGMT_PERMIT_JOINING_RESPONSE,
+				(void *) (&permitJoinNotify_CbW));
+	}
+	// Timer creation management
+	if (timeout > 0x00000000 && timeout != 0xffffffff) {
+		// Convert timeout from milliseconds to seconds (ceil)
+		timeout = timeout / 1000 + ((timeout % 1000) ? 1 : 0);
+		///	Set the timer for stopping the startGatewayDevice process
+		functionsContext.permitJoin.fTimeout = (int) timeout;
+#ifdef DEBUG_ACTIVE_MA
+		pLogger->debug("permitJoin - timeout value = %d (sec)", functionsContext.permitJoin.fTimeout);
+#endif
+		if (!functionsContext.permitJoin.setTimer(&timerThread, this,
+				&ManagementAgent::onPermitJoin)) {
+			pLogger->error("permitJoin - ERROR creating permitJoin timer!");
+			pGalZb->unregisterListener(ZB_MGMT_PERMIT_JOINING_RESPONSE,
+					(void *) (&permitJoinNotify_CbW));
+			functionsContext.permitJoin.unlock(Canceled);
+			pthread_mutex_unlock(&mux);
+			// RPC response Callback
+			RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED, TIMER_ERROR);
+			CALL_RESPONSE (rpcContextData)(-1, rpcContextData->getSessionId(),
+					&rpcReqStatus);
+			return TIMER_ERROR;
+		}
+	} else {
+		// If timeout value is 0xffffffff (infinite amount of time) or 0x00000000 do not use timer
+		pLogger->info("permitJoin - timeout value infinite or zero - timer disabled");
+	}
+	// Reset result value
+	functionsContext.permitJoin.result = FSUCCESS;
+	functionsContext.permitJoin.rpcContext = *rpcContextData;
+
+	dst_addr_mode = 0x02;
+	dst_addr[0] = LSB_USHORT(nwk_addr);
+	dst_addr[1] = MSB_USHORT(nwk_addr);
+	dst_ep = 0x00;
+	profile_id = 0x0000;
+	cluster_id = 0x0036;
+	src_ep = 0x00;
+	asdu_len = 0x03;
+	asdu[0] = 0x03;
+	asdu[1] = LSB_USHORT(PermitDuration);
+	asdu[2] = TCSignificance;
+	tx_options = 0x00;
+	radius = 0xFF;
+
+#ifdef DEBUG_ACTIVE_MA
+	if (mAgent->debugEnabled == true)
+	pLogger->debug("Sending a permitJoinReq to 0x%02x%02x\n",dst_addr[1],dst_addr[0]);
+#endif
+	pGalZb->APSDE_DATA_request(dst_addr_mode, dst_addr, dst_ep, profile_id,
+			cluster_id, src_ep, asdu_len, asdu, tx_options, radius);
+	if (functionsContext.permitJoin.rpcContext.getRPCNotifyCb() != NULL) {
+#ifdef DEBUG_ACTIVE_MA
+		pLogger->debug("permitJoin - asynch request");
+#endif
+		RPCReqStatus rpcReqStatus(Running, FSUCCESS, AGENT_SUCCESS, true);
+		CALL_RESPONSE (rpcContextData)(AGENT_SUCCESS,
+				rpcContextData->getSessionId(), &rpcReqStatus);
+	}
+	pthread_mutex_unlock(&mux);
+	return AGENT_SUCCESS;
+}
+
+//This is just a wrapper to call a static function!
+template<class T>
+void ManagementAgent<T>::permitJoinNotify_CbW(uchar status) {
+	ManagementAgent* mAgent = ManagementAgent<T>::Instance();
+
+#ifdef DEBUG_ACTIVE_MA
+	if (mAgent->debugEnabled == true)
+	printf("ManagementAgent::permitJoinNotify_CbW\n");
+#endif
+
+	mAgent->permitJoinNotify_Cb(status);
+	return;
+}
+
+template<class T>
+void ManagementAgent<T>::permitJoinNotify_Cb(uchar status) {
+#ifdef DEBUG_ACTIVE_MA
+	pLogger->debug("permitJoinNotify_Cb");
+#endif
+
+	pthread_mutex_lock(&mux);
+
+#ifdef DEBUG_ACTIVE_MA
+	pLogger->debug("permitJoinNotify_Cb - completed");
+#endif
+
+	///	Unregister listener
+	pGalZb->unregisterListener(ZB_MGMT_PERMIT_JOINING_RESPONSE,
+			(void *) (&permitJoinNotify_CbW));
+
+	// Remove timer related to permitJoin
+	functionsContext.permitJoin.killTimer();
+
+	if (functionsContext.permitJoin.rpcContext.getRPCNotifyCb() != NULL) {
+
+#ifdef DEBUG_ACTIVE_MA
+		pLogger->debug("permitJoinNotify_Cb - asynch notification");
+#endif
+		RPCReqStatus rpcReqStatus(functionsContext.permitJoin, AGENT_SUCCESS);
+		FCALL_NOTIFY (functionsContext.permitJoin)(status, &rpcReqStatus);
+	} else {
+
+#ifdef DEBUG_ACTIVE_MA
+		pLogger->debug("permitJoinNotify_Cb - synch response");
+#endif
+		// RPC response Callback
+		RPCReqStatus rpcReqStatus(functionsContext.permitJoin, AGENT_SUCCESS);
+		FCALL_RESPONSE (functionsContext.permitJoin)(status,
+				functionsContext.permitJoin.rpcContext.getSessionId(),
+				&rpcReqStatus);
+	}
+	// permitJoin Completed
+	functionsContext.permitJoin.unlock();
+	pthread_mutex_unlock(&mux);
+	return;
+}
+
+/**
+ Protected method ManagementAgent initTimers
+ Timers initialization.
+
+ @param void Void.
+ @return Status.
+ */
+template<class T>
+int ManagementAgent<T>::initTimers(void) {
+	ThreadPoolAttr attr;
+
+	TPAttrInit(&attr);
+	TPAttrSetMaxThreads(&attr, MA_MAX_THREADS);
+	TPAttrSetMinThreads(&attr, MA_MIN_THREADS);
+	TPAttrSetJobsPerThread(&attr, MA_JOBS_PER_THREAD);
+	TPAttrSetIdleTime(&attr, MA_THREAD_IDLE_TIME);
+
+#ifdef NEW_VERSION
+	TPAttrSetMaxJobsTotal(&attr, MA_MAX_JOBS_TOTAL);
+#endif
+
+	if (ThreadPoolInit(&threadPool, &attr) != 0) {
+		return -1;
+	}
+	TimerThreadInit(&timerThread, &threadPool);
+	return 0;
+}
+
+template<class T>
+void ManagementAgent<T>::onPermitJoin() {
+	pthread_mutex_lock(&mux);
+	pLogger->info("onPermitJoin - timer expired");
+	/// Set result
+	functionsContext.permitJoin.result = FFAILED;
+	///	Unregister listener
+	pGalZb->unregisterListener(ZB_MGMT_PERMIT_JOINING_RESPONSE,
+			(void *) (&permitJoinNotify_CbW));
+
+	if (functionsContext.permitJoin.rpcContext.getRPCNotifyCb() != NULL) {
+		RPCReqStatus rpcReqStatus(functionsContext.permitJoin, TIMER_EXPIRED);
+		FCALL_NOTIFY (functionsContext.permitJoin)(-1, &rpcReqStatus);
+		// startGatewayDevice was invoked as an asynchronous procedure
+		pLogger->info("permitJoin - send a notification");
+	} else {
+		//startGatewayDevice was invoked as a synchronous procedure
+		pLogger->info("permitJoin - send a response");
+		// RPC response Callback
+		RPCReqStatus rpcReqStatus(functionsContext.permitJoin, TIMER_EXPIRED);
+
+		FCALL_RESPONSE (functionsContext.permitJoin)(-1,
+				functionsContext.permitJoin.rpcContext.getSessionId(),
+				&rpcReqStatus);
+	}
+	// canceled
+	functionsContext.permitJoin.unlock(Canceled);
+	pthread_mutex_unlock(&mux);
+}

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CManagementAgent.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CManagementAgent.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CManagementAgent.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,167 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef MANAGEMENTAGENT_H
+#define MANAGEMENTAGENT_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "ThreadPool.h"
+#include "TimerThread.h"
+
+#include "GalZbIf.h"
+#include "ZbNetDb.h"
+#include "CDebug.h"
+
+#include "Agents.h"
+
+/**
+ Management Agent is organized in macrofunctions, i.e. ......................
+ Each macrofunction is identified by a unique ID (please refer to the following ID list).
+ This unique ID is used as a key in associative arrays containing macrofunction context (e.g. the status
+ of the macrofunction, number of expected messages, ...) or the RPC listeners registered on the specific function.
+ */
+#define MA_TEST					1
+// TBD
+
+/**
+ Allmost all macrofunctions ( ................ ) use a timeout: once it has expired, the related function
+ is terminated with a failure result (i.e. function not properly ended).
+
+ */
+// TBD
+
+/**
+ Set of constants used in thread management.
+ */
+#define MA_MAX_THREADS					10
+#define MA_MIN_THREADS					10	
+#define MA_JOBS_PER_THREAD				10
+#define MA_THREAD_IDLE_TIME 				5000
+#define MA_MAX_JOBS_TOTAL 				10
+
+template<class T>
+class ManagementAgent {
+
+public:
+	// Constructors
+
+	// Destructor
+	~ManagementAgent();
+
+	// Functions: modifiers (set), selectors (get)
+
+	//	function pointers types related to RPC callbacks (Macrofunction LeaveNetwork)
+	typedef void *(T::*leaveResponseCb)(int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void *(T::*leaveNotifyCb)(uchar status, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef RPCContext<T, leaveResponseCb, leaveNotifyCb> LeaveCommandCtxt;
+
+	typedef void * (T::*createCallbackResponseCb)(int endpoint, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void * (T::*permitJoinResponseCb)(uchar status, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void * (T::*permitJoinNotifyCb)(uchar status,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef RPCContext<T, permitJoinResponseCb, permitJoinNotifyCb> permitJoinCtxt;
+
+	// Pattern Singleton
+	static ManagementAgent *Instance(void);
+
+	void init();
+
+	///	Macrofunction XYZ -- public methods: 
+
+	int leaveRequest(ushort nwk_addr, bool removeChildren, bool rejoin,
+			LeaveCommandCtxt *rpcContextData);
+
+	static void leaveCommandNotify_CbW(uchar status);
+
+	int permitJoin(ushort nwk_addr, ushort PermitDuration, bool TCSignificance,
+			unsigned long int timeout, permitJoinCtxt *rpcContextData);
+
+	static void permitJoinNotify_CbW(uchar status);
+
+	// iterators:
+	// Attributes visible by scope of instantiation and use
+
+protected:
+
+	///	Constructor (pattern Singleton)
+	ManagementAgent();
+
+	///	Macrofunction XYZ -- protected method: 
+
+	// TBD
+
+	//	function pointers types related to RPC callbacks (Macrofunction XYZ)
+
+	// Attributes visible to descendents
+
+	///	Pointer to GalZbIf object
+	GalZbIf *pGalZb;
+
+	///	Pointer to Gal database (refer to ZbNetDb class)
+	ZbNetDb *pGalDb;
+
+	///	Pointer to a Debug object -> logger
+	Debug *pLogger;
+
+	/// To enable/disable Debug (default value is 0)
+	bool debugEnabled;
+	int debugLevel;
+
+	void leaveCommandNotify_Cb(uchar status);
+
+	void permitJoinNotify_Cb(uchar status);
+
+	/// Timer handlers
+	void onPermitJoin();
+
+	typedef void *TIMERPROC;
+
+	int initTimers(void);
+
+private:
+	// Local attributes
+
+	// Pattern Singleton
+	static ManagementAgent instance;
+
+	///	Mutex
+	pthread_mutex_t mux;
+
+	///	Thread management
+	ThreadPool threadPool;
+
+	TimerThread timerThread;
+
+	//ThreadPoolJob job;
+
+	struct fContexts {
+		fContext<T, ManagementAgent, leaveResponseCb, leaveNotifyCb> leaveCommand;
+		fContext<T, ManagementAgent, permitJoinResponseCb, permitJoinNotifyCb> permitJoin;
+
+		fContexts(GalZbIf::FeatureControl *fc) :
+				leaveCommand(fc, 11), permitJoin(fc, AGO_PERMIT_JOIN) {
+		}
+	} functionsContext;
+};
+
+#include "CManagementAgent.cpp"
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CMessage.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CMessage.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CMessage.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,646 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include "CMessage.h"
+#include "zigbee.h"
+
+/**
+ Constructor
+
+ @param void Void.
+ @return Void.
+ */
+
+Message::Message() {
+
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("Message Constructor\n");
+#endif
+
+	init();
+	pLogger = new Debug("Message");
+}
+
+/**
+ Destructor
+
+ @param void Void.
+ @return Void.
+ */
+
+Message::~Message() {
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("Message Destructor\n");
+#endif	
+	if (dstAddr != NULL)
+		free(dstAddr);
+
+	if (srcAddr != NULL)
+		free(srcAddr);
+
+	if (payload != NULL)
+		free(payload);
+
+	delete (pLogger);
+}
+
+/**
+ Public method Message init
+
+ @param void Void.
+ @return Void.
+ */
+
+void Message::init() {
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("Message::init()\n");
+#endif
+
+	dstAddrMode = 0xFF;
+	dstAddr = NULL;
+	dstEp = 0xFF;
+	srcAddrMode = 0xFF;
+	srcAddr = NULL;
+	srcNwkAddr = 0xFFFF;
+	srcAddrLength = 0;
+	srcEp = 0xFF;
+	profileId = 0;
+	clusterId = 0;
+	payloadLength = 0;
+	payload = NULL;
+	txSettings = 0xFF;
+	maxHopsNumber = 0xFF;
+	wasBroadcast = 0xFF;
+	securityStatus = 0xFF;
+	msgId = 0;
+}
+
+/**
+ Public method Message setDstAddrMode
+
+ @param value Value to which dstAddrMode is being set.
+ @return Void.
+ */
+
+void Message::setDstAddrMode(uchar value) {
+	dstAddrMode = value;
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("dstAddrMode = %X (value = %X)\n", dstAddrMode, value);
+#endif
+}
+
+/**
+ Public method Message getDstAddrMode
+
+ @param void Void.
+ @return Destination Address Mode (dstAddrMode) value.
+ */
+
+uchar Message::getDstAddrMode() {
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("dstAddrMode = %X\n",dstAddrMode);
+#endif
+	return dstAddrMode;
+}
+
+/**
+ Public method Message setDstAddr
+
+ @param value Destination address value.
+ @return Status.
+ */
+
+int Message::setDstAddr(uchar *value) {
+	/// Check whether Destination Address Mode has already been set.
+	if (dstAddrMode == 0xFF) {
+#ifdef DEBUG_ACTIVE_MESSAGE
+		printf("Message::setDstAddr - ERROR Destination Address Mode not set!\n");
+#endif
+		return -1;
+	}
+
+	/// dstAddrMode is used to determine whether the destination address is short or extended.
+	switch (dstAddrMode) {
+
+	case 0x00: {
+#ifdef DEBUG_ACTIVE_MESSAGE
+		printf("Message::setDstAddr - dst_addr_mode = 0x00 - DstAddr not present\n");
+#endif
+		dstAddr = NULL;
+		dstAddrLength = 0;
+	}
+		break;
+
+	case 0x01: {
+#ifdef DEBUG_ACTIVE_MESSAGE
+		printf("Message::setDstAddr - dst_addr_mode = 0x01 - DstAddr 16 bit\n");
+#endif
+		dstAddr = (uchar *) malloc(SHORT_ADDR_LEN * sizeof(uchar));
+		memcpy(this->dstAddr, value, SHORT_ADDR_LEN);
+		dstAddrLength = SHORT_ADDR_LEN;
+#ifdef DEBUG_ACTIVE_MESSAGE
+		printf("Message::setDstAddr - dstAddr 0x%02x%02x\n",dstAddr[0],dstAddr[1]);
+#endif
+	}
+		break;
+
+	case 0x02: {
+#ifdef DEBUG_ACTIVE_MESSAGE
+		printf("Message::setDstAddr - dst_addr_mode = 0x02 - DstAddr 16 bit\n");
+#endif
+		dstAddr = (uchar *) malloc(SHORT_ADDR_LEN * sizeof(uchar));
+		memcpy(this->dstAddr, value, SHORT_ADDR_LEN);
+		dstAddrLength = SHORT_ADDR_LEN;
+#ifdef DEBUG_ACTIVE_MESSAGE
+		printf("Message::setDstAddr - dstAddr 0x%02x%02x\n",dstAddr[0],dstAddr[1]);
+#endif
+	}
+		break;
+
+	case 0x03: {
+#ifdef DEBUG_ACTIVE_MESSAGE
+		printf("Message::setDstAddr - dst_addr_mode = 0x03 - DstAddr 64 bit\n");
+#endif
+		dstAddr = (uchar *) malloc(IEEE_ADDR_LEN * sizeof(uchar));
+		memcpy(this->dstAddr, value, IEEE_ADDR_LEN);
+		dstAddrLength = IEEE_ADDR_LEN;
+#ifdef DEBUG_ACTIVE_MESSAGE
+		printf("Message::setDstAddr - dstAddr %X:%X:%X:%X:%X:%X:%X:%X\n",dstAddr[0],dstAddr[1],dstAddr[2],dstAddr[3],dstAddr[4],dstAddr[5],dstAddr[6],dstAddr[7]);
+#endif
+	}
+		break;
+
+	default: {
+#ifdef DEBUG_ACTIVE_MESSAGE
+		printf("Message::setDstAddr - ERROR: unknown dest addr mode 0x%02x\n",dstAddrMode);
+#endif
+		dstAddr = NULL;
+		dstAddrLength = 0;
+		return -1;
+	}
+	}
+
+	return 0;
+}
+
+/**
+ Public method Message getDstAddr
+
+ @param length Pointer to a variable in which the length of the destination address is to be stored.
+ @return Pointer to the destination address.
+ */
+
+uchar* Message::getDstAddr(int *length) {
+	if (length != NULL) {
+		*length = dstAddrLength;
+#ifdef DEBUG_ACTIVE_MESSAGE
+		printf("dstAddrLength = %d\n", *length);
+#endif
+	}
+	return dstAddr;
+}
+
+/**
+ Public method Message setDstEp
+
+ @param value Destination EndPoint value.
+ @return Void.
+ */
+
+void Message::setDstEp(uchar value) {
+	dstEp = value;
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("dstEp = %X (value = %X)\n", dstEp, value);
+#endif
+}
+
+/**
+ Public method Message getDstEp
+
+ @param void Void.
+ @return Destination EndPoint value.
+ */
+
+uchar Message::getDstEp() {
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("dstEp = %X\n",dstEp);
+#endif
+	return dstEp;
+}
+
+/**
+ Public method Message setSrcAddrMode.
+
+ @param value Source Address Mode value.
+ @return Void.
+ */
+
+void Message::setSrcAddrMode(uchar value) {
+	srcAddrMode = value;
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("srcAddrMode = %X (value = %X)\n", srcAddrMode, value);
+#endif
+}
+
+/**
+ Public method Message getSrcAddrMode.	
+
+ @param void Void.
+ @return Source Address Mode value.
+ */
+
+uchar Message::getSrcAddrMode() {
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("srcAddrMode = %X\n",srcAddrMode);
+#endif
+	return srcAddrMode;
+}
+
+/**
+ Public method Message setSrcAddr.	
+
+ @param value Source Address value.
+ @return Status.
+ */
+
+int Message::setSrcAddr(uchar *value) {
+
+	/// Check whether Source Address Mode has already been set.
+	if (srcAddrMode == 0xFF) {
+#ifdef DEBUG_ACTIVE_MESSAGE
+		printf("Message::setSrcAddr - ERROR Source Address Mode not set!\n");
+#endif
+		return -1;
+	}
+
+	/// srcAddrMode is used to determine whether the source address is short or extended.
+	switch (srcAddrMode) {
+
+	case ZB_AM_INDIRECT: {
+#ifdef DEBUG_ACTIVE_MESSAGE
+		printf("Message::setSrcAddr - src_addr_mode = ZB_AM_INDIRECT - srcAddr not present\n");
+#endif
+		srcAddr = NULL;
+		srcAddrLength = 0;
+	}
+		break;
+
+	case ZB_AM_DIRECT_GROUP: {
+#ifdef DEBUG_ACTIVE_MESSAGE
+		printf("Message::setSrcAddr - src_addr_mode = ZB_AM_DIRECT_GROUP - srcAddr 16 bit\n");
+#endif
+		srcAddr = (uchar *) malloc(SHORT_ADDR_LEN * sizeof(uchar));
+		memcpy(this->srcAddr, value, SHORT_ADDR_LEN);
+		srcAddrLength = SHORT_ADDR_LEN;
+#ifdef DEBUG_ACTIVE_MESSAGE
+		printf("Message::setSrcAddr - srcAddr %02x%02x--\n",srcAddr[0],srcAddr[1]);
+#endif
+	}
+		break;
+
+	case ZB_AM_DIRECT: {
+#ifdef DEBUG_ACTIVE_MESSAGE
+		printf("Message::setSrcAddr - src_addr_mode = ZB_AM_DIRECT - srcAddr 16 bit\n");
+#endif
+		srcAddr = (uchar *) malloc(SHORT_ADDR_LEN * sizeof(uchar));
+		memcpy(this->srcAddr, value, SHORT_ADDR_LEN);
+		srcAddrLength = SHORT_ADDR_LEN;
+#ifdef DEBUG_ACTIVE_MESSAGE
+		printf("Message::setSrcAddr - srcAddr %02x%02x--\n",srcAddr[0],srcAddr[1]);
+#endif
+	}
+		break;
+
+	case ZB_AM_DIRECT_EX: {
+#ifdef DEBUG_ACTIVE_MESSAGE
+		printf("Message::setSrcAddr - src_addr_mode = 0x03 - srcAddr 64 bit\n");
+#endif
+		srcAddr = (uchar *) malloc(IEEE_ADDR_LEN * sizeof(uchar));
+		memcpy(this->srcAddr, value, IEEE_ADDR_LEN);
+		srcAddrLength = IEEE_ADDR_LEN;
+#ifdef DEBUG_ACTIVE_MESSAGE
+		printf("Message::setSrcAddr - srcAddr %X:%X:%X:%X:%X:%X:%X:%X\n",srcAddr[0],srcAddr[1],srcAddr[2],srcAddr[3],srcAddr[4],srcAddr[5],srcAddr[6],srcAddr[7]);
+#endif
+	}
+		break;
+
+	default: {
+		printf("Message::setSrcAddr - ERROR: unknown src addr mode 0x%02x\n",
+				srcAddrMode);
+		srcAddr = NULL;
+		srcAddrLength = 0;
+		return -1;
+	}
+	}
+	return 0;
+}
+
+/**
+ Public method Message getSrcAddr.		
+
+ @param length Pointer to a variable in which the length of the source address is to be stored.
+ @return Pointer to the source address.
+ */
+
+uchar* Message::getSrcAddr(int *length) {
+
+	if (length != NULL) {
+		*length = srcAddrLength;
+#ifdef DEBUG_ACTIVE_MESSAGE
+		printf("getSrcAddr - srcAddrLength = %d\n", *length);
+#endif
+	}
+	return srcAddr;
+}
+
+int Message::setSrcNwkAddr(uchar *value) {
+	memcpy(&(this->srcNwkAddr), value, sizeof(short));
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("Message::setSrcNwkAddr - srcNwkAddr = 0x%02x%02x ",MSB_USHORT(srcNwkAddr),LSB_USHORT(srcNwkAddr));
+#endif
+	return 0;
+}
+
+int Message::setSrcNwkAddr(ushort value) {
+	this->srcNwkAddr = value;
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("Message::setSrcNwkAddr - srcNwkAddr = 0x%04x ",this->srcNwkAddr);
+#endif
+	return 0;
+}
+
+ushort Message::getSrcNwkAddr() {
+	return this->srcNwkAddr;
+}
+
+void Message::setSrcEp(uchar value) {
+	srcEp = value;
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("srcEp = %02X\n", srcEp);
+#endif
+}
+
+/**
+ Public method Message getSrcEp
+
+ @param void Void.
+ @return Source EndPoint value.
+ */
+
+uchar Message::getSrcEp() {
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("srcEp = %02X\n",srcEp);
+#endif
+	return srcEp;
+}
+
+/**
+ Public method Message setProfileId.		
+
+ @param value Profile Identifier value.
+ @return Void.
+ */
+
+void Message::setProfileId(ushort value) {
+	profileId = value;
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("profileId = %04X\n", profileId);
+#endif
+}
+
+/**
+ Public method Message getProfileId.
+
+ @param void Void.
+ @return Profile Identifier value.
+ */
+
+ushort Message::getProfileId() {
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("profileId = %04X\n",profileId);
+#endif
+	return profileId;
+}
+
+/**
+ Public method Message setClusterId.
+
+ @param value Cluster Identifier value.
+ @return Void.
+ */
+
+void Message::setClusterId(ushort value) {
+	clusterId = value;
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("clusterID = %04X\n", clusterId);
+#endif
+}
+
+/**
+ Public method Message getClusterId.
+
+ @param void Void.
+ @return Cluster Identifier value.
+ */
+ushort Message::getClusterId() {
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("clusterId = %04X\n",clusterId);
+#endif
+	return clusterId;
+}
+
+/*
+ void Message::setCommandID(
+ int value
+ )
+ {
+ commandId = value;
+ #ifdef DEBUG_ACTIVE_MESSAGE
+ printf("commandId = %04X\n", commandId);
+ #endif
+ }
+
+ int Message::getCommandID()
+ {
+ #ifdef DEBUG_ACTIVE_MESSAGE
+ printf("commandId = %04X\n",commandId);
+ #endif
+ return commandId;
+ }
+ */
+
+/**
+ Public method Message setPayload.
+
+ @param value Payload.
+ @param length Payload length.
+ @return void.
+ */
+
+void Message::setPayload(uchar *value, ushort length) {
+	payloadLength = length;
+
+	payload = (uchar *) malloc(((int) payloadLength) * sizeof(uchar));
+	memcpy(this->payload, value, ((int) payloadLength));
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("Payload - len = %d\n", ((int)payloadLength));
+#endif
+}
+
+/**
+ Public method Message getPayload.
+
+ @param length Pointer to a variable in which the payload length is to be stored.
+ @return Message payload.
+ */
+
+uchar* Message::getPayload(ushort *length) {
+	if (length != NULL) {
+		*length = payloadLength;
+#ifdef DEBUG_ACTIVE_MESSAGE
+		printf("payloadLength = %d\n", *length);
+#endif
+	}
+	return payload;
+}
+/*
+ int Message::getPayloadLength(){
+ return payloadLength;
+ }
+ */
+
+/**
+ Public method Message concatenateZCLHeaderAndPayload.
+
+
+ @param value header.
+ @param length header_length.
+ @param value zclpayload.
+ @param length zclpayload_length.
+ @return void.
+ */
+
+void Message::concatenateZCLHeaderAndPayload(uchar *header,
+		ushort header_length, uchar *zclpayload, ushort zclpayload_length) {
+	payloadLength = header_length + zclpayload_length;
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("Payload - len = %d\n (Hed: %d,Pay: %d)\n", ((int)payloadLength),header_length,zclpayload_length);
+#endif
+	payload = (uchar *) malloc(((int) payloadLength) * sizeof(uchar));
+	memcpy(this->payload, header, ((int) header_length));
+	memcpy(&(this->payload[header_length]), zclpayload,
+			((int) zclpayload_length));
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("Byte written: ");
+	for (int i=0; i != payloadLength; i++)
+	printf("%2x ",payload[i]);
+	printf("\n");
+#endif
+}
+
+/**
+ Public method Message setTxSettings.
+
+ @param value Tx Settings.
+ @return void.
+ */
+
+void Message::setTxSettings(uchar value) {
+	txSettings = value;
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("txSettings = %02X\n", txSettings);
+#endif
+}
+
+/**
+ Public method Message getTxSettings.
+
+ @param void Void.
+ @return txSettings value.
+ */
+
+uchar Message::getTxSettings() {
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("txSettings = %02X\n", txSettings);
+#endif
+	return txSettings;
+}
+
+/**
+ Public method Message setMaxHopsNumber
+
+ @param value MaxHopsNumber value.
+ @return Void.
+ */
+
+void Message::setMaxHopsNumber(uchar value) {
+	maxHopsNumber = value;
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("maxHopsNumber = %X (value = %X)\n", maxHopsNumber, value);
+#endif
+}
+
+/**
+ Public method Message getMaxHopsNumber.
+
+ @param void Void.
+ @return MaxHopsNumber value.
+ */
+
+uchar Message::getMaxHopsNumber() {
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("maxHopsNumber = %X\n",maxHopsNumber);
+#endif
+	return maxHopsNumber;
+}
+
+//TODO
+//		void Message::setWasBroadcast(uchar value);
+//		uchar Message::getWasBroadcast();
+//		void Message::setSecurityStatus(uchar value);
+//		uchar Message::getSecurityStatus();
+//-------------------------------------------------------------
+
+/**
+ Public method Message setMsgId.
+
+ @param value Msg identifier value.
+ @return Void.
+ */
+
+void Message::setMsgId(int value) {
+	msgId = value;
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("msgId = %d\n",msgId);
+#endif
+}
+
+/**
+ Public method Message getMsgId.
+
+ @param void Void.
+ @return Msg identifier value.
+ */
+
+int Message::getMsgId() {
+#ifdef DEBUG_ACTIVE_MESSAGE
+	printf("msgId = %d\n",msgId);
+#endif
+	return msgId;
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CMessage.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CMessage.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CMessage.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,136 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef MESSAGE_H
+#define MESSAGE_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string>
+
+#include "CDebug.h"
+
+#ifdef __GNUC__
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+#endif
+
+/**
+ length of the short and extended node address expressed in bytes
+ */
+#define SHORT_ADDR_LEN				2
+#define IEEE_ADDR_LEN				8
+
+class Message {
+
+public:
+	/// Constructors:
+	Message();
+
+	/// Destructor:
+	~Message();
+
+	/// Functions: modifiers (set), selectors (get)
+	void init();
+
+	void setDstAddrMode(uchar value);
+	uchar getDstAddrMode();
+
+	int setDstAddr(uchar *value);
+	uchar *getDstAddr(int *length);
+
+	void setDstEp(uchar value);
+	uchar getDstEp();
+
+	void setSrcAddrMode(uchar value);
+	uchar getSrcAddrMode();
+
+	int setSrcAddr(uchar *value);
+	uchar *getSrcAddr(int *length);
+
+	int setSrcNwkAddr(uchar *value);
+	int setSrcNwkAddr(ushort value);
+	ushort getSrcNwkAddr();
+
+	void setSrcEp(uchar value);
+	uchar getSrcEp();
+
+	void setProfileId(ushort value);
+	ushort getProfileId();
+
+	void setClusterId(ushort value);
+	ushort getClusterId();
+
+	//void setCommandID(int value);
+	//int getCommandID();
+
+	void setPayload(uchar *value, ushort length);
+	uchar *getPayload(ushort *length);
+	//int getPayloadLength();
+
+	void concatenateZCLHeaderAndPayload(uchar *header, ushort header_length,
+			uchar *zclpayload, ushort zclpayload_length);
+
+	void setTxSettings(uchar value);
+	uchar getTxSettings();
+
+	void setMaxHopsNumber(uchar value);
+	uchar getMaxHopsNumber();
+
+	void setWasBroadcast(uchar value);
+	uchar getWasBroadcast();
+
+	void setSecurityStatus(uchar value);
+	uchar getSecurityStatus();
+
+	void setMsgId(int value);
+	int getMsgId();
+
+	// itterators:
+	// Attributes visible by scope of instantiation and use
+
+protected:
+	// Attributes visible to descendents
+
+	/// Pointer to a Debug object -> logger
+	Debug *pLogger;
+
+private:
+	// Local attributes
+
+	uchar dstAddrMode;
+	uchar *dstAddr;
+	int dstAddrLength; // Internal use
+	uchar dstEp;
+
+	uchar srcAddrMode;
+	uchar *srcAddr;
+	ushort srcNwkAddr;
+
+	int srcAddrLength; // Internal use
+	uchar srcEp;
+
+	ushort profileId;
+	ushort clusterId;
+
+	ushort payloadLength;
+	uchar *payload; //NOTE: This attribute contains both the ZCLHeader and ZCLPayload
+
+	uchar txSettings;
+	uchar maxHopsNumber;
+
+	uchar wasBroadcast;
+	uchar securityStatus;
+
+	int msgId;
+
+};
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CQueryParser.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CQueryParser.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CQueryParser.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,192 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include "CQueryParser.h"
+
+QueryParser *QueryParser::pInstance = NULL;
+
+/**
+ Constructor
+ QueryParser constructor. It is a protected method (pattern Singleton)
+
+ @param void Void.
+ @return Void.
+ */
+
+QueryParser::QueryParser() {
+	ConfigurationRepository *_conf = ConfigurationRepository::instance();
+	// We load the configuration from the ConfigurationManager
+	this->debugEnabled = _conf->getint("main:debugEnabled", false);
+
+	pLogger = new Debug("QueryParser");
+	pLogger->setDebugMode(this->debugEnabled);
+	//pLogger->setDebugMode(DBG_ENABLED);
+	pLogger->setDebugLevel(DEBUGGING);
+	pLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+	pLogger->enableDebugOuput(DBG_SCREEN);
+	//pLogger->enableDebugOuput(DBG_LOGFILE);	
+
+#ifdef DEBUG_ACTIVE_QUERYPARSER
+	pLogger->debug("Constructor");
+#endif
+}
+
+/**
+ Destructor
+ QueryParser destructor.
+
+ @param void Void.
+ @return Void.
+ */
+
+QueryParser::~QueryParser() {
+#ifdef DEBUG_ACTIVE_QUERYPARSER
+	pLogger->debug("Destructor");
+#endif
+
+	delete pLogger;
+}
+
+/**
+ Public method QueryParser *Instance(void)
+ (pattern Singleton)
+
+ @param void Void.
+ @return Instance of QueryParser class.
+ */
+
+QueryParser *QueryParser::getQueryParser(void) {
+	if (pInstance == NULL) {
+		pInstance = new QueryParser;
+	}
+	return pInstance;
+}
+
+/**
+ Public method QueryParser init
+ QueryParser initialization: macrofunction context is initialized.
+
+
+ @param void Void.
+ @return Void.
+ */
+
+void QueryParser::init() {
+#ifdef DEBUG_ACTIVE_QUERYPARSER
+	pLogger->debug("init");
+#endif
+}
+
+/**
+ Public method QueryParser getParameter
+ This method allows obtaining the required parameter value (in string format) from a specific query string.
+
+ @param paramName Name of the parameter to be searched for in the query string.
+ @param queryString Query string.
+ @return String containing the required parameter value.
+ */
+
+bool QueryParser::getParameter(const char *paramName, const char *queryString,
+		std::string &paramValue) {
+	std::string query;
+	std::string searchStr;
+	std::string::size_type posParamName, startParamValue, endParamValue;
+
+	if (paramName == NULL || queryString == NULL) {
+		paramValue = std::string("");
+		return false;
+	}
+#ifdef DEBUG_ACTIVE_QUERYPARSER
+	pLogger->debug("getParameter - paranName = %s in queryString = %s", paramName, queryString);
+#endif
+
+	// Copy queryString into a stl String object
+	query = std::string(queryString);
+	// Define the search string = paramName + EQUAL. e.g.  "mode" + "="
+	searchStr = std::string(paramName);
+
+	for (posParamName = 0; posParamName < query.length(); posParamName++) {
+
+		posParamName = query.find(searchStr, posParamName);
+		if (posParamName == std::string::npos)
+			break;
+		startParamValue = posParamName + searchStr.length();
+		if (startParamValue >= query.length())
+			break;
+		if (query[startParamValue] == EQUAL
+				|| query[startParamValue] == DELIMITER) {
+			startParamValue++;
+			break;
+		}
+
+	}
+#ifdef DEBUG_ACTIVE_QUERYPARSER
+	pLogger->debug("getParameter - posParanName = %d", posParamName);
+#endif
+	if (posParamName == std::string::npos || posParamName >= query.length()) {
+#ifdef DEBUG_ACTIVE_QUERYPARSER
+		pLogger->debug("getParameter - paranName = %s not found in queryString = %s", paramName, queryString);
+#endif
+		paramValue = std::string("");
+		return false;
+	}
+
+	// start position
+#ifdef DEBUG_ACTIVE_QUERYPARSER
+	pLogger->debug("getParameter - startParamValue = %d", startParamValue);
+#endif
+	// end position
+	endParamValue = query.find(DELIMITER, startParamValue);
+#ifdef DEBUG_ACTIVE_QUERYPARSER
+	pLogger->debug("getParameter - endParamValue = %d", endParamValue);
+#endif
+
+	// Get parameter value from String query -> build a substring using start and end positions.
+	paramValue = query.substr(startParamValue, endParamValue - startParamValue);
+	return true;
+}
+
+bool QueryParser::isParameterPresent(const char *paramName,
+		const char *queryString) {
+	std::string query;
+	std::string searchStr;
+	std::string::size_type posParamName;
+
+	if (paramName == NULL || queryString == NULL) {
+		return false;
+	}
+#ifdef DEBUG_ACTIVE_QUERYPARSER
+	pLogger->debug("isParameterPresent - paranName = %s in queryString = %s", paramName, queryString);
+#endif
+
+	// Copy queryString into a stl String object
+	query = std::string(queryString);
+	// Define the search string = paramName 
+	searchStr = std::string(paramName);
+
+	posParamName = 0;
+	posParamName = query.find(searchStr, posParamName);
+	if (posParamName == std::string::npos || posParamName >= query.length()) {
+#ifdef DEBUG_ACTIVE_QUERYPARSER
+		pLogger->debug("isParameterPresent - paranName = %s not found in queryString = %s", paramName, queryString);
+#endif
+		return false;
+	} else
+		return true;
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CQueryParser.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CQueryParser.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CQueryParser.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,75 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef QUERYPARSER_H
+#define QUERYPARSER_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "ThreadPool.h"
+#include "TimerThread.h"
+
+#include "GalZbIf.h"
+#include "CMessage.h"
+#include "ZbNetDb.h"
+#include "CDebug.h"
+
+#include <string>
+
+///Character to separate parameter name and value
+#define EQUAL				'='
+#define DELIMITER			'&'
+
+class QueryParser {
+
+public:
+	// Constructors
+
+	// Destructor
+	~QueryParser();
+
+	// Functions: modifiers (set), selectors (get)
+
+	// Pattern Singleton
+	static QueryParser *getQueryParser(void);
+
+	void init();
+
+	bool getParameter(const char *paramName, const char *queryString,
+			std::string &value);
+
+	bool isParameterPresent(const char *paramName, const char *queryString);
+
+	// iterators:
+	// Attributes visible by scope of instantiation and use
+
+protected:
+
+	///	Constructor (pattern Singleton)
+	QueryParser();
+
+	// Attributes visible to descendents
+
+	///	Pointer to a Debug object -> logger
+	Debug *pLogger;
+
+	///	To enable/disable Debug (default value is 0)
+	bool debugEnabled;
+
+private:
+	// Local attributes
+
+	// Pattern Singleton
+	static QueryParser *pInstance;
+
+};
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTBroker.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTBroker.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTBroker.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,6281 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <iomanip>
+
+#define LOCAL_LOGGER pLogger
+#ifdef DEBUG_ACTIVE_RB
+#define LOCAL_DEBUG_ENABLED
+#endif
+
+#include "CRESTBroker.h"
+
+const RBResourceDescriptor RESTBroker::rootDesc[] = {
+		//	"/"  ->
+		RBResourceDescriptor("ib", NULL), RBResourceDescriptor("net", NULL),
+		RBResourceDescriptor("networks", NULL), RBResourceDescriptor("reset",
+				&RESTBroker::reset_Req), RBResourceDescriptor("startup",
+				&RESTBroker::startup_Req), RBResourceDescriptor("version",
+				&RESTBroker::version_Req),
+//#ifdef WSN_C_PROTOCOL_BACKWARD_COMPATIBILITY
+		RBResourceDescriptor("localnode", NULL),
+//#endif
+		RBResourceDescriptor("", NULL) };
+
+const RBResourceDescriptor RESTBroker::netDesc[] = {
+		//  "/net/<net Id>/"  ->
+		RBResourceDescriptor("aliases", &RESTBroker::listAddresses_Req),
+		RBResourceDescriptor("allaliases", &RESTBroker::listAllAddresses_Req),
+		RBResourceDescriptor("allwsnnodes", &RESTBroker::ndRoot_Req),
+		RBResourceDescriptor("callbacks", &RESTBroker::callbacks_Req),
+		RBResourceDescriptor("discovery", NULL), RBResourceDescriptor("ib",
+				NULL), RBResourceDescriptor("localnode", NULL),
+		RBResourceDescriptor("wsnnodes", &RESTBroker::wsnNodesList_Req),
+
+		RBResourceDescriptor("", NULL) };
+
+const RBResourceDescriptor RESTBroker::ibRootDesc[] = {
+		//	 "/ib/" (IB Attributes)  ->
+		RBResourceDescriptor("00", &RESTBroker::manageGIBAttr_Req),
+		RBResourceDescriptor("", NULL) };
+
+const RBResourceDescriptor RESTBroker::ibNetDesc[] = {
+		//	 "/net/<net Id>/ib/" (APS IB Attributes)  ->
+		RBResourceDescriptor("c3", &RESTBroker::informationBase_Req), //apsChannelMask
+		RBResourceDescriptor("c4", &RESTBroker::informationBase_Req), //apsUseExtendedPANID
+		RBResourceDescriptor("c8", &RESTBroker::informationBase_Req), //apsUseInsecureJoin
+		RBResourceDescriptor("*", &RESTBroker::informationBase_Req),
+		RBResourceDescriptor("", NULL) };
+
+const RBResourceDescriptor RESTBroker::nodeDesc[] = {
+		//	"/net/<net Id>/wsnnodes/<wsnnode Id>/"  ->
+		RBResourceDescriptor("services", &RESTBroker::ndServicesList_Req),
+		RBResourceDescriptor("allservices", NULL), RBResourceDescriptor(
+				"nodedescriptor", &RESTBroker::nodeDescriptor_Req),
+		RBResourceDescriptor("powerdescriptor",
+				&RESTBroker::ndPowerDescriptor_Req), RBResourceDescriptor(
+				"userdescriptor", NULL), RBResourceDescriptor("epgroups", NULL),
+		RBResourceDescriptor("bindings", &RESTBroker::lsBind_Req),
+		RBResourceDescriptor("unbindings", &RESTBroker::lsUnbind_Req),
+		RBResourceDescriptor("permitjoin", &RESTBroker::ndPermitJoin_Req),
+
+		RBResourceDescriptor("", &RESTBroker::ndRoot_Req) };
+
+const RBResourceDescriptor RESTBroker::lnNodeDesc[] = {
+		//	"/net/<net Id>/localnode/"  ->
+		RBResourceDescriptor("services", &RESTBroker::lndServicesList_Req),
+		RBResourceDescriptor("allservices", NULL), RBResourceDescriptor(
+				"nodedescriptor", &RESTBroker::nodeDescriptor_Req),
+		RBResourceDescriptor("powerdescriptor", NULL), RBResourceDescriptor(
+				"userdescriptor", NULL), RBResourceDescriptor("epgroups", NULL),
+		RBResourceDescriptor("frequencyagility",
+				&RESTBroker::frequencyAgility_Req), RBResourceDescriptor("",
+				&RESTBroker::ndRoot_Req) };
+
+//#ifdef WSN_C_PROTOCOL_BACKWARD_COMPATIBILITY
+const RBResourceDescriptor RESTBroker::lnNodeDescBC[] = {
+		//	"/localnode/"  ->
+		RBResourceDescriptor("nodedescriptor", &RESTBroker::nodeDescriptor_Req),
+		RBResourceDescriptor("services", NULL),
+
+		RBResourceDescriptor("", NULL) };
+
+const RBResourceDescriptor RESTBroker::servicesDescBC[] = {
+//	"/localnode/services/<service Id>/"  ->
+		RBResourceDescriptor("wsnconnection",
+				&RESTBroker::lsWsnConnection_BC_Req), RBResourceDescriptor("",
+				NULL) };
+
+const RBResourceDescriptor RESTBroker::connDescBC[] = {
+		//	"/localnode/services/<service Id>/wsnconnection"  ->
+		RBResourceDescriptor("message", &RESTBroker::lsMessage_Req),
+		RBResourceDescriptor("", NULL) };
+//#endif
+
+const RBResourceDescriptor RESTBroker::allnNodeDesc[] = {
+		//	"/net/<net Id>/allwsnnodes"
+		RBResourceDescriptor("services", &RESTBroker::awndServicesList_Req),
+		RBResourceDescriptor("allservices", NULL), RBResourceDescriptor(
+				"nodedescriptor", NULL), RBResourceDescriptor("powerdescriptor",
+				NULL), RBResourceDescriptor("userdescriptor", NULL),
+		RBResourceDescriptor("epgroups", NULL), RBResourceDescriptor("bindings",
+				&RESTBroker::lsBind_Req), RBResourceDescriptor("unbindings",
+				&RESTBroker::lsUnbind_Req), RBResourceDescriptor("permitjoin",
+				&RESTBroker::ndPermitJoin_Req), RBResourceDescriptor("lqi",
+				&RESTBroker::ndLQIInformation_Req), RBResourceDescriptor("",
+				&RESTBroker::ndRoot_Req) };
+
+const RBResourceDescriptor RESTBroker::allServicesDesc[] = {
+
+RBResourceDescriptor("wsnconnection",
+		&RESTBroker::lndAllServicesWsnConnection_Req), RBResourceDescriptor("",
+		NULL) };
+
+const RBResourceDescriptor RESTBroker::allServicesConnDesc[] = {
+
+RBResourceDescriptor("message", &RESTBroker::lndAllServicesMessage_Req),
+		RBResourceDescriptor("", NULL) };
+
+const RBResourceDescriptor RESTBroker::servicesDesc[] = {
+
+RBResourceDescriptor("wsnconnection", &RESTBroker::lsWsnConnection_Req),
+		RBResourceDescriptor("", &RESTBroker::clearEndpoin_Req) };
+
+const RBResourceDescriptor RESTBroker::connDesc[] = {
+
+RBResourceDescriptor("message", &RESTBroker::lsMessage_Req),
+		RBResourceDescriptor("", NULL) };
+
+bool IDResourcePredicate::operator ()(Resource *&val) {
+	return id == val->rd.path;
+}
+
+RESTBroker::RESTBroker() {
+	// Init mutex
+	pthread_mutex_init(&mux, NULL);
+
+	ConfigurationRepository *_conf = ConfigurationRepository::instance();
+	// We load the configuration from the ConfigurationManager
+	this->debugEnabled = _conf->getint("main:debugEnabled", false);
+	this->debugLevel = _conf->getint("Debug:RESTBrokerDL", TEST);
+
+	// Debug
+	pLogger = new Debug("RESTBroker");
+	// Set Debug parameters
+	pLogger->setDebugMode(this->debugEnabled);
+	pLogger->setDebugLevel(this->debugLevel);
+
+	pLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+	pLogger->enableDebugOuput(DBG_SCREEN);
+	//pLogger->enableDebugOuput(DBG_LOGFILE);
+
+	L_DEBUG("Constructor");
+
+	// Get XML Message Composer.
+	pXMLMsgComposer = XMLMsgComposer::Instance();
+
+	// Get XML Message Parser.
+	pXMLMsgParser = XMLMsgParser::Instance();
+
+	// Get REST Client and Server.
+	pRESTServer = new RESTServer(pXMLMsgParser, pXMLMsgComposer);
+	pRESTClient = RESTClient::getRESTClient();
+
+	// Get Query Parser.
+	pQueryParser = QueryParser::getQueryParser();
+
+	// Init pointers.
+	pLocalNode = NULL;
+	pDAgent = NULL;
+	pSAgent = NULL;
+	pMngmtAgent = NULL;
+	pTCAgent = NULL;
+}
+
+RESTBroker::~RESTBroker() {
+	printf("RESTBroker - Destructor\n");
+	tasks.wsnc.stop();
+	// Delete XML Message Composer and XML Query Parser
+	delete pQueryParser;
+	delete pRESTClient;
+	delete pRESTServer;
+	delete pLogger;
+}
+
+void RESTBroker::init(bool autostartFlag, bool startupModeFlag) {
+	ConfigurationRepository *conf;
+	bool ns;
+	int startupMode;
+
+	L_DEBUG("init");
+
+	pGWManagementMsgs = GWManagementMessages::Instance();
+
+	// Init query parser
+	pQueryParser->init();
+
+	// REST Client init
+	pRESTClient->init();
+
+	// REST Server init
+	if (pRESTServer->init()) {
+		L_ERROR("RESTBroker - initialization failed - exit");
+		exit(2);
+	}
+
+	// Get LocalNode
+	connectLocalNode();
+
+	wsnCAddress = "";
+
+	initListeners();
+
+	conf = ConfigurationRepository::instance();
+
+	// We load the configuration from the ConfigurationManager
+	// Note: autostart and startupMode are chosen by config.ini only if not specified as argument options
+	autostart = conf->getint("main:autostart", true);
+	if (autostartFlag == true) {
+		// "-a" option has higher priority than config.ini
+		autostart = true;
+	}
+	startupMode = conf->getint("main:startupMode", 0);
+	if (startupModeFlag == true) {
+		// "-m" option has higher priority than config.ini
+		startupMode = 1; //Only the second scenario described in config.ini use the NVM
+	}
+	pGalZb = GalZbIf::Instance();
+	pGalDb = pGalZb->getDb();
+	pGalDb->setStartModeSetting(startupMode);
+
+	ns = conf->getint("main:namespaces", true);
+
+	localRegToDAnnceEnabled = conf->getint("main:localRegToDAnnce", true);
+	L_DEBUG("init - localRegToDAnnceEnabled = %d",
+			this->localRegToDAnnceEnabled);
+
+	useDefaultNWKRootURI = conf->getint("RESTBroker:UseDefaultNWKRootURI",
+			true);
+	L_DEBUG("init - useDefaultNWKRootURI = %d", this->useDefaultNWKRootURI);
+
+	L_DEBUG("init - autostart = %d", autostart);
+
+	pXMLMsgComposer->enableNamespaces(ns);
+
+	wsncAttached = false;
+	numWSNConnctionsFromWsnc = 0;
+
+	this->customizedCallbackIdCounter = 0;
+
+	//Init bool variables
+	this->isAMLocallyEnabled = false;
+	this->isFMLocallyEnabled = false;
+
+	// Init REST Resources
+	// Create Root resources
+	createRootResources();
+
+	// Set NKW Root URI according to UseDefaultNWKRootURI in config.ini and create relevant sub-resources
+	if (this->useDefaultNWKRootURI) {
+		resources.defNet = createNetResources("default");
+		L_DEBUG("init - invoke createNetResources - default -");
+	} else {
+		StartupAttributeInfo* startAttributeSet;
+
+		startAttributeSet = pLocalNode->readStartupAttributeSet(0);
+		std::stringstream networkId;
+
+		for (int i = 0; i < 8; i++) {
+			networkId.width(2);
+			networkId.fill('0');
+			networkId << hex;
+			networkId << (unsigned int) startAttributeSet->extendedPANId[i];
+		}
+		resources.defNet = createNetResources(networkId.str().c_str());
+		L_DEBUG("init - invoke createNetResources - %s -",
+				networkId.str().c_str());
+	}
+
+	// create createIBResources
+	createIBResources();
+	L_DEBUG("init - invoke createIBResources for root path\r");
+
+	resources.defLocalNode = createNodeResources(resources.defNet, NULL);
+	resources.defCallbacks = pRESTServer->findResource(resources.defNet,
+			"callbacks");
+}
+
+void RESTBroker::createRootResources() {
+	L_DEBUG("createRootResources");
+	createResources(NULL, rootDesc);
+}
+
+Resource *RESTBroker::createNetResources(const char *name) {
+	Resource *r, *rp, *rc;
+
+	r = pRESTServer->findResource(NULL, "net");
+	r = createFolder(r, name);
+	createResources(r, netDesc);
+
+	rp = pRESTServer->findResource(r, "allwsnnodes");
+	rp->data.d = 0xFFFF;
+
+	createResources(rp, allnNodeDesc);
+
+	rc = pRESTServer->findResource(r, "ib");
+	createResources(rc, ibNetDesc);
+
+//#ifdef WSN_C_PROTOCOL_BACKWARD_COMPATIBILITY
+	Resource *rbc;
+
+	rbc = pRESTServer->findResource(NULL, "localnode");
+	createResources(rbc, lnNodeDescBC);
+//#endif
+
+	return r;
+}
+
+Resource *RESTBroker::createIBResources() {
+	Resource *r;
+
+	r = pRESTServer->findResource(NULL, "ib");
+	r = createFolder(r, "00");
+	createResources(r, ibRootDesc);
+
+	return r;
+}
+
+Resource *RESTBroker::createNodeResources(Resource *root, Node *node) {
+	char bufShortAddr[5];
+	char bufIeeeAddr[17];
+	char bufShortAddrToBeRemoved[5];
+	char bufEP[3];
+	Resource *rTmp, *r, *rDup, *rDel, *ep, *alls;
+
+	if (node != NULL) {
+		// Short Address
+		sprintf(bufShortAddr, "%04x", node->get_nwk_addr());
+		// IEEE Address
+		std::stringstream ieee;
+		ieee << hex;
+		for (int i = 0; i < 8; i++) {
+			ieee.width(2);
+			ieee.fill('0');
+			ieee << (unsigned int) node->get_ieee_addr()[i];
+		}
+		L_DEBUG(
+				"**** createNodeResources - Node shortAddr %s - IEEEAddr %s ****",
+				bufShortAddr, ieee.str().c_str());
+		sprintf(bufIeeeAddr, "%s", ieee.str().c_str());
+		rTmp = pRESTServer->findResource(root, "wsnnodes");
+		// Search whether the considered node is already present in the list of IEEE addresses
+		// If so, just update the resource description; otherwise, a now REST resource is created
+		rDup = pRESTServer->findResource(rTmp, bufIeeeAddr);
+		if (rDup != NULL) {
+			r = rDup;
+			//L_DEBUG("createNodeResources - IEEEAddress already existing!");
+			//Remove REST resource related to previous short address
+			sprintf(bufShortAddrToBeRemoved, "%04x", r->data.d);
+			//L_DEBUG ("createNodeResources - search for short address Node Resource - %s",bufShortAddrToBeRemoved);
+			rDel = pRESTServer->findResource(rTmp, bufShortAddrToBeRemoved);
+			if (rDel != NULL) {
+				//L_DEBUG ("createNodeResources - remove short address Node Resource - %s",bufShortAddrToBeRemoved);
+				pRESTServer->removeResource(rDel);
+			}
+		} else {
+			r = createFolder(rTmp, bufIeeeAddr, nodeDesc);
+		}
+
+		r->data.d = node->get_nwk_addr();
+		if (rDup == NULL) {
+			createResources(r, nodeDesc);
+			//L_DEBUG("createNodeResources - IEEE address Node Resource (short addr %d) created", r -> data.d);
+		}
+		// Search for already existing resources among the list of short addresses
+		rDup = pRESTServer->findResource(rTmp, bufShortAddr);
+		if (rDup != NULL) {
+			r = rDup;
+			//L_DEBUG("createNodeResources - short resource already existing - short address %d", r -> data.d);
+		} else {
+			r = createFolder(rTmp, bufShortAddr, nodeDesc);
+		}
+		r->data.d = node->get_nwk_addr();
+		//L_DEBUG("createNodeResources - going to create Node Resource - short addr %d", r -> data.d);
+		createResources(r, nodeDesc);
+		// If required, update information related to localnode resource
+		pGalZb = GalZbIf::Instance();
+		pGalDb = pGalZb->getDb();
+		ushort localNodeNwkAddr = pGalDb->root->get_nwk_addr();
+		if ((node->get_nwk_addr()) == localNodeNwkAddr) {
+			r = pRESTServer->findResource(root, "localnode");
+			r->data.d = node->get_nwk_addr();
+			//L_INFO("createNodeResources - localnode resource updated - data = %x", localNodeNwkAddr);
+		}
+	} else {
+		// Create REST "localnode" resource
+		r = pRESTServer->findResource(root, "localnode");
+		createResources(r, lnNodeDesc);
+		// Create REST resources related to "localnode"
+		alls = pRESTServer->findResource(r, "allservices");
+		createResources(alls, allServicesDesc);
+		alls = pRESTServer->findResource(alls, "wsnconnection");
+		createResources(alls, allServicesConnDesc);
+		//Add endpoint 0
+		rTmp = pRESTServer->findResource(root, "localnode");
+		;
+		sprintf(bufEP, "%02x", 0);
+		//L_INFO("createResource for localnode EndPoint 0");
+		ep = pRESTServer->findResource(rTmp, "services");
+		ep = createFolder(ep, bufEP, servicesDesc);
+		ep->data.d = 0;
+		createResources(ep, servicesDesc);
+		ep = pRESTServer->findResource(ep, "wsnconnection");
+		createResources(ep, connDesc);
+	}
+	return r;
+}
+
+Resource *RESTBroker::createCallbackResources(Resource *root, uriListener_t *l,
+		RBURIListenerList *rbl) {
+	std::stringstream s;
+	Resource *r;
+
+	s << l->id;
+
+	L_DEBUG("createCallbackResources - Callback ID: %s ", s.str().c_str());
+	r = createFolder(root, s.str().c_str(), &RESTBroker::cbCallback_Req);
+
+	r->data.p = rbl;
+
+	return r;
+}
+
+void RESTBroker::syncCallbackResources(Resource *root, RBURIListenerList *l) {
+	std::list<Resource *>::iterator i;
+	std::list<uriListener_t>::iterator j;
+	std::list<Resource *> removed;
+	IDResourcePredicate p;
+
+	for (i = root->children.begin(); i != root->children.end(); i++)
+		if ((*i)->data.p == l)
+			removed.push_back(*i);
+
+	for (j = l->listeners.begin(); j != l->listeners.end(); j++) {
+		p.id = j->id;
+		removed.remove_if(p);
+	}
+
+	for (i = removed.begin(); i != removed.end(); i++)
+		pRESTServer->removeResource(*i);
+}
+
+Resource *RESTBroker::createFolder(Resource *root, const char *path,
+		ResHandler handler) {
+	ResourceDescriptor *rd;
+	Resource *res;
+
+	rd = new RBResourceDescriptor(path, handler);
+
+	res = new Resource(rd, this, NULL);
+
+	pRESTServer->registerResource(res, root);
+
+	return res;
+}
+
+Resource *RESTBroker::createFolder(Resource *root, const char *path,
+		const RBResourceDescriptor rb[]) {
+	int i;
+
+	for (i = 0; rb[i].path != ""; i++) {
+
+	}
+
+	L_DEBUG("createFolder: rb len = %d -> value %s", i, rb[i].path.c_str());
+
+	return createFolder(root, path, rb[i].callback);
+}
+
+void RESTBroker::createResources(Resource *root,
+		const RBResourceDescriptor rb[]) {
+	int i;
+
+	L_DEBUG("createResources (%s)", root == NULL ? "/" : root->rd.path.c_str());
+	for (i = 0; rb[i].path != ""; i++) {
+		//L_DEBUG ("createResources: added", rb [i].path.c_str ());
+		pRESTServer->createResource(root, rb[i], this, NULL);
+	}
+}
+
+int RESTBroker::connectLocalNode() {
+	L_DEBUG("connectLocalNode");
+
+	// Get LocalNode
+	pLocalNode = LocalNode<RESTBroker>::getLocalNode();
+
+	return 0;
+}
+
+void RESTBroker::initAgents() {
+	L_DEBUG("initAgents");
+
+	// Get Agents
+	pDAgent = pLocalNode->getDiscoveryAgent();
+	pSAgent = pLocalNode->getServiceAgent();
+	pMngmtAgent = pLocalNode->getManagementAgent();
+	pDAgent->init();
+	pDAgent->initDAListeners();
+	pSAgent->init();
+	pMngmtAgent->init();
+}
+
+void RESTBroker::initListeners() {
+	ConfigurationRepository *conf;
+	const char *listener;
+	std::string s;
+
+	L_DEBUG("initListeners");
+
+	listeners.gwStatus.handler = this;
+	listeners.gwStatus.attach = NULL;
+	listeners.gwStatus.detach = NULL;
+
+	listeners.freshness.handler = this;
+	listeners.freshness.attach = &RESTBroker::nodeFreshnessAttach;
+	listeners.freshness.detach = &RESTBroker::nodeFreshnessDetach;
+
+	listeners.nodeAnnounce.handler = this;
+	listeners.nodeAnnounce.attach = &RESTBroker::nodeAnnounceAttach;
+	listeners.nodeAnnounce.detach = &RESTBroker::nodeAnnounceDetach;
+
+	listeners.nodeInquiry.handler = this;
+	listeners.nodeInquiry.attach = &RESTBroker::nodeInquiryAttach;
+	listeners.nodeInquiry.detach = &RESTBroker::nodeInquiryDetach;
+
+	listeners.nodeMgmt_Lqi.handler = this;
+	listeners.nodeMgmt_Lqi.attach = &RESTBroker::nodeMgmtLQIAttach;
+	listeners.nodeMgmt_Lqi.detach = &RESTBroker::nodeMgmtLQIDetach;
+
+	listeners.startup.handler = this;
+	listeners.startup.attach = &RESTBroker::startupAttach;
+	listeners.startup.detach = &RESTBroker::startupDetach;
+
+	listeners.serviceDiscovery.handler = this;
+	listeners.serviceDiscovery.attach = &RESTBroker::serviceDiscoveryAttach;
+	listeners.serviceDiscovery.detach = &RESTBroker::serviceDiscoveryDetach;
+
+	listeners.resetCommand.handler = this;
+	listeners.resetCommand.attach = &RESTBroker::resetCommandAttach;
+	listeners.resetCommand.detach = &RESTBroker::resetCommandDetach;
+
+	listeners.leaveCommand.handler = this;
+	listeners.leaveCommand.attach = &RESTBroker::leaveCommandAttach;
+	listeners.leaveCommand.detach = &RESTBroker::leaveCommandDetach;
+
+	listeners.permitJoin.handler = this;
+	listeners.permitJoin.attach = &RESTBroker::permitJoinAttach;
+	listeners.permitJoin.detach = &RESTBroker::permitJoinDetach;
+
+	listeners.getnodebinding.handler = this;
+	listeners.getnodebinding.attach = &RESTBroker::getnodebindingAttach;
+	listeners.getnodebinding.detach = &RESTBroker::getnodebindingDetach;
+
+	listeners.bind.handler = this;
+	listeners.bind.attach = &RESTBroker::bindAttach;
+	listeners.bind.detach = &RESTBroker::bindDetach;
+
+	listeners.unbind.handler = this;
+	listeners.unbind.attach = &RESTBroker::unbindAttach;
+	listeners.unbind.detach = &RESTBroker::unbindDetach;
+
+	listeners.serviceDescriptor.handler = this;
+	listeners.serviceDescriptor.attach = &RESTBroker::serviceDescriptorAttach;
+	listeners.serviceDescriptor.detach = &RESTBroker::serviceDescriptorDetach;
+
+	listeners.nodeDescriptor.handler = this;
+	listeners.nodeDescriptor.attach = &RESTBroker::nodeDescriptorAttach;
+	listeners.nodeDescriptor.detach = &RESTBroker::nodeDescriptorDetach;
+
+	listeners.allServices.handler = this;
+	listeners.allServices.attach = &RESTBroker::allServicesAttach;
+	listeners.allServices.detach = &RESTBroker::allServicesDetach;
+
+	pthread_mutex_lock(&mux);
+	conf = ConfigurationRepository::instance();
+	// We load the configuration from the ConfigurationManager
+	listener = conf->getstring("main:gwStatusChanged_DefaultURIListener", NULL);
+	if (listener == NULL) {
+		pthread_mutex_unlock(&mux);
+		L_DEBUG("init - gwStatusChanged_DefaultURIListener = NULL");
+		return;
+	}
+	L_DEBUG("init - gwStatusChanged_DefaultURIListener = %s", listener);
+	s = std::string(listener);
+	listeners.gwStatus.addListener(&s, LOCAL_REST_REQUEST_SESSION_ID);
+	setWSNCAddress(s);
+	pthread_mutex_unlock(&mux);
+}
+
+void RESTBroker::clearAllListeners() {
+	L_DEBUG("unistallListeners");
+	pthread_mutex_lock(&mux);
+	listeners.serviceDiscovery.removeListeners();
+	listeners.serviceDescriptor.removeListeners();
+	listeners.nodeDescriptor.removeListeners();
+	listeners.leaveCommand.removeListeners();
+	listeners.permitJoin.removeListeners();
+	listeners.freshness.removeListeners();
+	listeners.nodeAnnounce.removeListeners();
+	listeners.nodeInquiry.removeListeners();
+	listeners.nodeMgmt_Lqi.removeListeners();
+	listeners.allServices.removeListeners();
+
+	std::map<int, RBURIListenerList>::iterator i;
+	for (i = listeners.service.begin(); i != listeners.service.end(); ++i) {
+		(i->second).removeListeners();
+	}
+	listeners.service.clear();
+	for (i = listeners.customizedCallback.begin();
+			i != listeners.customizedCallback.end(); ++i) {
+		(i->second).removeListeners();
+	}
+	listeners.customizedCallback.clear();
+	for (i = listeners.service_BC.begin(); i != listeners.service_BC.end();
+			++i) {
+		(i->second).removeListeners();
+	}
+	listeners.service_BC.clear();
+	pthread_mutex_unlock(&mux);
+}
+
+void RESTBroker::setWSNCAddress(std::string &s) {
+	size_t begin, end;
+
+	begin = s.find("http://");
+	if (begin == std::string::npos)
+		return;
+
+	begin += strlen("http://");
+
+	L_DEBUG("init - string %s found in urilistener %s -> "
+			"startPos =%d", "http://", s.c_str(), begin);
+
+	end = s.find(":", begin);
+	if (end == std::string::npos)
+		end = s.length();
+
+	wsnCAddress = s.substr(begin, end - begin);
+
+	L_DEBUG("init - endPos = %d - wsnCAddress = %s", end, wsnCAddress.c_str());
+}
+
+void RESTBroker::start() {
+	L_DEBUG("start");
+
+	// Execute autorun
+	autorun();
+
+	pRESTServer->start();
+}
+
+void RESTBroker::autorun() {
+	// CreateCallback required contexts
+	LocalNode<RESTBroker>::CreateCallbackCtxt ccCtxt(
+			LOCAL_REST_REQUEST_SESSION_ID, this,
+			(LocalNode<RESTBroker>::createCallbackResponseCb) &RESTBroker::gwDescriptorLocal_RspCb,
+			NULL);
+	LocalNode<RESTBroker>::StatusChanged_Event_NotifyCtxt scCtxt(
+			LOCAL_REST_REQUEST_SESSION_ID, this, NULL,
+			(LocalNode<RESTBroker>::gwStatusChanged_Event_NotifyCb) &RESTBroker::gwStatusChanged_gwDescriptor_NtfCb);
+
+	// startAnnouncementsMode context
+	DiscoveryAgent<RESTBroker>::StartAnnouncementsModeCtxt samCtxt(
+			LOCAL_REST_REQUEST_SESSION_ID, this,
+			(DiscoveryAgent<RESTBroker>::startAnnouncementsModeResponseCb) &RESTBroker::wsnNodesList_StartAnnceMode_RspCb,
+			(DiscoveryAgent<RESTBroker>::announceNotifyCb) &RESTBroker::wsnNodeAnnce_NtfCb);
+
+	// startFreshnessMode context
+	DiscoveryAgent<RESTBroker>::StartFreshnessModeCtxt sfmCtxt(
+			LOCAL_REST_REQUEST_SESSION_ID, this,
+			(DiscoveryAgent<RESTBroker>::startFreshnessModeResponseCb) &RESTBroker::wsnNodesList_StartFreshnessMode_RspCb,
+			(DiscoveryAgent<RESTBroker>::freshnessNotifyCb) &RESTBroker::wsnNodeFreshnessAnnce_NtfCb);
+
+	// addDefaultService context
+	ServiceAgent<RESTBroker>::AddServiceCtxt asCtx(
+			LOCAL_REST_REQUEST_SESSION_ID, this,
+			(ServiceAgent<RESTBroker>::addServiceResponseCb) &RESTBroker::lndServicesList_RspCb,
+			NULL);
+
+	// startGatewayDevice context
+	LocalNode<RESTBroker>::StartGatewayDeviceCtxt stCtxt(
+			LOCAL_REST_REQUEST_SESSION_ID, this,
+			(LocalNode<RESTBroker>::startupResponseCb) &RESTBroker::startup_RspCb,
+			NULL);
+
+	L_DEBUG("autorun");
+
+	// Init Agents
+	initAgents();
+
+	// GW_DESCRIPTOR
+	pLocalNode->createCallback(&scCtxt, &ccCtxt);
+
+	// Start announcementsMode if this features is enabled (in the config file)
+	if (localRegToDAnnceEnabled) {
+		int samResult = pDAgent->startAnnouncementsMode(&samCtxt);
+		if (samResult == AGENT_SUCCESS)
+			isAMLocallyEnabled = true;
+		else
+			L_ERROR("autorun - ERROR invoking startAnnouncementsMode locally");
+	}
+
+	// Start freshnessMode as well
+	int sfmResult = pDAgent->startFreshnessMode(&sfmCtxt);
+	if (sfmResult == AGENT_SUCCESS)
+		isFMLocallyEnabled = true;
+	else
+		L_ERROR("autorun - ERROR invoking startFreshnessMode locally");
+
+	/*
+	 // Setup endpoint 0 for the ZigBee Gateway device
+	 L_DEBUG("autorun - setup endpoint 0");
+	 pSAgent-> addDefaultService(&asCtx);
+	 */
+	// Setup the default SimpleDescriptor for the ZigBee Gateway device
+	L_DEBUG("autorun - setup a default Simple Descriptor");
+	pSAgent->addDefaultService(&asCtx);
+
+	if (autostart) {
+		L_INFO("autostart enabled -> Execute LocalNode start");
+		// Call LocalNode::startup
+		pLocalNode->startGatewayDevice(0xffffffff, NULL, &stCtxt);
+	} else {
+		L_INFO(
+				"autorun disabled -> Waiting for startup request (calling a reset to init)");
+		//Send a reset command (needed for the Freescale dongle)!
+		pGalZb->ZDO_RESET_request(0x04);
+	}
+}
+
+void RESTBroker::handle(Resource *res, const char *reqUri, Method reqMethod,
+		const char *queryString, std::string *xmlMsg, HTTPSessionContext *ctxt)
+				throw (RESTException, HTTPException) {
+	const RBResourceDescriptor *rbrd;
+	RESTSessionContext *rctxt;
+
+	rbrd = dynamic_cast<const RBResourceDescriptor *>(&res->rd);
+	if (rbrd != NULL && rbrd->callback != NULL) {
+		rctxt = dynamic_cast<RESTSessionContext *>(ctxt);
+		(this->*rbrd->callback)(res, reqUri, reqMethod, queryString, xmlMsg,
+				rctxt);
+	} else {
+		pRESTServer->defaultHandler(res, reqUri, reqMethod, queryString, xmlMsg,
+				ctxt);
+	}
+
+}
+
+void RESTBroker::badMethod(Resource *res, HTTPSessionContext *ctxt)
+		throw (HTTPException) {
+	L_INFO("Request for method not allowed "
+			"on resource %s", res->uri.c_str());
+
+	throw HTTPException(405, "Method Not Allowed");
+}
+
+void RESTBroker::addListener(URIListenerList *l, uriListener_t *listener,
+		int sessionId) {
+	RBURIListenerList *rbl;
+
+	rbl = dynamic_cast<RBURIListenerList *>(l);
+	if (rbl != NULL && rbl->attach != NULL)
+		(this->*rbl->attach)(rbl, listener, sessionId, false);
+}
+
+void RESTBroker::updateListener(URIListenerList *l, uriListener_t *oldl,
+		uriListener_t *newl, int sessionId) {
+	RBURIListenerList *rbl;
+
+	L_DEBUG("updateListener");
+	rbl = dynamic_cast<RBURIListenerList *>(l);
+	if (rbl != NULL && rbl->attach != NULL)
+		(this->*rbl->attach)(rbl, newl, sessionId, true);
+}
+
+void RESTBroker::removeListeners(URIListenerList *l) {
+	RBURIListenerList *rbl;
+
+	rbl = dynamic_cast<RBURIListenerList *>(l);
+	if (rbl != NULL && rbl->detach != NULL)
+		(this->*rbl->detach)(rbl);
+}
+
+void RESTBroker::restSuccess_Evt(RBURIListenerList *uriList,
+		const char *detail) {
+	std::list<uriListener_t>::iterator i;
+
+	i = uriList->listeners.begin();
+	while (i != uriList->listeners.end()) {
+		if (!pRESTServer->restSuccess(detail, &*i))
+			i = uriList->removeListener(i);
+		else
+			i++;
+	}
+}
+
+void RESTBroker::restSuccess_Evt(RBURIListenerList *uriList, const char *detail,
+		bool isAsynchResponse) {
+	std::list<uriListener_t>::iterator i;
+
+	if (isAsynchResponse) {
+		L_WARN("!!!ERROR!!!!");
+		return;
+	}
+
+	i = uriList->listeners.begin();
+	while (i != uriList->listeners.end()) {
+		if (!pRESTServer->restSuccess(detail, &*i, isAsynchResponse))
+			i = uriList->removeListener(i);
+		else
+			i++;
+	}
+}
+
+void RESTBroker::restError_Evt(RBURIListenerList *uriList, int errorId,
+		const char *errorDesc, const char *nwkStatus) {
+	std::list<uriListener_t>::iterator i;
+
+	i = uriList->listeners.begin();
+	while (i != uriList->listeners.end())
+		if (!pRESTServer->restError(errorId, errorDesc, nwkStatus, &*i))
+			i = uriList->removeListener(i);
+		else
+			i++;
+}
+
+void RESTBroker::restEvent(const char *method, RBURIListenerList *uriList,
+		const char *detail, const char *nwkStatus, RPCReqStatus *status) {
+	const char *errorDesc;
+	RESTError ec;
+	AgentError returnValue;
+
+	if (status != NULL) {
+		returnValue = status->getReturnValue();
+		L_DEBUG("%s - fResult = %d", method, status->getFResult());
+	} else
+		returnValue = AGENT_SUCCESS;
+
+	if (returnValue != AGENT_SUCCESS) {
+		ec = AgentErrorMessages::getRESTError(returnValue);
+		errorDesc = AgentErrorMessages::getErrorMessage(returnValue);
+		L_INFO("%s - error code %d - %s", method, ec, errorDesc);
+		restError_Evt(uriList, ec, errorDesc, nwkStatus);
+	} else {
+		L_INFO("%s - success response", method);
+		restSuccess_Evt(uriList, detail);
+	}
+}
+
+void RESTBroker::restEvent(const char *method, RBURIListenerList *uriList,
+		const char *detail, RPCReqStatus *status, bool isAsynchResponse) {
+	const char *msg;
+	RESTError ec;
+	AgentError returnValue;
+
+	if (isAsynchResponse) {
+		restEvent(method, uriList, detail, NULL, status);
+		return;
+	}
+
+	if (status != NULL) {
+		returnValue = status->getReturnValue();
+		L_DEBUG("%s - fResult = %d", method, status->getFResult());
+	} else
+		returnValue = AGENT_SUCCESS;
+
+	if (returnValue != AGENT_SUCCESS) {
+		ec = AgentErrorMessages::getRESTError(returnValue);
+		msg = AgentErrorMessages::getErrorMessage(returnValue);
+		L_INFO("%s - error code %d - %s", method, ec, msg);
+		restError_Evt(uriList, ec, msg, NULL);
+	} else {
+		L_INFO("%s - success response", method);
+		restSuccess_Evt(uriList, detail, isAsynchResponse);
+	}
+}
+
+//#ifdef WSN_C_PROTOCOL_BACKWARD_COMPATIBILITY
+void RESTBroker::restEvent_BC(const char *method, RBURIListenerList *uriList,
+		const char *detail, RPCReqStatus *status) {
+	const char *msg;
+	RESTError ec;
+	AgentError returnValue;
+
+	if (status != NULL) {
+		returnValue = status->getReturnValue();
+		L_DEBUG("%s - fResult = %d", method, status->getFResult());
+	} else
+		returnValue = AGENT_SUCCESS;
+
+	if (returnValue != AGENT_SUCCESS) {
+		ec = AgentErrorMessages::getRESTError(returnValue);
+		msg = AgentErrorMessages::getErrorMessage(returnValue);
+		L_INFO("%s - error code %d - %s", method, ec, msg);
+		restError_Evt(uriList, ec, msg, NULL);
+	} else {
+		L_INFO("%s - success response", method);
+		restSuccess_Evt(uriList, detail); //Enabled on 07-12-2011
+
+		std::list<uriListener_t>::iterator i;
+
+		i = uriList->listeners.begin();
+		while (i != uriList->listeners.end())
+			if (!pRESTServer->restSuccess_BC(detail, &*i))
+				i = uriList->removeListener(i);
+			else
+				i++;
+	}
+}
+//#endif
+
+void RESTBroker::restResponse(const char *method, int sessionId,
+		const char *detail, enum RESTError ec) {
+	if (ec != NO_ERROR) {
+		L_INFO("%s - REST error code %d", method, ec);
+		pRESTServer->restError(ec, NULL, NULL, sessionId);
+	} else {
+		L_INFO("%s - success response", method);
+		pRESTServer->restSuccess(detail, sessionId);
+	}
+}
+
+void RESTBroker::restResponse(const char *method, int sessionId,
+		const char *detail, const char *nwkStatus, RPCReqStatus *status) {
+	const char *msg;
+	RESTError ec;
+	AgentError returnValue;
+
+	returnValue = status == NULL ? AGENT_SUCCESS : status->getReturnValue();
+
+	if (returnValue != AGENT_SUCCESS) {
+		ec = AgentErrorMessages::getRESTError(returnValue);
+		msg = AgentErrorMessages::getErrorMessage(returnValue);
+		L_INFO("%s - error code %d - %s", method, ec, msg);
+		pRESTServer->restError(ec, msg, nwkStatus, sessionId);
+		L_DEBUG("%s - fResult = %d", method, status->getFResult());
+		// Remove also the listener previously registered!
+		listeners.nodeMgmt_Lqi.removeListeners();
+	} else {
+		L_INFO("%s - success response", method);
+		pRESTServer->restSuccess(detail, sessionId);
+	}
+}
+
+//***********************************************************************************************
+//***************************  STARTUP functions  ***********************************************
+//***********************************************************************************************
+void RESTBroker::startup_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (RESTException, HTTPException) {
+	L_DEBUG("startup_Req");
+
+	switch (reqMethod) {
+
+	case M_GET: {
+		//readStartupAttributeSet
+		/*
+		 LocalNode<RESTBroker>::StartupResponseCtxt
+		 rpcContext (ctxt -> getSessionId (), this,
+		 (LocalNode<RESTBroker>::startupResponseCb)
+		 &RESTBroker::startup_RspCb, NULL);
+		 returnValue = pLocalNode->readStartupAttributeSet(&sai,&rpcContext);
+		 */
+
+		L_INFO("startup_Req - readStartupAttributeSet feature not supported");
+		throw RESTException(FEATURE_NOT_SUPPORTED,
+				"readStartupAttributeSet not implemented");
+	}
+		break;
+
+	case M_POST: {
+		std::string modeValue, *uri;
+		RBURIListenerList *rlist;
+		// Get "start" parameter
+		bool start;
+		pQueryParser->getParameter("start", queryString, modeValue);
+		if (modeValue.length() == 0) {
+			L_DEBUG("startup_Req - start parameter missing");
+			// This an error since a value for start must be present
+			throw RESTException(PARAMETER_MISSING, "Missing start parameter"); //It was WRONG_REQUEST
+		} else if (!modeValue.compare("true")) {
+			L_DEBUG("startup_Req - start parameter true");
+			start = true;
+		} else {
+			L_DEBUG("startup_Req - start parameter false");
+			start = false;
+		}
+
+		// Invoke the specific LocalNode methods, according to the value of "start" parameter
+		if (start) {
+			// start == true -> invoke StartGatewayDevice method
+
+			// Check whether "timeout" parameter is present in the request
+			unsigned long int timeout = 0;
+			L_DEBUG("startup_Req - timeoutSet = %d", ctxt->cbinfo.timeoutSet);
+
+			if (!(ctxt->cbinfo.timeoutSet)) {
+				L_WARN("startup_Req - timeout parameter missing");
+				// Fire RESTException since timeout parameter must be present
+				throw RESTException(PARAMETER_MISSING,
+						"Missing timeout parameter"); //It was WRONG_REQUEST
+			} else {
+				timeout = ctxt->cbinfo.timeout;
+				L_DEBUG("startup_Req - timeout parameter %x (%lu)", timeout,
+						timeout);
+			}
+
+			// Manage non-blocking and blocking startGatewayDevice procedure
+			if (ctxt->asynch()) {
+				L_INFO(
+						"startup_Req - startGatewayDevice (non-blocking procedure)");
+
+				uri = &ctxt->callbackDestination;
+				if (uri->length() == 0) {
+					L_WARN("startup_Req - "
+							"query not containing callback destination",
+							"(unreachable status)");
+
+					throw RESTException(PARAMETER_MISSING,
+							"Missing callbackDestination parameter"); //It was WRONG_REQUEST
+				}
+
+				rlist = &listeners.startup;
+
+				if (!rlist->addListener(uri, ctxt->getSessionId(),
+						new RESTCallbackInfo(ctxt->cbinfo))) {
+					restResponse("startup_Req", ctxt->getSessionId(), NULL,
+							URILISTENER_LIST_MAX_SIZE_EXCEEDED);
+				}
+				// Otherwise the response will be sent back by the attach handler (i.e. startupAttach method...or allServicesAttach)
+
+			} else {
+				L_INFO("startup_Req - startGatewayDevice (blocking procedure)");
+
+				// Get StartupAttributeInfo from XML message
+				StartupAttributeInfo sai;
+
+				int result = pXMLMsgParser->getStartupAttributeInfo(&sai,
+						xmlMsg);
+				if (result == 1)
+					throw RESTException(PARAMETER_MISSING,
+							"StartupAttributeInfo parameters missing");
+
+				if (result == 2)
+					throw RESTException(PARAMETER_MISSING,
+							"Mandatory parameter missing in StartupAttributeInfo XML message");
+
+				if (result == 3)
+					throw RESTException(BAD_PARAMETER,
+							"Invalid value in StartupAttributeInfo XML message");
+
+				LocalNode<RESTBroker>::StartGatewayDeviceCtxt rpcContext(
+						ctxt->getSessionId(), this,
+						(LocalNode<RESTBroker>::startupResponseCb) &RESTBroker::startup_RspCb,
+						NULL);
+
+				pLocalNode->startGatewayDevice(timeout, &sai, &rpcContext);
+			}
+		} else {
+			// If start == false then we're executing the ConfigureStartupAttributeSet Procedure
+			L_INFO("startup_Req - ConfigureStartupAttribute has to be invoked");
+			//ConfigureStartupAttributeSet not implemented since it is not mandatory!
+			throw RESTException(FEATURE_NOT_SUPPORTED,
+					"ConfigureStartupAttributeSet not implemented"); //It was WRONG_REQUEST
+		}
+	}
+		break;
+
+	default:
+		badMethod(res, ctxt);
+	}
+}
+
+/**
+ Protected method RESTBroker startup_RspCb
+ This method relates to LocalNode::startup response.
+
+ @param rpcContext RPC context.
+ @param rpcReqStatus Returned RPC request status.
+ @return Void.
+ */
+
+void RESTBroker::startup_RspCb(uchar commandStatus, int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+	int returnValue;
+	std::string tmpStr;
+	const char *nwkStatus;
+
+	L_DEBUG("startup_RspCb - commandStatus = 0x%02x", commandStatus);
+
+	returnValue = rpcReqStatus->getReturnValue();
+
+	// If a synchronous startGatewayDevice was performed and the result is successful,
+	// wsnnodes resources should be cleared
+	if (!rpcReqStatus->isReqAsynch() && returnValue == AGENT_SUCCESS) {
+		if (pGalDb->getStartModeSetting() != 0x01) {
+			// NVMSetting is not used -> clear wsnnodes resourses
+			L_DEBUG(
+					"startup_RspCb - NVM not used -> clear net/<network-id>/wsnnodes resources");
+
+			Resource *r;
+			r = pRESTServer->findResource(resources.defNet, "wsnnodes");
+			if (r != NULL) {
+				L_DEBUG("startup_RspCb - call clearResource ********");
+				// Delete all the resources apart from the "wsnnodes" path! (otherwise use removeResources)
+				pRESTServer->clearResource(r);
+			}
+		}
+	}
+
+	// If a synchronous startGatewayDevice was performed and the result is
+	// GW_STARTUP_FORMING_NETWORK_FAILED or GW_STARTUP_JOINING_NETWORK_FAILED
+	// wsnnodes resources should be cleared
+	if (!rpcReqStatus->isReqAsynch()
+			&& (returnValue == GW_STARTUP_FORMING_NETWORK_FAILED
+					|| returnValue == GW_STARTUP_JOINING_NETWORK_FAILED)) {
+		// clear wsnnodes resourses
+		L_INFO(
+				"startup_RspCb - Error in forming or joining a nwk - clear net/<network-id>/wsnnodes resources");
+		Resource *r;
+		r = pRESTServer->findResource(resources.defNet, "wsnnodes");
+		if (r != NULL) {
+			L_DEBUG("startup_RspCb - call clearResource ********");
+			// Delete all the resources apart from the "wsnnodes" path! (otherwise use removeResources)
+			pRESTServer->clearResource(r);
+		}
+	}
+
+	if (returnValue != AGENT_SUCCESS) {
+		int startup_ResultCode = (int) commandStatus;
+
+		if (startup_ResultCode != NOT_A_VALUE) {
+			std::stringstream tmp;
+			tmp << startup_ResultCode;
+			tmpStr = tmp.str();
+
+			nwkStatus = tmpStr.c_str();
+		} else {
+			L_DEBUG("startup_RspCb - nwkStatus = NULL");
+			nwkStatus = NULL;
+		}
+	} else {
+		nwkStatus = NULL;
+	}
+
+	if (sessionId == LOCAL_REST_REQUEST_SESSION_ID) {
+		L_DEBUG("startup_RspCb - It was a local REST request "
+				"(no HTTP request triggered the method invocation)");
+		return;
+	}
+
+	if (rpcReqStatus->getFState() == Canceled) {
+		L_DEBUG("startup_RspCb - rpcReqStatus->getFState() == Canceled");
+	}
+
+	restResponse("startup_RspCb", sessionId, NULL, nwkStatus, rpcReqStatus);
+}
+
+void RESTBroker::startup_NtfCb(uchar commandStatus,
+		RPCReqStatus *rpcReqStatus) {
+	std::string xmlNotification;
+	std::string tmpStr;
+	const char *detail;
+	const char *nwkStatus;
+	int returnValue;
+
+	L_DEBUG("startup_NtfCb - commandStatus = 0x%x", commandStatus);
+
+	returnValue = rpcReqStatus->getReturnValue();
+
+	if (returnValue == AGENT_SUCCESS) {
+		//xmlNotification = pXMLMsgComposer->createGenericResponseMsg();
+		//detail = xmlNotification.c_str ();
+		//L_DEBUG("startup_NtfCb - xmlNotification = %s", detail);
+		detail = NULL;
+
+		if (pGalDb->getStartModeSetting() != 0x01) {
+			// NVMSetting is not used -> clear wsnnodes resourses
+			L_DEBUG(
+					"startup_NtfCb - NVM not used -> clear net/<network-id>/wsnnodes resources");
+
+			Resource *r;
+			r = pRESTServer->findResource(resources.defNet, "wsnnodes");
+			if (r != NULL) {
+				L_DEBUG("startup_NtfCb - call clearResource ********");
+				// Delete all the resources apart from the "wsnnodes" path! (otherwise use removeResources)
+				pRESTServer->clearResource(r);
+			}
+		}
+
+		nwkStatus = NULL;
+	} else {
+
+		//2010-11-14***************************************
+		if (returnValue == GW_STARTUP_FORMING_NETWORK_FAILED
+				|| returnValue == GW_STARTUP_JOINING_NETWORK_FAILED) {
+			// clear wsnnodes resourses
+			L_INFO(
+					"startup_NtfCb - Error in forming or joining a nwk - clear net/<network-id>/wsnnodes resources");
+			Resource *r;
+			r = pRESTServer->findResource(resources.defNet, "wsnnodes");
+			if (r != NULL) {
+				L_DEBUG("startup_NtfCb - call clearResource ********");
+				// Delete all the resources apart from the "wsnnodes" path! (otherwise use removeResources)
+				pRESTServer->clearResource(r);
+			}
+		}
+		//2010-11-14***************************************
+
+		detail = NULL;
+
+		int startup_ResultCode = (int) commandStatus;
+
+		if (startup_ResultCode != NOT_A_VALUE) {
+			std::stringstream tmp;
+			tmp << startup_ResultCode;
+			tmpStr = tmp.str();
+
+			nwkStatus = tmpStr.c_str();
+		} else {
+			L_DEBUG("startup_NtfCb - nwkStatus = NULL");
+			nwkStatus = NULL;
+		}
+	}
+
+	restEvent("startup_NtfCb", &listeners.startup, detail, nwkStatus,
+			rpcReqStatus);
+
+	// The notification has been sent -> remove uri listener
+	L_INFO("startup_NtfCb - "
+			"StartGatewayDeviceEvent event -> remove uriListeners");
+	listeners.startup.running = false;
+	listeners.startup.removeListeners();
+
+}
+
+void RESTBroker::reset_Req(Resource *res, const char *reqUri, Method reqMethod,
+		const char *queryString, std::string *xmlMsg, RESTSessionContext *ctxt)
+				throw (HTTPException) {
+	std::string response;
+	Resource *r, *alls;
+
+	L_DEBUG("reset_Req");
+
+	switch (reqMethod) {
+	case M_GET: {
+		std::string *uri;
+		RBURIListenerList *rlist;
+
+		// Remove almost all the listeners
+		clearAllListeners();
+
+		if (ctxt->asynch()) {
+			L_INFO("reset_Req - asynch call");
+			uri = &ctxt->callbackDestination;
+			if (uri->length() == 0) {
+				L_WARN("reset_Req - callback destination not present");
+				throw RESTException(WRONG_REQUEST,
+						"Missing callbackDestination parameter");
+			}
+			rlist = &listeners.resetCommand;
+			if (!rlist->addListener(uri, ctxt->getSessionId(),
+					new RESTCallbackInfo(ctxt->cbinfo))) {
+				restResponse("reset_Req", ctxt->getSessionId(), NULL,
+						URILISTENER_LIST_MAX_SIZE_EXCEEDED);
+			}
+			// Otherwise the response will be sent back by the attach handler (i.e. resetCommandAttach method)
+		} else {
+			// Syncronous mode
+			std::string startModeValue;
+			// Store in ZbNetDb the NVM setting (it will overwrite the config.ini setting choose)
+			pQueryParser->getParameter("startMode", queryString,
+					startModeValue);
+			if (!startModeValue.compare("0x00")) {
+				L_DEBUG(
+						"reset_Req - startMode = 0x00 - Commissioning/Association");
+				pGalDb->setStartModeSetting(0);
+			} else if (!startModeValue.compare("0x01")) {
+				L_DEBUG("reset_Req - startMode = 0x01 - NVM");
+				pGalDb->setStartModeSetting(1);
+			} else if (!startModeValue.compare("0x02")) {
+				L_DEBUG(
+						"reset_Req - startMode = 0x02 - Commissioning/SilentStart");
+				pGalDb->setStartModeSetting(2);
+			} else {
+				L_DEBUG(
+						"reset_Req - startMode not present in %s! (Default=0x00)",
+						queryString);
+				pGalDb->setStartModeSetting(0);
+			}
+			// Delete the "services" resources whether
+			L_DEBUG("reset_Req - Delete all the endpoint resources!");
+			while (res->parent != NULL)
+				res = res->parent;
+			r = pRESTServer->findResource(res, "localnode");
+			if (r != NULL) {
+				alls = pRESTServer->findResource(r, "services");
+				pRESTServer->clearResource(alls);
+			}
+			// Prepare the context
+			LocalNode<RESTBroker>::ResetCommandCtxt rpcContext(
+					ctxt->getSessionId(), this,
+					(LocalNode<RESTBroker>::resetResponseCb) &RESTBroker::resetCommand_RspCb,
+					NULL);
+			// Call the reset function
+			pLocalNode->resetRequest(0x04, &rpcContext);
+		}
+		break;
+	}
+
+	default:
+		badMethod(res, ctxt);
+	}
+}
+
+void RESTBroker::version_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (HTTPException) {
+	std::string response;
+
+	L_DEBUG("version_Req");
+
+	switch (reqMethod) {
+	case M_GET:
+		response = pXMLMsgComposer->createVersionMsg();
+		pRESTServer->restSuccess(response.c_str(), ctxt);
+		break;
+
+	default:
+		badMethod(res, ctxt);
+	}
+}
+
+void RESTBroker::manageGIBAttr_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (HTTPException) {
+	std::string response;
+	std::stringstream out;
+	std::string value;
+
+	// We arrive here only if URI = /ib/0x00 - GatewayInformationBaseAttribute "ZigBeeNetworkStatus"
+	L_DEBUG("manageGIBAttr_Req");
+
+	switch (reqMethod) {
+	case M_GET:
+		//The attribute ID and type of the attribute value shall be as defined in [R1] sub-clause APS Information Base or NWK Information Base or [R7] sub-clause PHY PIB attributes.  A binding declares the mapping for the abstract types to RPC specific ones.
+		pGalZb = GalZbIf::Instance();
+		out << pGalZb->getGWStatus(); // It can assume one of the values of enum_ZigBeeNetworkStatus (Table 175  GMO Attributes)
+		value = out.str();
+		response = pXMLMsgComposer->createGetAttributeMsg(value);
+		pRESTServer->restSuccess(response.c_str(), ctxt);
+		break;
+
+	case M_PUT:
+		//Extract the ZigBeeNetworkStatus from the XMLMessage
+		if (pXMLMsgParser->getValueAttribute(&value, xmlMsg) == 1)
+			throw RESTException(BAD_PARAMETER, "Bad XML message");
+		L_DEBUG("manageGIBAttr_Req - Value attribute extracted %s",
+				value.c_str());
+		// We shall not be able to just set this value since this is a status that changes with the ZigBee network operations
+		pRESTServer->restError(METHOD_NOT_ALLOWED, "Not allowed", NULL, ctxt);
+		break;
+
+	default:
+		badMethod(res, ctxt);
+	}
+}
+
+void RESTBroker::informationBase_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (HTTPException, RESTException) {
+	std::string response;
+	char attrId[5];
+	char tempValue[30];
+	std::string value;
+	int reqUriLength = 0;
+	int currentSASIndex;
+	StartupAttributeInfo* sasInfo;
+
+	// Extract from reqUri= /net/default/ib/XX the string XX!
+	while (reqUri[reqUriLength] != '\0')
+		reqUriLength++;
+
+	attrId[0] = '0';
+	attrId[1] = 'x';
+	attrId[2] = reqUri[reqUriLength - 2];
+	attrId[3] = reqUri[reqUriLength - 1];
+	attrId[4] = '\0';
+
+	L_DEBUG("informationBase_Req - ReqURI %s", reqUri);
+	L_DEBUG("informationBase_Req - attributeID %s", attrId);
+	L_DEBUG("informationBase_Req - attribute converted %d",
+			strtoul(attrId, NULL, 16));
+
+	if (reqUri[reqUriLength - 3] != '/') {
+		L_DEBUG("informationBase_Req - IB value wrong, check the size");
+		pRESTServer->restError(0x05, NULL, NULL, ctxt); //REC_GENERAL_ERROR
+		return;
+	}
+
+	pGalZb = GalZbIf::Instance();
+	pGalDb = pGalZb->getDb();
+	currentSASIndex = pGalDb->getCurrentStartupAttributeSetIndex();
+	L_DEBUG("informationBase_Req - SASindex %d", currentSASIndex);
+	sasInfo = pGalDb->getStartupAttributeInfo(currentSASIndex);
+
+	switch (reqMethod) {
+	case M_GET:
+		//The attribute ID and type of the attribute value shall be as defined in [R1] sub-clause APS Information Base or NWK Information Base or [R7] sub-clause PHY PIB attributes.  A binding declares the mapping for the abstract types to RPC specific ones.
+		// -- [GwRootURI]/ib/[attr], to be used when accessing the Gateway Information Base
+		// -- [NwkRootURI]/ib/[attr], to be used when accessing the Application Information Base, Network Information Base or Physical Information Base.
+		switch (strtoul(attrId, NULL, 16)) {
+		case 0xc3: //apsChannelMask
+			sprintf(tempValue, "%ld", sasInfo->channelMask);
+			response = pXMLMsgComposer->createGetAttributeMsg(tempValue);
+			break;
+		case 0xc4: //apsUseExtendedPANID
+			sprintf(tempValue, "%02x %02x %02x %02x %02x %02x %02x %02x",
+					sasInfo->extendedPANId[0], sasInfo->extendedPANId[1],
+					sasInfo->extendedPANId[2], sasInfo->extendedPANId[3],
+					sasInfo->extendedPANId[4], sasInfo->extendedPANId[5],
+					sasInfo->extendedPANId[6], sasInfo->extendedPANId[7]);
+			response = pXMLMsgComposer->createGetAttributeMsg(tempValue);
+			break;
+		case 0xc8: //apsUseInsecureJoin
+			//sprintf( tempValue, "%d", apsDb.apsNonmemberRadius );
+			if (sasInfo->UseInsecureJoin)
+				response = pXMLMsgComposer->createGetAttributeMsg("00");
+			else
+				response = pXMLMsgComposer->createGetAttributeMsg("01");
+			break;
+		default:
+			L_DEBUG("informationBase_Req - Not supported attribute");
+			//pRESTServer -> restError (0x02,NULL, NULL, ctxt);	//REC_GENERAL_ERROR
+			throw RESTException(BAD_PARAMETER, "Invalid value");
+			return;
+		}
+		pRESTServer->restSuccess(response.c_str(), ctxt);
+		break;
+
+	case M_PUT:
+		// Extract first the value from the XML...
+		if (pXMLMsgParser->getValueAttribute(&value, xmlMsg) == 1) {
+			throw RESTException(BAD_PARAMETER, "Bad XML message");
+			return;
+		}
+		L_DEBUG("informationBase_Req - Value attribute extracted %s",
+				value.c_str());
+		//TODO: we shall verify the passed value before to store it!
+		switch (strtoul(attrId, NULL, 16)) {
+		case 0xc3: //apsChannelMask
+			sasInfo->channelMask = strtoul(value.c_str(), NULL, 16);
+			break;
+		case 0xc4: //apsUseExtendedPANID
+			//sasInfo->extendedPANId = value;	//strtoul(value.c_str(),NULL,16);
+			memcpy(sasInfo->extendedPANId, &value, 8);
+			break;
+		case 0xc8: //apsUseInsecureJoin
+			if (strtoul(value.c_str(), NULL, 16) == 0)
+				sasInfo->UseInsecureJoin = true;
+			else
+				sasInfo->UseInsecureJoin = false;
+			break;
+		default:
+			L_DEBUG("informationBase_Req - Not supported attribute");
+			pRESTServer->restError(0x02, NULL, NULL, ctxt); //REC_GENERAL_ERROR
+			return;
+		}
+		// NOTE: This is not standard since by default we don't have to return a response!
+		response = pXMLMsgComposer->setAttributeMsg();
+		pRESTServer->restSuccess(response.c_str(), ctxt);
+		break;
+
+	default:
+		badMethod(res, ctxt);
+	}
+}
+
+//***********************************************************************************************
+//***************************  GW_DESCRIPTOR functions  *****************************************
+//***********************************************************************************************
+
+void RESTBroker::gwDescriptorLocal_RspCb(int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+	L_DEBUG("gwDescriptorLocal_RspCb - "
+			"It was a local REST request "
+			"(no HTTP request triggered the method invocation)");
+}
+
+void RESTBroker::gwStatusChanged_gwDescriptor_NtfCb(GwDescriptor *desc,
+		RPCReqStatus *status) {
+	std::string detail;
+	int returnValue, startResult;
+	ConfigurationRepository *_conf;
+	int pa, pb;
+
+	L_DEBUG("gwStatusChanged_gwDescriptor_NtfCb - "
+			"RPCReqStatus - fState = %d - "
+			"fResult = %d - fReturnValue = %d", status->getFState(),
+			status->getFResult(), status->getReturnValue());
+
+	// Get returnValue
+	returnValue = status->getReturnValue();
+
+	if (returnValue == AGENT_SUCCESS) {
+
+		if (desc->getGwState() == GW_RUNNING) {
+			//L_DEBUG("gwStatusChanged_gwDescriptor_NtfCb - launch KeepAlive algorithm");
+			pDAgent->runKeepAliveAlgorithm();
+		}
+
+		detail = pXMLMsgComposer->createGwStatusChangedMsg(desc);
+		L_DEBUG("gwStatusChanged_gwDescriptor_NtfCb - "
+				"xmlNotification = %s", detail.c_str());
+
+//#ifdef WSN_C_PROTOCOL_BACKWARD_COMPATIBILITY
+		detail = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + detail;
+		restEvent_BC("gwStatusChanged_gwDescriptor_NtfCb", &listeners.gwStatus,
+				detail.c_str(), NULL);
+//#else
+		//restSuccess_Evt (&listeners.gwStatus, detail.c_str ());
+//#endif
+	}
+
+	if (wsnCAddress.length() != 0 && !tasks.wsnc.taskStarted) {
+		pthread_mutex_lock(&mux);
+		_conf = ConfigurationRepository::instance();
+		// We load the configuration from the ConfigurationManager
+		//int taskPeriod = _conf->getint("RESTBroker:GWDescriptorAsynchNotificationPeriod", 60);
+		pa = _conf->getint("RESTBroker:HelloMsgNotifyPeriod", 30);
+		pb = _conf->getint("RESTBroker:HelloMsg_WSNCAttached_NotifyPeriod",
+				150);
+
+		L_DEBUG("startPeriodicTask - Period A (seconds) = %d "
+				"- Period B (seconds) = %d", pa, pb);
+
+		startResult = tasks.wsnc.start(this, pa, pb,
+				notifyGWDescriptorToWsnc_SW);
+		pthread_mutex_unlock(&mux);
+		if (startResult)
+			L_DEBUG(
+					"gwStatusChanged_gwDescriptor_NtfCb - Error - Periodic task (type = %d) start failure",
+					startResult);
+	}
+}
+
+//***********************************************************************************************
+//***************************  CALLBACK functions  ****************************************
+//***********************************************************************************************
+void RESTBroker::cbCallback_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (RESTException, HTTPException) {
+	RBURIListenerList *rbl;
+	std::string s;
+
+	rbl = (RBURIListenerList *) res->data.p;
+
+	switch (reqMethod) {
+
+	case M_GET:
+		s = rbl->lastMessage;
+		if (s.empty())
+			throw RESTException(NO_MESSAGE_YET);
+
+		s = pXMLMsgComposer->createPolledAPSMessage(s);
+
+		pRESTServer->restSuccess(s.c_str(), ctxt);
+		break;
+
+	case M_DELETE:
+		s = res->rd.path;
+		rbl->removeListener(s);
+		restResponse("cbCallback_Req", ctxt->getSessionId(), NULL, NO_ERROR);
+		break;
+
+	default:
+		badMethod(res, ctxt);
+	}
+}
+
+//***********************************************************************************************
+//***************************  WSN_NODES_LIST functions  ****************************************
+//***********************************************************************************************
+
+void RESTBroker::listAddresses_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (RESTException, HTTPException) {
+	std::string modeValue, anncValue;
+
+	L_DEBUG("listAddresses_Req");
+
+	if (reqMethod != M_GET) {
+		// Note: A M_POST was a CreateAliasAddress procedure, at the moment not implemented
+		badMethod(res, ctxt);
+	}
+
+	//By default, the URI [NwkRootURI]/aliases lists out all of the addresses
+	//No optional parameters are supported at the moment
+
+	DiscoveryAgent<RESTBroker>::RetrieveNodesCtxt dctxt(ctxt->getSessionId(),
+			this,
+			(DiscoveryAgent<RESTBroker>::retrieveNodesResponseCb) &RESTBroker::listAddresses_RspCb,
+			NULL);
+	// Call DiscoveryAgent::retrieveNodes <<
+	pDAgent->retrieveNodes(&dctxt);
+}
+
+void RESTBroker::listAllAddresses_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (RESTException, HTTPException) {
+	std::string modeValue, anncValue;
+	L_DEBUG("listAllAddresses_Req");
+	if (reqMethod != M_GET) {
+		badMethod(res, ctxt);
+	}
+	DiscoveryAgent<RESTBroker>::RetrieveNodesCtxt dctxt(ctxt->getSessionId(),
+			this,
+			(DiscoveryAgent<RESTBroker>::retrieveNodesResponseCb) &RESTBroker::listAllAddresses_RspCb,
+			NULL);
+	pDAgent->retrieveNodes(&dctxt);
+}
+
+void RESTBroker::listAddresses_RspCb(ZbNetDb* buffer, int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+	const char *detail;
+	int returnValue;
+
+	L_DEBUG("listAddresses_RspCb");
+
+	returnValue = rpcReqStatus->getReturnValue();
+
+	if (returnValue == AGENT_SUCCESS) {
+		xmlResponse = pXMLMsgComposer->createAliasesMsg(
+				rpcReqStatus->getFResult(), buffer);
+		detail = xmlResponse.c_str();
+		L_INFO("listAddresses_RspCb - xmlResponse = %s", detail);
+	} else {
+		detail = NULL;
+	}
+	L_DEBUG("listAddresses_RspCb - fResult = %d", rpcReqStatus->getFResult());
+	restResponse("listAddresses_RspCb", sessionId, detail, NULL, rpcReqStatus);
+}
+
+void RESTBroker::listAllAddresses_RspCb(ZbNetDb* buffer, int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+	const char *detail;
+	int returnValue;
+	L_DEBUG("listAllAddresses_RspCb");
+	returnValue = rpcReqStatus->getReturnValue();
+	if (returnValue == AGENT_SUCCESS) {
+		xmlResponse = pXMLMsgComposer->createAliasesMsg(-1, buffer);
+		detail = xmlResponse.c_str();
+		L_INFO("listAllAddresses_RspCb - xmlResponse = %s", detail);
+	} else {
+		detail = NULL;
+	}
+	restResponse("listAllAddresses_RspCb", sessionId, detail, NULL,
+			rpcReqStatus);
+}
+
+void RESTBroker::wsnNodesList_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (RESTException, HTTPException) {
+	std::string modeValue, KAthresholdValue, anncValue, inquiryValue, lqiValue,
+			*uri;
+	bool cache, announcements, inquiry, lqi, nodeFreshness;
+	RBURIListenerList *rlist;
+
+	L_DEBUG("wsnNodesList_Req");
+
+	switch (reqMethod) {
+	case M_GET: {
+		pQueryParser->getParameter("mode", queryString, modeValue);
+		if (modeValue.length() == 0) {
+			L_DEBUG(
+					"wsnNodesList_Req - queryString = %s not containing mode parameter: start discovery",
+					queryString);
+			cache = false;
+		} else if (!modeValue.compare("cache")) {
+			L_DEBUG(
+					"wsnNodesList_Req - queryString = %s with cache parameter: no actual discovery needed",
+					queryString);
+			cache = true;
+		} else {
+			L_INFO("wsnNodesList_Req - queryString = %s unknown mode: %s",
+					queryString, modeValue.c_str());
+			throw RESTException(BAD_PARAMETER, "Bad mode parameter");
+		}
+
+		// Verify it the node list shall be taken or not from the cache
+		// cache ==  true -> a ReadNodeCache Procedure has to be performed
+		if (cache) {
+			DiscoveryAgent<RESTBroker>::RetrieveNodesCtxt dctxt(
+					ctxt->getSessionId(), this,
+					(DiscoveryAgent<RESTBroker>::retrieveNodesResponseCb) &RESTBroker::wsnNodesList_cache_RspCb,
+					NULL);
+			// Call DiscoveryAgent::retrieveNodes <<
+			pDAgent->retrieveNodes(&dctxt);
+			return;
+		}
+
+		// cache == false -> a StartNodeDiscovery has to be performed
+		nodeFreshness = pQueryParser->getParameter("freshness", queryString,
+				KAthresholdValue);
+		announcements = pQueryParser->getParameter("announcements", queryString,
+				anncValue);
+		inquiry = pQueryParser->getParameter("inquiry", queryString,
+				inquiryValue);
+		lqi = pQueryParser->getParameter("lqi", queryString, lqiValue);
+		uri = &ctxt->callbackDestination;
+
+		if (uri->length() == 0) {
+			L_WARN(
+					"wnsnodesList_Req - query not containing callback destination -> WRONG REQUEST");
+			throw RESTException(PARAMETER_MISSING,
+					"Missing callbackDestination parameter"); //It was WRONG_REQUEST
+		}
+
+		// Check whether "timeout" parameter is present in the request
+		unsigned long int timeout = 0;
+		L_DEBUG("wnsnodesList_Req - timeoutSet = %d", ctxt->cbinfo.timeoutSet);
+
+		if (!(ctxt->cbinfo.timeoutSet)) {
+			L_WARN("wnsnodesList_Req - timeout parameter missing");
+			// Fire RESTException since timeout parameter must be present
+			throw RESTException(PARAMETER_MISSING, "Missing timeout parameter"); //It was WRONG_REQUEST
+		} else {
+			timeout = ctxt->cbinfo.timeout;
+			L_DEBUG("wnsnodesList_Req - timeout parameter %x (%lu)", timeout,
+					timeout);
+		}
+
+		L_DEBUG("wnsnodesList_Req - %s - %s - %s - %s",
+				nodeFreshness ? "FRESHNESS_ON" : "FRESHNESS_OFF",
+				announcements ? "ANNOUNCEMENTS_ON" : "ANNOUNCEMENTS_OFF",
+				inquiry ? "INQUIRY_ON" : "INQUIRY_OFF",
+				lqi ? "LQI_ON" : "LQI_OFF");
+
+		if (!(announcements || inquiry || lqi || nodeFreshness)) {
+			// Remove all listeners!
+			L_INFO("wsnNodesList_Req - removing all uriListeners");
+			//listeners.freshness.removeListeners ();		//Maintain the freshness listener...
+			//listeners.nodeAnnounce.removeListeners ();	//Maintain the nodeAnnouncement listener...
+			listeners.nodeInquiry.removeListeners();
+			listeners.nodeMgmt_Lqi.removeListeners();
+			pRESTServer->restSuccess(NULL, ctxt->getSessionId());
+			return;
+		}
+
+		if (inquiry && lqi) {
+			L_INFO(
+					"wsnNodesList_Req - queryString = %s cannot contain both 'inquiry' and 'lqi'",
+					queryString);
+			throw RESTException(BAD_PARAMETER, "Bad mode parameter");
+		}
+		//FIXME!! If both announcements and inquiry | lqi are present -> two REST responses are triggered
+		// Actually, the above problem does not introduce a crash because there is a control at HTTPServer level
+		// However, the overall situation is not properly managed...
+		if (announcements) {
+			L_DEBUG("wnsnodesList_Req - announcements on");
+			rlist = &listeners.nodeAnnounce;
+			if (!rlist->addListener(uri, ctxt->getSessionId(),
+					new RESTCallbackInfo(ctxt->cbinfo))) {
+				L_WARN(
+						"wnsnodesList_Req - announcements - urilisteners list max size exceeded");
+				restResponse("wsnNodesList_Req", ctxt->getSessionId(), "",
+						URILISTENER_LIST_MAX_SIZE_EXCEEDED);
+			}
+		}
+		if (nodeFreshness) {
+			L_DEBUG("wnsnodesList_Req - nodeFreshness on");
+			rlist = &listeners.freshness;
+			if (!rlist->addListener(uri, ctxt->getSessionId(),
+					new RESTCallbackInfo(ctxt->cbinfo))) {
+				L_WARN(
+						"wnsnodesList_Req - nodeFreshness - urilisteners list max size exceeded");
+				restResponse("wsnNodesList_Req", ctxt->getSessionId(), "",
+						URILISTENER_LIST_MAX_SIZE_EXCEEDED);
+			}
+			// Update the KAthresholdValue value
+			L_DEBUG("wnsnodesList_Req - FreshnessValue from HTTP GET: %s",
+					KAthresholdValue.c_str());
+			int threshold = atoi(KAthresholdValue.c_str());
+			if (threshold != 0) //Ignore this call in case the user has no specified any value
+				pDAgent->setKAthreshold(threshold);
+		}
+		if (inquiry) {
+			L_DEBUG("wnsnodesList_Req - inquiry on");
+			rlist = &listeners.nodeInquiry;
+			if (!rlist->addListener(uri, ctxt->getSessionId(),
+					new RESTCallbackInfo(ctxt->cbinfo))) {
+				L_WARN(
+						"wnsnodesList_Req - inquiry - urilisteners list max size exceeded");
+				restResponse("wsnNodesList_Req", ctxt->getSessionId(), "",
+						URILISTENER_LIST_MAX_SIZE_EXCEEDED);
+			}
+		} else if (lqi) {
+			L_DEBUG("wnsnodesList_Req - lqi on");
+			rlist = &listeners.nodeMgmt_Lqi;
+			if (!rlist->addListener(uri, ctxt->getSessionId(),
+					new RESTCallbackInfo(ctxt->cbinfo))) {
+				L_WARN(
+						"wnsnodesList_Req - lqi - urilisteners list max size exceeded");
+				restResponse("wsnNodesList_Req", ctxt->getSessionId(), "",
+						URILISTENER_LIST_MAX_SIZE_EXCEEDED);
+			}
+		}
+		break;
+	}
+
+	default:
+		badMethod(res, ctxt);
+	}
+}
+
+/**
+ Protected method RESTBroker wnsnodesList_RspCb
+ This method relates to DiscoveryAgent::startInquiry response.
+
+ @param rpcContext RPC context.
+ @param rpcReqStatus Returned RPC request status.
+ @return Void.
+ */
+
+void RESTBroker::wsnNodesList_RspCb(int sessionId, RPCReqStatus *rpcReqStatus) {
+	int returnValue;
+
+	L_DEBUG("wnsnodesList_RspCb");
+	returnValue = rpcReqStatus->getReturnValue();
+
+	if (returnValue != AGENT_SUCCESS)
+		restResponse("wsnNodesList_RspCb", sessionId, NULL, NULL, rpcReqStatus);
+}
+
+/**
+ Protected method RESTBroker wnsnodesList_cancelInquiry_RspCb
+ This method relates to DiscoveryAgent::cancelInquiry response.
+
+ @param rpcContext RPC context.
+ @param rpcReqStatus Returned RPC request status.
+ @return Void.
+ */
+
+void RESTBroker::wsnNodesList_cancelInquiry_RspCb(int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+	L_DEBUG("wnsnodesList_cancelInquiry_RspCb");
+	/* No need to notify anybody. There is no way to explicitly cancel
+	 an inquiry, so we only get local requests */
+}
+
+/**
+ Protected method RESTBroker wnsnodesList_cache_RspCb
+ This method relates to DiscoveryAgent::retrieveNodes response.
+
+ @param buffer Buffer containing Inquiry macrofunction results.
+ @param rpcContext RPC context.
+ @param rpcReqStatus Returned RPC request status.
+ @return Void.
+ */
+
+void RESTBroker::wsnNodesList_cache_RspCb(ZbNetDb* buffer, int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+	const char *detail;
+	int returnValue;
+
+	L_DEBUG("wsnNodesList_cache_RspCb");
+
+	returnValue = rpcReqStatus->getReturnValue();
+
+	if (returnValue == AGENT_SUCCESS) {
+		xmlResponse = pXMLMsgComposer->createWSNNodesListMsg(
+				rpcReqStatus->getFResult(), buffer);
+		detail = xmlResponse.c_str();
+		L_INFO("wnsnodesList_cache_RspCb - xmlResponse = %s", detail);
+	} else
+		detail = NULL;
+
+	L_DEBUG("wnsnodesList_cache_RspCb - fResult = %d",
+			rpcReqStatus->getFResult());
+
+	restResponse("wsnNodesList_cache_RspCb", sessionId, detail, NULL,
+			rpcReqStatus);
+
+}
+
+void RESTBroker::wsnNodesList_sofar_RspCb(ZbNetDb* buffer, int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+	std::string xmlNotification;
+	int returnValue;
+	std::map<ushort, Node *>::const_iterator iter;
+	std::map<ushort, Node *> nodes;
+
+	L_DEBUG("wsnNodesList_sofar_RspCb");
+
+	returnValue = rpcReqStatus->getReturnValue();
+
+	if (returnValue != AGENT_SUCCESS)
+		return;
+
+	soFarBuffer = buffer;
+}
+
+void RESTBroker::wsnNodesList_StartAnnceMode_RspCb(int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+	L_DEBUG("wnsnodesList_StartAnnceMode_RspCb");
+
+	if (sessionId == LOCAL_REST_REQUEST_SESSION_ID) {
+		L_DEBUG(
+				"wsnNodesList_StartAnnceMode_RspCb - It was a local REST request "
+						"(no HTTP request triggered the method invocation)");
+		return;
+	}
+
+	restResponse("wnsnodesList_StartAnnceMode_RspCb", sessionId, NULL, NULL,
+			rpcReqStatus);
+}
+
+/**
+ Protected method RESTBroker wnsnodesList_CancelAnnceMode_RspCb
+ This method relates to DiscoveryAgent::startAnnouncementsMode response.
+
+ @param rpcContext RPC context.
+ @param rpcReqStatus Returned RPC request status.
+ @return Void.
+ */
+void RESTBroker::wsnNodesList_CancelAnnceMode_RspCb(int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+
+	L_DEBUG("wnsnodesList_CancelAnnceMode_RspCb");
+	/* No need to notify anybody. There is no way to explicitly cancel
+	 an inquiry, so we only get local requests */
+}
+
+void RESTBroker::wsnNodesList_StartFreshnessMode_RspCb(int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+	L_DEBUG("wsnNodesList_StartFreshnessMode_RspCb");
+
+	if (sessionId == LOCAL_REST_REQUEST_SESSION_ID) {
+		L_DEBUG(
+				"wsnNodesList_StartAnnceMode_RspCb - It was a local REST request "
+						"(no HTTP request triggered the method invocation)");
+		return;
+	}
+
+	restResponse("wsnNodesList_StartFreshnessMode_RspCb", sessionId, NULL, NULL,
+			rpcReqStatus);
+}
+
+void RESTBroker::wsnNodesList_CancelFreshnessMode_RspCb(int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+
+	L_DEBUG("wsnNodesList_CancelFreshnessMode_RspCb");
+	/* No need to notify anybody. There is no way to explicitly cancel
+	 an inquiry, so we only get local requests */
+}
+
+/**
+ Protected method RESTBroker wnsnodesList_NtfCb
+ This method relates to DiscoveryAgent::Inquiry_Cb notification.
+
+ @param node Pointer to a Node object (node discovered).
+ @param rpcReqStatus Returned RPC request status.
+ @return Void.
+ */
+
+void RESTBroker::wsnNodesList_NtfCb(Node *node, RPCReqStatus *rpcReqStatus) {
+	std::string xmlNotification;
+	const char *detail;
+	int returnValue;
+
+	L_DEBUG("wnsnodesList_NtfCb - "
+			"RPCReqStatus - fState = %d - fResult = %d - "
+			"fReturnValue = %d", rpcReqStatus->getFState(),
+			rpcReqStatus->getFResult(), rpcReqStatus->getReturnValue());
+
+	// Get returnValue
+	returnValue = rpcReqStatus->getReturnValue();
+
+	// A new NODE resource is created (Dynamic REST resources Management)
+	if (node != NULL && returnValue == AGENT_SUCCESS) {
+		L_INFO("wnsnodesList_NtfCb - createResource NODE - "
+				"node address %04X ", node->get_nwk_addr());
+		createNodeResources(resources.defNet, node);
+	}
+
+	if (returnValue == AGENT_SUCCESS) {
+		xmlNotification = pXMLMsgComposer->createWSNNodeMsg(
+				rpcReqStatus->getFResult(), node);
+		detail = xmlNotification.c_str();
+		L_DEBUG("wnsnodesList_NtfCb - xmlNotification = %s", detail);
+
+	} else
+		detail = NULL;
+
+	restEvent("wnsnodesList_NtfCb", &listeners.nodeInquiry, detail, NULL,
+			rpcReqStatus);
+
+	// The notification has been sent -> remove uri listener
+	if ((rpcReqStatus->getFState()) == End
+			|| (rpcReqStatus->getFState()) == Canceled) {
+		//L_INFO("wnsnodesList_NtfCb - Inquiry completed -> remove uriListeners");
+		listeners.nodeInquiry.running = false;
+		listeners.nodeInquiry.removeListeners();
+	}
+}
+
+void RESTBroker::MgmtLQI_RspCb(int sessionId, RPCReqStatus *rpcReqStatus) {
+	int returnValue;
+	L_DEBUG("MgmtLQI_RspCb");
+	returnValue = rpcReqStatus->getReturnValue();
+
+	if (returnValue != AGENT_SUCCESS)
+		restResponse("MgmtLQI_RspCb", sessionId, NULL, NULL, rpcReqStatus);
+}
+
+void RESTBroker::cancelMgmtLQI_RspCb(int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+	// No need to notify anybody. There is no way to explicitly cancel an inquiry, so we only get local requests
+	L_DEBUG("cancelMgmtLQI_RspCb - Nothing to do");
+}
+
+void RESTBroker::MgmtLQI_NtfCb(Node *node, RPCReqStatus *rpcReqStatus) {
+	std::string xmlNotification;
+	const char *detail;
+	int returnValue;
+
+	L_DEBUG("MgmtLQI_NtfCb");
+	L_DEBUG("MgmtLQI_NtfCb -  RPCReqStatus - fState = %d - fResult = %d - "
+			"fReturnValue = %d", rpcReqStatus->getFState(),
+			rpcReqStatus->getFResult(), rpcReqStatus->getReturnValue());
+	// Get returnValue
+	returnValue = rpcReqStatus->getReturnValue();
+	// A new NODE resource is created (Dynamic REST resources Management)
+	if (node != NULL && returnValue == AGENT_SUCCESS) {
+		L_INFO("MgmtLQI_NtfCb - createResource NODE - node address %04X ",
+				node->get_nwk_addr());
+		createNodeResources(resources.defNet, node);
+	}
+
+	// Discovery completed
+	if (returnValue == AGENT_SUCCESS && node == NULL) {
+		if ((rpcReqStatus->getFState()) == End) {
+			L_INFO(
+					"MgmtLQI_NtfCb - MgmtLQI completed (no notifications to be sent) -> remove uriListeners");
+			listeners.nodeMgmt_Lqi.running = false;
+			listeners.nodeMgmt_Lqi.removeListeners();
+		}
+		return;
+	}
+
+	if (returnValue == AGENT_SUCCESS) {
+		xmlNotification = pXMLMsgComposer->createWSNNodeMsg(
+				rpcReqStatus->getFResult(), node);
+		detail = xmlNotification.c_str();
+		L_DEBUG("MgmtLQI_NtfCb - xmlNotification = %s", detail);
+	} else
+		detail = NULL;
+
+	restEvent("MgmtLQI_NtfCb", &listeners.nodeMgmt_Lqi, detail, NULL,
+			rpcReqStatus);
+
+	// The notification has been sent -> remove uri listener
+	if ((rpcReqStatus->getFState()) == End
+			|| (rpcReqStatus->getFState()) == Canceled) {
+		L_INFO("MgmtLQI_NtfCb - MgmtLQI completed -> remove uriListeners");
+		listeners.nodeMgmt_Lqi.running = false;
+		listeners.nodeMgmt_Lqi.removeListeners();
+	}
+}
+
+/**
+ Protected method RESTBroker wnsnodesList_NtfCb
+ This method relates to DiscoveryAgent::Inquiry_Cb notification.
+
+ @param node Pointer to a Node object (node discovered).
+ @param rpcReqStatus Returned RPC request status.
+ @return Void.
+ */
+
+void RESTBroker::wsnNodeAnnce_NtfCb(Node *node, RPCReqStatus *rpcReqStatus) {
+	std::string xmlNotification;
+	const char *detail;
+	int returnValue;
+
+	L_DEBUG("wsnNodeAnnce_NtfCb -RPCReqStatus - fState = %d - fResult = %d - "
+			"fReturnValue = %d", rpcReqStatus->getFState(),
+			rpcReqStatus->getFResult(), rpcReqStatus->getReturnValue());
+
+	returnValue = rpcReqStatus->getReturnValue();
+
+	// if node is new, need to create the related resource 
+	// (Dynamic REST resources Management)
+	if (node != NULL && returnValue == AGENT_SUCCESS) {
+		L_INFO("wsnNodeAnnce_NtfCb - createResource NODE - "
+				"node address %04X ", node->get_nwk_addr());
+		createNodeResources(resources.defNet, node);
+	}
+
+	if (returnValue == AGENT_SUCCESS) {
+		xmlNotification = pXMLMsgComposer->createWSNNodeMsg(
+				rpcReqStatus->getFResult(), node);
+		detail = xmlNotification.c_str();
+		L_DEBUG("wsnNodeAnnce_NtfCb - xmlNotification = %s", detail);
+
+	} else
+		detail = NULL;
+
+	restEvent("wsnNodeAnnce_NtfCb", &listeners.nodeAnnounce, detail, NULL,
+			rpcReqStatus);
+}
+
+void RESTBroker::wsnNodeFreshnessAnnce_NtfCb(Node *node,
+		RPCReqStatus *rpcReqStatus) {
+	std::string xmlNotification;
+	const char *detail;
+	int returnValue;
+
+	L_DEBUG("wsnNodeFreshnessAnnce_NtfCb");
+	L_DEBUG("wsnNodeFreshnessAnnce_NtfCb - "
+			"RPCReqStatus - fState = %d - fResult = %d - "
+			"fReturnValue = %d", rpcReqStatus->getFState(),
+			rpcReqStatus->getFResult(), rpcReqStatus->getReturnValue());
+
+	returnValue = rpcReqStatus->getReturnValue();
+
+	if (returnValue == AGENT_SUCCESS) {
+		xmlNotification = pXMLMsgComposer->createWSNNodeMsg(
+				rpcReqStatus->getFResult(), node);
+		detail = xmlNotification.c_str();
+		L_DEBUG("wsnNodeFreshnessAnnce_NtfCb - xmlNotification = %s", detail);
+	} else
+		detail = NULL;
+
+	restEvent("wsnNodeFreshnessAnnce_NtfCb", &listeners.freshness, detail, NULL,
+			rpcReqStatus);
+	// Finally, remove the node resources as well (they will be created again once the node is up)
+	leaveCommandDeleteResources(node->get_nwk_addr());
+
+}
+
+void RESTBroker::callbacks_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (RESTException, HTTPException) {
+	Callback cb;
+	std::map<int, RBURIListenerList>::iterator it;
+	RBURIListenerList *l;
+	std::list<Resource *>::iterator i;
+	std::list < std::string > ids;
+	std::string response;
+
+	std::string *uri;
+
+	int returnValue;
+
+	L_DEBUG("callbacks_Req");
+
+	switch (reqMethod) {
+	case M_GET: {
+		L_DEBUG("callbacks_Req - ListCallbacks procedure invoked");
+		for (i = res->children.begin(); i != res->children.end(); i++)
+			ids.push_back((*i)->rd.path);
+
+		response = pXMLMsgComposer->createCallbacksMsg(ids);
+
+		restResponse("callbacks_Req", ctxt->getSessionId(), response.c_str(),
+				NO_ERROR);
+	}
+		break;
+
+	case M_POST: {
+		L_DEBUG("callbacks_Req - CreateCallback procedure invoked");
+		int result = pXMLMsgParser->getCallback(&cb, xmlMsg);
+
+		switch (result) {
+		case 0: {
+			L_INFO("callbacks_Req - Callback XML Message format correct");
+		}
+			break;
+
+		case 1: // Error in parsing the XML message
+		{
+			L_INFO("callbacks_Req - Error in parsing the Callback XML Message");
+			throw RESTException(BAD_PARAMETER, "Bad Callback XML message");
+		}
+			break;
+
+		case 2: // XML message not present -> Error
+		{
+			L_INFO("callbacks_Req - Missing Callback XML Message");
+			throw RESTException(PARAMETER_MISSING,
+					"Missing Callback XML Message"); //It was WRONG_REQUEST
+		}
+			break;
+
+		default: {
+			L_DEBUG("callbacks_Req - Error occurred in getCallback function");
+			throw RESTException(WRONG_REQUEST, "Error in Callback XML element");
+		}
+		}
+
+		if (cb.action.isDefined)
+			uri = &(cb.action.forwardingSpecification);
+		else
+			uri = NULL;
+
+		if (cb.filter.isDefined) {
+			// In case the levelSpec - level is != APSLevel, createCallback not supported
+			if (cb.filter.levelSpec.level.compare("APSLevel"))
+				throw RESTException(FEATURE_NOT_SUPPORTED, NULL);
+
+			// In case MessageSpecification-APSClusterGroup is defined, only the ZDP, ZCL and Discovery are supported
+			if (cb.filter.messageSpec.isDefined
+					&& cb.filter.messageSpec.isAPSClusterGroupDefined) {
+				if (cb.filter.messageSpec.APSClusterGroup.compare("ZDP")
+						&& cb.filter.messageSpec.APSClusterGroup.compare("ZCL")
+						&& cb.filter.messageSpec.APSClusterGroup.compare(
+								"Discovery"))
+					throw RESTException(FEATURE_NOT_SUPPORTED, NULL);
+			}
+
+			// In case MessageSpecification-APSClusterIdentifier is included within the filter,
+			// createCallback not supported
+			if (cb.filter.messageSpec.isDefined
+					&& cb.filter.messageSpec.isAPSClusterIdentifierDefined)
+				throw RESTException(FEATURE_NOT_SUPPORTED, NULL);
+		}
+
+		if (cb.action.isDefined) {
+			if (!cb.action.decodeSpecification.decodeLevel[DecodeAPS])
+				throw RESTException(FEATURE_NOT_SUPPORTED, NULL);
+		}
+
+		if (!cb.filter.isDefined) // Filter element not defined ******
+		{
+			L_INFO(
+					"callbacks_Req - Callback considered as a shorthand - EndPoint unset");
+
+			// Create RPC Context
+			ServiceAgent<RESTBroker>::CreateCallbackCtxt rpcContext(
+					ctxt->getSessionId(), this,
+					(ServiceAgent<RESTBroker>::createCallbackResponseCb) &RESTBroker::lndAllServicesWsnConnection_RspCb,
+					(ServiceAgent<RESTBroker>::messageReceivedNotifyCb) &RESTBroker::lndAllServicesWsnConnection_NtfCb);
+
+			// Call ServiceAgent::createCallback <<
+			returnValue = pSAgent->createCallback(ALL_ENDPOINTS, &rpcContext);
+
+			if (returnValue == AGENT_SUCCESS) {
+				L_INFO("callbacks_Req - "
+						"Connection created - ALL_ENDPOINTS - "
+						"Add UriListener %s", uri->c_str());
+				// Add URI listener to the list
+				listeners.allServices.addListener(uri, ctxt->getSessionId(),
+						new RESTCallbackInfo(ctxt->cbinfo));
+			}
+		} else // Filter element defined ******
+		{
+
+			if (!cb.filter.addressSpec.isNWKSourceAddressDefined
+					&& !cb.filter.addressSpec.isAPSSourceEndpointDefined
+					&& cb.filter.addressSpec.isAPSDestinationEndpointDefined
+					&& !cb.filter.messageSpec.isDefined) {
+
+				L_INFO(
+						"callbacks_Req - Callback considered as a shorthand - EndPoint set");
+
+				//Check
+				if (!pSAgent->isEndpointAvailable(
+						cb.filter.addressSpec.APSDestinationEndpoint)) {
+					L_WARN(
+							"callbacks_Req - Trying to register a callback or a non existing endpoint");
+					throw RESTException(WRONG_REQUEST,
+							"Trying to register a callback on a non existing Endpoint");
+				}
+
+				std::map<int, RBURIListenerList>::iterator i;
+				RBURIListenerList *l;
+
+				i = listeners.service.find(
+						cb.filter.addressSpec.APSDestinationEndpoint);
+				if (i == listeners.service.end()) {
+					l =
+							&listeners.service[cb.filter.addressSpec.APSDestinationEndpoint];
+
+					l->attach = &RESTBroker::serviceAttach;
+					l->detach = &RESTBroker::serviceDetach;
+					l->handler = this;
+					l->data.d = cb.filter.addressSpec.APSDestinationEndpoint;
+				} else
+					l = &i->second;
+
+				l->addListener(uri, ctxt->getSessionId(),
+						new RESTCallbackInfo(ctxt->cbinfo));
+
+			} else if (!cb.filter.addressSpec.isDefined
+					&& !cb.filter.messageSpec.isDefined) {
+
+				L_INFO(
+						"callbacks_Req - Callback considered as a shorthand - EndPoint unset");
+
+				// Create RPC Context
+				ServiceAgent<RESTBroker>::CreateCallbackCtxt rpcContext(
+						ctxt->getSessionId(), this,
+						(ServiceAgent<RESTBroker>::createCallbackResponseCb) &RESTBroker::lndAllServicesWsnConnection_RspCb,
+						(ServiceAgent<RESTBroker>::messageReceivedNotifyCb) &RESTBroker::lndAllServicesWsnConnection_NtfCb);
+
+				// Call ServiceAgent::createCallback <<
+				returnValue = pSAgent->createCallback(ALL_ENDPOINTS,
+						&rpcContext);
+
+				if (returnValue == AGENT_SUCCESS) {
+					L_INFO("callbacks_Req - "
+							"Connection created - ALL_ENDPOINTS - "
+							"Add UriListener %s", uri->c_str());
+					// Add URI listener to the list
+					listeners.allServices.addListener(uri, ctxt->getSessionId(),
+							new RESTCallbackInfo(ctxt->cbinfo));
+				}
+
+			} else {
+
+				if (cb.filter.addressSpec.isAPSDestinationEndpointDefined) {
+					//Check
+					if (!pSAgent->isEndpointAvailable(
+							cb.filter.addressSpec.APSDestinationEndpoint)) {
+						L_WARN(
+								"callbacks_Req - Trying to register a callback or a non existing endpoint");
+						throw RESTException(WRONG_REQUEST,
+								"Trying to register a callback on a non existing Endpoint");
+					}
+				}
+
+				// Generic callback
+				it = listeners.customizedCallback.find(
+						this->customizedCallbackIdCounter);
+				if (it == listeners.customizedCallback.end()) {
+					l =
+							&listeners.customizedCallback[this->customizedCallbackIdCounter];
+
+					l->attach = &RESTBroker::callbackAttach;
+					l->detach = &RESTBroker::callbackDetach;
+					l->handler = this;
+					l->data.d = this->customizedCallbackIdCounter;
+				} else
+					l = &it->second;
+
+				l->addListener(uri, ctxt->getSessionId(),
+						new RESTCallbackInfo(ctxt->cbinfo));
+
+				this->customizedCallbackIdCounter++;
+			}
+
+		}
+
+		break;
+	}
+
+	default:
+		badMethod(res, ctxt);
+	}
+}
+
+void RESTBroker::callbacks_RspCb(int endpoint, int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+	/* Ignore this. Response already sent */
+}
+
+void RESTBroker::callbacks_NtfCb(int localId, Message *message,
+		RPCReqStatus *rpcReqStatus) {
+	std::string xmlNotification;
+
+	L_DEBUG(
+			"callbacks_NtfCb - fState = %d, fResult = %d, fReturnValue = %d, Id =%d",
+			rpcReqStatus->getFState(), rpcReqStatus->getFResult(),
+			rpcReqStatus->getReturnValue(), localId);
+	if (message == NULL)
+		return;
+	xmlNotification = pXMLMsgComposer->createRXMessageMsg(message);
+	// Store the current XML message into lastMessage. In case, a PollCallback procedure is invoked on the relevant Callback ID, lastMessage will be returned.
+	listeners.customizedCallback[localId].lastMessage = xmlNotification;
+	L_INFO("callbacks_NtfCb - xmlNotification = %s", xmlNotification.c_str());
+	restEvent("callbacks_NtfCb", &listeners.customizedCallback[localId],
+			xmlNotification.c_str(), rpcReqStatus, false);
+}
+
+//***********************************************************************************************
+//***************************  LOCAL_NODE functions  ********************************************
+//***********************************************************************************************
+/**
+ Protected method RESTBroker lndServicesList_Req
+ This method implements the ConfigureEndpoint Procedure
+ */
+void RESTBroker::lndServicesList_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (HTTPException, RESTException) {
+	SimpleDescriptor sd;
+	int endPoints[ENDPOINT_240];
+	std::string xmlResponse;
+
+	L_DEBUG("lndSevicesList_Req");
+
+	if (reqMethod == M_GET) {
+		//Resource *r = res -> parent;
+		L_INFO("lndSevicesList_Req - getActiveEndPoints of the local node");
+		int numEndPoints = pSAgent->getCurrentServices((int *) &endPoints);
+		if (numEndPoints == 0) {
+			restResponse("lndSevicesList_Req", ctxt->getSessionId(), NULL,
+					METHOD_NOT_ALLOWED); //ENDPOINT_NOT_REGISTERED
+			return;
+		}
+		xmlResponse = pXMLMsgComposer->createActiveEndPointLocalNodeMsg(
+				numEndPoints, endPoints);
+		restResponse("lndSevicesList_Req", ctxt->getSessionId(),
+				xmlResponse.c_str(), NO_ERROR);
+	} else if (reqMethod == M_POST) {
+		ServiceAgent<RESTBroker>::AddServiceCtxt rpcContext(
+				ctxt->getSessionId(), this,
+				(ServiceAgent<RESTBroker>::addServiceResponseCb) &RESTBroker::lndServicesList_RspCb,
+				NULL);
+		//Get from input the "SimpleDescriptor" XML message
+		if (pXMLMsgParser->getSimpleDescriptor(&sd, xmlMsg) == 1) {
+			//An error occurs when extracting the  SimpleDescriptor
+			throw RESTException(BAD_PARAMETER, "Wrong SimpleDescriptor");
+		}
+		// Call ServiceAgent::addService <<
+		pSAgent->addService(&sd, &rpcContext);
+	} else
+		badMethod(res, ctxt);
+}
+
+/**
+ Protected method RESTBroker lndSevicesList_RspCb
+ This method relates to ServiceAgent::addService response.
+
+ @param serviceDesc Service Descriptor.
+ @param rpcContext RPC context.
+ @param rpcReqStatus Returned RPC request status.
+ @return Void.
+ */
+
+void RESTBroker::lndServicesList_RspCb(SimpleDescriptor *serviceDesc,
+		int sessionId, RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+	int returnValue;
+	Resource *r;
+	char buf[3];
+	const char *detail;
+
+	L_DEBUG("lndSevicesList_RspCb");
+	returnValue = rpcReqStatus->getReturnValue();
+
+	// Create new LOCAL_SERVICES resource <--
+	if (serviceDesc != NULL && returnValue == AGENT_SUCCESS) {
+		L_INFO(
+				"lndSevicesList_RspCb - createResource LOCAL_SERVICES - localnode EndPoint %02X ",
+				serviceDesc->end_point);
+		sprintf(buf, "%02x", serviceDesc->end_point); //FIX Tiki considers the resource %x
+
+		r = pRESTServer->findResource(resources.defLocalNode, "services");
+		r = createFolder(r, buf, servicesDesc);
+		r->data.d = serviceDesc->end_point;
+		createResources(r, servicesDesc);
+
+		r = pRESTServer->findResource(r, "wsnconnection");
+		createResources(r, connDesc);
+
+//#ifdef WSN_C_PROTOCOL_BACKWARD_COMPATIBILITY
+		Resource *rbc;
+		char buf_BC[3];
+
+		sprintf(buf_BC, "%02x", serviceDesc->end_point);
+
+		rbc = pRESTServer->findResource(NULL, "localnode");
+		rbc = pRESTServer->findResource(rbc, "services");
+
+		rbc = createFolder(rbc, buf_BC, servicesDesc);
+		rbc->data.d = serviceDesc->end_point;
+		createResources(rbc, servicesDescBC);
+
+		rbc = pRESTServer->findResource(rbc, "wsnconnection");
+		createResources(rbc, connDescBC);
+//#endif
+
+		xmlResponse = pXMLMsgComposer->createLocalNodeEndpointMsg(
+				rpcReqStatus->getFResult(), serviceDesc);
+		detail = xmlResponse.c_str();
+	} else
+		detail = NULL;
+
+	if (sessionId == LOCAL_REST_REQUEST_SESSION_ID) {
+		L_DEBUG("lndServicesList_RspCb - It was a local REST request "
+				"(no HTTP request triggered the method invocation)");
+		return;
+	} else
+		restResponse("lndServicesList_RspCb", sessionId, detail, NULL,
+				rpcReqStatus);
+}
+
+void RESTBroker::clearEndpoin_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (HTTPException, RESTException) {
+	char endPointString[3] = "00";
+	std::string xmlResponse;
+	const char *detail;
+	int returnValue;
+	int endPoint = 0;
+	int reqUriLength = 0;
+	Resource *r;
+
+	if (reqMethod != M_DELETE) { //M_GET for testing, otherwise M_DELETE
+		pRESTServer->defaultHandler(res, reqUri, reqMethod, queryString, xmlMsg,
+				ctxt);
+		return;
+	}
+
+	L_DEBUG("clearEndpoin_Req");
+
+	// Extract the endPoint to be removed from reqUri= /net/default/localnode/services/XX
+	while (reqUri[reqUriLength] != '\0')
+		reqUriLength++;
+	endPointString[0] = reqUri[reqUriLength - 2];
+	endPointString[1] = reqUri[reqUriLength - 1];
+	endPointString[2] = '\0';
+	endPoint = strtoul(endPointString, NULL, 16);
+	L_DEBUG("clearEndpoin_Req - ReqURI %s, length %d, endPoint %d", reqUri,
+			reqUriLength, endPoint);
+
+	// Call ServiceAgent::removeService <<
+	returnValue = pSAgent->removeService(endPoint);
+	if (returnValue == -1) {
+		L_DEBUG("clearEndpoin_Req - GW Running, procedure not allowed");
+		pRESTServer->restError(METHOD_NOT_ALLOWED, NULL, NULL, ctxt); /*WRONG_REQUEST*/
+		return;
+	} else if (returnValue == -2) {
+		L_DEBUG("clearEndpoin_Req - ERROR: End point %02x not allocated!",
+				endPoint);
+		pRESTServer->restError(BAD_PARAMETER, NULL, NULL, ctxt);
+		return;
+	}
+	// Remove the REST service resource related to the specific end point
+	char buf[3];
+	sprintf(buf, "%02x", endPoint);
+	buf[2] = '\0';
+	r = pRESTServer->findResource(resources.defLocalNode, "services");
+	r = pRESTServer->findResource(r, buf);
+
+	if (r != NULL) {
+		pRESTServer->clearResource(r);
+	} else
+		L_DEBUG("clearEndpoin_Req - Resource %s not found!", buf);
+
+	if (returnValue == -1) {
+		throw RESTException(BAD_PARAMETER,
+				"No entry found, endPoint not allocated");
+	}
+	// Return a response!
+	//xmlResponse = pXMLMsgComposer->createGenericResponseMsg();
+	//detail = xmlResponse.c_str ();
+	detail = NULL;
+
+	restResponse("clearEndpoin_Req", ctxt->getSessionId(), detail, NO_ERROR);
+}
+
+/**
+ Public method RESTBroker lndAllServicesWsnConnection_Req
+ This method allows creating a WSN connection on all services defined in the local node: the reception of a ZigBee message whose destination is one of the
+ registered endpoints will be notified invoking the registered RPC function. In case REST is used, lndAllServicesWsnConnection_NtfCbW will be considered.
+ In particular, the ServiceAgent::createCallback is invoked (refer to Service Agent) using parameter ALL_ENDPOINTS.
+ Moreover, a specific urilistener for notification can be registered.
+
+ @param reqUri reqUri.
+ @param reqMethod HTTP request method.
+ @param queryString Query string.
+ @param sessionId REST session identifier value.
+ @return Void.
+ */
+
+void RESTBroker::lndAllServicesWsnConnection_Req(Resource *res,
+		const char *reqUri, Method reqMethod, const char *queryString,
+		std::string *xmlMsg, RESTSessionContext *ctxt) throw (RESTException,
+				HTTPException) {
+	std::string *uri;
+	int returnValue;
+
+	L_DEBUG("lndAllServicesWsnConnection_Req");
+
+	if (reqMethod != M_POST)
+		badMethod(res, ctxt);
+
+	L_DEBUG("lndAllServicesWsnConnection_Req - "
+			"create a WsnConnection on all services");
+
+	// Get urilistener parameter from queryString
+	uri = &ctxt->callbackDestination;
+	if (uri->length() == 0) {
+		L_INFO("lndAllServicesWsnConnection_Req - "
+				"query not containing callback destination");
+		throw RESTException(PARAMETER_MISSING,
+				"Missing callbackDestination parameter"); //It was WRONG_REQUEST
+	}
+
+	// Create RPC Context
+	ServiceAgent<RESTBroker>::CreateCallbackCtxt rpcContext(
+			ctxt->getSessionId(), this,
+			(ServiceAgent<RESTBroker>::createCallbackResponseCb) &RESTBroker::lndAllServicesWsnConnection_RspCb,
+			(ServiceAgent<RESTBroker>::messageReceivedNotifyCb) &RESTBroker::lndAllServicesWsnConnection_NtfCb);
+
+	// Call ServiceAgent::createCallback <<
+	returnValue = pSAgent->createCallback(ALL_ENDPOINTS, &rpcContext);
+
+	if (returnValue == AGENT_SUCCESS) {
+		L_INFO("lndAllServicesWsnConnection_Req - "
+				"Connection created - ALL_ENDPOINTS - "
+				"Add UriListener %s", uri->c_str());
+		// Add URI listener to the list
+		listeners.allServices.addListener(uri, ctxt->getSessionId(),
+				new RESTCallbackInfo(ctxt->cbinfo));
+	}
+}
+
+/**
+ Protected method RESTBroker lndAllServicesWsnConnection_RspCb
+ This method relates to ServiceAgent::createCallback response.
+
+ @param endpoint EndPoint identifier value.
+ @param rpcContext RPC context.
+ @param rpcReqStatus Returned RPC request status.
+ @return Void.
+ */
+
+void RESTBroker::lndAllServicesWsnConnection_RspCb(int endpoint, int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+	/* Ignore this. Response already sent */
+}
+
+/**
+ Protected method RESTBroker lndAllServicesWsnConnection_NtfCb
+ This method relates to ServiceAgent::messageReceived_Cb notification. In particular, the received message is posted to the URI listener registered
+ on WSN connection - ALL_ENDPOINTS.
+
+ @param message Message received.
+ @param rpcReqStatus Returned RPC request status.
+ @return Void.
+ */
+
+void RESTBroker::lndAllServicesWsnConnection_NtfCb(int destEP, Message *message,
+		RPCReqStatus *rpcReqStatus) {
+	std::string xmlNotification;
+
+	L_DEBUG(
+			"lndAllServicesWsnConnection_NtfCb - RPCReqStatus - fState = %d - fResult = %d - fReturnValue = %d",
+			rpcReqStatus->getFState(), rpcReqStatus->getFResult(),
+			rpcReqStatus->getReturnValue());
+
+	// Create XML Response		
+	xmlNotification = pXMLMsgComposer->createRXMessageMsg(message);
+	L_INFO("lndAllServicesWsnConnection_NtfCb - xmlResponse = %s",
+			xmlNotification.c_str());
+
+	listeners.allServices.lastMessage = xmlNotification;
+	/*	TODO: Why this part is commented?!
+	 /// The received message is posted to registered URI listener List
+	 restEvent ("lndAllServicesWsnConnection_NtfCb",
+	 &listeners.allServices, xmlNotification.c_str (), NULL,
+	 rpcReqStatus);
+
+	 */
+
+}
+
+/**
+ Public method RESTBroker lndAllServicesMessage_Req
+ This method allows getting the last received ZigBee message (stored in msgCache, defined in CServiceAgent.h) related to one of the registered endpoints. Only GET method is allowed.
+ In particular, the ServiceAgent::getLastRxMsg is invoked (refer to Service Agent) using parameter ALL_ENDPOINTS.
+
+ @param reqUri reqUri.
+ @param reqMethod HTTP request method.
+ @param queryString Query string.
+ @param sessionId REST session identifier value.
+ @return Void.
+ */
+
+void RESTBroker::lndAllServicesMessage_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (HTTPException) {
+	ServiceAgent<RESTBroker>::GetLastRxMsgCtxt rpcContext(ctxt->getSessionId(),
+			this,
+			(ServiceAgent<RESTBroker>::getLastRxMsgResponseCb) &RESTBroker::lndAllServicesMessage_RspCb,
+			NULL);
+
+	L_DEBUG("lndAllServicesMessage_Req");
+
+	if (reqMethod != M_GET)
+		badMethod(res, ctxt);
+
+	pSAgent->getLastRxMsg(ALL_ENDPOINTS, &rpcContext);
+}
+
+/**
+ Protected method RESTBroker lndAllServicesMessage_RspCb
+ This method relates to ServiceAgent::getLastRxMsg response.
+
+ @param msg Last ZigBee message received.
+ @param rpcContext RPC context.
+ @param rpcReqStatus Returned RPC request status.
+ @return Void.
+ */
+
+void RESTBroker::lndAllServicesMessage_RspCb(Message *msg, int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+	const char *detail;
+	int returnValue;
+
+	L_DEBUG("lndAllServicesMessage_RspCb");
+
+	// Create XML Response
+	returnValue = rpcReqStatus->getReturnValue();
+	if (returnValue == AGENT_SUCCESS) {
+		xmlResponse = pXMLMsgComposer->createRXMessageMsg(msg);
+		detail = xmlResponse.c_str();
+	} else
+		detail = NULL;
+
+	// Update REST Session status and set XML Response
+	restResponse("lndAllServicesMessage_RspCb", sessionId, detail, NULL,
+			rpcReqStatus);
+}
+
+#if 0
+
+//***********************************************************************************************
+//***************************  TRUSTCENTER functions  *******************************************
+//***********************************************************************************************
+
+/**
+ Public method RESTBroker trustCenter_Req
+ This method allows registering a REST RPC listener in the TrustCenter Agent. When a new device joins the considered ZigBee network
+ the registered RPC function (i.e. RESTBroker::trustCenter_DeviceJoinIndication_NtfCbW ) is invoked by TrustCenterAgent::loginNode.
+ In particular, the TrustCenterAgent::registerRPCListener is called (refer to TrustCenter Agent).
+
+ @param reqUri reqUri.
+ @param reqMethod HTTP request method.
+ @param queryString Query string.
+ @param sessionId REST session identifier value.
+ @return Void.
+ */
+
+void RESTBroker::trustCenter_Req(
+		Uri *reqUri,
+		int reqMethod,
+		const char *queryString,
+		int sessionId
+)
+{
+	int returnValue;
+	std::string uriListenerValue;
+
+	L_INFO("trustCenter_Req");
+
+	if ( reqMethod != GET_METHOD )
+	{
+		L_INFO("trustCenter_Req - reqMethod %d not allowed on resource TRUSTCENTER", reqMethod);
+		this->restError_Rsp(METHOD_NOT_ALLOWED, "TRUSTCENTER", sessionId);
+		return;
+	}
+
+	// Get urilistener parameter from queryString
+	uriListenerValue = pQueryParser->getParameter(QS_URI_LISTENER, queryString);
+	if ( uriListenerValue.length() == 0 )
+	{
+		// No urilistener is present -> Error "Wrong Request"
+		L_ERROR("trustCenter_Req - query not containing parameter %s",QS_URI_LISTENER);
+		this->restError_Rsp(WRONG_REQUEST, "TRUSTCENTER", sessionId);
+		return;
+	}
+
+	// Create RPC Context
+	RPCContext *rpcContext = new RPCContext(
+			sessionId,
+			(void *)(&trustCenter_RspCbW),
+			(void *)(&trustCenter_DeviceJoinIndication_NtfCbW)
+	);
+	// Call TrustCenterAgent::registerRPCListener<<
+	returnValue = pTCAgent->registerRPCListener(rpcContext);
+	// Delete RPC Context
+	delete(rpcContext);
+
+	if ( returnValue == AGENT_SUCCESS)
+	{
+		if ( uriListenerValue.length() != 0 )
+		{
+			L_INFO("trustCenter_Req - Connection to TrustCenterAgent created - Add UriListener %s", uriListenerValue.c_str());
+			// Add URI listener to the list
+			this->addUriListener( &uriListenerValue, TRUSTCENTER, 0);
+		} else
+		{
+			L_ERROR("trustCenter_Req - Error: No UriListener -> TrustCenterAgent should not be called");
+		}
+	}
+}
+
+/**
+ Public static method RESTBroker trustCenter_RspCbW
+ This method is called by TrustCenter Agent as asynchronous response to the request trustCenter_Req.
+ In particular, this is a static member function, used as a wrapper to callback to the related non-static member function.
+
+ @param rpcContext RPC context.
+ @param rpcReqStatus Returned RPC request status.
+ @return Void.
+ */
+
+void RESTBroker::trustCenter_RspCbW(
+		RPCContext *rpcContext,
+		RPCReqStatus *rpcReqStatus
+)
+{
+	printf("RESTBroker::trustCenter_RspCbW\n");
+	RESTBroker *restBroker = RESTBroker::Instance();
+	restBroker->trustCenter_RspCb(rpcContext, rpcReqStatus);
+}
+
+/**
+ Protected method RESTBroker trustCenter_RspCb
+ This method relates to TrustCenterAgent::registerRPCListener response.
+
+ @param rpcContext RPC context.
+ @param rpcReqStatus Returned RPC request status.
+ @return Void.
+ */
+
+void RESTBroker::trustCenter_RspCb(
+		RPCContext *rpcContext,
+		RPCReqStatus *rpcReqStatus
+)
+{
+	int returnValue;
+
+	L_DEBUG("trustCenter_RspCb");
+
+	// Create XML Response
+	std::string xmlResponse;
+	returnValue = rpcReqStatus->getReturnValue();
+	if ( returnValue != AGENT_SUCCESS )
+	{
+		xmlResponse = pXMLMsgComposer->createErrorMsg("TRUSTCENTER AGENT", returnValue, pAgentErrorMsgs->getErrorMessage(returnValue),"[registerRPCListener]");
+	} else
+	{
+		xmlResponse = pXMLMsgComposer->createInfoMsg("TRUSTCENTER AGENT", "registerRPCListener Called");
+	}
+
+	L_INFO("trustCenter_RspCb - xmlResponse = %s", xmlResponse.c_str());
+	L_INFO("trustCenter_RspCb - fResult = %d ", rpcReqStatus->getFResult());
+
+	// Update REST Session status and set XML Response
+	restSuccess_Rsp (xmlResponse.c_str(), rpcContext->getSessionId());
+}
+
+/**
+ Public static method RESTBroker trustCenter_DeviceJoinIndication_NtfCbW
+ This method is called by TrustCenter Agent as asynchronous notification indicating that a new node is joining the ZigBee network. In facts, this notification
+ is used for asking to WSN-C whether the node is allowed to join the network (join permission).
+ In particular, this is a static member function, used as a wrapper to callback to the related non-static member function.
+
+ @param eventType A device join indication can be called in case of ZB_NLME_JOIN_INDICATION or ZB_APSME_UPDATE_DEVICE_INDICATION or other login events. The specific event is identified by eventType.
+ @param joiningNode Pointer to a NodeMapItem object (joining node).
+ @param rpcReqStatus Returned RPC request status.
+ @return Void.
+ */
+
+void RESTBroker::trustCenter_DeviceJoinIndication_NtfCbW(
+		int eventType,
+		NodeMapItem *joiningNode,
+		RPCReqStatus *rpcReqStatus
+)
+{
+	printf("RESTBroker::trustCenter_DeviceJoinIndication_NtfCb\n");
+	RESTBroker *restBroker = RESTBroker::Instance();
+	restBroker->trustCenter_DeviceJoinIndication_NtfCb( eventType, joiningNode, rpcReqStatus);
+}
+
+/**
+ Protected method RESTBroker trustCenter_DeviceJoinIndication_NtfCb
+ This method relates to TrustCenterAgent::loginNode notification.
+
+ @param eventType A device join indication can be called in case of ZB_NLME_JOIN_INDICATION or ZB_APSME_UPDATE_DEVICE_INDICATION or other login events. The specific event is identified by eventType.
+ @param joiningNode Pointer to a NodeMapItem object (joining node).
+ @param rpcReqStatus Returned RPC request status.
+ @return Void.
+ */
+
+void RESTBroker::trustCenter_DeviceJoinIndication_NtfCb(
+		int eventType,
+		NodeMapItem *joiningNode,
+		RPCReqStatus *rpcReqStatus
+)
+{
+	int returnValue;
+	std::string xmlNotification;
+
+	L_DEBUG("trustCenter_DeviceJoinIndication_NtfCb");
+	L_DEBUG("trustCenter_DeviceJoinIndication_NtfCb - RPCReqStatus - fState = %d - fResult = %d - fReturnValue = %d",rpcReqStatus->getFState(), rpcReqStatus->getFResult(), rpcReqStatus->getReturnValue());
+
+	// Get returnValue
+	returnValue = rpcReqStatus->getReturnValue();
+
+	int key;
+	key = TRUSTCENTER * KEY_FACTOR;
+	L_DEBUG("trustCenter_DeviceJoinIndication_NtfCb - key = %d", key);
+
+	if ( this->uriListenersList[key].empty() )
+	{
+		L_ERROR("trustCenter_DeviceJoinIndication_NtfCb - No uriListener available!");
+		return;
+	}
+	// Only one uriListener is allowed
+	if ( this->uriListenersList[key].size() > 1 )
+	{
+		L_ERROR("trustCenter_DeviceJoinIndication_NtfCb - uriListenerList size >  1 -> ERROR");
+		return;
+	}
+	// Create XML Response
+	if (joiningNode != NULL)
+	{
+		xmlNotification = pXMLMsgComposer->createJoiningNodesMsg(rpcReqStatus->getFResult(), joiningNode);
+	} else
+	{
+		xmlNotification = pXMLMsgComposer->createErrorMsg("TRUSTCENTER AGENT", returnValue, pAgentErrorMsgs->getErrorMessage(returnValue),"[trustCenter_DeviceJoinIndication_NtfCb]");
+	}
+	L_INFO("trustCenter_DeviceJoinIndication_NtfCb - xmlResponse = %s", xmlNotification.c_str());
+
+	L_INFO("trustCenter_DeviceJoinIndication_NtfCb - POST message to UriListener List");
+	// The notification message is posted to the registered URI listener
+	pRESTClient->sendPostData(&(this->uriListenersList[key]), &xmlNotification);
+}
+
+/**
+ Public method RESTBroker tcAccessList_Req
+ This method mainly deals with WSN-C response to the join permission request for a specific node (refer to RESTBroker::trustCenter_DeviceJoinIndication_NtfCbW).
+ In this case a POST method is invoked on the specific REST resource. If a GET HTTP method is considered, the up-to-date TrustCenter list of nodes is returned.
+ In particular, as regards the POST method, the TrustCenterAgent::FromWSNC_Authorization_cb is called (refer to TrustCenter Agent).
+ GET method is actually unsopported: a proper XML error message is returned.
+
+ @param reqUri reqUri.
+ @param reqMethod HTTP request method.
+ @param queryString Query string.
+ @param xmlMsg XML message received as post data.
+ @param sessionId REST session identifier value.
+ @return Void.
+ */
+
+void RESTBroker::tcAccessList_Req(
+		Uri *reqUri,
+		int reqMethod,
+		const char *queryString,
+		std::string *xmlMsg,
+		int sessionId
+)
+{
+	std::string modeValue;
+	int returnValue;
+
+	L_DEBUG("tcAccessList_Req");
+
+	if ( reqMethod != GET_METHOD && reqMethod != POST_METHOD )
+	{
+		L_INFO("tcAccessList_Req - reqMethod %d not allowed on resource TC_ACCESS_LIST", reqMethod);
+		this->restError_Rsp(METHOD_NOT_ALLOWED, "TC_ACCESS_LIST", sessionId);
+		return;
+	}
+
+	switch (reqMethod) {
+		case GET_METHOD:
+		{
+			L_INFO("tcAccessList_Req - reqMethod %d (GET) -> retrieve up-to-date TC list of nodes", reqMethod);
+			this->restError_Rsp(FEATURE_NOT_SUPPORTED, "TC_ACCESS_LIST", sessionId);
+		}
+		break;
+
+		case POST_METHOD:
+		{
+			L_INFO("tcAccessList_Req - reqMethod %d (POST) ->", reqMethod);
+			L_INFO("tcAccessList_Req - POST rx xmlMsg = %s ", xmlMsg->c_str());
+
+			std::string *joiningNodeShortAddr;
+			int nodeAddr;
+			joiningNodeShortAddr = pXMLMsgParser->getXMLAttributeValue("ShortAddr",xmlMsg);
+
+			if ( joiningNodeShortAddr != NULL )
+			{
+				L_INFO("tcAccessList_Req - joiningNodeShortAddr = %s ", joiningNodeShortAddr->c_str());
+				sscanf(joiningNodeShortAddr->c_str(),"%04x", &nodeAddr);
+				delete(joiningNodeShortAddr);
+			} else
+			{
+				this->restError_Rsp(WRONG_REQUEST, "TRUSTCENTER AGENT", sessionId);
+				return;
+			}
+
+			std::string *joinAllowedValue;
+			bool joinAllowed;
+			joinAllowedValue = pXMLMsgParser->getXMLElementValue("JoinAllowed",xmlMsg);
+			if ( joinAllowedValue != NULL )
+			{
+				L_INFO("tcAccessList_Req - JoinAllowed value = %s ", joinAllowedValue->c_str());
+				if ( strcmp(joinAllowedValue->c_str(), "true") == 0 )
+				{
+					joinAllowed = true;
+				} else
+				{
+					joinAllowed = false;
+				}
+				delete(joinAllowedValue);
+			} else
+			{
+				this->restError_Rsp(WRONG_REQUEST, "TRUSTCENTER AGENT", sessionId);
+				return;
+			}
+
+			// Create RPC Context
+			RPCContext *rpcContext = new RPCContext( sessionId, (void *)(&tcAccessList_RspCbW), NULL );
+			// Call TrustCenterAgent::FromWSNC_Authorization_cb <<
+			returnValue = pTCAgent->FromWSNC_Authorization_cb( (ushort) nodeAddr, joinAllowed , rpcContext);
+			// Delete RPC Context
+			delete(rpcContext);
+		}
+		break;
+
+		default:
+		{
+			L_ERROR("tcAccessList_Req - HTTP Method %d not not allowed on resource TC_ACCESS_LIST",reqMethod);
+		}
+	}
+}
+
+/**
+ Public static method RESTBroker tcAccessList_RspCbW
+ This method is called by TrustCenter Agent as asynchronous response to the request tcAccessList_Req (when the HTTP POST method is considered).
+ In particular, this is a static member function, used as a wrapper to callback to the related non-static member function.
+
+ @param addr Node short address.
+ @param granted It relates to join permission for a specific node.
+ @param rpcContext RPC context.
+ @param rpcReqStatus Returned RPC request status.
+ @return Void.
+ */
+
+void RESTBroker::tcAccessList_RspCbW(
+		ushort addr,
+		bool granted,
+		RPCContext *rpcContext,
+		RPCReqStatus *rpcReqStatus
+)
+{
+	printf("RESTBroker::tcAccessList_RspCbW\n");
+	RESTBroker *restBroker = RESTBroker::Instance();
+	restBroker->tcAccessList_RspCb( addr, granted,rpcContext, rpcReqStatus);
+}
+
+/**
+ Protected method RESTBroker tcAccessList_RspCb
+ This method relates to TrustCenterAgent::FromWSNC_Authorization_cb response.
+
+ @param addr Node short address.
+ @param granted It relates to join permission for a specific node.
+ @param rpcContext RPC context.
+ @param rpcReqStatus Returned RPC request status.
+ @return Void.
+ */
+
+void RESTBroker::tcAccessList_RspCb(
+		ushort addr,
+		bool granted,
+		RPCContext *rpcContext,
+		RPCReqStatus *rpcReqStatus
+)
+{
+	int returnValue;
+	L_DEBUG("tcAccessList_RspCb");
+
+	returnValue = rpcReqStatus->getReturnValue();
+
+	// Create XML Response
+	std::string xmlResponse;
+	if ( returnValue != AGENT_SUCCESS )
+	{
+		xmlResponse = pXMLMsgComposer->createErrorMsg("TRUSTCENTER AGENT", returnValue, pAgentErrorMsgs->getErrorMessage(returnValue),"[FromWSNC_Authorization_cb]");
+	} else
+	{
+		std::string resultDescription;
+		resultDescription = std::string("FromWSNC_Authorization_cb - ");
+		char tmp_str[200];
+		sprintf(tmp_str,"Node %04X successfully ", addr);
+		tmp_str[strlen(tmp_str)] = '\0';
+		resultDescription += tmp_str;
+		if (granted == true)
+		{
+			resultDescription += "authorized";
+		} else
+		{
+			resultDescription += "removed";
+		}
+		xmlResponse = pXMLMsgComposer->createInfoMsg("TRUSTCENTER AGENT", resultDescription.c_str());
+	}
+
+	L_INFO("tcAccessList_RspCb - xmlResponse = %s", xmlResponse.c_str());
+	L_DEBUG("tcAccessList_RspCb - fResult = %d", rpcReqStatus->getFResult());
+
+	// Update REST Session status and set XML Response
+	restSuccess_Rsp (xmlResponse.c_str(), rpcContext->getSessionId());
+}
+
+#endif
+
+//***********************************************************************************************
+//***************************  LOCAL_SERVICES functions  ****************************************
+//***********************************************************************************************
+
+/**
+ Public method RESTBroker lsWsnConnection_Req
+ This method allows creating a WSN connection on a specific service defined in the local node: the reception of a ZigBee message whose destination is the
+ considered endpoint will be notified invoking the registered RPC function. In case REST is used, lsWsnConnection_NtfCbW will be considered.
+ In particular, the ServiceAgent::createCallback is invoked (refer to Service Agent).
+ Moreover, a specific urilistener for notification can be registered.
+
+ @param reqUri reqUri.
+ @param reqMethod HTTP request method.
+ @param queryString Query string.
+ @param sessionId REST session identifier value.
+ @return Void.
+ */
+
+void RESTBroker::lsWsnConnection_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (RESTException, HTTPException) {
+	std::map<int, RBURIListenerList>::iterator i;
+	RBURIListenerList *l;
+	std::string *uri;
+	Resource *r;
+	int ep;
+
+	L_DEBUG("lsWsnConnection_Req");
+
+	r = res->parent;
+	ep = r->data.d;
+
+	uri = &ctxt->callbackDestination;
+	if (uri->length() == 0) {
+		L_WARN("lsWsnConnection_Req - "
+				"query not containing callback destination");
+		throw RESTException(PARAMETER_MISSING,
+				"Missing callbackDestination parameter"); //It was WRONG_REQUEST
+	}
+
+	switch (reqMethod) {
+	case M_POST:
+
+		i = listeners.service.find(ep);
+		if (i == listeners.service.end()) {
+			l = &listeners.service[ep];
+
+			l->attach = &RESTBroker::serviceAttach;
+			l->detach = &RESTBroker::serviceDetach;
+			l->handler = this;
+			l->data.d = ep;
+		} else
+			l = &i->second;
+
+		l->addListener(uri, ctxt->getSessionId(),
+				new RESTCallbackInfo(ctxt->cbinfo));
+
+		break;
+
+	default:
+		badMethod(res, ctxt);
+
+	}
+
+}
+
+/**
+ Protected method RESTBroker lsWsnConnection_RspCb
+ This method relates to ServiceAgent::createCallback response.
+
+ @param endpoint EndPoint identifier value.
+ @param rpcContext RPC context.
+ @param rpcReqStatus Returned RPC request status.
+ @return Void.
+ */
+
+void RESTBroker::lsWsnConnection_RspCb(int endpoint, int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+	/* Ignore this. Response already sent */
+}
+
+/**
+ Protected method RESTBroker lsWsnConnection_NtfCb
+ This method relates to ServiceAgent::messageReceived_Cb notification. In particular, the received message is posted to the URI listener registered
+ on WSN connection related to a specific endpoint.
+
+ @param message Message received.
+ @param rpcReqStatus Returned RPC request status.
+ @return Void.
+ */
+
+void RESTBroker::lsWsnConnection_NtfCb(int destEP, Message *message,
+		RPCReqStatus *rpcReqStatus) {
+	std::string xmlNotification;
+
+	L_DEBUG("lsWsnConnection_NtfCb");
+	L_DEBUG("lsWsnConnection_NtfCb - RPCReqStatus - "
+			"fState = %d - fResult = %d - fReturnValue = %d",
+			rpcReqStatus->getFState(), rpcReqStatus->getFResult(),
+			rpcReqStatus->getReturnValue());
+
+	if (message == NULL)
+		return;
+
+	xmlNotification = pXMLMsgComposer->createRXMessageMsg(message);
+
+	// Store the current XML message into lastMessage. In case, a PollCallback procedure is invoked
+	// on the relevant Callback ID, lastMessage will be returned.
+	listeners.service[destEP].lastMessage = xmlNotification;
+
+	/*
+	 L_INFO("lsWsnConnection_NtfCb - xmlNotification = %s",
+	 xmlNotification.c_str());
+	 */
+	// Instead of %s let print each single char since often not all the XML message is printed out!
+#ifdef DEBUG_ACTIVE_RB
+	if (this->debugEnabled)
+	{
+		printf("lsWsnConnection_NtfCb - xmlNotification = ");
+		const char * temp = xmlNotification.c_str();
+		for (ushort i=0; i < strlen(temp);i++)
+		printf("%c",temp[i]);
+		printf("\r\n");
+	}
+#endif
+
+	restEvent("lsWsnConnection_NtfCb", &listeners.service[destEP],
+			xmlNotification.c_str(), rpcReqStatus, false);
+
+//#ifdef WSN_C_PROTOCOL_BACKWARD_COMPATIBILITY
+	std::string xmlNotification_BC;
+
+	xmlNotification_BC = pXMLMsgComposer->createRXMessageMsg_BC(message);
+	listeners.service_BC[destEP].lastMessage = xmlNotification_BC;
+
+	L_INFO("lsWsnConnection_NtfCb - BC xmlResponse = %s",
+			xmlNotification_BC.c_str());
+
+	restEvent_BC("lsWsnConnection_NtfCb", &listeners.service_BC[destEP],
+			xmlNotification_BC.c_str(), rpcReqStatus);
+//#endif
+
+}
+
+void RESTBroker::lsWsnConnection_deleteCallback_RspCb(int endpoint,
+		int sessionId, RPCReqStatus *rpcReqStatus) {
+	/* Currently this is done at urlistener level, so the
+	 * session id is local */
+}
+
+//#ifdef WSN_C_PROTOCOL_BACKWARD_COMPATIBILITY
+void RESTBroker::lsWsnConnection_BC_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (RESTException, HTTPException) {
+	std::map<int, RBURIListenerList>::iterator i;
+	RBURIListenerList *l;
+	std::string *uri;
+	Resource *r;
+	int ep;
+
+	L_DEBUG("lsWsnConnection_BC_Req");
+
+	r = res->parent;
+	ep = r->data.d;
+
+	uri = &ctxt->callbackDestination;
+	if (uri->length() == 0) {
+		L_WARN("lsWsnConnection_Req - "
+				"query not containing callback destination");
+		throw RESTException(PARAMETER_MISSING,
+				"Missing callbackDestination parameter"); //It was WRONG_REQUEST
+	}
+
+	switch (reqMethod) {
+	case M_GET:
+
+		i = listeners.service_BC.find(ep);
+		if (i == listeners.service_BC.end()) {
+			l = &listeners.service_BC[ep];
+
+			l->attach = &RESTBroker::serviceAttach_BC;
+			l->detach = &RESTBroker::serviceDetach;
+			l->handler = this;
+			l->data.d = ep;
+		} else
+			l = &i->second;
+
+		l->addListener(uri, ctxt->getSessionId(),
+				new RESTCallbackInfo(ctxt->cbinfo));
+
+		break;
+
+	default:
+		badMethod(res, ctxt);
+
+	}
+
+}
+//#endif
+
+/**
+ Public method RESTBroker lsMessage_Req
+ When GET method is considered, lsMessage_Req allows retrieving the last received message whose destination is a specific endpoint (i.e. service)
+ in the local node. In particular, the ServiceAgent::getLastRxMsg is invoked (refer to Service Agent).
+ When POST method is used, lsMessage_Req allows sending a message to a ZigBee node in the considered network. At the moment, this feature is not supported.
+
+
+ @param reqUri reqUri.
+ @param reqMethod HTTP request method.
+ @param queryString Query string.
+ @param xmlMsg XML message received as post data.
+ @param sessionId REST session identifier value.
+ @return Void.
+ */
+void RESTBroker::lsMessage_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (RESTException, HTTPException) {
+	Message ZCLmsg;
+	Message APSmsg;
+	Resource *r;
+	unsigned txTime;
+	uchar status;
+	std::string s;
+	int ep;
+	ushort tmpShortAddr;
+	std::string stringValue, urilistener;
+	int timeout;
+	r = res->parent;
+	ep = r->data.d; //TODO: This endPoint is not taken correctly - try it with http://127.0.0.1:9000/net/default//localnode/services/08/wsnconnection/message
+
+	ServiceAgent<RESTBroker>::GetLastRxMsgCtxt rpcContext(ctxt->getSessionId(),
+			this,
+			(ServiceAgent<RESTBroker>::getLastRxMsgResponseCb) &RESTBroker::lsMessage_RspCb,
+			NULL);
+
+	L_DEBUG("lsMessage_Req");
+
+	switch (reqMethod) {
+	case M_GET:
+		pSAgent->getLastRxMsg(ep, &rpcContext);
+		break;
+
+	case M_POST:
+
+		//This call gets all the values contained in a 'ZCLCommand' type or 'APSMessage' type
+		if (pXMLMsgParser->getZCLCommandToWSN(&ZCLmsg, xmlMsg)) {
+			// This is not an ZCLCommand, check then if it could be an 'APSMessage' command
+			if (pXMLMsgParser->getAPSMessageToWSN(&APSmsg, xmlMsg))
+				throw RESTException(WRONG_REQUEST,
+						"Message not sent: Error parsing XML message");
+			pQueryParser->getParameter("timeout", queryString, stringValue);
+			if (stringValue.length() == 0) {
+				L_DEBUG("lsMessage_Req - ERROR: timeout parameter missing");
+				// This an error since a value for timeout must be present
+				throw RESTException(PARAMETER_MISSING,
+						"Missing timeout parameter"); //It was WRONG_REQUEST
+			} else {
+				timeout = atoi(stringValue.c_str());
+				L_DEBUG("lsMessage_Req - timeout parameter %x", timeout);
+			}
+			// Intercept an eventual NodeDescriptor request
+			if (APSmsg.getClusterId() == 0x0002
+					&& APSmsg.getProfileId() == 0x0000
+					&& APSmsg.getDstEp() == 0x00) {
+				tmpShortAddr = (APSmsg.getDstAddr(NULL)[0] << 8)
+						+ APSmsg.getDstAddr(NULL)[1];
+				L_DEBUG(
+						"lsMessage_Req - Intercepted a NodeDescriptorRequest for 0x%04x, use the correct handler!",
+						tmpShortAddr);
+				//This is a NodeDescriptorRequest, thus register an handler
+				DiscoveryAgent<RESTBroker>::NodeDescriptorCtxt rpcContext(
+						ctxt->getSessionId(), this,
+						(DiscoveryAgent<RESTBroker>::nodeDescriptorResponseCb) &RESTBroker::nodeDescriptor_RspCb,
+						(DiscoveryAgent<RESTBroker>::nodeDescriptorNotifyCb) &RESTBroker::nodeDescriptor_NtfCb);
+				pDAgent->getNodeDescriptor(timeout, tmpShortAddr, &rpcContext);
+				return;
+			}
+			// Check whether the "callbackDestination" parameter is present. If not, raise an exception since the relevant feature is not supported
+			pQueryParser->getParameter("urilistener", queryString, stringValue);
+			if (stringValue.length() == 0) {
+				L_DEBUG(
+						"lsMessage_Req -  no callbackDestination(urilistener) - this is a synch call");
+			} else {
+				L_DEBUG(
+						"lsMessage_Req - ERROR: callbackDestination parameter %s present but feature not supported",
+						urilistener.c_str());
+				throw RESTException(FEATURE_NOT_SUPPORTED,
+						"CallbackDestination parameter not supported");
+			}
+			// We arrive here if we have a valid APSMessage extracted, so we can send it!
+			if (pSAgent->send(&APSmsg, status, txTime))
+				throw RESTException(GENERIC_REST_ERROR,
+						"Message not sent: Error sending APSMessage");
+			// Generate a response
+			s = pXMLMsgComposer->createAPSResultMsg(status, txTime);
+			restResponse("lsMessage_RspCb", ctxt->getSessionId(), s.c_str(),
+					NO_ERROR);
+		} else {
+			// Valid case, then the message received is a 'ZCLCommand' type
+			// Extract the "timeout" parameter
+			pQueryParser->getParameter("timeout", queryString, stringValue);
+			if (stringValue.length() == 0) {
+				L_DEBUG("lsMessage_Req - timeout parameter missing");
+				// This an error since a value for timeout must be present
+				throw RESTException(PARAMETER_MISSING,
+						"Missing timeout parameter"); //It was WRONG_REQUEST
+			} else {
+				timeout = atoi(stringValue.c_str());
+				L_DEBUG("lsMessage_Req - timeout parameter %x", timeout);
+			}
+			// Extract the "callbackDestination" parameter
+			pQueryParser->getParameter("urilistener", queryString, stringValue);
+			if (stringValue.length() == 0) {
+				L_DEBUG(
+						"lsMessage_Req - callbackDestination(urilistener) parameter missing");
+				// This is not an error since the parameter is optional
+			} else {
+				urilistener = stringValue;
+				L_DEBUG("lsMessage_Req - callbackDestination parameter %s",
+						urilistener.c_str());
+			}
+			// Send the ZigBee message!
+			if (pSAgent->send(&ZCLmsg, status, txTime))
+				throw RESTException(GENERIC_REST_ERROR,
+						"Message not sent: Error sending ZCLCommand");
+			// Generate a response
+			s = pXMLMsgComposer->createZCLMessage(status, txTime, &ZCLmsg);
+			restResponse("lsMessage_RspCb", ctxt->getSessionId(), s.c_str(),
+					NO_ERROR);
+		}
+		break;
+
+	default:
+		badMethod(res, ctxt);
+	}
+}
+
+void RESTBroker::lsMessage_RspCb(Message *msg, int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+	const char *detail;
+	int returnValue;
+
+	L_DEBUG("lsMessage_RspCb");
+
+	returnValue = rpcReqStatus->getReturnValue();
+	if (returnValue == AGENT_SUCCESS) {
+		xmlResponse = pXMLMsgComposer->createRXMessageMsg(msg);
+		detail = xmlResponse.c_str();
+	} else
+		detail = NULL;
+
+	L_DEBUG("lsMessage_RspCb - xmlResponse = %s", xmlResponse.c_str());
+	L_DEBUG("lsMessage_RspCb - fResult = %d", rpcReqStatus->getFResult());
+
+	// Update REST Session status and set XML Response
+	restResponse("lsMessage_RspCb", sessionId, detail, NULL, rpcReqStatus);
+}
+
+//***********************************************************************************************
+//***************************  NODE functions  **************************************************
+//***********************************************************************************************
+
+void RESTBroker::lsBind_Req(Resource *res, const char *reqUri, Method reqMethod,
+		const char *queryString, std::string *xmlMsg, RESTSessionContext *ctxt)
+				throw (RESTException, HTTPException) {
+	std::string modeValue, *uri;
+	RBURIListenerList *rlist;
+
+	L_DEBUG("lsBind_Req");
+
+	switch (reqMethod) {
+	case M_GET: {
+		ushort destAddr;
+		short startIndex;
+		Resource *r;
+		uchar nwk[8];
+		Node* tmpNode;
+		int z;
+		std::string stringValue;
+		bool isPresent;
+
+		L_DEBUG("lsBind_Req - GetNodeBinding");
+		//Note: This command correspond to send a ZDP-MGMT_BIND.request!
+		// Check whether "timeout" parameter is present in the request
+		unsigned long int timeout = 0;
+
+		if (!(ctxt->cbinfo.timeoutSet)) {
+			L_WARN("GetNodeBinding - timeout parameter missing!");
+			// Fire RESTException since timeout parameter must be present
+			throw RESTException(WRONG_REQUEST, "Missing timeout parameter");
+		} else {
+			timeout = ctxt->cbinfo.timeout;
+			L_DEBUG("GetNodeBinding - timeout parameter 0x%x (%lu ms)", timeout,
+					timeout);
+		}
+
+		if (ctxt->asynch()) {
+			L_INFO("GetNodeBinding - non-blocking procedure");
+			uri = &ctxt->callbackDestination;
+			if (uri->length() == 0) {
+				L_WARN("GetNodeBinding - callback destination not present");
+				throw RESTException(WRONG_REQUEST,
+						"Missing callbackDestination parameter");
+			}
+			rlist = &listeners.getnodebinding;
+			if (!rlist->addListener(uri, ctxt->getSessionId(),
+					new RESTCallbackInfo(ctxt->cbinfo))) {
+				restResponse("GetNodeBinding", ctxt->getSessionId(), NULL,
+						URILISTENER_LIST_MAX_SIZE_EXCEEDED);
+			}
+			// Otherwise the response will be sent back by the attach handler (i.e. )
+		} else {
+			L_INFO("GetNodeBinding - blocking procedure");
+			ServiceAgent<RESTBroker>::GetnodebindingCtxt rpcContext(
+					ctxt->getSessionId(), this,
+					(ServiceAgent<RESTBroker>::getnodebindingResponseCb) &RESTBroker::getnodebinding_RspCb,
+					NULL);
+			try {
+				//Get the IEEE Address
+				std::string tempIEEE, temphex;
+				int value;
+				r = res->parent; // r->uri.c_str() contains "/net/default/wsnnodes/0050c2d8b3b739b5"
+				tempIEEE = r->uri.substr(22, 16); // "0050c2d8b3b739b5"
+				for (z = 0; z < 16; z++) {
+					temphex = tempIEEE.substr(z, 2);
+					sscanf(temphex.c_str(), "%x", &value);
+					nwk[z / 2] = value;
+					z++;
+				}
+				L_DEBUG(
+						"GetNodeBinding - nwk addr %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+						nwk[0], nwk[1], nwk[2], nwk[3], nwk[4], nwk[5], nwk[6],
+						nwk[7]);
+				//Get the shortAddress
+				tmpNode = pGalDb->findNodeByIEEEAddr(nwk);
+				if (tmpNode != NULL)
+					destAddr = tmpNode->get_nwk_addr();
+				else {
+					L_DEBUG("Wrong IEEEAddress (or not present in DB yet)");
+					throw RESTException(WRONG_REQUEST,
+							"Wrong IEEEAddress (or not present in DB yet)");
+				}
+			} catch (RESTException &e) {
+				// This an error since a value for the destAddr must be present
+				throw RESTException(WRONG_REQUEST,
+						"Bad formatted destination address");
+			}
+			//Get the startIndex value (if present)
+			isPresent = pQueryParser->getParameter("index", queryString,
+					stringValue);
+			if (isPresent)
+				startIndex = atoi(stringValue.c_str());
+			else
+				startIndex = 0;
+			L_DEBUG("startIndex value = 0x%02x", startIndex);
+			// Send the message
+			pSAgent->getnodebindingRequest(timeout, destAddr, startIndex,
+					&rpcContext);
+		}
+	}
+		break;
+
+	case M_POST: {
+		// Check whether "timeout" parameter is present in the request
+		unsigned long int timeout = 0;
+
+		if (!(ctxt->cbinfo.timeoutSet)) {
+			L_WARN("lsBind_Req - timeout parameter missing!");
+			// Fire RESTException since timeout parameter must be present
+			throw RESTException(WRONG_REQUEST, "Missing timeout parameter");
+		} else {
+			timeout = ctxt->cbinfo.timeout;
+			L_DEBUG("lsBind_Req - timeout parameter 0x%x (%lu ms)", timeout,
+					timeout);
+		}
+
+		if (ctxt->asynch()) {
+			L_INFO("lsBind_Req - BindRequest (non-blocking procedure)");
+
+			uri = &ctxt->callbackDestination;
+			if (uri->length() == 0) {
+				L_WARN("lsBind_Req - callback destination not present");
+				throw RESTException(WRONG_REQUEST,
+						"Missing callbackDestination parameter");
+			}
+			rlist = &listeners.bind;
+			if (!rlist->addListener(uri, ctxt->getSessionId(),
+					new RESTCallbackInfo(ctxt->cbinfo))) {
+				restResponse("lsBind_Req", ctxt->getSessionId(), NULL,
+						URILISTENER_LIST_MAX_SIZE_EXCEEDED);
+			}
+			// Otherwise the response will be sent back by the attach handler (i.e. )
+		} else {
+			ZB_BIND_STRUCT bindParams;
+			L_INFO("lsBind_Req - BindRequest (blocking procedure)");
+
+			ServiceAgent<RESTBroker>::BindCtxt rpcContext(ctxt->getSessionId(),
+					this,
+					(ServiceAgent<RESTBroker>::bindResponseCb) &RESTBroker::bind_RspCb,
+					NULL);
+
+			if (pXMLMsgParser->getBindindCommand(&bindParams, xmlMsg))
+				throw RESTException(WRONG_REQUEST,
+						"Message not sent: Error parsing XML message");
+			pSAgent->bindRequest(timeout, bindParams, &rpcContext);
+		}
+	}
+		break;
+
+	default:
+		badMethod(res, ctxt);
+		break;
+	}
+}
+
+void RESTBroker::getnodebinding_RspCb(short bindingTableEntries,
+		short startIndex, short bindingTableListCount,
+		ZB_BIND_STRUCT *bindingtableList, int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+	const char *detail;
+	int returnValue;
+
+	L_DEBUG("getnodebinding_RspCb");
+
+	if (sessionId == LOCAL_REST_REQUEST_SESSION_ID) {
+		L_DEBUG("bind_RspCb - It was a local REST request "
+				"(no HTTP request triggered the method invocation)");
+		return;
+	}
+	if (rpcReqStatus->isReqAsynch()) {
+		restResponse("getnodebinding_RspCb", sessionId, NULL, NULL,
+				rpcReqStatus);
+	} else {
+		returnValue = rpcReqStatus->getReturnValue();
+		// Create XML Response
+		if (returnValue == AGENT_SUCCESS) {
+			xmlResponse = pXMLMsgComposer->createGetNodeBindingMsg(
+					rpcReqStatus->getFResult(), bindingTableEntries, startIndex,
+					bindingTableListCount, bindingtableList);
+			detail = xmlResponse.c_str();
+		} else if (returnValue == 0x8b) {
+			xmlResponse = pXMLMsgComposer->createGetNodeBindingMsg(
+					rpcReqStatus->getFResult(), bindingTableEntries, startIndex,
+					0, bindingtableList); //bindingTableListCount equals to zero will force to return an empty "binding" tag!
+			detail = xmlResponse.c_str();
+		} else
+			detail = NULL;
+		// Update REST Session status and set XML Response
+		restResponse("getnodebinding_RspCb", sessionId, detail, NULL,
+				rpcReqStatus);
+	}
+}
+
+void RESTBroker::getnodebinding_NtfCb(short bindingTableEntries,
+		short startIndex, short bindingTableListCount,
+		ZB_BIND_STRUCT *bindingtableList, RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+	const char *detail;
+	int returnValue;
+
+	L_DEBUG("getnodebinding_NtfCb");
+
+	returnValue = rpcReqStatus->getReturnValue();
+
+	if (returnValue == AGENT_SUCCESS) {
+		xmlResponse = pXMLMsgComposer->createGetNodeBindingMsg(
+				rpcReqStatus->getFResult(), bindingTableEntries, startIndex,
+				bindingTableListCount, bindingtableList);
+		detail = xmlResponse.c_str();
+	} else if (returnValue == 0x8b) {
+		xmlResponse = pXMLMsgComposer->createGetNodeBindingMsg(
+				rpcReqStatus->getFResult(), bindingTableEntries, startIndex, 0,
+				bindingtableList); //bindingTableListCount equals to zero will force to return an empty "binding" tag!
+		detail = xmlResponse.c_str();
+	} else
+		detail = NULL;
+
+#ifdef DEBUG_ACTIVE_RB
+	printf("getnodebinding_NtfCb - xmlResponse = ");
+	const char * temp = xmlResponse.c_str();
+	for (ushort i=0; i < strlen(temp);i++)
+	printf("%c",temp[i]);
+	printf("\r\n");
+#endif
+	L_DEBUG("getnodebinding_NtfCb - fResult = %d", rpcReqStatus->getFResult());
+	restEvent("getnodebinding_NtfCb", &listeners.getnodebinding, detail, NULL,
+			rpcReqStatus);
+	// The notification has been sent -> remove uri listener
+	L_INFO("getnodebinding_NtfCb - event -> remove uriListeners");
+	listeners.getnodebinding.running = false;
+	listeners.getnodebinding.removeListeners();
+}
+
+void RESTBroker::bind_RspCb(
+//ZB_BIND_STRUCT bindParams,
+		int sessionId, RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+	//const char *detail;
+	//int returnValue;
+
+	L_DEBUG("bind_RspCb");
+
+	if (sessionId == LOCAL_REST_REQUEST_SESSION_ID) {
+		L_DEBUG("bind_RspCb - It was a local REST request "
+				"(no HTTP request triggered the method invocation)");
+		return;
+	}
+	if (rpcReqStatus->isReqAsynch()) {
+		restResponse("bind_RspCb", sessionId, NULL, NULL, rpcReqStatus);
+	} else {
+		//returnValue = rpcReqStatus->getReturnValue();
+		// Update REST Session status and set XML Response
+		restResponse("bind_RspCb", sessionId, NULL, NULL, rpcReqStatus);
+	}
+}
+
+void RESTBroker::bind_NtfCb(
+//ZB_BIND_STRUCT bindParams,
+		RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+
+	L_DEBUG("bind_NtfCb");
+
+#ifdef DEBUG_ACTIVE_RB
+	printf("bind_NtfCb - xmlResponse = ");
+	const char * temp = xmlResponse.c_str();
+	for (ushort i=0; i < strlen(temp);i++)
+	printf("%c",temp[i]);
+	printf("\r\n");
+#endif
+	L_DEBUG("bind_NtfCb - fResult = %d", rpcReqStatus->getFResult());
+	restEvent("bind_NtfCb", &listeners.bind, NULL, NULL, rpcReqStatus);
+	// The notification has been sent -> remove uri listener
+	L_INFO("bind_NtfCb - event -> remove uriListeners");
+	listeners.bind.running = false;
+	listeners.bind.removeListeners();
+}
+
+void RESTBroker::lsUnbind_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (RESTException, HTTPException) {
+	std::string modeValue, *uri;
+	RBURIListenerList *rlist;
+
+	L_DEBUG("lsUnbind_Req");
+
+	switch (reqMethod) {
+	case M_POST: {
+		unsigned long int timeout = 0;
+		if (!(ctxt->cbinfo.timeoutSet)) {
+			L_WARN("lsUnbind_Req - timeout parameter missing!");
+			// Fire RESTException since timeout parameter must be present
+			throw RESTException(WRONG_REQUEST, "Missing timeout parameter");
+		} else {
+			timeout = ctxt->cbinfo.timeout;
+			L_DEBUG("lsUnbind_Req - timeout parameter 0x%x (%lu ms)", timeout,
+					timeout);
+		}
+
+		if (ctxt->asynch()) {
+			L_INFO("lsUnbind_Req - UnbindRequest (non-blocking procedure)");
+
+			uri = &ctxt->callbackDestination;
+			if (uri->length() == 0) {
+				L_WARN("lsUnbind_Req - callback destination not present");
+				throw RESTException(WRONG_REQUEST,
+						"Missing callbackDestination parameter");
+			}
+			rlist = &listeners.unbind;
+			if (!rlist->addListener(uri, ctxt->getSessionId(),
+					new RESTCallbackInfo(ctxt->cbinfo))) {
+				restResponse("lsUnbind_Req", ctxt->getSessionId(), NULL,
+						URILISTENER_LIST_MAX_SIZE_EXCEEDED);
+			}
+			// Otherwise the response will be sent back by the attach handler (i.e. )
+		} else {
+			ZB_BIND_STRUCT bindParams;
+			L_INFO("lsUnbind_Req - UnbindRequest (blocking procedure)");
+
+			ServiceAgent<RESTBroker>::UnbindCtxt rpcContext(
+					ctxt->getSessionId(), this,
+					(ServiceAgent<RESTBroker>::unbindResponseCb) &RESTBroker::unbind_RspCb,
+					NULL);
+
+			if (pXMLMsgParser->getBindindCommand(&bindParams, xmlMsg))
+				throw RESTException(WRONG_REQUEST,
+						"Message not sent: Error parsing XML message");
+			pSAgent->unbindRequest(timeout, bindParams, &rpcContext);
+		}
+	}
+		break;
+
+	default:
+		badMethod(res, ctxt);
+		break;
+	}
+}
+
+void RESTBroker::unbind_RspCb(int sessionId, RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+	//const char *detail;
+	//int returnValue;
+
+	L_DEBUG("unbind_RspCb");
+
+	if (sessionId == LOCAL_REST_REQUEST_SESSION_ID) {
+		L_DEBUG("unbind_RspCb - It was a local REST request "
+				"(no HTTP request triggered the method invocation)");
+		return;
+	}
+	if (rpcReqStatus->isReqAsynch()) {
+		restResponse("unbind_RspCb", sessionId, NULL, NULL, rpcReqStatus);
+	} else {
+		//returnValue = rpcReqStatus->getReturnValue();
+		// Update REST Session status and set XML Response
+		restResponse("unbind_RspCb", sessionId, NULL, NULL, rpcReqStatus);
+	}
+}
+
+void RESTBroker::unbind_NtfCb(RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+	//const char *detail;
+	//int returnValue;
+
+	L_DEBUG("unbind_NtfCb");
+
+	//returnValue = rpcReqStatus->getReturnValue();
+#ifdef DEBUG_ACTIVE_RB
+	printf("unbind_NtfCb - xmlResponse = ");
+	const char * temp = xmlResponse.c_str();
+	for (ushort i=0; i < strlen(temp);i++)
+	printf("%c",temp[i]);
+	printf("\r\n");
+#endif
+	L_DEBUG("unbind_NtfCb - fResult = %d", rpcReqStatus->getFResult());
+	restEvent("unbind_NtfCb", &listeners.unbind, NULL, NULL, rpcReqStatus);
+	// The notification has been sent -> remove uri listener
+	L_INFO("unbind_NtfCb - event -> remove uriListeners");
+	listeners.unbind.running = false;
+	listeners.unbind.removeListeners();
+}
+
+/**
+ Public method RESTBroker nodedescriptor_Req
+ This method allows retrieving the Node Descriptor for a specific ZigBee node.
+ In particular, the DiscoveryAgent::getNodeDescriptor method is invoked (refer to Discovery Agent).
+
+ @param reqUri reqUri.
+ @param reqMethod HTTP request method.
+ @param queryString Query string.
+ @param sessionId REST session identifier value.
+ @return Void.
+ */
+
+void RESTBroker::nodeDescriptor_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (RESTException, HTTPException) {
+	std::string modeValue, *uri;
+	RBURIListenerList *rlist;
+
+	//L_DEBUG("nodedescriptor_Req");
+
+	if (reqMethod != M_GET)
+		badMethod(res, ctxt);
+
+	// Check whether "timeout" parameter is present in the request
+	unsigned long int timeout = 0;
+	//L_DEBUG ("nodedescriptor_Req - timeoutSet = %d", ctxt->cbinfo.timeoutSet);
+
+	if (!(ctxt->cbinfo.timeoutSet)) {
+		L_WARN("nodedescriptor_Req - timeout parameter missing!");
+		// Fire RESTException since timeout parameter must be present
+		throw RESTException(WRONG_REQUEST, "Missing timeout parameter");
+	} else {
+		timeout = ctxt->cbinfo.timeout;
+		L_DEBUG("nodedescriptor_Req - timeout parameter 0x%x (%lu ms)", timeout,
+				timeout);
+	}
+
+	if (ctxt->asynch()) {
+		L_INFO(
+				"nodedescriptor_Req - getNodeDescriptor (non-blocking procedure)");
+
+		uri = &ctxt->callbackDestination;
+		if (uri->length() == 0) {
+			L_WARN("nodedescriptor_Req - callback destination not present");
+			throw RESTException(WRONG_REQUEST,
+					"Missing callbackDestination parameter");
+		}
+
+		rlist = &listeners.nodeDescriptor;
+
+		if (!rlist->addListener(uri, ctxt->getSessionId(),
+				new RESTCallbackInfo(ctxt->cbinfo))) {
+			restResponse("nodedescriptor_Req", ctxt->getSessionId(), NULL,
+					URILISTENER_LIST_MAX_SIZE_EXCEEDED);
+		}
+		// Otherwise the response will be sent back by the attach handler (i.e. )
+	} else {
+		Resource *r;
+		ushort nwk;
+
+		L_INFO("nodedescriptor_Req - getNodeDescriptor (blocking procedure)");
+
+		DiscoveryAgent<RESTBroker>::NodeDescriptorCtxt rpcContext(
+				ctxt->getSessionId(), this,
+				(DiscoveryAgent<RESTBroker>::nodeDescriptorResponseCb) &RESTBroker::nodeDescriptor_RspCb,
+				NULL);
+
+		r = res->parent;
+		nwk = r->data.d;
+
+		// Call DiscoveryAgent::getNodeDescriptor <<
+		pDAgent->getNodeDescriptor(timeout, nwk, &rpcContext);
+	}
+}
+
+/**
+ Protected method RESTBroker nodeDescriptor_RspCb
+ This method relates to DiscoveryAgent::getNodeDescriptor_Cb response.
+
+ @param nwk_addr Node short address.
+ @param ieee_addr Node full address.
+ @param nodeDesc Node descriptor.
+ @param rpcContext RPC context.
+ @param rpcReqStatus Returned RPC request status.
+ @return Void.
+ */
+
+void RESTBroker::nodeDescriptor_RspCb(ushort nwk_addr, uchar *ieee_addr,
+		NodeDescriptor *nodeDesc, int sessionId, RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+	const char *detail;
+	int returnValue;
+
+	L_DEBUG("nodeDescriptor_RspCb");
+
+	if (sessionId == LOCAL_REST_REQUEST_SESSION_ID) {
+		L_DEBUG("sServiceDescriptor_RspCb - It was a local REST request "
+				"(no HTTP request triggered the method invocation)");
+		return;
+	}
+
+	if (rpcReqStatus->isReqAsynch()) {
+		restResponse("nodeDescriptor_RspCb", sessionId, NULL, NULL,
+				rpcReqStatus);
+	} else {
+		returnValue = rpcReqStatus->getReturnValue();
+
+		// Create XML Response
+		if (returnValue == AGENT_SUCCESS) {
+			xmlResponse = pXMLMsgComposer->createNodeDescMsg(
+					rpcReqStatus->getFResult(), *nodeDesc);
+			detail = xmlResponse.c_str();
+		} else
+			detail = NULL;
+
+		// Update REST Session status and set XML Response
+		restResponse("nodeDescriptor_RspCb", sessionId, detail, NULL,
+				rpcReqStatus);
+
+	}
+
+}
+
+void RESTBroker::nodeDescriptor_NtfCb(Node *node, RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+	const char *detail;
+	int returnValue;
+
+	L_DEBUG("nodeDescriptor_NtfCb");
+
+	returnValue = rpcReqStatus->getReturnValue();
+
+	if (returnValue == AGENT_SUCCESS) {
+		xmlResponse = pXMLMsgComposer->createNodeDescMsg(
+				rpcReqStatus->getFResult(), node->node_desc);
+		detail = xmlResponse.c_str();
+	} else
+		detail = NULL;
+
+#ifdef DEBUG_ACTIVE_RB
+	printf("nodeDescriptor_NtfCb - xmlResponse = ");
+	const char * temp = xmlResponse.c_str();
+	for (ushort i=0; i < strlen(temp);i++)
+	printf("%c",temp[i]);
+	printf("\r\n");
+#endif
+
+	L_DEBUG("nodeDescriptor_NtfCb - fResult = %d", rpcReqStatus->getFResult());
+
+	restEvent("nodeDescriptor_NtfCb", &listeners.nodeDescriptor, detail, NULL,
+			rpcReqStatus);
+
+	// The notification has been sent -> remove uri listener
+	L_INFO("nodeDescriptor_NtfCb - event -> remove uriListeners");
+	listeners.nodeDescriptor.running = false;
+	listeners.nodeDescriptor.removeListeners();
+}
+
+void RESTBroker::frequencyAgility_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (RESTException, HTTPException) {
+	unsigned long int scanChannel = 0x07FFF800; // All channels (default value)
+	unsigned int scanDuration = 0xFE; // 254 sec (special meaning that force to swap channel)
+	bool isPresent;
+	std::string stringValue;
+
+	if (reqMethod != M_GET)
+		badMethod(res, ctxt);
+	unsigned long int timeout = 0;
+
+	if (!(ctxt->cbinfo.timeoutSet)) {
+		L_WARN("frequencyAgility_Req - timeout parameter missing!");
+		throw RESTException(WRONG_REQUEST, "Missing timeout parameter");
+	} else {
+		timeout = ctxt->cbinfo.timeout;
+		L_DEBUG("frequencyAgility_Req - timeout parameter 0x%x (%lu ms)",
+				timeout, timeout);
+	}
+	//Get the scanDuration value (if present)
+	isPresent = pQueryParser->getParameter("scanDuration", queryString,
+			stringValue);
+	if (isPresent)
+		scanDuration = atoi(stringValue.c_str());
+	L_DEBUG("frequencyAgility_Req - scanDuration value = 0x%02x", scanDuration);
+	//Get the scanChannel value (if present)
+	isPresent = pQueryParser->getParameter("scanChannel", queryString,
+			stringValue);
+	if (isPresent) {
+		int decimalValue = atoi(stringValue.c_str());
+		if (decimalValue == 0) {
+			// All/any channel
+			scanChannel = 0x07FFF800;
+		} else if (decimalValue >= 11 && decimalValue <= 26) {
+			// Shift the bit 1 by "n" positions!
+			scanChannel = 1 << decimalValue;
+		} else {
+			pLogger->error("frequencyAgility_Req - INVALID scanChannel: %d",decimalValue);
+			return;
+		}
+		L_DEBUG("frequencyAgility_Req - scanChannel value = %d", decimalValue);
+		/*
+		 switch (decimalValue) {
+		 case 26:
+		 scanChannel = 0x04000000;
+		 break;
+		 case 25:
+		 scanChannel = 0x02000000;
+		 break;
+		 case 24:
+		 scanChannel = 0x01000000;
+		 break;
+		 case 23:
+		 scanChannel = 0x00800000;
+		 break;
+		 case 22:
+		 scanChannel = 0x00400000;
+		 break;
+		 case 21:
+		 scanChannel = 0x00200000;
+		 break;
+		 case 20:
+		 scanChannel = 0x00100000;
+		 break;
+		 case 19:
+		 scanChannel = 0x00080000;
+		 break;
+		 case 18:
+		 scanChannel = 0x00040000;
+		 break;
+		 case 17:
+		 scanChannel = 0x00020000;
+		 break;
+		 case 16:
+		 scanChannel = 0x00010000;
+		 break;
+		 case 15:
+		 scanChannel = 0x00008000;
+		 break;
+		 case 14:
+		 scanChannel = 0x00004000;
+		 break;
+		 case 13:
+		 scanChannel = 0x00002000;
+		 break;
+		 case 12:
+		 scanChannel = 0x00001000;
+		 break;
+		 case 11:
+		 scanChannel = 0x00000800;
+		 break;
+		 case 0:
+		 // All/any channel
+		 scanChannel = 0x07FFF800;
+		 break;
+		 default:
+		 pLogger->error("frequencyAgility_Req - INVALID scanChannel: %d",decimalValue);
+		 return;
+		 }
+		 L_DEBUG("frequencyAgility_Req - scanChannel value = %d",decimalValue);
+		 */
+	}
+	if (ctxt->asynch()) {
+		L_INFO(
+				"frequencyAgility_Req - ERROR: non-blocking procedure not implemented!");
+		restResponse("frequencyAgility_Req", ctxt->getSessionId(), NULL,
+				WRONG_REQUEST);
+	} else {
+		L_INFO("frequencyAgility_Req - blocking procedure");
+		//pLocalNode->runFrequencyAgility();
+		pGalZb->ZDP_MGMT_NWK_UPDATE_request(scanChannel, scanDuration);
+		restResponse("frequencyAgility_Req", ctxt->getSessionId(), NULL,
+				NO_ERROR);
+	}
+}
+
+/**
+ Public method RESTBroker ndPowerDescriptor_Req
+ This method allows retrieving the Power Descriptor for a specific ZigBee node.
+ In particular, the DiscoveryAgent::getPowerDescriptor method is invoked (refer to Discovery Agent).
+
+ @param reqUri reqUri.
+ @param reqMethod HTTP request method.
+ @param queryString Query string.
+ @param sessionId REST session identifier value.
+ @return Void.
+ */
+
+void RESTBroker::ndPowerDescriptor_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (HTTPException) {
+	DiscoveryAgent<RESTBroker>::PowerDescriptorCtxt rpcContext(
+			ctxt->getSessionId(), this,
+			(DiscoveryAgent<RESTBroker>::powerDescriptorResponseCb) &RESTBroker::ndPowerDescriptor_RspCb,
+			NULL);
+	Resource *r;
+	ushort nwk;
+
+	L_DEBUG("ndPowerDescriptor_Req");
+
+	if (reqMethod != M_GET)
+		badMethod(res, ctxt);
+
+	r = res->parent;
+	nwk = r->data.d;
+
+	pDAgent->getPowerDescriptor(nwk, &rpcContext);
+}
+
+/// This function is responsible to delete all the REST and ZbNetDb resources
+/// related to a specific node that just left the network
+void RESTBroker::leaveCommandDeleteResources(ushort nwk) {
+	char bufShortAddr[5];
+	char bufIeeeAddr[17];
+	Resource *r, *rTmp;
+	Node * node;
+	std::stringstream ieee;
+
+	// 1. Start from the REST Resource...
+	pGalZb = GalZbIf::Instance();
+	pGalDb = pGalZb->getDb();
+	node = pGalDb->findNodeByNwkAddr(nwk);
+	if (node == NULL) {
+		L_DEBUG("leaveCommandDeleteResources - node not found - %04x", nwk);
+		return;
+	}
+	// Convert the Short Address
+	sprintf(bufShortAddr, "%04x", nwk);
+	// Convert/get IEEE Address
+	ieee << hex;
+	for (int i = 0; i < 8; i++) {
+		ieee.width(2);
+		ieee.fill('0');
+		ieee << (unsigned int) node->get_ieee_addr()[i];
+	}
+	L_DEBUG("leaveCommandDeleteResources - Removing node %s, IEEE address %s",
+			bufShortAddr, ieee.str().c_str());
+	sprintf(bufIeeeAddr, "%s", ieee.str().c_str());
+
+	rTmp = pRESTServer->findResource(resources.defNet, "wsnnodes");
+	r = pRESTServer->findResource(rTmp, bufIeeeAddr);
+	if (r != NULL) {
+#ifdef DEBUG_ACTIVE_RB
+		if (this->debugEnabled)
+		L_DEBUG("leaveCommandDeleteResources - deleting IEEE address");
+#endif
+		pRESTServer->removeResource(r);
+	}
+	//Remove REST resource related to previous short address
+	r = pRESTServer->findResource(rTmp, bufShortAddr);
+	if (r != NULL) {
+#ifdef DEBUG_ACTIVE_RB
+		if (this->debugEnabled)
+		L_DEBUG ("leaveCommandDeleteResources - deleting short address");
+#endif
+		pRESTServer->removeResource(r);
+	}
+
+	// 2. Concluding by deleting all the resources present in the ZbNetDb...
+	node = pGalDb->findNodeByNwkAddr(nwk);
+	if (node != NULL) {
+#ifdef DEBUG_ACTIVE_RB
+		if (this->debugEnabled)
+		L_DEBUG ("leaveCommandDeleteResources - remove entried related to the ZbNetDb");
+#endif
+		node->setKANodeTimer((long) (0xFFFFFFFF));
+		node->setnumOfPingsDone(0);
+		pGalDb->removeTranslationEntry(nwk);
+		pGalDb->removeNodeByNwkAddr(nwk);
+	}
+}
+
+void RESTBroker::ndRoot_Req(Resource *res, const char *reqUri, Method reqMethod,
+		const char *queryString, std::string *xmlMsg, RESTSessionContext *ctxt)
+				throw (HTTPException) {
+	int timeout, reqUriLength;
+	char destAddr[5] = "0000";
+	unsigned txTime;
+	uchar status;
+	std::string urilistener, stringValue, s;
+	Message msgToWSN;
+
+	L_INFO("ndRoot_Req - INVOKED");
+
+	switch (reqMethod) {
+
+	case M_GET: {
+		L_INFO("ndRoot_Req - defaultHandler invoked");
+		pRESTServer->defaultHandler(res, reqUri, reqMethod, queryString, xmlMsg,
+				ctxt);
+	}
+		break;
+
+	case M_POST: {
+		// Extract the "timeout" parameter
+		pQueryParser->getParameter("timeout", queryString, stringValue);
+		if (stringValue.length() == 0) {
+			L_DEBUG("ndRoot_Req - timeout parameter missing");
+			// This an error since a value for timeout must be present
+			throw RESTException(PARAMETER_MISSING, "Missing timeout parameter"); //It was WRONG_REQUEST
+		} else {
+			timeout = atoi(stringValue.c_str());
+			L_DEBUG("ndRoot_Req - timeout parameter %x", timeout);
+		}
+		// Extract the "callbackDestination" parameter
+		pQueryParser->getParameter("urilistener", queryString, stringValue);
+		if (stringValue.length() == 0) {
+			L_DEBUG(
+					"ndRoot_Req - callbackDestination(urilistener) parameter missing");
+			// This is not an error since the parameter is optional
+		} else {
+			urilistener = stringValue;
+			L_DEBUG("ndRoot_Req - callbackDestination parameter %s",
+					urilistener.c_str());
+		}
+		try {
+			// Get the Destination address (unsigned16bit): Extract it from reqUri= /net/wsnnodes/XXXX
+			reqUriLength = 0;
+			while (reqUri[reqUriLength] != '\0')
+				reqUriLength++;
+			destAddr[0] = reqUri[reqUriLength - 4];
+			destAddr[1] = reqUri[reqUriLength - 3];
+			destAddr[2] = reqUri[reqUriLength - 2];
+			destAddr[3] = reqUri[reqUriLength - 1];
+			destAddr[4] = '\0';
+
+			L_DEBUG("ndRoot_Req - ReqURI %s, length %d", reqUri, reqUriLength);
+			L_DEBUG("ndRoot_Req - attributeID %s", destAddr);
+			L_DEBUG("ndRoot_Req - attribute converted %4x",
+					strtoul(destAddr, NULL, 16)); //16 is the base (hex)
+		} catch (RESTException &e) {
+			// This an error since a value for timeout must be present
+			throw RESTException(WRONG_REQUEST,
+					"Bad formatted destination address");
+		}
+		// Get all the elements of 'ZDPCommand' xml...
+		if (pXMLMsgParser->getZDPCommandToWSN(&msgToWSN, xmlMsg))
+			throw RESTException(WRONG_REQUEST,
+					"Message not sent: Error parsing XML message");
+		// We arrive here if we have a valid XMLMessage extracted, so send the ZigBee message!
+		if (pSAgent->send(&msgToWSN, status, txTime))
+			throw RESTException(GENERIC_REST_ERROR,
+					"Message not sent: Error sending ZDPCommand");
+		pGalZb = GalZbIf::Instance();
+		pGalDb = pGalZb->getDb();
+		//Set source address
+		uchar tmpShortAddrr[2];
+		tmpShortAddrr[0] = LSB_USHORT(pGalDb->root->get_nwk_addr());
+		tmpShortAddrr[1] = MSB_USHORT(pGalDb->root->get_nwk_addr());
+		msgToWSN.setSrcAddrMode(0x02);
+		msgToWSN.setSrcAddr(tmpShortAddrr);
+		s = pXMLMsgComposer->createZDPMessage(status, txTime, &msgToWSN);
+		restResponse("lsMessage_RspCb", ctxt->getSessionId(), s.c_str(),
+				NO_ERROR);
+		break;
+	}
+		break;
+
+	case M_DELETE: {
+		std::string *uri;
+		RBURIListenerList *rlist;
+
+		if (ctxt->asynch()) {
+			L_INFO("ndLeave_Req - asynch call");
+
+			uri = &ctxt->callbackDestination;
+			if (uri->length() == 0) {
+				L_WARN("ndLeave_Req - callback destination not present");
+				throw RESTException(WRONG_REQUEST,
+						"Missing callbackDestination parameter");
+			}
+			rlist = &listeners.leaveCommand;
+
+			if (!rlist->addListener(uri, ctxt->getSessionId(),
+					new RESTCallbackInfo(ctxt->cbinfo))) {
+				restResponse("ndLeave_Req", ctxt->getSessionId(), NULL,
+						URILISTENER_LIST_MAX_SIZE_EXCEEDED);
+			}
+			// Otherwise the response will be sent back by the attach handler (i.e. serviceDiscoveryAttach)
+		} else {
+			Resource *r;
+			ushort nwk;
+			int result;
+			std::map<ushort, Node *> nodes;
+			std::map<ushort, Node *>::const_iterator iter;
+			bool removeChildren = true;
+			bool rejoin = false;
+			bool isPresent;
+
+			// Ask to the selected resource to leave the network!
+			ManagementAgent<RESTBroker>::LeaveCommandCtxt rpcContext(
+					ctxt->getSessionId(), this,
+					(ManagementAgent<RESTBroker>::leaveResponseCb) &RESTBroker::ndLeaveCommand_RspCb,
+					NULL);
+
+			L_INFO("ndRoot - DELETE method invoked");
+			isPresent = pQueryParser->isParameterPresent("remove-children",
+					queryString);
+			if (isPresent == false) {
+				L_DEBUG("ndLeave_Req - queryString = %s "
+						"not containing remove-children parameter",
+						queryString);
+				// Let use a default value (as specification it must be false)
+				removeChildren = false;
+			} else {
+				removeChildren = true;
+			}
+			isPresent = pQueryParser->isParameterPresent("rejoin", queryString);
+			if (isPresent == false) {
+				L_DEBUG("ndLeave_Req - queryString = %s "
+						"not containing rejoin parameter", queryString);
+				// Let use a default value (as specification it must be false)
+				rejoin = false;
+			} else {
+				rejoin = true;
+			}
+			r = res;
+			nwk = r->data.d;
+			L_INFO("ndLeave_Req - NWK address %d", nwk);
+			result = pMngmtAgent->leaveRequest(nwk, removeChildren, rejoin,
+					&rpcContext);
+			if (result == AGENT_SUCCESS) {
+				// Command sent. Instead of wait for a confirm, we delete all the resources specific for the selected device now!
+				if (nwk == 0xffff || nwk == 0xfffc) {
+					r = pRESTServer->findResource(resources.defNet, "wsnnodes");
+					// Delete all the resources apart from the "wsnnodes" path! (otherwise use removeResources)
+					pRESTServer->clearResource(r);
+					// Delete all the information related to the ZbNetDb
+					pGalZb = GalZbIf::Instance();
+					pGalDb = pGalZb->getDb();
+					//Save the root node!
+					pGalDb->clearAllButRoot();
+					pDAgent->clearDeadingNodeList();
+				} else
+					//It is just one node!
+					leaveCommandDeleteResources(nwk);
+			}
+		}
+	}
+		break;
+
+	default:
+		L_DEBUG("ndRoot_Req - No action associated to this event");
+		return;
+	}
+
+}
+
+void RESTBroker::resetCommand_RspCb(int sessionId, RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+	const char *detail;
+	int returnValue;
+
+	L_DEBUG("resetCommand_RspCb");
+
+	returnValue = rpcReqStatus->getReturnValue();
+
+	// Create XML Response
+	if (returnValue == AGENT_SUCCESS) {
+		xmlResponse = pXMLMsgComposer->createGenericResponseMsg();
+		detail = xmlResponse.c_str();
+	} else
+		detail = NULL;
+
+	L_INFO("resetCommand_RspCb - xmlResponse = %s", xmlResponse.c_str());
+	L_DEBUG("resetCommand_RspCb - fResult = %d", rpcReqStatus->getFResult());
+
+	// Update REST Session status and set XML Response
+	restResponse("resetCommand_RspCb", sessionId, detail, NULL, rpcReqStatus);
+}
+
+void RESTBroker::resetCommand_NtfCb(uchar status, RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+	const char *detail;
+	int returnValue;
+
+	L_DEBUG("resetCommand_NtfCb");
+	returnValue = rpcReqStatus->getReturnValue();
+	// Create XML Response
+	if (returnValue == AGENT_SUCCESS) {
+		detail = NULL;
+		/*
+		 std::string xmlNotification = pXMLMsgComposer->createGenericResponseMsg();
+		 detail = xmlNotification.c_str ();
+		 L_DEBUG("resetCommand_NtfCb - xmlNotification = %s", detail);
+		 */
+	} else
+		detail = NULL;
+	//L_INFO("resetCommand_NtfCb - xmlResponse = %s", xmlResponse.c_str());
+	//L_DEBUG("resetCommand_NtfCb - fResult = %d", rpcReqStatus->getFResult());
+
+	// Update REST Session status and set XML Response
+	restEvent("resetCommand_NtfCb", &listeners.resetCommand, detail, NULL,
+			rpcReqStatus);
+
+	// The notification has been sent -> remove uri listener
+	L_INFO("resetCommand_NtfCb -> remove uriListeners");
+	listeners.resetCommand.running = false;
+	listeners.resetCommand.removeListeners();
+}
+
+void RESTBroker::ndLeaveCommand_RspCb(int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+	const char *detail;
+	int returnValue;
+
+	L_DEBUG("ndLeaveCommand_RspCb");
+
+	returnValue = rpcReqStatus->getReturnValue();
+
+	// Create XML Response
+	if (returnValue == AGENT_SUCCESS) {
+		//xmlResponse = pXMLMsgComposer->createGenericResponseMsg();
+		//detail = xmlResponse.c_str ();
+		detail = NULL;
+	} else
+		detail = NULL;
+
+	L_INFO("ndLeaveCommand_RspCb - xmlResponse = %s", xmlResponse.c_str());
+	L_DEBUG("ndLeaveCommand_RspCb - fResult = %d", rpcReqStatus->getFResult());
+
+	// Update REST Session status and set XML Response
+	restResponse("nddLeaveRequest_RspCb", sessionId, detail, NULL,
+			rpcReqStatus);
+}
+
+void RESTBroker::ndLeaveCommand_NtfCb(uchar status, int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+	const char *detail;
+	int returnValue;
+
+	L_DEBUG("ndLeaveCommand_NtfCb");
+
+	returnValue = rpcReqStatus->getReturnValue();
+
+	// Create XML Response
+	if (returnValue == AGENT_SUCCESS) {
+		//xmlResponse = pXMLMsgComposer->createGenericResponseMsg();
+		//detail = xmlResponse.c_str ();
+		detail = NULL;
+	} else
+		detail = NULL;
+
+	L_INFO("ndLeaveCommand_NtfCb - xmlResponse = %s", xmlResponse.c_str());
+	L_DEBUG("ndLeaveCommand_NtfCb - fResult = %d", rpcReqStatus->getFResult());
+
+	// Update REST Session status and set XML Response
+	restEvent("ndLeaveCommand_NtfCb", &listeners.leaveCommand, detail, NULL,
+			rpcReqStatus);
+
+	// The notification has been sent -> remove uri listener
+	L_INFO("ndLeaveCommand_NtfCb -> remove uriListeners");
+	listeners.leaveCommand.running = false;
+	listeners.leaveCommand.removeListeners();
+}
+
+void RESTBroker::ndPermitJoin_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (RESTException, HTTPException) {
+	std::string modeValue;
+	int PermitDuration;
+	bool TCSignificance;
+	std::string *uri;
+	RBURIListenerList *rlist;
+
+	if (reqMethod != M_POST)
+		badMethod(res, ctxt);
+
+	// Check whether "timeout" parameter is present in the request
+	unsigned long int timeout = 0;
+	L_DEBUG("ndPermitJoin_Req - timeoutSet = %d", ctxt->cbinfo.timeoutSet);
+
+	if (!(ctxt->cbinfo.timeoutSet)) {
+		L_WARN("ndPermitJoin_Req - timeout parameter missing");
+		// Fire RESTException since timeout parameter must be present
+		throw RESTException(WRONG_REQUEST, "Missing timeout parameter");
+	} else {
+		timeout = ctxt->cbinfo.timeout;
+		L_DEBUG("ndPermitJoin_Req - timeout parameter 0x%02x (%lu) ms", timeout,
+				timeout);
+	}
+
+	if (ctxt->asynch()) {
+		L_INFO("ndPermitJoin_Req - asynch call");
+
+		uri = &ctxt->callbackDestination;
+		if (uri->length() == 0) {
+			L_WARN("ndPermitJoin_Req - callback destination not present");
+			throw RESTException(WRONG_REQUEST,
+					"Missing callbackDestination parameter");
+		}
+		rlist = &listeners.permitJoin;
+
+		if (!rlist->addListener(uri, ctxt->getSessionId(),
+				new RESTCallbackInfo(ctxt->cbinfo))) {
+			restResponse("ndPermitJoin_Req", ctxt->getSessionId(), NULL,
+					URILISTENER_LIST_MAX_SIZE_EXCEEDED);
+		}
+		// Otherwise the response will be sent back by the attach handler (i.e. serviceDiscoveryAttach)
+	} else {
+		Resource *r;
+		ushort nwk;
+		ManagementAgent<RESTBroker>::permitJoinCtxt rpcContext(
+				ctxt->getSessionId(), this,
+				(ManagementAgent<RESTBroker>::permitJoinResponseCb) &RESTBroker::ndPermitJoin_RspCb,
+				NULL);
+
+		L_DEBUG("ndPermitJoin_Req - direct call");
+
+		//Get from input the XML message
+		if (pXMLMsgParser->getJoiningInfoValues(&PermitDuration,
+				&TCSignificance, xmlMsg) == 1) {
+			//An error occurs when extracting input from XML message
+			throw RESTException(BAD_PARAMETER, "Wrong JoiningInfo values");
+		}
+
+		try {
+			r = res->parent;
+			nwk = r->data.d;
+
+			L_DEBUG("wsnNodesList_Req - nwk addr %d (dec) - %x (hex)", nwk,
+					nwk);
+
+		} catch (RESTException &e) {
+			// This an error since a value for the destAddr must be present
+			throw RESTException(WRONG_REQUEST,
+					"Bad formatted destination address");
+		}
+		pMngmtAgent->permitJoin(nwk, PermitDuration, TCSignificance, timeout,
+				&rpcContext);
+	}
+}
+
+void RESTBroker::ndPermitJoin_RspCb(uchar status, int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+	const char *detail;
+	int returnValue;
+
+	L_DEBUG("ndPermitJoin_RspCb");
+
+	detail = NULL;
+	returnValue = rpcReqStatus->getReturnValue();
+
+	if (rpcReqStatus->isReqAsynch()) {
+		if (returnValue == AGENT_SUCCESS) {
+			L_DEBUG(
+					"ndPermitJoin_RspCb - asynch Request - notification will be sent later");
+		} else {
+			// Asynch request - an error occurred -> remove listeners
+			L_INFO(
+					"ndPermitJoin_ResponseCb -> permitjoin request failed -> return error response");
+			listeners.permitJoin.running = false;
+			listeners.permitJoin.removeListeners();
+		}
+
+		restResponse("ndPermitJoin_RspCb", sessionId, detail, NULL,
+				rpcReqStatus);
+	} else {
+		// Create XML Response
+		if (returnValue == AGENT_SUCCESS) {
+			detail = NULL;
+			L_INFO("ndPermitJoin_RspCb - AGENT_SUCCESS");
+		} else {
+			detail = NULL;
+			L_INFO("ndPermitJoin_RspCb - NOT SUCCESS!!");
+		}
+
+		restResponse("ndPermitJoin_RspCb", sessionId, detail, NULL,
+				rpcReqStatus);
+
+		L_INFO("ndPermitJoin_RspCb - xmlResponse = %s", xmlResponse.c_str());
+		L_DEBUG("ndPermitJoin_RspCb - fResult = %d",
+				rpcReqStatus->getFResult());
+	}
+}
+
+void RESTBroker::ndPermitJoin_NtfCb(uchar status, RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+	const char *detail;
+	int returnValue;
+
+	L_DEBUG("ndPermitJoin_ResponseCb");
+
+	returnValue = rpcReqStatus->getReturnValue();
+
+	// Create XML Response
+	if (returnValue == AGENT_SUCCESS) {
+		//xmlResponse = pXMLMsgComposer->createGenericResponseMsg();
+		//detail = xmlResponse.c_str ();
+		detail = NULL;
+	} else
+		detail = NULL;
+
+	L_INFO("ndPermitJoin_ResponseCb - xmlResponse = %s", xmlResponse.c_str());
+	L_DEBUG("ndPermitJoin_ResponseCb - fResult = %d",
+			rpcReqStatus->getFResult());
+
+	// Update REST Session status and set XML Response
+	restEvent("ndPermitJoin_ResponseCb", &listeners.permitJoin, detail, NULL,
+			rpcReqStatus);
+
+	// The notification has been sent -> remove uri listener
+	L_INFO("ndPermitJoin_ResponseCb -> remove uriListeners");
+	listeners.permitJoin.running = false;
+	listeners.permitJoin.removeListeners();
+}
+
+void RESTBroker::ndLQIInformation_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (RESTException, HTTPException) {
+	std::string xmlResponse;
+	const char *detail;
+
+	L_DEBUG("ndLQIInformation_Req");
+	xmlResponse = pXMLMsgComposer->createLQIInformationMsg(pGalDb);
+	detail = xmlResponse.c_str();
+	//L_INFO("ndLQIInformation_Req - xmlResponse = %s", detail);
+	restResponse("ndLQIInformation_Req", ctxt->getSessionId(), detail, NULL,
+			NULL);
+}
+
+/**
+ Protected method RESTBroker ndPowerDescriptor_RspCb
+ This method relates to DiscoveryAgent::getPowerDescriptor_Cb response.
+
+ @param nwk_addr Node short address.
+ @param ieee_addr Node full address.
+ @param powerDesc Power descriptor.
+ @param rpcContext RPC context.
+ @param rpcReqStatus Returned RPC request status.
+ @return Void.
+ */
+
+void RESTBroker::ndPowerDescriptor_RspCb(ushort nwk_addr, uchar *ieee_addr,
+		PowerDescriptor *powerDesc, int sessionId, RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+	const char *detail;
+	int returnValue;
+
+	L_DEBUG("ndPowerDescriptor_RspCb");
+
+	returnValue = rpcReqStatus->getReturnValue();
+
+	// Create XML Response
+	if (returnValue == AGENT_SUCCESS) {
+		xmlResponse = pXMLMsgComposer->createPowerDescMsg(
+				rpcReqStatus->getFResult(), nwk_addr, ieee_addr, *powerDesc);
+		detail = xmlResponse.c_str();
+	} else
+		detail = NULL;
+
+	L_INFO("ndPowerDescriptor_RspCb - xmlResponse = %s", xmlResponse.c_str());
+	L_DEBUG("ndPowerDescriptor_RspCb - fResult = %d",
+			rpcReqStatus->getFResult());
+
+	// Update REST Session status and set XML Response
+	restResponse("ndPowerDescriptor_RspCb", sessionId, detail, NULL,
+			rpcReqStatus);
+}
+
+/**
+ Public method RESTBroker ndServicesList_Req
+ This method allows retrieving the list of active services (i.e. endpoints) for a specific node.
+ In particular, the ServiceAgent::getActiveEndPoints method is invoked (refer to Service Agent).
+
+ @param reqUri reqUri.
+ @param reqMethod HTTP request method.
+ @param queryString Query string.
+ @param sessionId REST session identifier value.
+ @return Void.
+ */
+
+void RESTBroker::ndServicesList_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (RESTException, HTTPException) {
+	std::string modeValue, *uri;
+	RBURIListenerList *rlist;
+
+	// This procedure implements the REST procedure startServiceDiscovery
+	if (reqMethod != M_GET)
+		badMethod(res, ctxt);
+
+	// Check whether "timeout" parameter is present in the request
+	unsigned long int timeout = 0;
+	//L_DEBUG ("ndServicesList_Req - timeoutSet = %d", ctxt->cbinfo.timeoutSet);
+	if (!(ctxt->cbinfo.timeoutSet)) {
+		L_WARN("ndServicesList_Req - timeout parameter missing");
+		// Fire RESTException since timeout parameter must be present
+		throw RESTException(WRONG_REQUEST, "Missing timeout parameter");
+	} else {
+		timeout = ctxt->cbinfo.timeout;
+		L_DEBUG("ndServicesList_Req - timeout parameter 0x%x (%lu ms)", timeout,
+				timeout);
+	}
+
+	if (ctxt->asynch()) {
+		L_INFO(
+				"ndServicesList_Req - startServiceDiscovery/getActiveEndPoints (non-blocking procedure)");
+
+		uri = &ctxt->callbackDestination;
+		if (uri->length() == 0) {
+			L_WARN("ndServicesList_Req - callback destination not present");
+			throw RESTException(WRONG_REQUEST,
+					"Missing callbackDestination parameter");
+		}
+
+		rlist = &listeners.serviceDiscovery;
+
+		if (!rlist->addListener(uri, ctxt->getSessionId(),
+				new RESTCallbackInfo(ctxt->cbinfo))) {
+			restResponse("ndServicesList_Req", ctxt->getSessionId(), NULL,
+					URILISTENER_LIST_MAX_SIZE_EXCEEDED);
+		}
+		// Otherwise the response will be sent back by the attach handler (i.e. serviceDiscoveryAttach)
+	} else {
+		Resource *r;
+		ushort nwk;
+
+		L_INFO(
+				"ndServicesList_Req - startServiceDiscovery/getActiveEndPoints (blocking procedure)");
+
+		ServiceAgent<RESTBroker>::ActiveEndPointsCtxt rpcContext(
+				ctxt->getSessionId(), this,
+				(ServiceAgent<RESTBroker>::activeEndPointsResponseCb) &RESTBroker::ndServicesList_RspCb,
+				NULL);
+
+		r = res->parent;
+		nwk = r->data.d;
+
+		pSAgent->getActiveEndPoints(timeout, nwk, &rpcContext);
+	}
+
+}
+
+/**
+ Protected method RESTBroker ndServicesList_RspCb
+ This method relates to ServiceAgent::getActiveEndPoints_Cb response.
+
+ @param node Node taken into account.
+ @param rpcContext RPC context.
+ @param rpcReqStatus Returned RPC request status.
+ @return Void.
+ */
+
+void RESTBroker::ndServicesList_RspCb(Node *node, int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+	std::list<Resource *>::iterator i;
+	std::list<int>::iterator j;
+	std::list<int> endpoints;
+	std::string xmlResponse;
+	ResHandler hnd;
+	Resource *r, *epr;
+	const char *detail;
+	int returnValue;
+	char buf[3];
+
+	L_DEBUG("ndServicesList_RspCb");
+
+	returnValue = rpcReqStatus->getReturnValue();
+
+	// Dynamic REST resources Management
+	if (returnValue == AGENT_SUCCESS && node != NULL) {
+		// Remove SERVICES resource related to the specific node
+		r = pRESTServer->findResource(resources.defNet, "wsnnodes");
+
+		int counter = 0;
+		for (i = r->children.begin(); i != r->children.end(); i++) {
+			if ((*i)->data.d == node->get_nwk_addr()) {
+				counter++;
+				if (i != r->children.end()) {
+					r = pRESTServer->findResource(*i, "services");
+					hnd = &RESTBroker::sServiceDescriptor_Req;
+					pRESTServer->clearResource(r);
+					endpoints = node->getEndPointList();
+					for (j = endpoints.begin(); j != endpoints.end(); j++) {
+						sprintf(buf, "%02x", *j);
+						epr = createFolder(r, buf, hnd);
+						epr->data.d = *j;
+					}
+				}
+			}
+			if (counter == 2)
+				break;
+		}
+
+	}
+	if (sessionId == LOCAL_REST_REQUEST_SESSION_ID) {
+		L_DEBUG("ndServicesList_RspCb - It was a local REST request "
+				"(no HTTP request triggered the method invocation)");
+		return;
+	}
+
+	if (rpcReqStatus->isReqAsynch()) {
+		restResponse("ndServicesList_RspCb", sessionId, NULL, NULL,
+				rpcReqStatus);
+	} else {
+		// Create XML Response
+		if (returnValue == AGENT_SUCCESS) {
+			xmlResponse = pXMLMsgComposer->createActiveEndPointMsg(
+					rpcReqStatus->getFResult(), node);
+			detail = xmlResponse.c_str();
+		} else
+			detail = NULL;
+
+		L_INFO("ndServicesList_RspCb - xmlResponse = %s", xmlResponse.c_str());
+		L_DEBUG("ndServicesList_RspCb - fResult = %d",
+				rpcReqStatus->getFResult());
+
+		// Update REST Session status and set XML Response
+		restResponse("ndServicesList_RspCb", sessionId, detail, NULL,
+				rpcReqStatus);
+
+	}
+}
+
+void RESTBroker::ndServicesList_NtfCb(Node *node, RPCReqStatus *rpcReqStatus) {
+	std::list<Resource *>::iterator i;
+	std::list<int>::iterator j;
+	std::list<int> endpoints;
+	std::string xmlResponse;
+	ResHandler hnd;
+	Resource *r, *epr;
+	const char *detail;
+	int returnValue;
+	char buf[3];
+
+	L_DEBUG("ndServicesList_NtfCb");
+
+	returnValue = rpcReqStatus->getReturnValue();
+
+	// Dynamic REST resources Management
+	if (returnValue == AGENT_SUCCESS && node != NULL) {
+		// Remove SERVICES resource related to the specific node
+		r = pRESTServer->findResource(resources.defNet, "wsnnodes");
+
+		int counter = 0;
+		for (i = r->children.begin(); i != r->children.end(); i++) {
+			if ((*i)->data.d == node->get_nwk_addr()) {
+				counter++;
+				if (i != r->children.end()) {
+					r = pRESTServer->findResource(*i, "services");
+					hnd = &RESTBroker::sServiceDescriptor_Req;
+					pRESTServer->clearResource(r);
+					endpoints = node->getEndPointList();
+					for (j = endpoints.begin(); j != endpoints.end(); j++) {
+						sprintf(buf, "%02x", *j);
+						epr = createFolder(r, buf, hnd);
+						epr->data.d = *j;
+					}
+				}
+			}
+			if (counter == 2)
+				break;
+		}
+
+	}
+
+	// Create XML Response
+	if (returnValue == AGENT_SUCCESS) {
+		xmlResponse = pXMLMsgComposer->createActiveEndPointMsg(
+				rpcReqStatus->getFResult(), node);
+		detail = xmlResponse.c_str();
+	} else
+		detail = NULL;
+
+	L_INFO("ndServicesList_NtfCb - xmlResponse = %s", xmlResponse.c_str());
+	L_DEBUG("ndServicesList_NtfCb - fResult = %d", rpcReqStatus->getFResult());
+
+	// Update REST Session status and set XML Response
+	restEvent("ndServicesList_NtfCb", &listeners.serviceDiscovery, detail, NULL,
+			rpcReqStatus);
+
+	// The notification has been sent -> remove uri listener
+	L_INFO("ndServicesList_NtfCb - "
+			"ServiceDiscoveryEvent event -> remove uriListeners");
+	listeners.serviceDiscovery.running = false;
+	listeners.serviceDiscovery.removeListeners();
+}
+
+//***********************************************************************************************
+//***************************  SERVICES functions  ********************************************
+//***********************************************************************************************
+
+/**
+ Public method RESTBroker sServiceDescriptor_Req
+ This method allows retrieving the Service Descriptor for a specific node - service identifier (i.e. endpoint).
+ In particular, the ServiceAgent::getServiceDescriptor method is invoked (refer to Service Agent).
+
+ @param reqUri reqUri.
+ @param reqMethod HTTP request method.
+ @param queryString Query string.
+ @param sessionId REST session identifier value.
+ @return Void.
+ */
+
+void RESTBroker::sServiceDescriptor_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (RESTException, HTTPException) {
+	std::string modeValue, *uri;
+	RBURIListenerList *rlist;
+	//L_DEBUG("sServiceDescriptor_Req");
+	if (reqMethod != M_GET)
+		badMethod(res, ctxt);
+	// Check whether "timeout" parameter is present in the request
+	unsigned long int timeout = 0;
+	//L_DEBUG ("sServiceDescriptor_Req - timeoutSet = %d", ctxt->cbinfo.timeoutSet);
+	if (!(ctxt->cbinfo.timeoutSet)) {
+		L_WARN("sServiceDescriptor_Req - timeout parameter missing!");
+		// Fire RESTException since timeout parameter must be present
+		throw RESTException(WRONG_REQUEST, "Missing timeout parameter");
+	} else {
+		timeout = ctxt->cbinfo.timeout;
+		L_DEBUG("sServiceDescriptor_Req - timeout parameter 0x%x (%lu ms)",
+				timeout, timeout);
+	}
+	if (ctxt->asynch()) {
+		L_INFO(
+				"sServiceDescriptor_Req - getServiceDescriptor (non-blocking procedure)");
+		uri = &ctxt->callbackDestination;
+		if (uri->length() == 0) {
+			L_WARN("sServiceDescriptor_Req - callback destination not present");
+			throw RESTException(WRONG_REQUEST,
+					"Missing callbackDestination parameter");
+		}
+
+		rlist = &listeners.serviceDescriptor;
+
+		if (!rlist->addListener(uri, ctxt->getSessionId(),
+				new RESTCallbackInfo(ctxt->cbinfo))) {
+			restResponse("sServiceDescriptor_Req", ctxt->getSessionId(), NULL,
+					URILISTENER_LIST_MAX_SIZE_EXCEEDED);
+		}
+		// Otherwise the response will be sent back by the attach handler (i.e. )
+
+	} else {
+		Resource *r;
+		ushort nwk;
+
+		L_INFO(
+				"sServiceDescriptor_Req - getServiceDescriptor (blocking procedure)");
+
+		ServiceAgent<RESTBroker>::ServiceDescriptorCtxt rpcContext(
+				ctxt->getSessionId(), this,
+				(ServiceAgent<RESTBroker>::serviceDescriptorResponseCb) &RESTBroker::sServiceDescriptor_RspCb,
+				NULL);
+
+		r = res->parent->parent;
+		nwk = r->data.d;
+
+		pSAgent->getServiceDescriptor(timeout, nwk, res->data.d, &rpcContext);
+	}
+
+}
+
+/**
+ Protected method RESTBroker sServiceDescriptor_RspCb
+ This method relates to ServiceAgent::getServiceDescriptor_Cb response.
+
+ @param node Node taken into account.
+ @param endpoint Considered endpoint.
+ @param rpcContext RPC context.
+ @param rpcReqStatus Returned RPC request status.
+ @return Void.
+ */
+
+void RESTBroker::sServiceDescriptor_RspCb(Node *node, int endpoint,
+		int sessionId, RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+	const char *detail;
+	int returnValue;
+
+	L_DEBUG("sServiceDescriptor_RspCb");
+	if (sessionId == LOCAL_REST_REQUEST_SESSION_ID) {
+		L_DEBUG("sServiceDescriptor_RspCb - It was a local REST request "
+				"(no HTTP request triggered the method invocation)");
+		return;
+	}
+	if (rpcReqStatus->isReqAsynch()) {
+		restResponse("sServiceDescriptor_RspCb", sessionId, NULL, NULL,
+				rpcReqStatus);
+	} else {
+		returnValue = rpcReqStatus->getReturnValue();
+
+		if (returnValue == AGENT_SUCCESS) {
+			xmlResponse = pXMLMsgComposer->createServiceDescriptorMsg(
+					rpcReqStatus->getFResult(), node, endpoint);
+			detail = xmlResponse.c_str();
+		} else
+			detail = NULL;
+
+		L_INFO("sServiceDescriptor_RspCb - xmlResponse = %s",
+				xmlResponse.c_str());
+		L_DEBUG("sServiceDescriptor_RspCb - fResult = %d",
+				rpcReqStatus->getFResult());
+
+		restResponse("sServiceDescriptor_RspCb", sessionId, detail, NULL,
+				rpcReqStatus);
+	}
+
+}
+
+void RESTBroker::sServiceDescriptor_NtfCb(Node *node, int endpoint,
+		RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+	const char *detail;
+	int returnValue;
+
+	L_DEBUG("sServiceDescriptor_NtfCb");
+
+	returnValue = rpcReqStatus->getReturnValue();
+
+	if (returnValue == AGENT_SUCCESS) {
+		xmlResponse = pXMLMsgComposer->createServiceDescriptorMsg(
+				rpcReqStatus->getFResult(), node, endpoint);
+		detail = xmlResponse.c_str();
+	} else
+		detail = NULL;
+
+#ifdef DEBUG_ACTIVE_RB
+	printf("sServiceDescriptor_NtfCb - xmlResponse = ");
+	const char * temp = xmlResponse.c_str();
+	for (ushort i=0; i < strlen(temp);i++)
+	printf("%c",temp[i]);
+	printf("\r\n");
+#endif
+
+	L_DEBUG("sServiceDescriptor_NtfCb - fResult = %d",
+			rpcReqStatus->getFResult());
+
+	restEvent("sServiceDescriptor_NtfCb", &listeners.serviceDescriptor, detail,
+			NULL, rpcReqStatus);
+
+	// The notification has been sent -> remove uri listener
+	L_INFO("sServiceDescriptor_NtfCb - "
+			"serviceDescriptor event -> remove uriListeners");
+	listeners.serviceDescriptor.running = false;
+	listeners.serviceDescriptor.removeListeners();
+}
+
+//***********************************************************************************************
+//***************************  ALL_WSN_NODES functions  *****************************************
+//***********************************************************************************************
+
+/**
+ Public method RESTBroker awndAllDescriptors_Req
+ This method allows executing the macrofunction DA_SUPER_DISCOVERY defined in Discovery Agent.
+ In particular, the DiscoveryAgent::superDiscovery method is invoked (refer to Service Agent).
+
+ @param reqUri reqUri.
+ @param reqMethod HTTP request method.
+ @param queryString Query string.
+ @param sessionId REST session identifier value.
+ @return Void.
+ */
+
+void RESTBroker::awndServicesList_Req(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt) throw (HTTPException) {
+	std::string modeValue;
+	bool cache;
+	DiscoveryAgent<RESTBroker>::SuperDiscoveryCtxt rpcContext(
+			ctxt->getSessionId(), this,
+			(DiscoveryAgent<RESTBroker>::superDiscoveryResponseCb) &RESTBroker::awndServicesList_RspCb,
+			NULL);
+
+	L_DEBUG("awndServicesList_Req");
+
+	if (reqMethod != M_GET)
+		badMethod(res, ctxt);
+
+	// The first thing to do is to check if the "?mode=cache" is present or not!
+	pQueryParser->getParameter("mode", queryString, modeValue);
+	if (modeValue.length() == 0) {
+		L_DEBUG("awsnServicesList_Req - queryString = %s "
+				"not containing mode parameter: start discovery", queryString);
+		cache = false;
+	} else if (!modeValue.compare("cache")) {
+		L_DEBUG("wsnServicesList_Req - queryString = %s "
+				"with cache parameter: no discovery needed", queryString);
+		cache = true;
+	} else {
+		L_INFO("wsnServicesList_Req - queryString = %s "
+				"unknown mode: %s", queryString, modeValue.c_str());
+		throw RESTException(BAD_PARAMETER, "Bad mode parameter");
+	}
+
+	// If "?mode=cache" is present, then we're executing a ReadServiceCache Procedure
+	if (cache) {
+		DiscoveryAgent<RESTBroker>::RetrieveNodesCtxt dctxt(
+				ctxt->getSessionId(), this,
+				(DiscoveryAgent<RESTBroker>::retrieveNodesResponseCb) &RESTBroker::awndServicesList_cache_RspCb,
+				NULL);
+		// Call DiscoveryAgent::retrieveNodes <<
+		pDAgent->retrieveNodes(&dctxt);
+	} else {
+		// In this case we are executing a StartServiceDiscovery Procedure
+		pDAgent->superDiscovery(&rpcContext);
+	}
+}
+
+void RESTBroker::awndServicesList_cache_RspCb(ZbNetDb *dbNodes, int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+	std::string xmlResponse;
+	const char *detail;
+	int returnValue;
+
+	L_DEBUG("awndServicesList_cache_RspCb");
+
+	returnValue = rpcReqStatus->getReturnValue();
+
+	if (returnValue == AGENT_SUCCESS) {
+		xmlResponse = pXMLMsgComposer->createAllNodesServiceDescMsg(
+				rpcReqStatus->getFResult(), dbNodes);
+		detail = xmlResponse.c_str();
+	} else
+		detail = NULL;
+
+	L_INFO("awndServicesList_cache_RspCb - xmlResponse = %s",
+			xmlResponse.c_str());
+	L_DEBUG("awndServicesList_cache_RspCb - fResult = %d",
+			rpcReqStatus->getFResult());
+
+	// Update REST Session status and set XML Response
+	restResponse("awndServicesList_cache_RspCb", sessionId, detail, NULL,
+			rpcReqStatus);
+}
+
+void RESTBroker::awndServicesList_RspCb(ZbNetDb *dbNodes, int sessionId,
+		RPCReqStatus *rpcReqStatus) {
+	std::list<Resource *>::iterator i;
+	std::list<int>::iterator j;
+	std::list<int> endpoints;
+	std::string xmlResponse;
+	ResHandler hnd;
+	Resource *r, *nr, *epr;
+	const char *detail;
+	int returnValue;
+	char buf[5];
+	Node *node;
+
+	L_DEBUG("awndServicesList_RspCb");
+
+	returnValue = rpcReqStatus->getReturnValue();
+
+	// Dynamic REST resources Management
+	if (returnValue == AGENT_SUCCESS && dbNodes != NULL) {
+		// Remove SERVICES resource related to the specific node
+		r = pRESTServer->findResource(resources.defNet, "wsnnodes");
+		pRESTServer->clearResource(r);
+
+		for (node = dbNodes->getFirstNode(); node != NULL;
+				node = dbNodes->getNextNode(node)) {
+
+			L_INFO(
+					"awndServicesList_RspCb - createResource NODE - node address %04X ",
+					node->get_nwk_addr());
+
+			nr = createNodeResources(resources.defNet, node);
+
+			nr = pRESTServer->findResource(nr, "services");
+			endpoints = node->getEndPointList();
+			hnd = &RESTBroker::sServiceDescriptor_Req;
+			for (j = endpoints.begin(); j != endpoints.end(); j++) {
+				sprintf(buf, "%02x", *j);
+				epr = createFolder(nr, buf, hnd);
+				epr->data.d = *j;
+			}
+
+		}
+	}
+
+	// Create XML Response
+	if (returnValue == AGENT_SUCCESS) {
+		xmlResponse = pXMLMsgComposer->createAllNodesServiceDescMsg(
+				rpcReqStatus->getFResult(), dbNodes);
+		detail = xmlResponse.c_str();
+	} else
+		detail = NULL;
+
+	L_INFO("awndServicesList_RspCb - xmlResponse = %s", xmlResponse.c_str());
+	L_DEBUG("awndServicesList_RspCb - fResult = %d",
+			rpcReqStatus->getFResult());
+
+	// Update REST Session status and set XML Response
+	restResponse("awndServicesList_RspCb", sessionId, detail, NULL,
+			rpcReqStatus);
+}
+
+//***********************************************************************************************
+//************************ Periodic Tasks management (different threads) *************************
+//***********************************************************************************************
+
+RESTBroker::Task::Task(void) {
+	taskStarted = false;
+}
+
+int RESTBroker::Task::start(RESTBroker *restBrokerPointer, int taskPeriodA,
+		int taskPeriodB, void *(*notify)(void *)) {
+	Debug *pLogger;
+	int returnValue = 0;
+
+	pLogger = restBrokerPointer->pLogger;
+
+	L_DEBUG("startPeriodicTask");
+
+	if (taskStarted) {
+		L_ERROR("startPeriodicTask - Thread already started!!!!"
+				"(unreachable state)");
+		return -1;
+	}
+
+	taskStarted = true;
+	this->restBrokerPointer = restBrokerPointer;
+	this->taskPeriodA = taskPeriodA;
+	this->taskPeriodB = taskPeriodB;
+
+	returnValue = pthread_create(&tid, NULL, notify, this);
+	if (returnValue) {
+		L_ERROR("startPeriodicTask - Error in creating thread");
+		taskStarted = false;
+	}
+
+	return returnValue;
+}
+
+void RESTBroker::Task::stop(void) {
+	if (taskStarted) {
+		taskStarted = false;
+		pthread_join(tid, NULL);
+	}
+}
+
+void* RESTBroker::notifyGWDescriptorToWsnc_SW(void *arg) {
+	RESTBroker *pRESTBroker = NULL;
+	printf("RESTBroker::notifyGWDescriptorToWsnc_SW\n");
+
+	//pRESTClient = (RESTClient *) arg;
+	pRESTBroker = ((RESTBroker::Task *) arg)->restBrokerPointer;
+
+	pRESTBroker->notifyGWDescriptorToWsnc((RESTBroker::Task *) arg);
+	return 0;
+}
+
+void* RESTBroker::notifyGWDescriptorToWsnc(RESTBroker::Task *task) {
+	std::string xmlNotification;
+	int taskPeriodSecs = task->taskPeriodA;
+	GwDescriptor *gwDescriptor;
+
+	while (task->taskStarted) {
+		sleep(taskPeriodSecs);
+
+		taskPeriodSecs = wsncAttached ? task->taskPeriodB : task->taskPeriodA;
+
+		L_INFO("notifyGWDescriptorToWsnc - Send a NOTIFY!");
+
+		gwDescriptor = pLocalNode->getGwDescriptor();
+		if (gwDescriptor != NULL) {
+
+			xmlNotification = pXMLMsgComposer->createGwStatusChangedMsg(
+					gwDescriptor);
+			L_DEBUG("notifyGWDescriptorToWsnc - xmlNotification = %s",
+					xmlNotification.c_str());
+
+			L_INFO(
+					"notifyGWDescriptorToWsnc - POST message to UriListener List");
+
+			/// The GW Descriptor is posted to registered URI listener List
+
+//#ifdef WSN_C_PROTOCOL_BACKWARD_COMPATIBILITY
+			xmlNotification = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+					+ xmlNotification;
+			restEvent_BC("notifyGWDescriptorToWsnc", &listeners.gwStatus,
+					xmlNotification.c_str(), NULL);
+//#else
+			//restSuccess_Evt (&listeners.gwStatus,
+			//		 xmlNotification.c_str ());
+//#endif
+		}
+	}
+	return NULL;
+}
+
+void RESTBroker::nodeFreshnessAttach(RBURIListenerList *l, uriListener_t *t,
+		int sessionId, bool updated) {
+	DiscoveryAgent<RESTBroker>::StartFreshnessModeCtxt rpcContext(sessionId,
+			this,
+			(DiscoveryAgent<RESTBroker>::startFreshnessModeResponseCb) &RESTBroker::wsnNodesList_StartFreshnessMode_RspCb,
+			(DiscoveryAgent<RESTBroker>::freshnessNotifyCb) &RESTBroker::wsnNodeFreshnessAnnce_NtfCb);
+
+	L_DEBUG("nodeFreshnessAttach");
+
+	if (!l->running) {
+		RESTCallbackInfo *cbinfo;
+		cbinfo = dynamic_cast<RESTCallbackInfo *>(t->hback);
+
+		std::string KAthresholdValue;
+		pQueryParser->getParameter("freshness",
+				cbinfo->refRestSessionCtxt->getQueryStr(), KAthresholdValue);
+		int threshold = atoi(KAthresholdValue.c_str());
+		L_DEBUG("nodeFreshnessAttach - KAthresholdValue = %s - (int value = %d",
+				KAthresholdValue.c_str(), threshold);
+		pDAgent->startFreshnessMode(&rpcContext);
+		l->running = true;
+	} else
+		restResponse("nodeFreshnessAttach", sessionId, NULL, NO_ERROR);
+}
+
+void RESTBroker::nodeFreshnessDetach(RBURIListenerList *l) {
+	DiscoveryAgent<RESTBroker>::CancelFreshnessModeCtxt rpcContext(
+			LOCAL_REST_REQUEST_SESSION_ID, this,
+			(DiscoveryAgent<RESTBroker>::cancelFreshnessModeResponseCb) &RESTBroker::wsnNodesList_CancelFreshnessMode_RspCb,
+			NULL);
+
+	L_DEBUG("nodeFreshnessDetach");
+
+//	if (l -> listeners.empty () && l -> running && !isFMLocallyEnabled) {
+//		pDAgent -> cancelFreshnessMode (&rpcContext);
+//		l -> running = false;
+//	}
+
+	if (l->listeners.empty() && l->running) {
+		if (!isFMLocallyEnabled)
+			pDAgent->cancelFreshnessMode(&rpcContext);
+		l->running = false;
+	}
+
+}
+
+void RESTBroker::nodeAnnounceAttach(RBURIListenerList *l, uriListener_t *t,
+		int sessionId, bool updated) {
+	DiscoveryAgent<RESTBroker>::StartAnnouncementsModeCtxt rpcContext(sessionId,
+			this,
+			(DiscoveryAgent<RESTBroker>::startAnnouncementsModeResponseCb) &RESTBroker::wsnNodesList_StartAnnceMode_RspCb,
+			(DiscoveryAgent<RESTBroker>::announceNotifyCb) &RESTBroker::wsnNodeAnnce_NtfCb);
+
+	L_DEBUG("nodeAnnounceAttach");
+
+	//NEW PART!
+	/*
+	 if (l -> running){
+	 L_DEBUG("nodeAnnounceAttach - Already called, overwriting the context!");
+	 // Return a success but still run the announcement with the new context!
+	 //restResponse ("nodeAnnounceAttach", sessionId,  NULL, NO_ERROR);
+	 }
+	 pDAgent -> startAnnouncementsMode(&rpcContext);
+	 l -> running = true;
+	 */
+
+	/* OLD - up to 28/12/2011*/
+	if (!l->running) {
+		pDAgent->startAnnouncementsMode(&rpcContext);
+		l->running = true;
+	} else {
+		L_DEBUG("nodeAnnounceAttach - Already called - just send response");
+		restResponse("nodeAnnounceAttach", sessionId, NULL, NO_ERROR);
+	}
+}
+
+void RESTBroker::nodeAnnounceDetach(RBURIListenerList *l) {
+	DiscoveryAgent<RESTBroker>::CancelAnnouncementsModeCtxt rpcContext(
+			LOCAL_REST_REQUEST_SESSION_ID, this,
+			(DiscoveryAgent<RESTBroker>::cancelAnnouncementsModeResponseCb) &RESTBroker::wsnNodesList_CancelAnnceMode_RspCb,
+			NULL);
+
+	L_DEBUG("nodeAnnounceDetach");
+
+//	if (l -> listeners.empty () && l -> running && !isAMLocallyEnabled) {
+//		pDAgent -> cancelAnnouncementsMode (&rpcContext);
+//		l -> running = false;
+//	}
+
+	if (l->listeners.empty() && l->running) {
+		if (!isAMLocallyEnabled)
+			pDAgent->cancelAnnouncementsMode(&rpcContext);
+		l->running = false;
+	}
+}
+
+void RESTBroker::nodeInquiryAttach(RBURIListenerList *l, uriListener_t *t,
+		int sessionId, bool updated) {
+	Resource *r;
+	std::map<ushort, Node *>::const_iterator iter;
+	std::map<ushort, Node *> nodes;
+	std::string xmlNotification;
+	const char *detail;
+	DiscoveryAgent<RESTBroker>::InquiryCtxt rpcContext(sessionId, this,
+			(DiscoveryAgent<RESTBroker>::inquiryResponseCb) &RESTBroker::wsnNodesList_RspCb,
+			(DiscoveryAgent<RESTBroker>::inquiryNotifyCb) &RESTBroker::wsnNodesList_NtfCb);
+
+	L_DEBUG("nodeInquiryAttach");
+
+	if (l->running) {
+		/* Send the nodes already discovered so far */
+		DiscoveryAgent<RESTBroker>::RetrieveNodesCtxt dctxt(sessionId, this,
+				(DiscoveryAgent<RESTBroker>::retrieveNodesResponseCb) &RESTBroker::wsnNodesList_sofar_RspCb,
+				NULL);
+		// Call DiscoveryAgent::retrieveNodes <<
+		soFarBuffer = NULL;
+		pDAgent->retrieveNodes(&dctxt);
+
+		//soFarBuffer is set in wsnNodesList_sofar_RspCb
+		if (soFarBuffer == NULL)
+			return;
+
+		nodes = soFarBuffer->getNodeDict();
+		for (iter = nodes.begin(); iter != nodes.end(); iter++) {
+			xmlNotification = pXMLMsgComposer->createWSNNodeMsg(FSUCCESS,
+					iter->second);
+
+			detail = xmlNotification.c_str();
+			pRESTServer->restSuccess(detail, t);
+		}
+	} else {
+		r = pRESTServer->findResource(resources.defNet, "wsnnodes");
+		pRESTServer->clearResource(r);
+
+		RESTCallbackInfo *cbinfo;
+		cbinfo = dynamic_cast<RESTCallbackInfo *>(t->hback);
+
+		unsigned long int timeout = cbinfo->timeout;
+		L_DEBUG("nodeInquiryAttach - timeout value = %lu", timeout);
+
+		L_DEBUG("nodeInquiryAttach - calling startInquiry");
+		pDAgent->startInquiry(timeout, &rpcContext);
+		l->running = true;
+	}
+}
+
+void RESTBroker::nodeInquiryDetach(RBURIListenerList *l) {
+	DiscoveryAgent<RESTBroker>::CancelInquiryCtxt rpcContext(
+			LOCAL_REST_REQUEST_SESSION_ID, this,
+			(DiscoveryAgent<RESTBroker>::cancelInquiryResponseCb) &RESTBroker::wsnNodesList_cancelInquiry_RspCb,
+			NULL);
+
+	L_DEBUG("nodeInquiryDetach");
+
+	if (l->listeners.empty() && l->running) {
+		pDAgent->cancelInquiry(&rpcContext);
+		l->running = false;
+	}
+}
+
+void RESTBroker::nodeMgmtLQIAttach(RBURIListenerList *l, uriListener_t *t,
+		int sessionId, bool updated) {
+	Resource *r;
+	std::map<ushort, Node *>::const_iterator iter;
+	std::map<ushort, Node *> nodes;
+	std::string xmlNotification;
+	const char *detail;
+	AgentError status;
+	DiscoveryAgent<RESTBroker>::MgmtLQICtxt rpcContext(sessionId, this,
+			(DiscoveryAgent<RESTBroker>::MgmtLQIResponseCb) &RESTBroker::MgmtLQI_RspCb,
+			(DiscoveryAgent<RESTBroker>::MgmtLQINotifyCb) &RESTBroker::MgmtLQI_NtfCb);
+
+	L_DEBUG("nodeMgmtLQIAttach");
+
+	if (l->running) {
+		L_DEBUG(
+				"nodeMgmtLQIAttach - ATTENTION: Discovery still running, overwriting it!");
+	}
+	/* OLD PART that returns the cache...
+	 // Discovery still running, sends the nodes already discovered so far
+	 L_DEBUG("nodeMgmtLQIAttach - ATTENTION: Discovery still running, sends the nodes already discovered so far!");
+	 DiscoveryAgent<RESTBroker>::RetrieveNodesCtxt dctxt (sessionId, this,
+	 (DiscoveryAgent<RESTBroker>::retrieveNodesResponseCb)
+	 &RESTBroker::wsnNodesList_sofar_RspCb, NULL);
+	 // Call DiscoveryAgent::retrieveNodes
+	 soFarBuffer = NULL;
+	 pDAgent -> retrieveNodes (&dctxt);
+	 //soFarBuffer is set in wsnNodesList_sofar_RspCb
+	 if (soFarBuffer == NULL)
+	 {
+	 L_DEBUG("nodeMgmtLQIAttach - No nodes discovered so far");
+	 return;
+	 }
+	 nodes = soFarBuffer -> getNodeDict ();
+	 for (iter = nodes.begin (); iter != nodes.end (); iter++){
+	 if ( (iter -> second)->getIsActive() == true){
+	 xmlNotification = pXMLMsgComposer->createWSNNodeMsg (FSUCCESS, iter -> second);
+	 detail = xmlNotification.c_str ();
+	 pRESTServer -> restSuccess (detail, t);
+	 }
+	 }
+	 */
+	//} else {
+	// Call the Mgmt_LQI_Req (delete first all the current resources)
+	r = pRESTServer->findResource(resources.defNet, "wsnnodes");
+	pRESTServer->clearResource(r);
+
+	RESTCallbackInfo *cbinfo;
+	cbinfo = dynamic_cast<RESTCallbackInfo *>(t->hback);
+
+	unsigned long int timeout = cbinfo->timeout;
+	L_DEBUG("nodeMgmtLQIAttach - calling MgmtLQI_Req (timeout value = %lu)",
+			timeout);
+	status = pDAgent->MgmtLQI_Req(timeout, &rpcContext);
+	if (status == AGENT_SUCCESS)
+		l->running = true;
+	//}
+}
+
+void RESTBroker::nodeMgmtLQIDetach(RBURIListenerList *l) {
+	DiscoveryAgent<RESTBroker>::CancelMgmtLQICtxt rpcContext(
+			LOCAL_REST_REQUEST_SESSION_ID, this,
+			(DiscoveryAgent<RESTBroker>::cancelMgmtLQIResponseCb) &RESTBroker::cancelMgmtLQI_RspCb,
+			NULL);
+
+	L_DEBUG("nodeMgmtLQIDetach");
+
+	if (l->listeners.empty() && l->running) {
+		L_DEBUG("nodeMgmtLQIDetach - calling cancelMgmtLQI_Req");
+		pDAgent->cancelMgmtLQI_Req(&rpcContext);
+		l->running = false;
+	}
+}
+
+void RESTBroker::startupAttach(RBURIListenerList *l, uriListener_t *t,
+		int sessionId, bool updated) {
+	L_DEBUG("startupAttach");
+
+	LocalNode<RESTBroker>::StartGatewayDeviceCtxt rpcContext(sessionId, this,
+			(LocalNode<RESTBroker>::startupResponseCb) &RESTBroker::startup_RspCb,
+			(LocalNode<RESTBroker>::startupNotifyCb) &RESTBroker::startup_NtfCb);
+
+	if (l->running) {
+		L_DEBUG("startupAttach - l->running true, already called");
+	} else {
+		//L_DEBUG("startupAttach - l->running == 0");
+		RESTCallbackInfo *cbinfo;
+		cbinfo = dynamic_cast<RESTCallbackInfo *>(t->hback);
+
+		unsigned long int timeout = cbinfo->timeout;
+		L_DEBUG("startupAttach - timeout value = %lu", timeout);
+
+		// Get StartupAttributeInfo from XML message
+		StartupAttributeInfo sai;
+
+		int result =
+				pXMLMsgParser->getStartupAttributeInfo(&sai,
+						((RESTCallbackInfo*) (t->hback))->refRestSessionCtxt->getRxDataBuffer());
+		if (result == 1)
+			throw RESTException(BAD_PARAMETER,
+					"Bad StartupAttributeInfo XML message");
+		if (result == 2)
+			throw RESTException(WRONG_REQUEST,
+					"Mandatory parameter missing in StartupAttributeInfo XML message");
+		if (result == 3)
+			throw RESTException(BAD_PARAMETER,
+					"Invalid value in StartupAttributeInfo XML message");
+		pLocalNode->startGatewayDevice(timeout, &sai, &rpcContext);
+		l->running = true;
+	}
+}
+
+void RESTBroker::startupDetach(RBURIListenerList *l) {
+	L_DEBUG("startupDetach");
+
+	if (l->listeners.empty() && l->running) {
+		l->running = false;
+	}
+}
+
+void RESTBroker::serviceDiscoveryAttach(RBURIListenerList *l, uriListener_t *t,
+		int sessionId, bool updated) {
+	Resource *r;
+	ushort nwk;
+	ServiceAgent<RESTBroker>::ActiveEndPointsCtxt rpcContext(sessionId, this,
+			(ServiceAgent<RESTBroker>::activeEndPointsResponseCb) &RESTBroker::ndServicesList_RspCb,
+			(ServiceAgent<RESTBroker>::activeEndPointsNotifyCb) &RESTBroker::ndServicesList_NtfCb);
+
+	if (l->running) {
+		L_DEBUG(
+				"serviceDiscoveryAttach - WARNING: An istance is already running!, overwriting it!");
+	} else
+		l->running = true;
+	unsigned long int timeout = ((RESTCallbackInfo*) (t->hback))->timeout;
+	r = ((RESTCallbackInfo*) (t->hback))->refResource->parent;
+	nwk = r->data.d;
+	L_DEBUG("serviceDiscoveryAttach - timeout value = %lu, NodeId = %04x",
+			timeout, nwk);
+	pSAgent->getActiveEndPoints(timeout, nwk, &rpcContext);
+}
+
+void RESTBroker::serviceDiscoveryDetach(RBURIListenerList *l) {
+	L_DEBUG("serviceDiscoveryDetach");
+
+	if (l->listeners.empty() && l->running) {
+
+		l->running = false;
+	}
+}
+
+void RESTBroker::permitJoinAttach(RBURIListenerList *l, uriListener_t *t,
+		int sessionId, bool updated) {
+	Resource *r;
+	ushort nwk;
+	int PermitDuration;
+	bool TCSignificance;
+
+	L_DEBUG("permitJoinAttach");
+
+	RESTCallbackInfo *cbinfo;
+	cbinfo = dynamic_cast<RESTCallbackInfo *>(t->hback);
+
+	unsigned long int timeout = cbinfo->timeout;
+	L_DEBUG("permitJoinAttach - timeout value = %lu ms", timeout);
+
+	ManagementAgent<RESTBroker>::permitJoinCtxt rpcContext(sessionId, this,
+			(ManagementAgent<RESTBroker>::permitJoinResponseCb) &RESTBroker::ndPermitJoin_RspCb,
+			(ManagementAgent<RESTBroker>::permitJoinNotifyCb) &RESTBroker::ndPermitJoin_NtfCb);
+
+	if (l->listeners.empty() && l->running) {
+		L_DEBUG("permitJoinAttach -> NOTE: overwriting a previous call!");
+		//l -> running = false;
+	}
+
+	//Get from input the XML message
+	if (pXMLMsgParser->getJoiningInfoValues(&PermitDuration, &TCSignificance,
+			((RESTCallbackInfo*) (t->hback))->refRestSessionCtxt->getRxDataBuffer())
+			== 1) {
+		//An error occurs when extracting input from the XML message
+		throw RESTException(BAD_PARAMETER, "Wrong JoiningInfo values");
+	}
+
+	try {
+		r = ((RESTCallbackInfo*) (t->hback))->refResource->parent;
+		nwk = r->data.d;
+		L_DEBUG("permitJoinAttach - nwk addr %d (dec) - %x (hex)", nwk, nwk);
+	} catch (RESTException &e) {
+		// This an error since a value for timeout must be present
+		throw RESTException(WRONG_REQUEST, "Bad formatted destination address");
+	}
+	pMngmtAgent->permitJoin(nwk, PermitDuration, TCSignificance, timeout,
+			&rpcContext);
+	l->running = true;
+}
+
+void RESTBroker::permitJoinDetach(RBURIListenerList *l) {
+	L_DEBUG("permitJoinDetach");
+
+	if (l->listeners.empty() && l->running) {
+		l->running = false;
+	}
+}
+
+void RESTBroker::resetCommandAttach(RBURIListenerList *l, uriListener_t *t,
+		int sessionId, bool updated) {
+	Resource *r, *alls;
+
+	L_DEBUG("resetCommandAttach");
+
+	RESTCallbackInfo *cbinfo = dynamic_cast<RESTCallbackInfo *>(t->hback);
+
+	unsigned long int timeout = cbinfo->timeout;
+	L_DEBUG("resetCommandAttach - timeout value = %lu", timeout);
+
+	if (l->running) {
+		L_DEBUG("resetCommandAttach - ATTENTION: reset is already running!");
+		// Next time allow to call the reset (this is just to unlock a scenario where the previous call have had a problem)
+		l->running = false;
+	} else {
+		bool restartOption;
+		std::string startModeValue;
+		// Set the restart bit
+		restartOption = pQueryParser->isParameterPresent("restart",
+				cbinfo->refRestSessionCtxt->getQueryStr());
+		/*
+		 if (restartOption == false) {
+		 L_DEBUG ("reset_Req - 'restart' not present. Gateway will just init");
+		 } else {
+		 L_DEBUG ("reset_Req - 'restart' the gateway activated");
+		 }
+		 */
+		// Store in ZbNetDb the NVM setting (it will overwrite the config.ini setting choose)
+		pQueryParser->getParameter("startMode",
+				cbinfo->refRestSessionCtxt->getQueryStr(), startModeValue);
+		if (!startModeValue.compare("0x00")) {
+			L_DEBUG("reset_Req - startMode = 0x00 - Commissioning/Association");
+			pGalDb->setStartModeSetting(0);
+		} else if (!startModeValue.compare("0x01")) {
+			L_DEBUG("reset_Req - startMode = 0x01 - NVM");
+			pGalDb->setStartModeSetting(1);
+		} else if (!startModeValue.compare("0x02")) {
+			L_DEBUG("reset_Req - startMode = 0x02 - Commissioning/SilentStart");
+			pGalDb->setStartModeSetting(2);
+		} else {
+			L_DEBUG("reset_Req - startMode not present in %s! (Default=0x00)",
+					cbinfo->refRestSessionCtxt->getQueryStr());
+			pGalDb->setStartModeSetting(0);
+		}
+		// Delete the "services" resources...
+		L_DEBUG("reset_Req - Delete all the endpoint resources!");
+		r = pRESTServer->findResource(NULL, "localnode");
+		if (r != NULL) {
+			alls = pRESTServer->findResource(r, "services");
+			pRESTServer->clearResource(alls);
+		}
+		// Prepare the context
+		LocalNode<RESTBroker>::ResetCommandCtxt rpcContext(sessionId, this,
+				(LocalNode<RESTBroker>::resetResponseCb) &RESTBroker::resetCommand_RspCb,
+				(LocalNode<RESTBroker>::resetNotifyCb) &RESTBroker::resetCommand_NtfCb);
+		// Call the reset function
+		if (restartOption)
+			pLocalNode->resetRequest(0x05, &rpcContext);
+		else
+			pLocalNode->resetRequest(0x04, &rpcContext);
+		// Set that this listener is running!
+		l->running = true;
+	}
+}
+
+void RESTBroker::resetCommandDetach(RBURIListenerList *l) {
+	L_DEBUG("resetCommandDetach");
+
+	if (l->listeners.empty() && l->running) {
+		l->running = false;
+	}
+}
+
+void RESTBroker::leaveCommandAttach(RBURIListenerList *l, uriListener_t *t,
+		int sessionId, bool updated) {
+	//L_DEBUG("leaveCommandAttach");
+	RESTCallbackInfo *cbinfo = dynamic_cast<RESTCallbackInfo *>(t->hback);
+	unsigned long int timeout = cbinfo->timeout;
+	L_DEBUG("leaveCommandAttach - timeout value = %lu", timeout);
+	ManagementAgent<RESTBroker>::LeaveCommandCtxt rpcContext(sessionId, this,
+			(ManagementAgent<RESTBroker>::leaveResponseCb) &RESTBroker::ndLeaveCommand_RspCb,
+			(ManagementAgent<RESTBroker>::leaveNotifyCb) &RESTBroker::ndLeaveCommand_NtfCb);
+	if (l->running) {
+		L_DEBUG("leaveCommandAttach - Already running!");
+		// Do not allow this time the call but let the user to call it next time
+		l->running = false;
+	} else {
+		Resource *r;
+		ushort nwk;
+		int result;
+		std::map<ushort, Node *> nodes;
+		std::map<ushort, Node *>::const_iterator iter;
+		bool removeChildren = true;
+		bool rejoin = false;
+		bool isPresent;
+
+		isPresent = pQueryParser->isParameterPresent("remove-children",
+				cbinfo->refRestSessionCtxt->getQueryStr());
+		if (isPresent == false) {
+			L_DEBUG(
+					"leaveCommandAttach - queryString = %s not containing remove-children parameter",
+					cbinfo->refRestSessionCtxt->getQueryStr());
+			// Let use a default value (as specification it must be false)
+			removeChildren = false;
+		} else {
+			removeChildren = true;
+		}
+		isPresent = pQueryParser->isParameterPresent("rejoin",
+				cbinfo->refRestSessionCtxt->getQueryStr());
+		if (isPresent == false) {
+			L_DEBUG(
+					"leaveCommandAttach - queryString = %s not containing rejoin parameter",
+					cbinfo->refRestSessionCtxt->getQueryStr());
+			// Let use a default value (as specification it must be false)
+			rejoin = false;
+		} else {
+			rejoin = true;
+		}
+		r = ((RESTCallbackInfo*) (t->hback))->refResource;
+		nwk = r->data.d;
+		L_INFO(
+				"leaveCommandAttach - NWK address 0x%04x, removeChildren %d, rejoin %d",
+				nwk, removeChildren, rejoin);
+		result = pMngmtAgent->leaveRequest(nwk, removeChildren, rejoin,
+				&rpcContext);
+
+		if (result == AGENT_SUCCESS) {
+			// Command sent. Instead of wait for a confirm, we delete all the resources specific for the selected device now!
+			if (nwk == 0xffff || nwk == 0xfffc) {
+				r = pRESTServer->findResource(resources.defNet, "wsnnodes");
+				// Delete all the resources apart from the "wsnnodes" path! (otherwise use removeResources)
+				pRESTServer->clearResource(r);
+				// Delete all the information related to the ZbNetDb
+				pGalZb = GalZbIf::Instance();
+				pGalDb = pGalZb->getDb();
+				pGalDb->clearAllButRoot();
+				pDAgent->clearDeadingNodeList();
+			} else
+				//It is just one node!
+				leaveCommandDeleteResources(nwk);
+		}
+		l->running = true;
+	}
+}
+
+void RESTBroker::leaveCommandDetach(RBURIListenerList *l) {
+	L_DEBUG("leaveCommandDetach");
+
+	if (l->listeners.empty() && l->running) {
+		l->running = false;
+	}
+}
+
+void RESTBroker::serviceDescriptorAttach(RBURIListenerList *l, uriListener_t *t,
+		int sessionId, bool updated) {
+//	L_DEBUG("serviceDescriptorAttach");
+	ServiceAgent<RESTBroker>::ServiceDescriptorCtxt rpcContext(sessionId, this,
+			(ServiceAgent<RESTBroker>::serviceDescriptorResponseCb) &RESTBroker::sServiceDescriptor_RspCb,
+			(ServiceAgent<RESTBroker>::serviceDescriptorNotifyCb) &RESTBroker::sServiceDescriptor_NtfCb);
+	if (l->running) {
+		L_DEBUG("serviceDescriptorAttach - WARNING: Service already running!");
+	} else {
+		Resource *r;
+		ushort nwk;
+		uchar endpoint;
+		unsigned long int timeout = ((RESTCallbackInfo*) (t->hback))->timeout;
+		r = ((RESTCallbackInfo*) (t->hback))->refResource->parent->parent;
+		nwk = r->data.d;
+		endpoint = ((RESTCallbackInfo*) (t->hback))->refResource->data.d;
+		L_DEBUG(
+				"serviceDescriptorAttach - timeout= %lu, NodeId=%04x, EndPoint=%d",
+				timeout, nwk, endpoint);
+		pSAgent->getServiceDescriptor(timeout, nwk, endpoint, &rpcContext);
+		l->running = true;
+	}
+}
+
+void RESTBroker::serviceDescriptorDetach(RBURIListenerList *l) {
+	L_DEBUG("serviceDescriptorDetach");
+
+	if (l->listeners.empty() && l->running) {
+
+		l->running = false;
+	}
+}
+
+//***********************************************************
+//***********************************************************
+
+void RESTBroker::nodeDescriptorAttach(RBURIListenerList *l, uriListener_t *t,
+		int sessionId, bool updated) {
+	//L_DEBUG("nodeDescriptorAttach");
+	DiscoveryAgent<RESTBroker>::NodeDescriptorCtxt rpcContext(sessionId, this,
+			(DiscoveryAgent<RESTBroker>::nodeDescriptorResponseCb) &RESTBroker::nodeDescriptor_RspCb,
+			(DiscoveryAgent<RESTBroker>::nodeDescriptorNotifyCb) &RESTBroker::nodeDescriptor_NtfCb);
+	if (l->running) {
+		L_DEBUG(
+				"nodeDescriptorAttach - WARNING: Another request is already running!");
+	} else {
+		Resource *r;
+		ushort nwk;
+		//L_DEBUG("nodeDescriptorAttach - l->running == 0");
+		unsigned long int timeout = ((RESTCallbackInfo*) (t->hback))->timeout;
+		r = ((RESTCallbackInfo*) (t->hback))->refResource->parent;
+		nwk = r->data.d;
+		L_DEBUG("nodeDescriptorAttach - timeout value = %lu, NodeId = %04x",
+				timeout, nwk);
+		pDAgent->getNodeDescriptor(timeout, nwk, &rpcContext);
+		l->running = true;
+	}
+}
+
+void RESTBroker::nodeDescriptorDetach(RBURIListenerList *l) {
+	L_DEBUG("nodeDescriptorDetach");
+	if (l->listeners.empty() && l->running) {
+		l->running = false;
+	}
+}
+
+void RESTBroker::getnodebindingAttach(RBURIListenerList *l, uriListener_t *t,
+		int sessionId, bool updated) {
+	short destAddr;
+	short startIndex;
+	Resource *r;
+	uchar nwk[8];
+	Node* tmpNode;
+	int z;
+	std::string stringValue;
+	bool isPresent;
+
+	L_DEBUG("getnodebindingAttach");
+	ServiceAgent<RESTBroker>::GetnodebindingCtxt rpcContext(sessionId, this,
+			(ServiceAgent<RESTBroker>::getnodebindingResponseCb) &RESTBroker::getnodebinding_RspCb,
+			(ServiceAgent<RESTBroker>::getnodebindingNotifyCb) &RESTBroker::getnodebinding_NtfCb);
+
+	if (l->running) {
+		L_DEBUG(
+				"getnodebindingAttach - WARNING: Another request is already running!");
+	} else {
+		unsigned long int timeout = ((RESTCallbackInfo*) (t->hback))->timeout;
+		L_DEBUG("getnodebindingAttach - timeout value = %lu", timeout);
+		try {
+			//Get the IEEE Address
+			std::string tempIEEE, temphex;
+			int value;
+			r = ((RESTCallbackInfo*) (t->hback))->refResource->parent; // this contains "/net/default/wsnnodes/0050c2d8b3b739b5"
+			tempIEEE = r->uri.substr(22, 16); // "0050c2d8b3b739b5"
+			for (z = 0; z < 16; z++) {
+				temphex = tempIEEE.substr(z, 2);
+				sscanf(temphex.c_str(), "%x", &value);
+				nwk[z / 2] = value;
+				z++;
+			}
+			L_DEBUG(
+					"GetNodeBinding - nwk addr %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+					nwk[0], nwk[1], nwk[2], nwk[3], nwk[4], nwk[5], nwk[6],
+					nwk[7]);
+			//Get the shortAddress
+			tmpNode = pGalDb->findNodeByIEEEAddr(nwk);
+			if (tmpNode != NULL)
+				destAddr = tmpNode->get_nwk_addr();
+			else {
+				L_DEBUG("Wrong IEEEAddress (or not present in DB yet)");
+				throw RESTException(WRONG_REQUEST,
+						"Wrong IEEEAddress (or not present in DB yet)");
+			}
+		} catch (RESTException &e) {
+			// This an error since a value for the destAddr must be present
+			throw RESTException(WRONG_REQUEST,
+					"Bad formatted destination address");
+		}
+		//Get the startIndex value (if present)
+		isPresent =
+				pQueryParser->getParameter("index",
+						((RESTCallbackInfo*) (t->hback))->refRestSessionCtxt->getQueryStr(),
+						stringValue);
+		if (isPresent)
+			startIndex = atoi(stringValue.c_str());
+		else
+			startIndex = 0;
+		L_DEBUG("startIndex value = 0x%02x", startIndex);
+		// Send the message
+		pSAgent->getnodebindingRequest(timeout, destAddr, startIndex,
+				&rpcContext);
+		l->running = true;
+	}
+}
+
+void RESTBroker::getnodebindingDetach(RBURIListenerList *l) {
+	L_DEBUG("getnodebindingDetach");
+	if (l->listeners.empty() && l->running) {
+		l->running = false;
+	}
+}
+
+void RESTBroker::bindAttach(RBURIListenerList *l, uriListener_t *t,
+		int sessionId, bool updated) {
+	ZB_BIND_STRUCT bindParams;
+
+	L_DEBUG("bindAttach");
+	ServiceAgent<RESTBroker>::BindCtxt rpcContext(sessionId, this,
+			(ServiceAgent<RESTBroker>::bindResponseCb) &RESTBroker::bind_RspCb,
+			(ServiceAgent<RESTBroker>::bindNotifyCb) &RESTBroker::bind_NtfCb);
+
+	if (l->running) {
+		L_DEBUG("bindAttach - WARNING: Another request is already running!");
+	} else {
+		unsigned long int timeout = ((RESTCallbackInfo*) (t->hback))->timeout;
+		L_DEBUG("bindAttach - timeout value = %lu", timeout);
+
+		if (pXMLMsgParser->getBindindCommand(&bindParams,
+				((RESTCallbackInfo*) (t->hback))->refRestSessionCtxt->getRxDataBuffer()))
+			throw RESTException(WRONG_REQUEST,
+					"Message not sent: Error parsing XML message");
+		pSAgent->bindRequest(timeout, bindParams, &rpcContext);
+		l->running = true;
+	}
+}
+
+void RESTBroker::bindDetach(RBURIListenerList *l) {
+	L_DEBUG("bindDetach");
+	if (l->listeners.empty() && l->running) {
+		l->running = false;
+	}
+}
+
+void RESTBroker::unbindAttach(RBURIListenerList *l, uriListener_t *t,
+		int sessionId, bool updated) {
+	ZB_BIND_STRUCT bindParams;
+
+	L_DEBUG("unbindAttach");
+	ServiceAgent<RESTBroker>::UnbindCtxt rpcContext(sessionId, this,
+			(ServiceAgent<RESTBroker>::unbindResponseCb) &RESTBroker::unbind_RspCb,
+			(ServiceAgent<RESTBroker>::unbindNotifyCb) &RESTBroker::unbind_NtfCb);
+
+	if (l->running) {
+		L_DEBUG("unbindAttach - WARNING: Another request is already running!");
+	} else {
+		unsigned long int timeout = ((RESTCallbackInfo*) (t->hback))->timeout;
+		L_DEBUG("unbindAttach - timeout value = %lu", timeout);
+
+		if (pXMLMsgParser->getBindindCommand(&bindParams,
+				((RESTCallbackInfo*) (t->hback))->refRestSessionCtxt->getRxDataBuffer()))
+			throw RESTException(WRONG_REQUEST,
+					"Message not sent: Error parsing XML message");
+		pSAgent->unbindRequest(timeout, bindParams, &rpcContext);
+		l->running = true;
+	}
+}
+
+void RESTBroker::unbindDetach(RBURIListenerList *l) {
+	L_DEBUG("unbindDetach");
+	if (l->listeners.empty() && l->running) {
+		l->running = false;
+	}
+}
+
+void RESTBroker::checkWsncAttach(RBURIListenerList *l, uriListener_t *listener,
+		int endpointId) {
+	std::string xmlNotification;
+
+	L_INFO("checkWsncAttach");
+
+	if (wsnCAddress.length() == 0 || wsncAttached)
+		return;
+
+	if (listener->URL.find(wsnCAddress) == std::string::npos)
+		return;
+
+	// The current urilistener relates to the WSN-C server --> Notify event
+	// --> The current WSNConnection is being created by WSN-C
+	L_INFO("addUriListener - EVENT: WSNConnection is being "
+			"created by WSN-C");
+
+	wsncAttached = true;
+	numWSNConnctionsFromWsnc++;
+
+	// Create XML Event Notification
+	xmlNotification = pXMLMsgComposer->createWsncWSNConnEventMsg(endpointId,
+			listener->URL.c_str(), "created");
+
+	L_INFO("addUriListener - xmlNotification = %s", xmlNotification.c_str());
+
+	L_INFO("lsWsnConnection_NtfCb - POST message to UriListener List");
+
+	restEvent("checkWsncAttach", l, xmlNotification.c_str(), NULL,
+			(RPCReqStatus*) NULL);
+	//GIANNI
+}
+
+void RESTBroker::checkWsncDetach(RBURIListenerList *l, int endpointId) {
+	std::string xmlNotification;
+	uriListener_t *listener;
+
+	if (wsnCAddress.length() == 0 || !wsncAttached)
+		return;
+
+	listener = l->findListenerByHost(&wsnCAddress);
+	if (listener != NULL)
+		return;
+
+	L_INFO("addUriListener - EVENT: "
+			"WSNConnection is being removed by WSN-C");
+
+	numWSNConnctionsFromWsnc--;
+
+	// Set wsncAttached value
+	if (numWSNConnctionsFromWsnc == 0)
+		wsncAttached = false;
+
+	// Create XML Event Notification
+	xmlNotification = pXMLMsgComposer->createWsncWSNConnEventMsg(endpointId,
+			listener->URL.c_str(), "deleted");
+
+	L_INFO("addUriListener - xmlNotification = %s", xmlNotification.c_str());
+
+	L_INFO("lsWsnConnection_NtfCb - POST message to UriListener List");
+
+	restEvent("checkWsncAttach", l, xmlNotification.c_str(), NULL,
+			(RPCReqStatus*) NULL);
+	//GIANNI
+}
+
+void RESTBroker::allServicesAttach(RBURIListenerList *l,
+		uriListener_t *listener, int sessionId, bool updated) {
+	std::string response;
+
+	if (!updated) {
+		checkWsncAttach(l, listener, ALL_ENDPOINTS);
+		createCallbackResources(resources.defCallbacks, listener, l);
+	}
+
+	response = pXMLMsgComposer->createCallbackIdentifierMsg(listener->id);
+
+	restResponse("allServicesAttach", sessionId, response.c_str(), NO_ERROR);
+}
+
+void RESTBroker::allServicesDetach(RBURIListenerList *l) {
+	checkWsncDetach(l, ALL_ENDPOINTS);
+	syncCallbackResources(resources.defCallbacks, l);
+}
+
+void RESTBroker::serviceAttach(RBURIListenerList *l, uriListener_t *listener,
+		int sessionId, bool updated) {
+	ServiceAgent<RESTBroker>::CreateCallbackCtxt rpcContext(sessionId, this,
+			(ServiceAgent<RESTBroker>::createCallbackResponseCb) &RESTBroker::lsWsnConnection_RspCb,
+			(ServiceAgent<RESTBroker>::messageReceivedNotifyCb) &RESTBroker::lsWsnConnection_NtfCb);
+	std::string response;
+
+	if (!updated) {
+		if (!l->running) {
+			pSAgent->createCallback(l->data.d, &rpcContext);
+			l->running = true;
+		}
+
+		checkWsncAttach(l, listener, l->data.d);
+
+		createCallbackResources(resources.defCallbacks, listener, l);
+	}
+
+	response = pXMLMsgComposer->createCallbackIdentifierMsg(listener->id);
+
+	restResponse("serviceAttach", sessionId, response.c_str(), NO_ERROR);
+}
+
+void RESTBroker::serviceDetach(RBURIListenerList *l) {
+	ServiceAgent<RESTBroker>::DeleteCallbackCtxt rpcContext(
+			LOCAL_REST_REQUEST_SESSION_ID, this,
+			(ServiceAgent<RESTBroker>::deleteCallbackResponseCb) &RESTBroker::lsWsnConnection_deleteCallback_RspCb,
+			NULL);
+	checkWsncDetach(l, l->data.d);
+	syncCallbackResources(resources.defCallbacks, l);
+	if (l->listeners.empty() && l->running) {
+		pSAgent->deleteCallback(l->data.d, &rpcContext);
+		l->running = false;
+	}
+}
+
+//#ifdef WSN_C_PROTOCOL_BACKWARD_COMPATIBILITY
+
+void RESTBroker::serviceAttach_BC(RBURIListenerList *l, uriListener_t *listener,
+		int sessionId, bool updated) {
+	ServiceAgent<RESTBroker>::CreateCallbackCtxt rpcContext(sessionId, this,
+			(ServiceAgent<RESTBroker>::createCallbackResponseCb) &RESTBroker::lsWsnConnection_RspCb,
+			(ServiceAgent<RESTBroker>::messageReceivedNotifyCb) &RESTBroker::lsWsnConnection_NtfCb);
+	std::string response;
+
+	L_DEBUG("serviceAttach_BC");
+
+	if (!updated) {
+		if (!l->running) {
+			pSAgent->createCallback(l->data.d, &rpcContext);
+			l->running = true;
+		}
+
+		checkWsncAttach(l, listener, l->data.d);
+	}
+
+	response = pXMLMsgComposer->createCallbackIdentifierMsg(listener->id);
+	restResponse("serviceAttach_BC", sessionId, response.c_str(), NO_ERROR);
+}
+
+//#endif
+
+void RESTBroker::callbackAttach(RBURIListenerList *l, uriListener_t *listener,
+		int sessionId, bool updated) {
+	Callback cb;
+
+	ServiceAgent<RESTBroker>::CreateCallbackCtxt rpcContext(sessionId, this,
+			(ServiceAgent<RESTBroker>::createCallbackResponseCb) &RESTBroker::callbacks_RspCb,
+			(ServiceAgent<RESTBroker>::messageReceivedNotifyCb) &RESTBroker::callbacks_NtfCb);
+
+	std::string response;
+
+	L_INFO("callbackAttach - entered");
+
+	if (!updated) {
+		if (!l->running) {
+			//RESTCallbackInfo *cbinfo;
+			//cbinfo = dynamic_cast<RESTCallbackInfo *> (listener -> hback);
+			int result =
+					pXMLMsgParser->getCallback(&cb,
+							((RESTCallbackInfo*) (listener->hback))->refRestSessionCtxt->getRxDataBuffer());
+			if (result)
+				L_WARN("callbackAttach - WARNING");
+			cb.internalId = l->data.d;
+			// Call ServiceAgent::createCallback <<
+			pSAgent->createCallback(&cb, &rpcContext);
+			l->running = true;
+		}
+		createCallbackResources(resources.defCallbacks, listener, l);
+	}
+	response = pXMLMsgComposer->createCallbackIdentifierMsg(listener->id);
+	restResponse("callbackAttach", sessionId, response.c_str(), NO_ERROR);
+}
+
+void RESTBroker::callbackDetach(RBURIListenerList *l) {
+	ServiceAgent<RESTBroker>::DeleteCallbackCtxt rpcContext(
+			LOCAL_REST_REQUEST_SESSION_ID, this,
+			(ServiceAgent<RESTBroker>::deleteCallbackResponseCb) &RESTBroker::lsWsnConnection_deleteCallback_RspCb,
+			NULL);
+
+	checkWsncDetach(l, l->data.d);
+	syncCallbackResources(resources.defCallbacks, l);
+	if (l->listeners.empty() && l->running) {
+		pSAgent->deleteCustomizedCallback(l->data.d, &rpcContext);
+		l->running = false;
+	}
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTBroker.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTBroker.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTBroker.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,881 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+/*
+ * This file contains the implementation of each procedure defined
+ * by the REST. It uses a RESTServer to comply with the common
+ * mechanisms (such as response encapsulation), XMLMsgParser to decode
+ * requests, the agents to perform them, and XMLMsgComposer to generate
+ * the response documents.
+ */
+
+#ifndef RESTBROKER_H
+#define RESTBROKER_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string>
+
+#include "ThreadPool.h"
+#include "TimerThread.h"
+
+#include "GalZbIf.h"
+#include "Agents.h"
+#include "GWManagement.h"		// used for GW_DESCRIPTOR
+#include "CDiscoveryAgent.h"
+#include "CServiceAgent.h"
+#include "CTrustCenterAgent.h"
+#include "CLocalNode.h"
+
+#include "ZbNetDb.h"
+#include "CMessage.h"
+#include "XMLProcessor.h"
+#include "CQueryParser.h"
+
+#include "CRESTServer.h"
+#include "CRESTClient.h"
+#include "CResource.h"
+
+#include "RESTErrors.h"
+
+#include "CDebug.h"
+
+#include "ConfigurationRepository.h"
+
+/*
+ * These template instantiations are not strictly needed,
+ * however they force compilation of all the methods
+ * so we can get all the potential errors immediately
+ */
+class RESTBroker;
+
+template class DiscoveryAgent<RESTBroker> ;
+template class ServiceAgent<RESTBroker> ;
+template class ManagementAgent<RESTBroker> ;
+#if 0
+template class TrustCenterAgent<RESTBroker>;
+#endif
+
+template class LocalNode<RESTBroker> ;
+
+/**
+ Set of constants that could be used for timer management. Actually, this feature is not used.
+ */
+#define RB_XXXXXXX			1
+
+/**
+ Set of constants used in thread management.
+ */
+#define DA_MAX_THREADS					10
+#define DA_MIN_THREADS					10
+#define DA_JOBS_PER_THREAD				10
+#define DA_THREAD_IDLE_TIME 				5000
+#define DA_MAX_JOBS_TOTAL 				10
+
+//TODO	Change DA_... into RB_...
+
+/**
+ Dummy Session ID used when calling Agents' methods without having received an actual HTTP REST request
+ e.g. when LocalNode methods are called during RESTBroker::autorun()
+ */
+#define LOCAL_REST_REQUEST_SESSION_ID			-1
+#define REMOTE_REST_REQUEST_SESSION_ID			 0
+
+class RESTBroker;
+struct RBURIListenerList;
+
+/**
+ * A delegate resource handler. This is a method pointer roughly
+ * equivalent to ResourceHandler#handle, the only notable difference
+ * being that it is a delegate rather than an abstract function.
+ * The conversion between the two callback mechanisms is done by
+ * RESTBroker#handle.
+ */
+typedef void (RESTBroker::*ResHandler)(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *xmlMsg,
+		RESTSessionContext *ctxt);
+
+/**
+ * A delegate attach handler. This is a method pointer roughly
+ * equivalent to URIListenerHandler#addListener, the only notable
+ * difference being that it is a delegate rather than an abstract
+ * function.  The conversion between the two callback mechanisms is
+ * done by RESTBroker#addListener.
+ */
+typedef void (RESTBroker::*AttachHandler)(RBURIListenerList *l,
+		uriListener_t *t, int sessionId, bool updated);
+
+/**
+ * A delegate detach handler. This is a method pointer roughly
+ * equivalent to URIListenerHandler#removeListener, the only notable
+ * difference being that it is a delegate rather than an abstract
+ * function.  The conversion between the two callback mechanisms is
+ * done by RESTBroker#removeListener.
+ */
+typedef void (RESTBroker::*DetachHandler)(RBURIListenerList *l);
+
+/**
+ * The counterpart of an URIListenerList, where the listeners
+ * has been replaced with a tuple of delegate handlers. The reason
+ * for doing this is that the same class (i.e. RESTBroker) can
+ * implement a several list handler behaviors without having to 
+ * define multiple inner classes. A list may be marked as running,
+ * in case some resource-specific action is currently in process.
+ * Running lists have the #running flag set.
+ */
+struct RBURIListenerList: URIListenerList {
+
+	/** The attach handler delegate pointer */
+	AttachHandler attach;
+
+	/** The detach handler delegate pointer */
+	DetachHandler detach;
+
+	/** Set when  */
+	bool running;
+
+	/** The last message sent so far */
+	std::string lastMessage;
+
+	/**
+	 * Constructor. 
+	 *	@param attach attach handler (optional)
+	 *	@param detach detach handler (optional)
+	 */
+	RBURIListenerList(AttachHandler attach = NULL, DetachHandler detach = NULL) :
+			URIListenerList(NULL), attach(attach), detach(detach), running(
+					false) {
+	}
+};
+
+/**
+ * A predicate that can be used to search for a resource with
+ * a specific identifier.
+ */
+struct IDResourcePredicate {
+
+	/** The identifier to look for */
+	std::string id;
+
+	/**
+	 * Predicate method needed to implement the 
+	 * predicate pattern.
+	 *	@param val the resource to be evaluated
+	 *	@return true if matching
+	 */
+	bool operator ()(Resource *&val);
+};
+
+/**
+ * The counterpart of a ResourceDescriptor, where the resorce handler
+ * has been replaced with a delegate handler. The reason
+ * for doing this is that the same class (i.e. RESTBroker) can
+ * implement a several resource handler behaviors without having to 
+ * define multiple inner classes. 
+ */
+struct RBResourceDescriptor: ResourceDescriptor {
+
+	/** The callback delegate method */
+	ResHandler callback;
+
+	/**
+	 * Constructor
+	 *	@param path The URI subpath, relative to its parent
+	 *	@param callback the resource delegate method
+	 */
+	RBResourceDescriptor(const char *path, ResHandler callback) :
+			ResourceDescriptor(path), callback(callback) {
+	}
+};
+
+/**
+ * The class implementing the REST binding for all procedures.
+ * It makes use of a number of support classes, namely
+ * <ul>
+ *	<li>A RESTServer to exchange XML documents, delegating
+ *		event encapsulation and general parameter handling;
+ * 	<li>XMLMsgComposer and XMLMsgParser to translate XML documents
+ *		into internal structures and vice versa;
+ *	<li>The agents, that perform the actual job
+ * </ul>
+ * The REST binding defines several resources, which are notified by
+ * the RESTServer through the ResourceHandler interface. Instead
+ * of creating an inner class implementing that interface for each
+ * resource, the ResourceHandler class is implemented only once,
+ * by this class. After that, the request is dispatched to one
+ * of the delegate member functions that match the ResHandler template.
+ * The same mechanism applies to URIListenerList's: the RESTBroker
+ * class implements the URIListenerHandler interface, then dispatches
+ * that invocation to a delegate member function (either AttachHandler
+ * or DetachHandler).
+ */
+class RESTBroker: private ResourceHandler, private URIListenerHandler {
+
+public:
+	// Constructors
+	RESTBroker();
+
+	// Destructor
+	~RESTBroker();
+
+	// Functions: modifiers (set), selectors (get)
+
+	/**
+	 * RESTBroker initialization: a link to the local node is 
+	 * used to get the agents and REST server and client init is 
+	 * considered.
+	 * Moreover, the map modeCodes is filled: in particular, 
+	 * it is a conversion table containing the relationship between 
+	 * the values allowed for the query string
+	 * parameter QS_MODE (defined in CResource.h) and specific 
+	 * code numbers.
+	 */
+	void init(bool autostartFlag, bool startupModeFlag);
+
+	/**
+	 * This method enables connection between RESTBroker and LocalNode.
+	 */
+	int connectLocalNode();
+
+	/**
+	 * Obtains and intializes all the agents.
+	 */
+	void initAgents();
+
+	void initListeners();
+
+	void clearAllListeners();
+
+	void setWSNCAddress(std::string &s);
+
+	/**
+	 * Starts the REST server
+	 */
+	void start();
+
+	static void *notifyGWDescriptorToWsnc_SW(void *arg);
+
+	// iterators:
+	// Attributes visible by scope of instantiation and use
+
+protected:
+
+	void autorun();
+
+	struct Task {
+		RESTBroker *restBrokerPointer; //TODO	//In fact, RESTBroker use singleton... it should be not required!
+		bool taskStarted;
+		int taskPeriodA;
+		int taskPeriodB;
+		pthread_t tid;
+
+		int start(RESTBroker *restBrokerPointer, int taskPeriodA,
+				int taskPeriodB, void *(*notify)(void *));
+
+		void stop();
+
+		Task();
+
+	};
+
+	struct {
+		Task wsnc;
+	} tasks;
+
+	bool wsncAttached;
+	int numWSNConnctionsFromWsnc;
+
+	int customizedCallbackIdCounter;
+
+protected:
+	void handle(Resource *res, const char *reqUri, Method reqMethod,
+			const char *queryString, std::string *xmlMsg,
+			HTTPSessionContext *ctxt) throw (RESTException, HTTPException);
+
+	void addListener(URIListenerList *l, uriListener_t *listener,
+			int sessionId);
+
+	void updateListener(URIListenerList *l, uriListener_t *oldl,
+			uriListener_t *newl, int sessionId);
+
+	void removeListeners(URIListenerList *l);
+
+	void badMethod(Resource *res, HTTPSessionContext *ctxt)
+			throw (HTTPException);
+
+	/// REST Errors management
+	void restError_Rsp(int errorId, const char *text, int sessionId);
+
+	void restError_Evt(RBURIListenerList *uriList, int errorId,
+			const char *errorDesc, const char *nwkStatus);
+
+	/// REST success management
+	void restSuccess_Rsp(const char *detail, int sessionId);
+
+	void restSuccess_Evt(RBURIListenerList *uriList, const char *detail);
+
+	void restSuccess_Evt(RBURIListenerList *uriList, const char *detail,
+			bool isAsynchResponse);
+
+	void restEvent(const char *method, RBURIListenerList *uriList,
+			const char *detail, const char *nwkStatus, RPCReqStatus *status);
+
+	void restEvent(const char *method, RBURIListenerList *uriList,
+			const char *detail, RPCReqStatus *status, bool isAsynchResponse);
+
+//#ifdef WSN_C_PROTOCOL_BACKWARD_COMPATIBILITY
+	void restEvent_BC(const char *method, RBURIListenerList *uriList,
+			const char *detail, RPCReqStatus *status);
+//#endif
+
+	void restResponse(const char *method, int sessionId, const char *detail,
+			RESTError ec);
+
+	void restResponse(const char *method, int sessionId, const char *detail,
+			const char *nwkStatus, RPCReqStatus *status);
+
+	void startup_Req(Resource *res, const char *reqUri, Method reqMethod,
+			const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (RESTException, HTTPException);
+
+	/**
+	 Protected method RESTBroker startup_RspCb
+	 This method relates to LocalNode::startup response.
+
+	 @param rpcContext RPC context.
+	 @param rpcReqStatus Returned RPC request status.
+	 @return Void.
+	 */
+	void startup_RspCb(uchar commandStatus, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	void startup_NtfCb(uchar commandStatus, RPCReqStatus *rpcReqStatus);
+
+	void reset_Req(Resource *res, const char *reqUri, Method reqMethod,
+			const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (HTTPException);
+
+	void version_Req(Resource *res, const char *reqUri, Method reqMethod,
+			const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (HTTPException);
+
+	void manageGIBAttr_Req(Resource *res, const char *reqUri, Method reqMethod,
+			const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (HTTPException);
+
+	void informationBase_Req(Resource *res, const char *reqUri,
+			Method reqMethod, const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (HTTPException, RESTException);
+
+	void gwDescriptorLocal_RspCb(int sessionId, RPCReqStatus *rpcReqStatus);
+
+	void gwStatusChanged_gwDescriptor_NtfCb(
+//                int gwStatus,
+//		int errorCode,
+			GwDescriptor *gwDescriptor, RPCReqStatus *rpcReqStatus);
+
+	void cbCallback_Req(Resource *res, const char *reqUri, Method reqMethod,
+			const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (RESTException, HTTPException);
+
+	/// WSN_NODES_LIST functions
+
+	void listAddresses_Req(Resource *res, const char *reqUri, Method reqMethod,
+			const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (RESTException, HTTPException);
+	void listAllAddresses_Req(Resource *res, const char *reqUri,
+			Method reqMethod, const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (RESTException, HTTPException);
+
+	void listAddresses_RspCb(ZbNetDb* buffer, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+	void listAllAddresses_RspCb(ZbNetDb* buffer, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	void wsnNodesList_Req(Resource *res, const char *reqUri, Method reqMethod,
+			const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (RESTException, HTTPException);
+
+	void wsnNodesList_RspCb(int sessionId, RPCReqStatus *rpcReqStatus);
+
+	void wsnNodesList_NtfCb(Node *node, RPCReqStatus *rpcReqStatus);
+
+	void MgmtLQI_RspCb(int sessionId, RPCReqStatus *rpcReqStatus);
+
+	void cancelMgmtLQI_RspCb(int sessionId, RPCReqStatus *rpcReqStatus);
+
+	void MgmtLQI_NtfCb(Node *node, RPCReqStatus *rpcReqStatus);
+
+	void wsnNodesList_cache_RspCb(ZbNetDb* buffer, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	void wsnNodesList_sofar_RspCb(ZbNetDb* buffer, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	void wsnNodesList_cancelInquiry_RspCb(int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	void wsnNodesList_StartAnnceMode_RspCb(int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	void wsnNodesList_CancelAnnceMode_RspCb(int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	void wsnNodesList_StartFreshnessMode_RspCb(int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	void wsnNodesList_CancelFreshnessMode_RspCb(int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	void wsnNodeAnnce_NtfCb(Node *node, RPCReqStatus *rpcReqStatus);
+
+	void wsnNodeFreshnessAnnce_NtfCb(Node *node, RPCReqStatus *rpcReqStatus);
+
+	void callbacks_Req(Resource *res, const char *reqUri, Method reqMethod,
+			const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (RESTException, HTTPException);
+
+	void callbacks_RspCb(int endpoint, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	void callbacks_NtfCb(int localId, Message *message,
+			RPCReqStatus *rpcReqStatus);
+
+	/// LOCAL_NODE functions
+	void lndServicesList_Req(Resource *res, const char *reqUri,
+			Method reqMethod, const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (HTTPException, RESTException);
+
+	void lndServicesList_RspCb(SimpleDescriptor *serviceDesc, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	void clearEndpoin_Req(Resource *res, const char *reqUri, Method reqMethod,
+			const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (HTTPException, RESTException);
+
+	void lndAllServicesWsnConnection_Req(Resource *res, const char *reqUri,
+			Method reqMethod, const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (RESTException, HTTPException);
+
+	void lndAllServicesWsnConnection_RspCb(int endpoint, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	void lndAllServicesWsnConnection_NtfCb(int destEP, Message *message,
+			RPCReqStatus *rpcReqStatus);
+
+	void lndAllServicesMessage_Req(Resource *res, const char *reqUri,
+			Method reqMethod, const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (HTTPException);
+
+	void lndAllServicesMessage_RspCb(Message *msg, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+#if 0
+	/// TRUSTCENTER functions
+	void trustCenter_Req(
+			Uri *reqUri,
+			int reqMethod,
+			const char *queryString,
+			int sessionId
+	);
+
+	void trustCenter_RspCb(
+			RPCContext *rpcContext,
+			RPCReqStatus *rpcReqStatus
+	);
+
+	void trustCenter_DeviceJoinIndication_NtfCb(
+			int eventType,
+			NodeMapItem *joiningNode,
+			RPCReqStatus *rpcReqStatus
+	);
+
+	void tcAccessList_Req(
+			Uri *reqUri,
+			int reqMethod,
+			const char *queryString,
+			std::string *xmlMsg,
+			int sessionId
+	);
+
+	void tcAccessList_RspCb(
+			ushort addr,
+			bool granted,
+			RPCContext *rpcContext,
+			RPCReqStatus *rpcReqStatus
+	);
+#endif
+
+	/// LOCAL_SERVICES functions
+	void lsWsnConnection_Req(Resource *res, const char *reqUri,
+			Method reqMethod, const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (RESTException, HTTPException);
+
+	void lsWsnConnection_RspCb(int endpoint, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	void lsWsnConnection_deleteCallback_RspCb(int endpoint, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	void lsWsnConnection_NtfCb(int destEP, Message *message,
+			RPCReqStatus *rpcReqStatus);
+
+//#ifdef WSN_C_PROTOCOL_BACKWARD_COMPATIBILITY
+	void lsWsnConnection_BC_Req(Resource *res, const char *reqUri,
+			Method reqMethod, const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (RESTException, HTTPException);
+//#endif
+
+	void lsMessage_Req(Resource *res, const char *reqUri, Method reqMethod,
+			const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (RESTException, HTTPException);
+
+	void lsMessage_RspCb(Message *msg, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	/// NODE functions
+	void nodeDescriptor_Req(Resource *res, const char *reqUri, Method reqMethod,
+			const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (RESTException, HTTPException);
+
+	void nodeDescriptor_RspCb(ushort nwk_addr, uchar *ieee_addr,
+			NodeDescriptor *nodeDesc, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	void nodeDescriptor_NtfCb(Node *node, RPCReqStatus *rpcReqStatus);
+
+	void frequencyAgility_Req(Resource *res, const char *reqUri,
+			Method reqMethod, const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (RESTException, HTTPException);
+
+	void lsBind_Req(Resource *res, const char *reqUri, Method reqMethod,
+			const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (RESTException, HTTPException);
+
+	void getnodebinding_RspCb(short bindingTableEntries, short startIndex,
+			short bindingTableListCount, ZB_BIND_STRUCT *bindingtableList,
+			int sessionId, RPCReqStatus *rpcReqStatus);
+
+	void getnodebinding_NtfCb(short bindingTableEntries, short startIndex,
+			short bindingTableListCount, ZB_BIND_STRUCT *bindingtableList,
+			RPCReqStatus *rpcReqStatus);
+
+	void bind_RspCb(
+	//ZB_BIND_STRUCT bindParams,
+			int sessionId, RPCReqStatus *rpcReqStatus);
+
+	void bind_NtfCb(
+	//ZB_BIND_STRUCT bindParams,
+			RPCReqStatus *rpcReqStatus);
+
+	void lsUnbind_Req(Resource *res, const char *reqUri, Method reqMethod,
+			const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (RESTException, HTTPException);
+
+	void unbind_RspCb(int sessionId, RPCReqStatus *rpcReqStatus);
+
+	void unbind_NtfCb(RPCReqStatus *rpcReqStatus);
+
+	void leaveCommandDeleteResources(ushort nwk);
+
+	void ndRoot_Req(Resource *res, const char *reqUri, Method reqMethod,
+			const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (HTTPException);
+
+	void resetCommand_RspCb(int sessionId, RPCReqStatus *rpcReqStatus);
+
+	void resetCommand_NtfCb(uchar status, RPCReqStatus *rpcReqStatus);
+
+	void ndLeaveCommand_RspCb(int sessionId, RPCReqStatus *rpcReqStatus);
+
+	void ndLeaveCommand_NtfCb(uchar status, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	void ndPermitJoin_Req(Resource *res, const char *reqUri, Method reqMethod,
+			const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (RESTException, HTTPException);
+
+	void ndPermitJoin_RspCb(uchar status, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	void ndPermitJoin_NtfCb(uchar status, RPCReqStatus *rpcReqStatus);
+
+	void ndLQIInformation_Req(Resource *res, const char *reqUri,
+			Method reqMethod, const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (RESTException, HTTPException);
+
+	void ndPowerDescriptor_Req(Resource *res, const char *reqUri,
+			Method reqMethod, const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (HTTPException);
+
+	void ndPowerDescriptor_RspCb(ushort nwk_addr, uchar *ieee_addr,
+			PowerDescriptor *powerDesc, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	void ndServicesList_Req(Resource *res, const char *reqUri, Method reqMethod,
+			const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (RESTException, HTTPException);
+
+	void ndServicesList_RspCb(Node *node, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	void ndServicesList_NtfCb(Node *node, RPCReqStatus *rpcReqStatus);
+
+	/// SERVICES
+	void sServiceDescriptor_Req(Resource *res, const char *reqUri,
+			Method reqMethod, const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (RESTException, HTTPException);
+
+	void sServiceDescriptor_RspCb(Node *node, int endpoint, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	void sServiceDescriptor_NtfCb(Node *node, int endpoint,
+			RPCReqStatus *rpcReqStatus);
+
+	/// ALL_WSN_NODES functions
+	void awndServicesList_Req(Resource *res, const char *reqUri,
+			Method reqMethod, const char *queryString, std::string *xmlMsg,
+			RESTSessionContext *ctxt) throw (HTTPException);
+
+	void awndServicesList_cache_RspCb(ZbNetDb *dbNodes, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	void awndServicesList_RspCb(ZbNetDb *dbNodes, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	void nodeFreshnessAttach(RBURIListenerList *l, uriListener_t *t,
+			int sessionId, bool updated);
+
+	void nodeFreshnessDetach(RBURIListenerList *l);
+
+	void nodeAnnounceAttach(RBURIListenerList *l, uriListener_t *t,
+			int sessionId, bool updated);
+
+	void nodeAnnounceDetach(RBURIListenerList *l);
+
+	void nodeInquiryAttach(RBURIListenerList *l, uriListener_t *t,
+			int sessionId, bool updated);
+
+	void nodeInquiryDetach(RBURIListenerList *l);
+
+	void nodeMgmtLQIAttach(RBURIListenerList *l, uriListener_t *t,
+			int sessionId, bool updated);
+
+	void nodeMgmtLQIDetach(RBURIListenerList *l);
+
+	void startupAttach(RBURIListenerList *l, uriListener_t *t, int sessionId,
+			bool updated);
+
+	void startupDetach(RBURIListenerList *l);
+
+	void serviceDiscoveryAttach(RBURIListenerList *l, uriListener_t *t,
+			int sessionId, bool updated);
+
+	void serviceDiscoveryDetach(RBURIListenerList *l);
+
+	void resetCommandAttach(RBURIListenerList *l, uriListener_t *t,
+			int sessionId, bool updated);
+
+	void resetCommandDetach(RBURIListenerList *l);
+
+	void permitJoinAttach(RBURIListenerList *l, uriListener_t *t, int sessionId,
+			bool updated);
+
+	void permitJoinDetach(RBURIListenerList *l);
+
+	void leaveCommandAttach(RBURIListenerList *l, uriListener_t *t,
+			int sessionId, bool updated);
+
+	void leaveCommandDetach(RBURIListenerList *l);
+
+	void serviceDescriptorAttach(RBURIListenerList *l, uriListener_t *t,
+			int sessionId, bool updated);
+
+	void serviceDescriptorDetach(RBURIListenerList *l);
+
+	void nodeDescriptorAttach(RBURIListenerList *l, uriListener_t *t,
+			int sessionId, bool updated);
+
+	void nodeDescriptorDetach(RBURIListenerList *l);
+
+	void getnodebindingAttach(RBURIListenerList *l, uriListener_t *t,
+			int sessionId, bool updated);
+
+	void getnodebindingDetach(RBURIListenerList *l);
+
+	void bindAttach(RBURIListenerList *l, uriListener_t *t, int sessionId,
+			bool updated);
+
+	void bindDetach(RBURIListenerList *l);
+
+	void unbindAttach(RBURIListenerList *l, uriListener_t *t, int sessionId,
+			bool updated);
+
+	void unbindDetach(RBURIListenerList *l);
+
+	void allServicesAttach(RBURIListenerList *l, uriListener_t *t,
+			int sessionId, bool updated);
+
+	void allServicesDetach(RBURIListenerList *l);
+
+	void serviceAttach(RBURIListenerList *l, uriListener_t *t, int sessionId,
+			bool updated);
+
+	void serviceDetach(RBURIListenerList *l);
+
+//#ifdef WSN_C_PROTOCOL_BACKWARD_COMPATIBILITY
+	void serviceAttach_BC(RBURIListenerList *l, uriListener_t *t, int sessionId,
+			bool updated);
+//#endif
+
+	void callbackAttach(RBURIListenerList *l, uriListener_t *listener,
+			int sessionId, bool updated);
+
+	void callbackDetach(RBURIListenerList *l);
+
+	void checkWsncAttach(RBURIListenerList *l, uriListener_t *listener,
+			int endpointId);
+
+	void checkWsncDetach(RBURIListenerList *l, int endpointId);
+
+	/// Timers management
+	typedef void *TIMERPROC;
+
+	int initTimers(void);
+
+	void createRootResources(void);
+	Resource *createNetResources(const char *name);
+	Resource *createIBResources(void);
+	Resource *createNodeResources(Resource *root, Node *node);
+	Resource *createCallbackResources(Resource *root, uriListener_t *l,
+			RBURIListenerList *rbl);
+	void syncCallbackResources(Resource *root, RBURIListenerList *l);
+
+	Resource *createFolder(Resource *root, const char *path,
+			ResHandler handler = NULL);
+
+	Resource *createFolder(Resource *root, const char *path,
+			const RBResourceDescriptor rb[]);
+
+	void createResources(Resource *root, const RBResourceDescriptor rb[]);
+
+	/// REST Server and Client
+	RESTServer *pRESTServer;
+	RESTClient *pRESTClient;
+
+	/// Pointer to XML Message Composer
+	XMLMsgComposer *pXMLMsgComposer;
+
+	/** Temporary buffer storing the node cache. It is valid
+	 *  only inside of nodeInquiryAttach
+	 */
+	ZbNetDb *soFarBuffer;
+
+	/// Pointer to XML Message Parser
+	XMLMsgParser *pXMLMsgParser;
+
+	/// Pointer to QueryParser
+	QueryParser *pQueryParser;
+
+	/// Pointer to Local Node
+	LocalNode<RESTBroker> *pLocalNode;
+
+	/// Pointers to GAL Agents
+	DiscoveryAgent<RESTBroker> *pDAgent;
+	ServiceAgent<RESTBroker> *pSAgent;
+	ManagementAgent<RESTBroker> *pMngmtAgent;
+	TrustCenterAgent<RESTBroker> *pTCAgent;
+
+	/// Pointer to GAL object containing GW Management Error Messages list and GW states descriptions
+	GWManagementMessages *pGWManagementMsgs;
+
+	///	Pointer to GalZbIf object
+	GalZbIf *pGalZb;
+
+	/// Pointer to Gal database (refer to ZbNetDb class)
+	ZbNetDb *pGalDb;
+
+	/// Pointer to a Debug object -> logger
+	Debug *pLogger;
+
+	bool debugEnabled;
+	int debugLevel;
+
+	bool autostart;
+
+	bool localRegToDAnnceEnabled;
+	bool useDefaultNWKRootURI;
+
+	//isAMLocallyEnabled is true if Announcement Mode has been enabled locally by the RESTBroker
+	bool isAMLocallyEnabled;
+	//isRFLocallyEnabled is true if Refresh Mode has been enabled locally by the RESTBroker
+	bool isFMLocallyEnabled;
+
+	string wsnCAddress;
+
+	void *notifyGWDescriptorToWsnc(RESTBroker::Task *task);
+
+private:
+	/// Mutex
+	pthread_mutex_t mux;
+
+	std::map<int, pthread_t> pthread_tMap;
+
+	struct {
+		Resource *defNet;
+		Resource *defLocalNode;
+		Resource *defCallbacks;
+	} resources;
+
+	const static RBResourceDescriptor rootDesc[];
+	const static RBResourceDescriptor netDesc[];
+	const static RBResourceDescriptor ibRootDesc[];
+	const static RBResourceDescriptor ibNetDesc[];
+	const static RBResourceDescriptor nodeDesc[];
+	const static RBResourceDescriptor lnNodeDesc[];
+	const static RBResourceDescriptor allnNodeDesc[];
+	const static RBResourceDescriptor allServicesDesc[];
+	const static RBResourceDescriptor allServicesConnDesc[];
+	const static RBResourceDescriptor servicesDesc[];
+	const static RBResourceDescriptor connDesc[];
+
+//#ifdef WSN_C_PROTOCOL_BACKWARD_COMPATIBILITY
+	const static RBResourceDescriptor lnNodeDescBC[];
+	const static RBResourceDescriptor servicesDescBC[];
+	const static RBResourceDescriptor connDescBC[];
+//#endif
+
+	struct Listeners {
+		RBURIListenerList gwStatus;
+		RBURIListenerList startup;
+		RBURIListenerList serviceDiscovery;
+		RBURIListenerList serviceDescriptor;
+		RBURIListenerList nodeDescriptor;
+		RBURIListenerList getnodebinding;
+		RBURIListenerList bind;
+		RBURIListenerList unbind;
+		RBURIListenerList resetCommand;
+		RBURIListenerList leaveCommand;
+		RBURIListenerList permitJoin;
+		RBURIListenerList freshness;
+		RBURIListenerList nodeAnnounce;
+		RBURIListenerList nodeInquiry;
+		RBURIListenerList nodeMgmt_Lqi;
+		RBURIListenerList allServices;
+		std::map<int, RBURIListenerList> service;
+		std::map<int, RBURIListenerList> customizedCallback;
+		//#ifdef WSN_C_PROTOCOL_BACKWARD_COMPATIBILITY
+		std::map<int, RBURIListenerList> service_BC;
+		//#endif
+	} listeners;
+
+};
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTClient.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTClient.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTClient.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,285 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <winport.h>
+
+#include "CRESTClient.h"
+
+RESTClient *RESTClient::pInstance = NULL;
+
+/**
+ Constructor
+ RESTClient constructor. It is a protected method (pattern Singleton)
+
+ @param void Void.
+ @return Void.
+ */
+
+RESTClient::RESTClient() {
+	ConfigurationRepository *_conf = ConfigurationRepository::instance();
+	// We load the configuration from the ConfigurationManager
+	this->debugEnabled = _conf->getint("main:debugEnabled", false);
+	this->debugLevel = _conf->getint("Debug:RESTClientDL", TEST);
+
+	pLogger = new Debug("RESTClient");
+	pLogger->setDebugMode(this->debugEnabled);
+	pLogger->setDebugLevel(this->debugLevel);
+
+	pLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+	pLogger->enableDebugOuput(DBG_SCREEN);
+
+	pthread_mutex_init(&mux, NULL);
+
+#ifdef DEBUG_ACTIVE_RESTCLIENT
+	pLogger->debug("Constructor");
+#endif
+}
+
+/**
+ Destructor
+ RESTClient destructor.
+
+ @param void Void.
+ @return Void.
+ */
+
+RESTClient::~RESTClient() {
+	std::map<int, HTTPClient *>::iterator i;
+	std::map<int, pthread_t>::iterator j;
+
+#ifdef DEBUG_ACTIVE_RESTCLIENT
+	printf("RESTClient - Destructor\n");
+#endif
+
+	std::list<postMessage>::iterator bufIt;
+	//delete httpClient;
+	running = false;
+	for (j = pthread_tMap.begin(); j != pthread_tMap.end(); j++)
+		pthread_join(j->second, NULL);
+	for (i = httpClientPool.begin(); i != httpClientPool.end(); i++)
+		delete i->second;
+	if (pLogger != NULL) {
+		delete pLogger;
+		pLogger = NULL;
+	}
+}
+
+/**
+ Public method RESTClient *Instance(void)
+ (pattern Singleton)
+
+ @param void Void.
+ @return Instance of RESTClient class.
+ */
+
+RESTClient *RESTClient::getRESTClient(void) {
+	if (pInstance == NULL) {
+		pInstance = new RESTClient;
+	}
+	return pInstance;
+}
+
+/**
+ Public method RESTClient init
+ RESTClient initialization: dispatchPostData thread is created.
+
+ @param void Void.
+ @return Void.
+ */
+
+void RESTClient::init() {
+	int tcRet;
+#ifdef DEBUG_ACTIVE_RESTCLIENT
+	pLogger->debug("init");
+#endif
+
+	pthread_mutex_lock(&mux);
+	ConfigurationRepository *_conf = ConfigurationRepository::instance();
+	// We load the configuration from the ConfigurationManager
+	int httpOptTimeout = _conf->getint("RESTClient:httpOptTimeout", 3);
+#ifdef DEBUG_ACTIVE_RB
+	pLogger->debug("init - httpOptTimeout = %d", httpOptTimeout);
+#endif
+	pthread_mutex_unlock(&mux);
+
+	int i = 0;
+	int bufferId = 1;
+	running = true;
+	for (i = 0; i < 2; i++) {
+		threadContextMap[bufferId].bufferId = bufferId;
+		threadContextMap[bufferId].restClientPointer = this;
+
+		/// dispatchPostData thread is created.
+		tcRet = pthread_create(&(this->pthread_tMap[bufferId]), NULL,
+				dispatchPostData_SW, &(threadContextMap[bufferId]));
+
+		if (tcRet) {
+			pLogger->error("init - Error in creating thread dispatchPostData");
+		} else {
+			httpClientPool[bufferId] = new HTTPClient();
+			httpClientPool[bufferId]->setOptTimeout(httpOptTimeout);
+		}
+		bufferId++;
+	}
+
+}
+
+int RESTClient::sendPostData(uriListener_t *uriListener, std::string *data) {
+	struct postMessage postMsg;
+	postMsg.URL = uriListener->URL;
+	postMsg.data = *data;
+
+	// The POST message is stored into a specific buffer among those contained in postMessagesBuffers.
+	// If the size of the considered buffer is bigger than MAX_POST_MESSAGE_BUFFER_SIZE, the considered message is discarded.
+	pthread_mutex_lock(&mux);
+	if (this->postMessagesBuffers[uriListener->type].size() < MAX_POST_MESSAGE_BUFFER_SIZE) {
+		this->postMessagesBuffers[uriListener->type].push_back(postMsg);
+		pthread_mutex_unlock(&mux);
+#ifdef DEBUG_ACTIVE_RESTCLIENT
+		pLogger->info("sendPostData- stored postMsg to %s (bufferId %d, size %d)",postMsg.URL.c_str(),uriListener->type, this->postMessagesBuffers[uriListener->type].size());
+#endif
+	} else {
+		pthread_mutex_unlock(&mux);
+		pLogger->error("WARNING: sendPostData - Max size reached (%d) for bufferId %d",this->postMessagesBuffers[uriListener->type].size(), uriListener->type);
+	}
+	return 0;
+}
+
+int RESTClient::sendPostData(std::list<uriListener_t> *uriList,
+		std::string *data) {
+#ifdef DEBUG_ACTIVE_RESTCLIENT
+	pLogger->debug("sendPostData ( uriList, data )");
+#endif
+
+	std::list<uriListener_t>::iterator it;
+	it = uriList->begin();
+
+	for (it = uriList->begin(); it != uriList->end(); it++) {
+#ifdef DEBUG_ACTIVE_RESTCLIENT
+		pLogger->info("sendPostData ( uriList, data ) - POST message to UriListener  %s -> use sendPostData ( URL, data )", it->URL.c_str());
+#endif
+
+		// The received message is posted to registered URI listener
+		this->sendPostData(&(*it), data);
+	}
+	return 0; //TODO		Define new return code (e.g. the number of tram
+}
+
+/**
+ Public method RESTClient dispatchPostData_SW
+ Static wrapper: RESTClient dispatchPostData is called. In particular, this is used in dispatchPostData thread creation.
+
+ @param arg Pointer to the RESTClient object.
+ @return Void.
+ */
+
+void* RESTClient::dispatchPostData_SW(void *arg) {
+	RESTClient *pRESTClient = ((threadContext_t *) arg)->restClientPointer;
+	/*
+	 #ifdef DEBUG_ACTIVE_RESTCLIENT
+	 if (pRESTClient->debugEnabled == true)
+	 printf("RESTClient::dispatchPostData_SW\n");
+	 #endif
+	 */
+	pRESTClient->dispatchPostData(((threadContext_t *) arg)->bufferId);
+	return 0;
+}
+
+/**
+ Public method RESTClient dispatchPostData
+ This method works in a separate thread. In details, the message buffer is continuously checked: if its size is greater than zero, the stored messages are sent
+ through a HTTP POST (using HTTPServer public method postData).
+
+ @param bufferId Identifier of the considered buffer.
+ @return Void.
+ */
+
+void* RESTClient::dispatchPostData(int bufferId) {
+#ifdef DEBUG_ACTIVE_RESTCLIENT
+	pLogger->debug("dispatchPostData");
+#endif
+
+	while (running) {
+
+		if (this->postMessagesBuffers[bufferId].size() > 0) {
+			std::list<postMessage>::iterator bufIt;
+			bufIt = this->postMessagesBuffers[bufferId].begin();
+			if (bufIt != this->postMessagesBuffers[bufferId].end()) {
+#ifdef DEBUG_ACTIVE_RESTCLIENT
+				pLogger->info("dispatchPostData - postMsg to URL %s",bufIt->URL.c_str());
+				const char * temp = bufIt->data.c_str();
+				for (ushort i=0; i < strlen(temp);i++)
+				printf("%c",temp[i]);
+				printf("\r\n");
+#endif
+				httpClientPool[bufferId]->postData(&bufIt->URL, &bufIt->data,
+						(void *) (&receivePostResponse_SW));
+				// Remove post message from POST Messagge Buffer.
+				pthread_mutex_lock(&mux);
+				this->postMessagesBuffers[bufferId].pop_front();
+				pthread_mutex_unlock(&mux);
+			}
+		} else
+			usleep(POST_POLL_TIMEOUT);
+	}
+
+	return NULL;
+}
+
+/**
+ Public static method RESTClient receivePostResponse_SW
+ This method is registered when httpClient->postData is called. On POST response reception, this method is invoked: in this way, the data is passed to this function
+ directly instead of being redirected to stdout. The input parameters have been defined according to HTTP Client curl library.
+
+ @param buffer Buffer containing the HTTP POST response.
+ @param size Size of each data element in the buffer.
+ @param nmemb Number of data elements in the buffer.
+ @param userp Data structure used by libcurl.
+ @return Number of bytes that have been processed (i.e. size*nmemb).
+ */
+
+size_t RESTClient::receivePostResponse_SW(void *buffer, size_t size,
+		size_t nmemb, void *userp) {
+	RESTClient *restClient = RESTClient::getRESTClient();
+#ifdef DEBUG_ACTIVE_RESTCLIENT
+	if (restClient->debugEnabled == true)
+	printf("RESTBroker::wnsnodesList_RspCbW\n");
+#endif
+	return restClient->receivePostResponse(buffer, size, nmemb, userp);
+}
+
+/**
+ Protected method RESTClient receivePostResponse
+
+
+ @param buffer Buffer containing the HTTP POST response.
+ @param size Size of each data element in the buffer.
+ @param nmemb Number of data elements in the buffer.
+ @param userp Data structure used by libcurl.
+ @return Number of bytes that have been processed (i.e. size*nmemb).
+ */
+
+size_t RESTClient::receivePostResponse(void *buffer, size_t size, size_t nmemb,
+		void *userp) {
+
+#ifdef DEBUG_ACTIVE_RESTCLIENT
+	pLogger->debug("receivePostResponse - POST Response received (size %d, length %d). Buffer %s)", size, nmemb, (char *) buffer);
+#endif
+	//printf("receivePostResponse - POST Response received (size %d, length %d). Buffer %s\n", size, nmemb ,(char *)buffer);
+	return size * nmemb;
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTClient.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTClient.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTClient.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,128 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef RESTCLIENT_H
+#define RESTCLIENT_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <string>
+
+#include "ThreadPool.h"
+#include "TimerThread.h"
+#include <pthread.h>
+
+#include "CHTTPClient.h"
+#include "CResource.h"
+#include "CMessage.h"
+#include "ZbNetDb.h"
+
+#include "CDebug.h"
+
+#include "ConfigurationRepository.h"  
+
+/**
+ RESTClient is in charge of sending RESTBroker messages through HTTP POST. In details, the public method "sendPostData" is offered: This function stores
+ all these messages in a FIFO list i.e. postMessagesBuffers. Moreover, a new thread is created executing dispatchPostData protected method: this function
+ continously checks the message buffer and, if it is not empty, the cointained messages are sent through a HTTP POST (using HTTPServer public method postData).
+
+ POST_POLL_TIMEOUT is the delay between two subsequents check on postMessagesBuffers
+ */
+#define POST_POLL_TIMEOUT				200000
+
+/**
+ MAX_POST_MESSAGE_BUFFER_SIZE is the maximum postMessagesBuffers size allowed. When the public method "sendPostData" is called, the message is stored in the
+ FIFO list postMessagesBuffers only if its size is less than MAX_POST_MESSAGE_BUFFER_SIZE.
+ */
+#define MAX_POST_MESSAGE_BUFFER_SIZE			100
+
+class RESTClient {
+
+public:
+	// Constructors
+
+	// Destructor
+	~RESTClient();
+
+	// Functions: modifiers (set), selectors (get)
+
+	// Pattern Singleton
+	static RESTClient *getRESTClient(void);
+
+	void init();
+
+	int sendPostData(std::string *URL, std::string *data);
+
+	int sendPostData(std::list<uriListener_t> *uriList, std::string *data);
+
+	// Mainly used as protected method by sendPostData( std::list < uriListener_t > *uriList, std::string *data );
+	int sendPostData(uriListener_t *uriListener, std::string *data);
+
+	static void *dispatchPostData_SW(void *arg);
+
+	static size_t receivePostResponse_SW(void *buffer, size_t size,
+			size_t nmemb, void *userp);
+
+	// iterators:
+	// Attributes visible by scope of instantiation and use
+
+protected:
+
+	///	Constructor (pattern Singleton)
+	RESTClient();
+
+	///	Data management
+	void *dispatchPostData(int bufferId);
+
+	size_t receivePostResponse(void *buffer, size_t size, size_t nmemb,
+			void *userp);
+
+	// Attributes visible to descendents
+
+	///	Pointer to a Debug object -> logger
+	Debug *pLogger;
+
+	/// To enable/disable Debug (default value is 0)
+	bool debugEnabled;
+	int debugLevel;
+
+	typedef struct {
+		RESTClient *restClientPointer;
+		int bufferId;
+	} threadContext_t;
+
+	std::map<int, threadContext_t> threadContextMap;
+	std::map<int, HTTPClient *> httpClientPool;
+
+private:
+	// Local attributes
+	bool running;
+
+	// Pattern Singleton
+	static RESTClient *pInstance;
+
+	///	Mutex
+	pthread_mutex_t mux;
+
+	///	Thread descriptor
+	//pthread_t tId;
+	std::map<int, pthread_t> pthread_tMap;
+
+	///	Data structure containing POST message and related destination URL.
+	struct postMessage {
+		std::string URL;
+		std::string data;
+	};
+	///	postMessagesBuffers is a FIFO list containing POST messages.
+	std::map<int, std::list<postMessage> > postMessagesBuffers;
+};
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTServer.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTServer.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTServer.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,700 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#define LOCAL_LOGGER pLogger
+#ifdef DEBUG_ACTIVE_RESTSERVER
+#define LOCAL_DEBUG_ENABLED
+#endif
+
+#include "CRESTServer.h"
+#include "CQueryParser.h"
+
+static struct {
+	int restCode;
+	const char *msg;
+} ctable[] = { { /*NO_ERROR*/REC_SUCCESS, "" },
+
+{ /*METHOD_NOT_ALLOWED*/REC_NOT_ALLOWED, "Method not allowed on resource" },
+
+{ /*WRONG_REQUEST*/REC_GENERAL_ERROR, "Wrong request on resource" },
+
+{ /*FEATURE_NOT_SUPPORTED*/REC_GENERAL_ERROR, "Feature not supported" },
+
+{ /*GENERIC_REST_ERROR*/REC_GENERAL_ERROR, "REST Error" },
+
+{ /*BAD_PARAMETER*/REC_PARAMETER_INVALID_VALUE, "Bad input parameter" },
+
+{ /*PARAMETER_MISSING*/REC_PARAMETER_MISSING, "Parameter missing" },
+
+{ /*URILISTENER_ALREADY_REGISTERED*/REC_PARAMETER_INVALID_VALUE,
+		"URIListener already registered" },
+
+{ /*URILISTENER_NOT_REGISTERED*/REC_PARAMETER_INVALID_VALUE,
+		"URIListener not previously registered" },
+
+{ /*URILISTENER_LIST_MAX_SIZE_EXCEEDED*/REC_MEMORY_ERROR,
+		"URIListener list maximum size exceeded" },
+
+{ /*TIMEOUT*/REC_TIMEOUT, "Timeout" },
+
+{ /*NO_MESSAGE_YET*/REC_EMPTY, "No message received so far" },
+
+{ /*ZB_NWK_FAILURE*/REC_NETWORK_FAILURE, "ZigBee Network Failure" } };
+
+unsigned RESTSessionContext::ridgen = (unsigned) time(NULL);
+
+UriListenerHandback *RESTCallbackInfo::clone(void) {
+	return new RESTCallbackInfo(*this);
+}
+
+void RESTCallbackInfo::setTimeout(std::string s) throw (RESTException) {
+	char *end;
+	// Init expiry
+	expiry = NO_EXPIRY_TIME;
+
+	timeoutSet = !s.empty();
+	if (!timeoutSet)
+		return;
+
+	// Read the timeout value (expressed as a number of base 16) and convert it into
+	// unsigned long int (base 10)
+	timeout = strtoul(s.c_str(), &end, 16);
+
+	if (*end)
+		throw RESTException(BAD_PARAMETER, "Bad timeout parameter");
+
+	// If timeout == 0xffffffff or timeout == 0 -> no timer has to be created
+	// However, timeoutSet should not be set to false.
+	// timeoutSet could be used to check whether the timeout parameter has been included.
+	// In fact, the timeout is not mandatory in every function. Anyway, when this parameter
+	// is mandatory, if it is not present, an error should be included in the HTTP Response.
+	if (timeout > 0 && timeout < 0xffffffffU) {
+		expiry = time(NULL) + timeout;
+		/*
+		 #ifdef DEBUG_ACTIVE_RESTSERVER
+		 printf("\nExpiry time (0 < timeout < 0xffffffffU) = %d\n", (int) expiry);
+		 #endif
+		 */
+	} else {
+		expiry = NO_EXPIRY_TIME;
+#ifdef DEBUG_ACTIVE_RESTSERVER
+//		printf("\nExpiry timeout not set\n");
+#endif
+	}
+}
+
+bool RESTCallbackInfo::expired(void) {
+	/*
+	 #ifdef DEBUG_ACTIVE_RESTSERVER
+	 printf("\nRESTCallbackInfo::expired - %d > %ld ?\n",timeoutSet&&time(NULL), expiry);
+	 #endif
+	 */
+	if (expiry == NO_EXPIRY_TIME)
+		return false;
+	else
+		return timeoutSet && time(NULL) > expiry;
+}
+
+RESTSessionContext::RESTSessionContext(RESTServer &server, shttpd_arg *context) :
+		HTTPSessionContext(context), server(server) {
+	makeRequestIdentifier();
+	server.addContext(this);
+}
+
+RESTSessionContext::~RESTSessionContext(void) {
+	server.removeContext(this);
+}
+
+bool RESTSessionContext::asynch(void) {
+	return callbackDestinationSet;
+}
+
+bool RESTSessionContext::polled(void) {
+	return callbackDestinationSet && callbackDestination.empty();
+}
+
+const char *RESTSessionContext::getRequestIdentifier(void) {
+	return asynch() ? cbinfo.requestIdentifier.c_str() : NULL;
+}
+
+const char *RESTSessionContext::makeRequestIdentifier(void) {
+	char buf[20];
+
+	snprintf(buf, 20, "%08x", ridgen++);
+
+	cbinfo.requestIdentifier = buf;
+
+	return cbinfo.requestIdentifier.c_str();
+}
+
+void RESTSessionContext::parse(const char *qs) throw (RESTException) {
+	QueryParser *qp;
+	std::string s;
+
+	qp = QueryParser::getQueryParser();
+	callbackDestinationSet = qp->getParameter("urilistener", qs,
+			callbackDestination);
+	qp->getParameter("timeout", qs, s);
+	cbinfo.setTimeout(s);
+}
+
+RESTServer::RequestsHandler::RequestsHandler(XMLMsgParser *pXMLMsgParser,
+		XMLMsgComposer *pXMLMsgComposer, RESTServer *server) :
+		pXMLMsgParser(pXMLMsgParser), pXMLMsgComposer(pXMLMsgComposer), server(
+				server) {
+	/* empty */
+}
+
+void RESTServer::RequestsHandler::handle(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *body,
+		HTTPSessionContext *hctxt) throw (RESTException, HTTPException) {
+	RESTSessionContext *ctxt;
+	std::string timeout;
+
+	ctxt = (RESTSessionContext *) res->data.p;
+	if (ctxt->getSessionStatus() >= S_SERVED)
+		throw new HTTPException(404, "Not Found");
+
+	switch (reqMethod) {
+	case M_PUT:
+		if (pXMLMsgParser->getValue(timeout, body))
+			throw RESTException(BAD_PARAMETER, "Bad value parameter");
+		ctxt->cbinfo.setTimeout(timeout);
+		break;
+
+	case M_GET:
+		if (ctxt->response.empty())
+			throw new RESTException(NO_MESSAGE_YET);
+
+		server->restSuccess(ctxt->response.c_str(), hctxt);
+		break;
+
+	default:
+		throw HTTPException(405, "Method Not Allowed");
+	}
+}
+
+RESTServer::RESTServer(XMLMsgParser *pXMLMsgParser,
+		XMLMsgComposer *pXMLMsgComposer) :
+		pXMLMsgParser(pXMLMsgParser), pXMLMsgComposer(pXMLMsgComposer), requestsHandler(
+				pXMLMsgParser, pXMLMsgComposer, this) {
+
+	//	Mutex init
+	pthread_mutex_init(&mux, NULL);
+
+	ConfigurationRepository *_conf = ConfigurationRepository::instance();
+	//	We load the configuration from the ConfigurationManager
+	this->debugEnabled = _conf->getint("main:debugEnabled", false);
+
+	pLogger = new Debug("RESTServer");
+	//	Set Debug parameters
+	pLogger->setDebugMode(this->debugEnabled);
+	//pLogger->setDebugMode(DBG_ENABLED);	
+	//pLogger->setDebugMode(DBG_DISABLED);
+	//pLogger->setDebugLevel(DEBUGGING);
+	pLogger->setDebugLevel(TEST);
+	pLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+	pLogger->enableDebugOuput(DBG_SCREEN);
+	//pLogger->enableDebugOuput(DBG_LOGFILE);		
+	//L_DEBUG("Constructor");
+}
+
+RESTServer::~RESTServer() {
+#ifdef DEBUG_ACTIVE_RESTSERVER
+	printf("RESTServer Destructor\n");
+#endif
+	delete pXMLMsgComposer;
+	//delete pXMLMsgParser;
+	delete pLogger;
+}
+
+int RESTServer::init() {
+	ConfigurationRepository *conf;
+
+	L_DEBUG("init");
+
+	conf = ConfigurationRepository::instance();
+
+	initSSL(conf);
+	if (initPorts(conf)) {
+		L_ERROR("init - RESTServer initialization failed");
+		return 1;
+	}
+	initDigest(conf);
+	initResources();
+
+	pRESTClient = RESTClient::getRESTClient();
+
+	// Init successfully completed
+	return 0;
+}
+
+void RESTServer::initSSL(ConfigurationRepository *conf) {
+	const char *p;
+
+	pthread_mutex_lock(&mux);
+	sslEnabled = conf->getint("RESTServer:ssl", false);
+	p = conf->getstring("RESTServer:sslCertFile", NULL);
+	pthread_mutex_unlock(&mux);
+
+	L_DEBUG("init - sslEnabled = %d", sslEnabled);
+	if (!sslEnabled)
+		return;
+
+	if (p != NULL) {
+		L_DEBUG("init - sslCertFile = %s", p);
+
+		sslCertificateFile = std::string(p);
+		setOption("ssl_cert", sslCertificateFile.c_str());
+	} else {
+		L_DEBUG("init - sslCertFile = NULL value: disabling SSL");
+		sslEnabled = false;
+	}
+
+}
+
+int RESTServer::initPorts(ConfigurationRepository *conf) {
+	const char *p, *tok, *delim;
+	char *q, *save;
+	int len;
+
+	// We load the configuration from the ConfigurationManager
+	pthread_mutex_lock(&mux);
+	p = conf->getstring("RESTServer:serverPorts", DEFAULT_SERVER_PORT);
+	pthread_mutex_unlock(&mux);
+
+	if (p != NULL) {
+		L_DEBUG("init - serverPorts = %s", p);
+	} else {
+		L_DEBUG("init - serverPorts = NULL value");
+		L_WARN("init - serverPorts NULL value defaulting to %s",
+				DEFAULT_SERVER_PORT);
+		p = DEFAULT_SERVER_PORT;
+	}
+
+	serverPorts = std::string(p);
+	if (!sslEnabled) {
+		L_DEBUG("SSL is not enabled, removing trailing 's'");
+		q = strdup(p);
+		if (q != NULL) {
+			serverPorts = "";
+			delim = "";
+			for (tok = strtok_r(q, " \t,", &save); tok != NULL;
+					tok = strtok_r(NULL, " \t,", &save)) {
+				len = strcspn(tok, "Ss");
+				serverPorts += delim;
+				serverPorts.append(tok, len);
+				delim = ",";
+			}
+
+			L_DEBUG("Resulting string is '%s'", serverPorts.c_str());
+			free(q);
+		} else
+			L_WARN("Failed to fix ports string (oom)");
+	}
+
+	int result = setOption("ports", serverPorts.c_str());
+	if (result)
+		L_ERROR("initPorts - FAILED");
+
+	return result;
+}
+
+void RESTServer::initDigest(ConfigurationRepository *conf) {
+	const char *p;
+
+	// We load the configuration from the ConfigurationManager
+	pthread_mutex_lock(&mux);
+	httpDigestAuthEnabled = conf->getint("RESTServer:httpDigestAuth", false);
+	p = conf->getstring("RESTServer:httpDigestAuthPwdFile", NULL);
+	pthread_mutex_unlock(&mux);
+	L_DEBUG("init - httpDigestAuth = %d", httpDigestAuthEnabled);
+
+	if (!httpDigestAuthEnabled)
+		return;
+
+	if (p != NULL) {
+		L_DEBUG("init - httpDigestAuthPwdFile = %s", p);
+		httpDigestAuthPwdFile = std::string(p);
+
+	} else {
+		L_DEBUG("init - httpDigestAuthPwdFile = NULL value: "
+				"disabling Digest");
+		httpDigestAuthEnabled = false;
+	}
+}
+
+void RESTServer::initResources() {
+	ResourceDescriptor *rd;
+
+	rd = new ResourceDescriptor("requests");
+	resources.requests = new Resource(rd, NULL, NULL);
+
+	registerResource(resources.requests, NULL);
+}
+
+void RESTServer::start() {
+
+	HTTPServer::start();
+
+	L_DEBUG("REST Server started at port %s\n", serverPorts.c_str());
+}
+
+void RESTServer::serveRequest(Resource *resource, HTTPSessionContext *ctxt)
+		throw (HTTPException) {
+	const char *queryString, *reqUri;
+	RESTSessionContext *rctxt;
+	std::string *xmlMsg, xmlResponse;
+	Method reqMethod;
+	const char *rid;
+
+	L_DEBUG("serveRequest");
+
+	reqUri = ctxt->getReqURI();
+	reqMethod = ctxt->getReqMethod();
+	queryString = ctxt->getQueryStr();
+	xmlMsg = ctxt->getRxDataBuffer();
+
+	rctxt = dynamic_cast<RESTSessionContext *>(ctxt);
+
+	L_DEBUG("dispatcher - reqURI = %s ", reqUri);
+	L_DEBUG("dispatcher - reqMethod = %d ", reqMethod);
+	L_DEBUG("dispatcher - query string = %s ", queryString);
+	//L_INFO ("dispatcher - rxDataBuffer = ##%s##", xmlMsg -> c_str());
+	// Instead of %s let print each single char since often not all the XML message is printed out!
+	L_INFO("dispatcher - rxDataBuffer =>");
+#ifdef DEBUG_ACTIVE_RESTSERVER
+	if (this->debugEnabled)
+	{
+		const char * temp = xmlMsg-> c_str();
+		for (ushort i=0; i < strlen(temp);i++)
+		printf("%c",temp[i]);
+		printf("\r\n");
+	}
+#endif
+	// Get all the mandatory values (timeout & callbackDestination)
+	rctxt->parse(queryString);
+
+	// Store the class pointer to the reference RESTSessionContext instance
+	rctxt->cbinfo.refRestSessionCtxt = rctxt;
+	// Store the class pointer to the reference Resource instance
+	rctxt->cbinfo.refResource = resource;
+
+	// Get query string
+	try {
+		if (resource->handler != NULL)
+			resource->handler->handle(resource, reqUri, reqMethod, queryString,
+					xmlMsg, ctxt);
+		else
+			defaultHandler(resource, reqUri, reqMethod, queryString, xmlMsg,
+					ctxt);
+
+		if (rctxt->asynch() && ctxt->getSessionStatus() != S_READY) {
+			L_DEBUG("serveRequest - asynch call");
+			rid = rctxt->getRequestIdentifier();
+			xmlResponse = pXMLMsgComposer->createSuccessMsg(NULL, NULL, rid);
+			rctxt->setResponse(xmlResponse);
+			rctxt->setSessionStatus(S_READY);
+		}
+	} catch (RESTException &e) {
+		L_WARN("RESTException!");
+		restError(e.eid, e.msg, NULL, ctxt);
+	}
+}
+
+void RESTServer::defaultHandler(Resource *res, const char *reqUri,
+		Method reqMethod, const char *queryString, std::string *body,
+		HTTPSessionContext *ctxt) {
+	std::string detail;
+
+	detail = pXMLMsgComposer->createResourceInfoMsg(res);
+
+	restSuccess(detail.c_str(), ctxt);
+}
+
+void RESTServer::addContext(RESTSessionContext *ctxt) {
+	createRequestResources(ctxt);
+}
+
+void RESTServer::removeContext(RESTSessionContext *ctxt) {
+	destroyRequestResources(ctxt);
+}
+
+Resource *RESTServer::createRequestResources(RESTSessionContext *ctxt) {
+	ResourceDescriptor *rd;
+	const char *path;
+	Resource *r;
+
+	path = ctxt->cbinfo.requestIdentifier.c_str();
+	rd = new ResourceDescriptor(path);
+
+	r = new Resource(rd, &requestsHandler, ctxt);
+
+	registerResource(r, resources.requests);
+
+	return r;
+}
+
+void RESTServer::destroyRequestResources(RESTSessionContext *ctxt) {
+	const char *path;
+	Resource *r;
+
+	path = ctxt->cbinfo.requestIdentifier.c_str();
+	r = findResource(resources.requests, path);
+	if (r != NULL)
+		removeResource(r);
+}
+
+HTTPSessionContext *RESTServer::makeSessionContext(shttpd_arg *arg)
+		throw (HTTPException) {
+	return new RESTSessionContext(*this, arg);
+}
+
+void RESTServer::restError(int errorId, const char *errorDesc,
+		const char *nwkStatus, int sessionId) {
+	restError(errorId, errorDesc, nwkStatus,
+			this->getHTTPSessionContext(sessionId));
+}
+
+void RESTServer::restError(int errorId, const char *errorDesc,
+		const char *nwkStatus, HTTPSessionContext *ctxt) {
+	RESTSessionContext *rctxt;
+	std::string xmlResponse;
+
+	if (ctxt == NULL) {
+		pLogger->error("restError - ctxt == NULL - ERROR!");
+		return;
+	}
+
+	rctxt = dynamic_cast<RESTSessionContext *>(ctxt);
+
+	L_DEBUG("restError_Rsp");
+
+	if (errorDesc == NULL)
+		errorDesc = ctable[errorId].msg;
+
+	// Call XMLMsgComposer method to build a XML Response.
+	xmlResponse = pXMLMsgComposer->createErrorMsg(ctable[errorId].restCode,
+			errorDesc, nwkStatus, rctxt->getRequestIdentifier());
+
+	L_DEBUG("restError - xmlResponse = %s", xmlResponse.c_str());
+
+	send(rctxt, xmlResponse);
+}
+
+bool RESTServer::restError(int errorId, const char *errorDesc,
+		const char *nwkStatus, uriListener_t *listener) {
+	RESTCallbackInfo *cbinfo;
+	std::string xmlResponse;
+	const char *rid;
+
+	cbinfo = dynamic_cast<RESTCallbackInfo *>(listener->hback);
+
+	L_DEBUG("restError_Rsp - errorDesc = %s", errorDesc);
+	L_DEBUG("restError_Rsp - nwkStatus = %s", nwkStatus);
+
+	if (cbinfo != NULL) {
+		if (cbinfo->expired())
+			return false;
+		rid = cbinfo->requestIdentifier.c_str();
+	} else
+		rid = NULL;
+
+	// Call XMLMsgComposer method to build a XML Response.
+	xmlResponse = pXMLMsgComposer->createErrorMsg(ctable[errorId].restCode,
+			errorDesc, nwkStatus, rid);
+
+#ifdef DEBUG_ACTIVE_RESTSERVER
+	if (this->debugEnabled) {
+		printf("restError_Rsp - sending a POST data to listener %s ",listener->URL.c_str ());
+#ifdef DEBUG_ACTIVE_RESTSERVER
+		const char * temp = xmlResponse.c_str();
+		for (ushort i=0; i < strlen(temp);i++)
+		printf("%c",temp[i]);
+#endif
+		printf("\r\n");
+	}
+#endif
+	pRESTClient->sendPostData(listener, &xmlResponse);
+
+	return true;
+}
+
+bool RESTServer::restSuccess(const char *detail, uriListener_t *listener) {
+	RESTCallbackInfo *cbinfo;
+	std::string xmlResponse;
+	const char *rid;
+
+	cbinfo = dynamic_cast<RESTCallbackInfo *>(listener->hback);
+
+	L_DEBUG("restSuccess (event)");
+
+	if (cbinfo != NULL) {
+
+		if (cbinfo->expired()) {
+			L_WARN("\ncbinfo -> expired () != 0");
+			return false;
+		}
+		rid = cbinfo->requestIdentifier.c_str();
+
+	} else
+		rid = NULL;
+
+	// Call XMLMsgComposer method to build a XML Response.
+	xmlResponse = pXMLMsgComposer->createSuccessMsg(detail, NULL, rid);
+	//#ifdef DEBUG_ACTIVE_RESTSERVER
+	if (this->debugEnabled) {
+		printf("restSuccess (event) - sending a POST data to listener %s ",
+				listener->URL.c_str());
+#ifdef DEBUG_ACTIVE_RESTSERVER
+		const char * temp = xmlResponse.c_str();
+		for (ushort i=0; i < strlen(temp);i++)
+		printf("%c",temp[i]);
+#endif
+		printf("\r\n");
+	}
+	//#endif
+	pRESTClient->sendPostData(listener, &xmlResponse);
+	return true;
+}
+
+bool RESTServer::restSuccess(const char *detail, uriListener_t *listener,
+		bool isAsynchRespose) {
+	RESTCallbackInfo *cbinfo;
+	std::string xmlResponse;
+	const char *cid;
+
+	cbinfo = dynamic_cast<RESTCallbackInfo *>(listener->hback);
+
+	L_DEBUG("restSuccess (event)");
+
+	if (cbinfo != NULL) {
+
+		if (cbinfo->expired()) {
+			L_WARN("\ncbinfo -> expired () != 0");
+			return false;
+		}
+		cid = listener->id.c_str();
+
+	} else
+		cid = NULL;
+
+	// Call XMLMsgComposer method to build a XML Response.
+	xmlResponse = pXMLMsgComposer->createRestInfoMsg(0, NULL, detail, NULL, cid,
+			NULL);
+#ifdef DEBUG_ACTIVE_RESTSERVER
+	if (this->debugEnabled) {
+		printf("restSuccess (event, isAsynchRespose) - sending a POST data to listener %s ",listener->URL.c_str ());
+#ifdef DEBUG_ACTIVE_RESTSERVER
+		const char * temp = xmlResponse.c_str();
+		for (ushort i=0; i < strlen(temp);i++)
+		printf("%c",temp[i]);
+#endif
+		printf("\r\n");
+	}
+#endif
+	pRESTClient->sendPostData(listener, &xmlResponse);
+	return true;
+}
+
+//#ifdef WSN_C_PROTOCOL_BACKWARD_COMPATIBILITY
+bool RESTServer::restSuccess_BC(const char *detail, uriListener_t *listener) {
+	L_DEBUG("restSuccess_BC");
+	//RESTCallbackInfo *cbinfo = dynamic_cast<RESTCallbackInfo *> (listener -> hback);
+	std::string xmlResponse(detail);
+#ifdef DEBUG_ACTIVE_RESTSERVER
+	if (this->debugEnabled)
+	{
+		printf("restSuccess_BC - sending a POST data to listener %s = ",listener->URL.c_str ());
+		const char * temp = xmlResponse.c_str();
+		for (ushort i=0; i < strlen(temp);i++)
+		printf("%c",temp[i]);
+		printf("\r\n");
+	}
+#endif
+	pRESTClient->sendPostData(listener, &xmlResponse);
+	return true;
+}
+//#endif
+
+void RESTServer::restSuccess(const char *detail, int sessionId) {
+	L_DEBUG("restSuccess");
+	restSuccess(detail, getHTTPSessionContext(sessionId));
+}
+
+void RESTServer::restSuccess(const char *detail, HTTPSessionContext *ctxt) {
+	RESTSessionContext *rctxt;
+
+	L_DEBUG("restSuccess");
+
+	if (ctxt == NULL) {
+		pLogger->error("restSuccess - ctxt == NULL - ERROR!");
+		return;
+	}
+
+	rctxt = dynamic_cast<RESTSessionContext *>(ctxt);
+	L_DEBUG("restSuccess - dynamic cast executed");
+
+	std::string xmlResponse;
+
+	// Call XMLMsgComposer method to build a XML Response.
+	xmlResponse = pXMLMsgComposer->createSuccessMsg(detail, NULL,
+			rctxt->getRequestIdentifier());
+#ifdef DEBUG_ACTIVE_RESTSERVER
+	if (this->debugEnabled) {
+		printf("restSuccess - xmlResponse = ");
+		const char * temp = xmlResponse.c_str();
+		for (ushort i=0; i < strlen(temp);i++)
+		printf("%c",temp[i]);
+		printf("\r\n");
+	}
+#endif
+	send(rctxt, xmlResponse);
+}
+
+void RESTServer::send(RESTSessionContext *rctxt, std::string &xmlResponse) {
+	// If not served yet, the response will
+	if (rctxt->getSessionStatus() == S_SERVED && rctxt->asynch()) {
+#ifdef DEBUG_ACTIVE_RESTSERVER
+		if (this->debugEnabled) {
+			printf("RESTServer::send - sending a POST data to listener %s ", (char *) &rctxt -> callbackDestination);
+#ifdef DEBUG_ACTIVE_RESTSERVER
+			const char * temp = xmlResponse.c_str();
+			for (ushort i=0; i < strlen(temp);i++)
+			printf("%c",temp[i]);
+#endif
+			printf("\r\n");
+		}
+#endif
+		uriListener_t uriListener;
+		size_t pos;
+		uriListener.URL = rctxt->callbackDestination;
+		pos = uriListener.URL.find("http://127.0.0.1");
+		if (pos == std::string::npos)
+			pos = uriListener.URL.find("http://localhost");
+		uriListener.type =
+				pos == std::string::npos ?
+						REMOTE_APP_URILISTENER : LOCAL_APP_URILISTENER;
+		pRESTClient->sendPostData(&uriListener, &xmlResponse);
+		delete rctxt;
+	} else if (rctxt->getSessionStatus() >= S_SERVING) {
+		rctxt->setResponse(xmlResponse);
+		rctxt->setSessionStatus(S_READY);
+	}
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTServer.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTServer.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CRESTServer.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,473 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+/*
+ * This class, derived from HTTPServer, implements all the ZGD
+ * and REST mechanisms specified by ZigBee. In particular, here
+ * is where the asynchronous paradigme is actually implemented,
+ * and proper incapsulation of command/response XML documents
+ * is applied.
+ */
+
+#ifndef RESTSERVER_H
+#define RESTSERVER_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string>
+#include <list>
+#include <map>
+
+#include "ThreadPool.h"
+#include "TimerThread.h"
+
+#include "CHTTPServer.h"
+#include "CRESTClient.h"
+#include "CResource.h"
+
+#include "CMessage.h"
+#include "ZbNetDb.h"
+
+#include "RESTErrors.h"
+#include "XMLProcessor.h"
+
+#include "ConfigurationRepository.h"
+
+#include "CDebug.h"
+
+/**
+ Default HTTP Server port	
+ */
+#define DEFAULT_SERVER_PORT				"9000"
+
+/**
+ KEY_FACTOR is a constant used to calculate the index key for a
+ resource in the Resource Dictionary (refer to resDictionary).
+ */
+#define KEY_FACTOR					100000
+
+#define ALL_RESOURCES				100000
+
+#define NO_EXPIRY_TIME				-1
+
+/**
+ * An exception thrown whenever the processing must stop and
+ * a REST error shall be generated. This does not imply that an HTTP
+ * error response will be generated. Indeed the expected behaviour
+ * of the handler is to generate a 200 Ok response with a nonzero
+ * Info/Code tag.
+ */
+class RESTException: public std::exception {
+
+public:
+	/**
+	 * Constructor.
+	 *	@param code the error ID
+	 *	@param msg an optional reason phrase
+	 */
+	RESTException(RESTError eid, const char *msg = NULL) :
+			eid(eid), msg(msg) {
+	}
+
+public:
+	/** The REST error code */
+	RESTError eid;
+
+	/** The reason phrase */
+	const char *msg;
+};
+
+class RESTSessionContext;
+
+struct RESTCallbackInfo: public UriListenerHandback {
+
+	/** The RequestIdentifier general parameter */
+	std::string requestIdentifier;
+
+	/** The expiry time. Meaningful only if #timeoutSet is true and if it is larger than zero*/
+	time_t expiry;
+
+	/** The timeout parameter. Meaningful only if #timeoutSet is true */
+	unsigned long timeout;
+
+	/** True if and only if the request contained a timeout parameter */
+	bool timeoutSet;
+
+	UriListenerHandback *clone();
+
+	void setTimeout(std::string s) throw (RESTException);
+
+	bool expired();
+
+	RESTSessionContext *refRestSessionCtxt;
+	Resource *refResource;
+
+};
+
+class RESTServer;
+
+/**
+ * The additional conversation state needed to track a ZGD REST
+ * session. In addition to all the HTTP base status, we 
+ * store the contents of "General Parameters" (if any).
+ */
+class RESTSessionContext: public HTTPSessionContext {
+
+public:
+	/** 
+	 * Constructor.
+	 *	@param server the REST server that created this instance
+	 *	@param context the shttpd context
+	 */
+	RESTSessionContext(RESTServer &server, shttpd_arg *context);
+
+	/**
+	 * Desctructor. 
+	 */
+	virtual ~RESTSessionContext();
+
+	/**
+	 * Parses the query string of an HTTP request, updating
+	 * its fields accordingly.
+	 *	@param query the query string
+	 */
+	virtual void parse(const char *query) throw (RESTException);
+
+	/**
+	 * Returns the Request-Identifier. If the operation shall complete
+	 * synchronously, this method returns NULL.
+	 *	@return the request identifier
+	 */
+	const char *getRequestIdentifier();
+
+	/**
+	 * Tells whether the current transaction shall be treated
+	 * asynchronously.
+	 *	@return true if it should
+	 */
+	bool asynch();
+
+	/**
+	 * Tells whether the current transaction shall be treated
+	 * in polling mode.
+	 *	@return true if it should
+	 */
+	bool polled();
+
+public:
+	/** The CallbackDestination parameter. Empty if polled */
+	std::string callbackDestination;
+
+	/** Set if CallbackDestination was specified */
+	bool callbackDestinationSet;
+
+	/** The last message sent */
+	std::string response;
+
+	/** Information needed to send an asynchronous response
+	 *  to that transaction */
+	RESTCallbackInfo cbinfo;
+
+private:
+	/**
+	 * Assigns a new Request-Identifier to this instance
+	 *	@return the newly generated request identifier
+	 */
+	const char *makeRequestIdentifier(void);
+
+	/** A request identifier generator. Randomly initialized
+	 *  then incremented each time #makeRequestIdentifier
+	 *  gets called */
+	static unsigned ridgen;
+
+	/**
+	 * The REST server that created this instance
+	 */
+	RESTServer &server;
+};
+
+/**
+ * A shttpd-based REST server. This class is built on top of HTTPServer,
+ * and inherits all its features (in particular session and 
+ * resource handling). In addition, it provides the general communication
+ * framework specified for a REST-based ZGD, i.e. synchronous vs. 
+ * asynchronous communication, event generation and info/status XML
+ * documents. Besides this, it also returns the sub-resources of
+ * a resource if no handler is associated to it.
+ */
+class RESTServer: public HTTPServer {
+
+private:
+	class RequestsHandler: public ResourceHandler {
+
+	public:
+		RequestsHandler(XMLMsgParser *pXMLMsgParser,
+				XMLMsgComposer *pXMLMsgComposer, RESTServer *server);
+
+		void handle(Resource *res, const char *reqUri, Method reqMethod,
+				const char *queryString, std::string *body,
+				HTTPSessionContext *ctxt) throw (RESTException, HTTPException);
+	private:
+		XMLMsgParser *pXMLMsgParser;
+
+		XMLMsgComposer *pXMLMsgComposer;
+
+		RESTServer *server;
+	};
+
+public:
+	// Constructors
+	RESTServer(XMLMsgParser *pXMLMsgParser, XMLMsgComposer *pXMLMsgComposer);
+
+	// Destructor
+	virtual ~RESTServer();
+
+	/**
+	 * RESTServer initialization. This methods reads all the
+	 * settings from the configuration file (rest, SSL, ...)
+	 * applying them to the underlying SHTTPD library.
+	 */
+	virtual int init();
+
+	/**
+	 * Accepts connections from the HTTP server, 
+	 * blocking until #pollTimeout milliseconds have elapsed.
+	 */
+	virtual void start();
+
+	// iterators:
+	// Attributes visible by scope of instantiation and use
+
+protected:
+	/**
+	 * Initializes the error-code to error-message bindings
+	 * (#errorMessage and #errorCode fields)
+	 */
+	void initMessages();
+
+	/**
+	 * Initializes the SSL settings, loading from the configuration
+	 * repository.
+	 *	@param conf the configuration repository
+	 */
+	void initSSL(ConfigurationRepository *conf);
+
+	/**
+	 * Initializes the ports settings, loading from the configuration
+	 * repository.
+	 *	@param conf the configuration repository
+	 */
+	int initPorts(ConfigurationRepository *conf);
+
+	/**
+	 * Initializes the Digest settings, loading from the configuration
+	 * repository.
+	 *	@param conf the configuration repository
+	 */
+	void initDigest(ConfigurationRepository *conf);
+
+	void initResources();
+
+public:
+	/**
+	 * Completes a transaction, reporting an error.
+	 * This class will handle the synchronous vs. asynchronous
+	 * housekeeping, deciding whether to report an event
+	 * or put the information into the HTTP response.
+	 *	@param errorId the error ID, see RestErrors.h
+	 *	@param text optional clarification text
+	 *	@param ctxt the transaction context
+	 */
+	void restError(int errorId, const char *errorDesc, const char *nwkStatus,
+			HTTPSessionContext *ctxt);
+
+	/**
+	 * Completes a transaction, reporting an error.
+	 * This class will handle the synchronous vs. asynchronous
+	 * housekeeping, deciding whether to report an event
+	 * or put the information into the HTTP response.
+	 *	@param errorId the error ID, see RestErrors.h
+	 *	@param text optional clarification text
+	 *	@param sessionId the session ID
+	 */
+	void restError(int errorId, const char *errorDesc, const char *nwkStatus,
+			int sessionId);
+
+	/**
+	 * Continues a transaction, reporting an error.
+	 * This class is used to send error events without changing
+	 * the state of the transaction (which is optional).
+	 * The typical usage is to report events on transactions
+	 * that support multiple notifications (e.g. discovery).
+	 * If the listener's timeout has expired, the message
+	 * is not sent, and this method returns <tt>false</tt>
+	 *	@param errorId the error ID, see RestErrors.h
+	 *	@param text optional clarification text
+	 *	@param listener the listener
+	 *	@return false if the listener timeout has expired
+	 */
+	bool restError(int errorId, const char *errorDesc, const char *nwkStatus,
+			uriListener_t *listener);
+
+	/**
+	 * Completes a transaction, reporting an error.
+	 * This class will handle the synchronous vs. asynchronous
+	 * housekeeping, deciding whether to report an event
+	 * or put the information into the HTTP response.
+	 *	@param errorId the error ID, see RestErrors.h
+	 *	@param detail contents of the detail tag
+	 *	@param ctxt the transaction context
+	 */
+	void restSuccess(const char *detail, HTTPSessionContext *ctxt);
+
+	/**
+	 * Completes a transaction, reporting an error.
+	 * This class will handle the synchronous vs. asynchronous
+	 * housekeeping, deciding whether to report an event
+	 * or put the information into the HTTP response.
+	 *	@param errorId the error ID, see RestErrors.h
+	 *	@param detail contents of the detail tag
+	 *	@param sessionId the session ID
+	 */
+	void restSuccess(const char *detail, int sessionId);
+
+	/**
+	 * Continues a transaction, reporting an event.
+	 * This class is used to send error events without changing
+	 * the state of the transaction (which is optional).
+	 * The typical usage is to report events on transactions
+	 * that support multiple notifications (e.g. discovery)
+	 * If the listener's timeout has expired, the message
+	 * is not sent, and this method returns <tt>false</tt>
+	 *	@param errorId the error ID, see RestErrors.h
+	 *	@param text optional clarification text
+	 *	@param listener the listener
+	 *	@return false if the listener timeout has expired
+	 */
+	bool restSuccess(const char *detail, uriListener_t *listener);
+	bool restSuccess(const char *detail, uriListener_t *listener,
+			bool isAsynchRespose);
+
+//#ifdef WSN_C_PROTOCOL_BACKWARD_COMPATIBILITY
+	bool restSuccess_BC(const char *detail, uriListener_t *listener);
+//#endif
+
+	/**
+	 * Provides a default handling for unmanaged resources.
+	 * The current implementation generates an XML document
+	 * containint all the subresources of the selected resource.
+	 *	@param res the resource being accessed
+	 *	@param reqUri the request URI
+	 *	@param reqMethod the HTTP method
+	 *	@param queryString the query string
+	 *	@param body body of the HTTP request
+	 *	@param ctxt the session context
+	 */
+	virtual void defaultHandler(Resource *res, const char *reqUri,
+			Method reqMethod, const char *queryString, std::string *body,
+			HTTPSessionContext *ctxt);
+
+	/**
+	 * This method is called each time a new context is attached
+	 * to the server. Derived classes may override this
+	 * method to maintan the list of active session contexts.
+	 *	@param ctxt the session context just created
+	 */
+	virtual void addContext(RESTSessionContext *ctxt);
+
+	/**
+	 * This method is called each time a context is detached
+	 * from the server. Derived classes may override this
+	 * method to maintan the list of active session contexts.
+	 *	@param ctxt the session context to be removed
+	 */
+	virtual void removeContext(RESTSessionContext *ctxt);
+
+protected:
+	/**
+	 * This method actually sends a response to a request
+	 * inside of a context. It is meant as a backend to
+	 * all the public methods, since it just deals with
+	 * session state and does deal with XML document generation.
+	 *	@param ctxt the session context
+	 *	@param xmlResponse response to be sent
+	 */
+	void send(RESTSessionContext *ctxt, std::string &xmlResponse);
+
+	Resource *createRequestResources(RESTSessionContext *ctxt);
+
+	void destroyRequestResources(RESTSessionContext *ctxt);
+
+protected:
+	/**
+	 * Override of CHTTPSessionContext::makeSessionContext method.
+	 * This method creates a RESTSessionContext object, so
+	 * it can store additional conversation information needed
+	 * by ZGD REST specs.
+	 *	@return a newly created RESTSessionContext object 
+	 */
+	virtual HTTPSessionContext *makeSessionContext(shttpd_arg *arg)
+			throw (HTTPException);
+
+	/**
+	 * Serves an incoming request. This method takes care of
+	 * updating the RESTSesionContext object with the contents
+	 * of the actual parameter, and handling the transaction,
+	 * either in synchronous or in an asynchronous fashion.
+	 *	@param resource the resource being accessed
+	 *	@param the context
+	 */
+	virtual void serveRequest(Resource *resource,
+			HTTPSessionContext *httpContext) throw (HTTPException);
+
+	/// HTTP Server ports
+	std::string serverPorts;
+
+	///	To enable/disable Debug (default value is 0)
+	bool debugEnabled;
+
+	/// Pointer to a Debug object -> logger
+	Debug *pLogger;
+
+	/// If set, SSL is enabled
+	bool sslEnabled;
+
+	/// The SSL certificate file. It is meaningful only 
+	/// is #sslEnabled is set
+	std::string sslCertificateFile;
+
+	/// If set, HTTP Digest authentication is enabled
+	bool httpDigestAuthEnabled;
+
+	/// The HTTP Digest secrets file. It is meaningful only
+	/// if #httpDigestAuthEnatbled is set
+	std::string httpDigestAuthPwdFile;
+
+	/// Pointer to XML Message Parser
+	XMLMsgParser *pXMLMsgParser;
+
+	/// Pointer to XML Message Composer
+	XMLMsgComposer *pXMLMsgComposer;
+
+	/// Pointer to REST client. Needed to post notifications
+	RESTClient *pRESTClient;
+
+	RequestsHandler requestsHandler;
+
+	struct {
+		Resource *requests;
+	} resources;
+
+private:
+	/// A mutex guarding the configuration repository
+	pthread_mutex_t mux;
+};
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CResource.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CResource.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CResource.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,226 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <time.h>
+
+#define LOCAL_LOGGER pLogger
+#ifdef DEBUG_ACTIVE_RESOURCE
+#define LOCAL_DEBUG_ENABLED
+#endif
+
+#include "CResource.h"
+
+static unsigned serial = time(NULL);
+
+uriListener_t::uriListener_t() {
+	std::stringstream s;
+
+	// Set id attribute (hex format)
+	s.width(8);
+	s.fill('0');
+	s << hex;
+	s << serial++;
+	id = s.str();
+
+//	printf("\n*******uriListener_t - id=%s -*************\n",
+//			id.c_str());
+
+	hback = NULL;
+}
+
+uriListener_t::uriListener_t(const uriListener_t &ul) {
+	hback = NULL;
+	*this = ul;
+}
+
+uriListener_t &uriListener_t::operator =(const uriListener_t &ul) {
+	URL = ul.URL;
+	type = ul.type;
+	id = ul.id;
+
+	if (hback != NULL)
+		delete hback;
+
+	hback = ul.hback == NULL ? NULL : ul.hback->clone();
+
+	return *this;
+}
+
+uriListener_t::~uriListener_t(void) {
+	if (hback != NULL)
+		delete hback;
+}
+
+//**************************************************************************
+//*************  ResourceDescriptor ****************************************
+//**************************************************************************
+ResourceDescriptor::ResourceDescriptor(const char *path) :
+		path(path) {
+	/* empty */
+}
+
+//**************************************************************************
+//*************  URIListenerList *******************************************
+//**************************************************************************
+URIListenerList::URIListenerList(URIListenerHandler *handler) :
+		handler(handler) {
+	/* empty */
+}
+
+bool URIListenerList::addListener(std::string *uri, int sessionId,
+		UriListenerHandback *hback) {
+	std::list<uriListener_t>::iterator i;
+	struct uriListener_t uriListener;
+	size_t pos;
+
+	L_DEBUG("addUriListener");
+
+	if (listeners.size() >= MAX_URILISTENERS_NUM) {
+		L_ERROR("addUriListener - uriListener max size exceeded");
+		return false;
+	}
+
+	for (i = listeners.begin(); i != listeners.end(); i++) {
+		if (!uri->compare(i->URL))
+			break;
+	}
+
+	uriListener.URL = *uri;
+	uriListener.hback = hback;
+
+	pos = uriListener.URL.find("http://127.0.0.1");
+	if (pos == std::string::npos)
+		pos = uriListener.URL.find("http://localhost");
+
+	uriListener.type =
+			pos == std::string::npos ?
+					REMOTE_APP_URILISTENER : LOCAL_APP_URILISTENER;
+
+	L_INFO("addUriListener - Urilistener type = %d", uriListener.type);
+
+	if (i != listeners.end()) {
+		L_INFO("addUriListener - uriListener already exists");
+		uriListener.id = i->id;
+
+		*i = uriListener;
+
+		if (handler != NULL)
+			handler->updateListener(this, &*i, &uriListener, sessionId);
+	} else {
+		L_INFO("addUriListener - uriListener not found -> Add to the list");
+
+		listeners.push_back(uriListener);
+		if (handler != NULL)
+			handler->addListener(this, &uriListener, sessionId);
+	}
+
+	return true;
+}
+
+bool URIListenerList::removeListener(std::string &id) {
+	URIListenerComparator c(id);
+
+	L_DEBUG("removeUriListener - %s", id);
+
+	if (!listeners.empty())
+		listeners.remove_if(c);
+	if (handler != NULL)
+		handler->removeListeners(this);
+	return true;
+}
+
+std::list<uriListener_t>::iterator URIListenerList::removeListener(
+		std::list<uriListener_t>::iterator i) {
+	i = listeners.erase(i);
+	if (handler != NULL)
+		handler->removeListeners(this);
+
+	return i;
+}
+
+bool URIListenerList::removeListeners() {
+	L_DEBUG("removeUriListener");
+
+	listeners.clear();
+	if (handler != NULL)
+		handler->removeListeners(this);
+
+	return true;
+}
+
+uriListener_t *URIListenerList::findListenerByHost(std::string *hostname) {
+	std::list<uriListener_t>::iterator i;
+
+	for (i = listeners.begin(); i != listeners.end(); i++)
+		if ((*i).URL.find(*hostname) != string::npos)
+			return &*i;
+
+	return NULL;
+}
+
+URIListenerList::URIListenerComparator::URIListenerComparator(std::string &id) :
+		id(id) {
+	/* empty */
+}
+
+bool URIListenerList::URIListenerComparator::operator ()(
+		const uriListener_t &value) {
+	return id == value.id;
+}
+
+//**************************************************************************
+//*************  Resource  *************************************************
+//**************************************************************************
+Resource::Resource(const ResourceDescriptor &rd, ResourceHandler *handler,
+		void *d) :
+		rd(rd), handler(handler) {
+	parent = NULL;
+	data.p = d;
+	dynrd = NULL;
+}
+
+Resource::Resource(ResourceDescriptor *rd, ResourceHandler *handler, void *d) :
+		rd(*rd), handler(handler) {
+	parent = NULL;
+	data.p = d;
+	dynrd = rd;
+}
+
+Resource::Resource(const ResourceDescriptor &rd) :
+		rd(rd) {
+	dynrd = NULL;
+}
+
+Resource::~Resource() {
+	if (dynrd != NULL)
+		delete dynrd;
+}
+
+void Resource::addChild(Resource *resource) {
+	L_DEBUG("Added resource: %s/ -> %s", uri, resource->rd.path);
+	children.push_back(resource);
+	resource->parent = this;
+	resource->uri = uri + "/" + resource->rd.path;
+}
+
+void Resource::removeChild(Resource *resource) {
+	L_DEBUG("Removed resource: %s/ -X %s", uri, resource->rd.path);
+	children.remove(resource);
+	resource->parent = NULL;
+	resource->uri = "";
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CResource.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CResource.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CResource.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,428 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef RESOURCE_H
+#define RESOURCE_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <list>
+#include <string>
+#include <sstream>
+
+#include "CDebug.h"
+
+/**
+ * Maximum allowed number of URI listeners registered on each URIListenerList
+ */
+#define MAX_URILISTENERS_NUM				20
+
+// Forward declarations
+class Resource;
+class ResourceDescriptor;
+class URIListenerList;
+class HTTPSessionContext;
+
+/**
+ * Different types of urilisteners supported. 
+ * LOCAL_APP_URILISTENER refer to urilisteners that 
+ * have been registered by local applications, 
+ * while REMOTE_APP_URILISTENER relates to urilisteners that have 
+ * been registered by applications hosted by remote devices.
+ */
+enum UriListenerType {
+	/// Local listener
+	LOCAL_APP_URILISTENER = 1,
+	/// Remote listener
+	REMOTE_APP_URILISTENER = 2
+};
+
+/**
+ * Classes deriving from this structure may be used as opaque objects
+ * handed back to a urilistener_t object when an event is fired on
+ * a resource. This pattern is more flexible than providing a simple
+ * <tt>void*</tt> reference because this way we can also clone objects
+ * when assigning from an uriListener_t to the other.
+ */
+struct UriListenerHandback {
+
+	virtual ~UriListenerHandback() {
+	}
+
+	virtual UriListenerHandback *clone() = 0;
+};
+
+/**
+ * This object represents a listener registered to a specific HTTP resource.
+ * Instances of this class may be attached to a single URIListener
+ * at a time and receive notifications when some HTTP/resource specific
+ * event is fired.
+ * The attribute id is automatically set when constructor is invoked.
+ */
+struct uriListener_t {
+	std::string URL;
+	UriListenerHandback *hback;
+	UriListenerType type;
+	std::string id;
+
+	uriListener_t();
+	uriListener_t(const uriListener_t &ul);
+	uriListener_t &operator =(const uriListener_t &ul);
+	virtual ~uriListener_t();
+};
+
+/**
+ * This enumeration contains all the methods known to the HTTP server
+ * plus a catch-all constant for unsupported verbs.
+ */
+enum Method {
+	/** HTTP GET method */
+	M_GET,
+
+	/** HTTP POST method */
+	M_POST,
+
+	/** HTTP PUT method */
+	M_PUT,
+
+	/** HTTP DELETE method */
+	M_DELETE,
+
+	/** Any other HTTP method */
+	M_OTHER
+};
+
+/**
+ * Implementations of this class may be registered at a URIListenerList
+ * object to receive notifications when the set of listeners changes.
+ */
+class URIListenerHandler {
+
+public:
+	/**
+	 * Virtual desctructor
+	 */
+	virtual ~URIListenerHandler() {
+	}
+	;
+
+	/**
+	 * Notifies when a new listener is to be added to the list.
+	 * This method is called right after adding it to the list,
+	 * and only if it is not present yet.
+	 *	@param l the list
+	 *	@param listener the new listener
+	 *	@param sessionId the session identifier (if any)
+	 *		of the transaction that requested that operation
+	 */
+	virtual void addListener(URIListenerList *l, uriListener_t *listener,
+			int sessionId) = 0;
+
+	/**
+	 * Notifies when a listener is replaced with a new instance
+	 * sharing the same object ID.
+	 *	@param l the list
+	 *	@param oldl the listener being replaced
+	 *	@param newl the replacement
+	 *	@param sessionId the session identifier of the
+	 *		transaction that requested that operation
+	 */
+	virtual void updateListener(URIListenerList *l, uriListener_t *oldl,
+			uriListener_t *newl, int sessionId) = 0;
+
+	/**
+	 * Notifies when one or more listeners have been removed 
+	 * from a list.
+	 * This method is called right after removing them from the list.
+	 *	@param l the list
+	 */
+	virtual void removeListeners(URIListenerList *l) = 0;
+};
+
+/**
+ * This class provides the common code for managing a list of urilistener_t
+ * objects. An instance of this class can be used by an HTTP server
+ * to mantain the list of objects that need to be notified when some
+ * event happens to the object represented by an HTTP resource.
+ * The concept of "event" is specific to the HTTP server and the resource,
+ * and there's no interpretation of that in this context.
+ * An additional feature supported by this class is the possibility
+ * to register an URIListenerHandlers that will receive notifications
+ * when a listener is added or removed from the list. This mechanism
+ * may be useful, e.g. when some action must be started when at least
+ * one listener is registered on a resource, and must be stopped when
+ * that list becomes empty.
+ */
+struct URIListenerList {
+
+public:
+	/** A list of listeners registered on this resource. */
+	std::list<uriListener_t> listeners;
+
+	/** The handler */
+	URIListenerHandler *handler;
+
+	/** An opaque object, meaningful to the URIListenerHandler */
+	union {
+		void *p;
+		int d;
+	} data;
+
+public:
+	/**
+	 * Constructor.
+	 *	@param handler the handler
+	 */
+	URIListenerList(URIListenerHandler *handler);
+
+	/**
+	 * Virtual destructor
+	 */
+	virtual ~URIListenerList(void) {
+	}
+
+	/**
+	 * Adds a listener to the list of objects to be notified when
+	 * something changes the status of the resource.
+	 * As a side-effect, it will also invoke 
+	 * ResourceHandler::addListener on its handler, if any.
+	 *	@param uri the callback URI
+	 *	@param sessionId the session identifier (if any)
+	 *		of the transaction that requested that operation
+	 *	@param hback an opaque data handed back to the handler
+	 *	@return true if successful
+	 */
+	bool addListener(std::string *uri, int sessionId,
+			UriListenerHandback *hback = NULL);
+
+	/**
+	 * Removes a listener from the list of objects to be notified when
+	 * something changes the status of the resource.
+	 * As a side-effect, it will also invoke 
+	 * ResourceHandler::removeListener on its handler, if any.
+	 *	@param id the unique identifier
+	 *	@return true if successful
+	 */
+	bool removeListener(std::string &id);
+
+	/**
+	 * Removes a listener from the list of objects to be notified when
+	 * something changes the status of the resource.
+	 * As a side-effect, it will also invoke 
+	 * ResourceHandler::removeListener on its handler, if any.
+	 *	@param i an iterator
+	 *	@return the iterator pointing to the next valid position
+	 */
+	std::list<uriListener_t>::iterator
+	removeListener(std::list<uriListener_t>::iterator i);
+
+	/**
+	 * Removes all the listeners from list.
+	 *	@return true if successful
+	 */
+	bool removeListeners();
+
+	/**
+	 * Looks for the first listener registered at an HTTP URI
+	 * whose host part matches the argument
+	 *	@param hostname the host part of the URI
+	 *	@return the first uri listener, or NULL
+	 */
+	uriListener_t *findListenerByHost(std::string *hostname);
+
+private:
+	/**
+	 * A comparator the URIListenerList class to scan
+	 * for a listener matching a specific ID.
+	 */
+	class URIListenerComparator {
+
+	public:
+		/**
+		 * Constructor.
+		 *	@param id the ID to be matched against
+		 */
+		URIListenerComparator(std::string &id);
+
+		/**
+		 * Comparator method needed to implement the 
+		 * comparator pattern.
+		 *	@param value the listener to be checked
+		 *	@return true if matching
+		 */
+		bool operator ()(const uriListener_t &value);
+
+	private:
+		/** The ID to be matched against */
+		std::string id;
+	};
+
+};
+
+/**
+ * The static description of a set of resources of the same kind.
+ * In many cases, there is a one to one relationship between
+ * resource descriptors and resources, because a resource
+ * can appear in just one place. In other cases (e.g. when
+ * a path contains a set of of objects of the same kind) this
+ * descriptor can be regarded as the class of resources.
+ * Currently it only contains a reference to the name of the
+ * resources, however derived classes may add other attributes.
+ */
+struct ResourceDescriptor {
+
+	/** The URI subpath, relative to its parent */
+	std::string path;
+
+	/**
+	 * Constructor
+	 *	@param path The URI subpath, relative to its parent
+	 */
+	ResourceDescriptor(const char *path);
+
+	/**
+	 * Virtual Destructor.
+	 */
+	virtual ~ResourceDescriptor() {
+	}
+};
+
+/**
+ * A callback interface to call when a resource is being accessed.
+ * The purpose of this class is to provide a reference to the
+ * handler of Resource objects.
+ */
+class ResourceHandler {
+
+public:
+	/**
+	 * Virtual desctructor
+	 */
+	virtual ~ResourceHandler() {
+	}
+	;
+
+public:
+	/**
+	 * Implementations of this method shall handle access to 
+	 * a specific resource (represented by a Resource object).
+	 *	@param res the Resource object being accessed
+	 *	@param reqUri the HTTP Request-URI, as a string
+	 *	@param reqMethod the encoded HTTP method
+	 *	@param queryString the query string after the Request-URI
+	 *	@param body the body of the HTTP request
+	 *	@param ctxt session context
+	 */
+	virtual void handle(Resource *res, const char *reqUri, Method reqMethod,
+			const char *queryString, std::string *body,
+			HTTPSessionContext *ctxt) = 0;
+
+};
+
+/**
+ * An object that can be accessed through the HTTP server.
+ * It contains both a reference to the details of the specific resource
+ * and the ResourcHandler delegate object that can reply to the
+ * request. Resource objects are something like an instantiation
+ * of a ResourceDescriptor object, so they keep a pointer to
+ * its ResourceDescriptor and an opaque object (#data)
+ * that is instance-specific. Of course the #data pointer
+ * is to be interpreted by the ResourceHandler and is defined
+ * at resource creation time.
+ */
+struct Resource {
+
+	/** A reference to the resource descriptor */
+	const ResourceDescriptor &rd;
+
+	/** The handler that will react to actions on this resource */
+	ResourceHandler *handler;
+
+	/** The absolute path. This is built from the relative
+	 *  path of this resource and the absolute path of the
+	 *  parent resource */
+	std::string uri;
+
+	/**
+	 * If set, the resource descriptor that must be destroyed
+	 * when this object is deleted
+	 */
+	ResourceDescriptor *dynrd;
+
+	/** An opaque object, meaningful for the ResourceHandler */
+	union {
+		void *p;
+		unsigned d;
+	} data;
+
+	/** A pointer to the parent resource */
+	Resource *parent;
+
+	/** A list of child resources. Resource objects contained
+	 *  in this list all have their #parent field
+	 *  set to this instance */
+	std::list<Resource *> children;
+
+	/**
+	 * Constructor for resources with an handler. At creation
+	 * time this object is not inserted into any hierarchy, so
+	 * the #parent field is set to NULL and the #children list
+	 * is empty
+	 *	@param rd the resource descriptor
+	 *	@param handler the handler
+	 *	@param data opaque object
+	 */
+	Resource(const ResourceDescriptor &rd, ResourceHandler *handler,
+			void *data);
+
+	/**
+	 * Constructor for resources with an handler. At creation
+	 * time this object is not inserted into any hierarchy, so
+	 * the #parent field is set to NULL and the #children list
+	 * is empty. When the object is destroyed, the resource 
+	 * descriptor is deleted too.
+	 *	@param rd the resource descriptor
+	 *	@param handler the handler
+	 *	@param data opaque object
+	 */
+	Resource(ResourceDescriptor *rd, ResourceHandler *handler, void *data);
+
+	/**
+	 * Constructor for resources for unhandled resources. At creation
+	 * time this object is not inserted into any hierarchy, so
+	 * the #parent field is set to NULL and the #children list
+	 * is empty
+	 *	@param rd the resource descriptor
+	 *	@param handler the handler
+	 *	@param data opaque object
+	 */
+	Resource(const ResourceDescriptor &rd);
+
+	/**
+	 * Destructor.
+	 */
+	~Resource();
+
+	/**
+	 * Puts an object into a resource hierarchy, updating the
+	 * #children and (child's) #parent fields accordingly.
+	 *	@param resource the new child of this object
+	 */
+	void addChild(Resource *resource);
+
+	/**
+	 * Removes an object from the resource hierarchy, updating the
+	 * #children and (child's) #parent fields accordingly.
+	 *	@param resource a child of this object that will be orphaned
+	 */
+	void removeChild(Resource *resource);
+};
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CServiceAgent.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CServiceAgent.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CServiceAgent.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,3356 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include "CServiceAgent.h"
+
+#define DISCOVERY_CLUSTERS_LIST_LEN		22
+
+const static ushort Discovery_clusters[] = { 0x0013, //Device_annce
+		0x0014, //User_Desc_set
+		0x8000, //NWK_addr_rsp
+		0x8001, //IEEE_addr_rsp
+		0x8002, //Node_Desc_rsp
+		0x8003, //Power_Desc_rsp
+		0x8004, //Simple_Desc_rsp
+		0x8005, //Active_EP_rsp
+		0x8006, //Match_Desc_rsp
+		0x8010, //Complex_Desc_rsp
+		0x8011, //User_Desc_rsp
+		0x8014, //User_Desc_conf
+		0x8015, //System_Server_Discovery_rsp
+		0x8016, //Discovery_store_rsp
+		0x8017, //Node_Desc_store_rsp
+		0x8018, //Power_Desc_store_rsp
+		0x8019, //Active_EP_store_rsp
+		0x801a, //Simple_Desc_store_rsp
+		0x801b, //Remove_node_cache_rsp
+		0x801c, //Find_node_cache_rsp
+		0x801d, //Extended_Simple_Desc_rsp
+		0x801e //Extended_Active_EP_rsp
+		};
+
+template<class T>
+ServiceAgent<T> ServiceAgent<T>::instance;
+
+/**
+ Constructor
+ ServiceAgent constructor. It is a protected method (pattern Singleton)
+
+ @param void Void.
+ @return Void.
+ */
+template<class T>
+ServiceAgent<T>::ServiceAgent() :
+		functionsContext(GalZbIf::Instance()->getFeatureControl()) {
+	pthread_mutex_init(&mux, NULL);
+	pthread_mutex_init(&msgCacheMux, NULL);
+
+	pGalZb = GalZbIf::Instance();
+	initTimers();
+
+	// Init pointers.
+	//pDAgent = NULL;
+}
+
+/**
+ Destructor
+ ServiceAgent destructor.
+
+ @param void Void.
+ @return Void.
+ */
+template<class T>
+ServiceAgent<T>::~ServiceAgent() {
+	// Clear message cache
+	std::map<int, std::list<Message *> >::iterator iter;
+	std::list<Message *>::iterator it;
+
+	for (iter = msgCache.begin(); iter != msgCache.end(); ++iter) {
+		it = iter->second.begin();
+		while (it != iter->second.end()) {
+			delete (*it);
+			it++;
+		}
+		iter->second.clear();
+	}
+	msgCache.clear();
+
+	TimerThreadShutdown(&timerThread);
+	ThreadPoolShutdown(&threadPool);
+
+	delete pLogger;
+}
+
+/**
+ Public method ServiceAgent *Instance(void)
+ (pattern Singleton)
+
+ @param void Void.
+ @return Instance of ServiceAgent class.
+ */
+template<class T>
+ServiceAgent<T> *ServiceAgent<T>::Instance(void) {
+	return &instance;
+}
+
+/**
+ Public method ServiceAgent init
+ ServiceAgent initialization: macrofunction context is initialized.
+
+
+ @param void Void.
+ @return Void.
+ */
+template<class T>
+void ServiceAgent<T>::init() {
+	ConfigurationRepository *_conf = ConfigurationRepository::instance();
+	// We load the configuration from the ConfigurationManager
+	this->debugEnabled = _conf->getint("main:debugEnabled", false);
+
+	// Debug
+	pLogger = new Debug("ServiceAgent");
+	pLogger->setDebugMode(this->debugEnabled);
+	//pLogger->setDebugMode(DBG_ENABLED);
+	pLogger->setDebugLevel(DEBUGGING);
+	//pLogger->setDebugLevel(TEST);
+	pLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+	pLogger->enableDebugOuput(DBG_SCREEN);
+	//pLogger->enableDebugOuput(DBG_LOGFILE);
+
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("init");
+#endif
+
+	pGalDb = pGalZb->getDb();
+	pthread_mutex_lock(&mux);
+	// We load the configuration from the ConfigurationManager
+	this->autoDiscoveryUnknownNodeFeature = _conf->getint(
+			"main:autoDiscoveryUnknownNodes",
+			CALL_DA_GET_IEEE_ADDRESS_DISABLED);
+	pthread_mutex_unlock(&mux);
+
+	// Init macrofunctions context
+	functionsContext.activeEndpoints.fTimeout = SA_GET_ACTIVE_EPS_TIMEOUT_IA;
+	functionsContext.getServiceDescriptor.fTimeout =
+			SA_GET_SERVICE_DESCRIPTOR_TIMEOUT_IA;
+	functionsContext.activeEndpointsDiscovery.fTimeout =
+			SA_ACTIVE_ENDPOINTS_DISCOVERY_TIMEOUT_IA;
+	functionsContext.serviceDescriptorsDiscovery.fTimeout =
+			SA_SERVICE_DESCRIPTORS_DISCOVERY_TIMEOUT_IA;
+
+	dataListenerRegistered = FALSE;
+	msgIdCounter = 0;
+	maxMsgCacheSize = MAX_MSG_CACHE_SIZE_DEFAULT;
+
+	// Create entry related to endpoint 0 - Default
+	servicesTable[0].listener.features = AGO_NONE;
+
+	/// Register a ServiceAgent listener on event  in GalZbIf
+	pGalZb->registerListener(ZB_ZDO_MATCH_DESC_INDICATION,
+			(void *) (&autoMatchDescriptorRsp_CbW));
+
+	//DiscoveryAgent already initialized in RESTBroker::initAgents!
+	//pDAgent = DiscoveryAgent<ServiceAgent>::Instance();
+	//pDAgent->init();
+}
+
+template<class T>
+int ServiceAgent<T>::addZDOService(
+		RPCContext<T, addServiceResponseCb> *rpcContextData) {
+	SimpleDescriptor sd;
+
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("initZDOSimpleDescriptor");
+#endif
+
+	pGalDb = pGalZb->getDb();
+	pthread_mutex_lock(&mux);
+	ConfigurationRepository *_conf = ConfigurationRepository::instance();
+	// We load the endPoint from the ConfigurationManager
+	int defaultEndPoint = _conf->getint(
+			"DefaultStartupAttributeSet:DefaultEndPoint",
+			DEFAULT_END_POINT_NOT_SPECIFIED);
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("addDefaultService - add default endPoint %02x",defaultEndPoint);
+#endif
+	pthread_mutex_unlock(&mux);
+	pGalDb->createDefaultSimpleDescr(defaultEndPoint, &sd);
+	return addService(&sd, rpcContextData);
+}
+
+template<class T>
+int ServiceAgent<T>::addDefaultService(
+		RPCContext<T, addServiceResponseCb> *rpcContextData) {
+	SimpleDescriptor sd;
+
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("initDefaultSimpleDescriptor");
+#endif
+
+	pGalDb = pGalZb->getDb();
+	pthread_mutex_lock(&mux);
+	ConfigurationRepository *_conf = ConfigurationRepository::instance();
+	// We load the endPoint from the ConfigurationManager
+	int defaultEndPoint = _conf->getint(
+			"DefaultStartupAttributeSet:DefaultEndPoint",
+			DEFAULT_END_POINT_NOT_SPECIFIED);
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("addDefaultService - add default endPoint %02x",defaultEndPoint);
+#endif
+	pthread_mutex_unlock(&mux);
+	pGalDb->createDefaultSimpleDescr(defaultEndPoint, &sd);
+	return addService(&sd, rpcContextData);
+}
+
+/**
+ Public method ServiceAgent getActiveEndPoints
+ This method allows retrieving active services list related to a specific node (identified by its network address).
+
+ @param nwk_addr Short address of the device of interest.
+ @param rpcContextData RPC context data.
+ @return Status.
+ */
+template<class T>
+int ServiceAgent<T>::getActiveEndPoints(unsigned long int timeout,
+		ushort nwk_addr, ActiveEndPointsCtxt *rpcContextData) {
+	pthread_mutex_lock(&mux);
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("getActiveEndPoints - node %04X", nwk_addr);
+#endif
+	if (pGalZb->getGWStatus() != GW_RUNNING) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("getActiveEndPoints - Error GAL_NOT_RUNNING");
+#endif
+		pthread_mutex_unlock(&mux);
+		// RPC response Callback
+		RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED, GAL_NOT_RUNNING);
+		CALL_RESPONSE (rpcContextData)(NULL, rpcContextData->getSessionId(),
+				&rpcReqStatus);
+		// Return Error Code
+		return GAL_NOT_RUNNING;
+	}
+	// If a superDiscovery or an Inquiry is running (refer to DiscoveryAgent) -> getActiveEndPoints not allowed
+	// Moreover, if getActiveEndPoints is running -> superDiscovery or Inquiry are not allowed.
+	// The check is performed at GalZbIf level. Refer to
+	// fContexts (GalZbIf::FeatureControl *fc) : activeEndpoints (in CServiceAgent.h)
+	if (functionsContext.activeEndpoints.lock()) {
+		// getActiveEndPoints is not running: start getActiveEndPoints
+		assert(pGalDb != NULL);
+		// Timer creation management
+		if (timeout > 0x00000000 && timeout != 0xffffffff) {
+			// Convert timeout from milliseconds to seconds (ceil)
+			timeout = timeout / 1000 + ((timeout % 1000) ? 1 : 0);
+			///	Set the timer for stopping the getActiveEndPoints process
+			functionsContext.activeEndpoints.fTimeout = (int) timeout;
+#ifdef DEBUG_ACTIVE_SA
+			pLogger->info("getActiveEndPoints - timeout value = %d (sec)", functionsContext.activeEndpoints.fTimeout);
+#endif
+			/// Set the timer for stopping the discovery process
+			if (!functionsContext.activeEndpoints.setTimer(&timerThread, this,
+					&ServiceAgent::onActiveEndpoints)) {
+				pLogger->error("getActiveEndPoints - ERROR creating timer!");
+				functionsContext.activeEndpoints.unlock(Canceled);
+				pthread_mutex_unlock(&mux);
+				// RPC response Callback
+				RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED,
+						TIMER_ERROR);
+				CALL_RESPONSE (rpcContextData)(NULL,
+						rpcContextData->getSessionId(), &rpcReqStatus);
+				return TIMER_ERROR;
+			}
+		} else {
+			/// If timeout value is 0xffffffff (infinite amount of time) or 0x00000000 do not use timer
+#ifdef DEBUG_ACTIVE_SA
+			pLogger->debug("getActiveEndPoints - timeout value infinite or zero - timer disabled");
+#endif
+		}
+		functionsContext.activeEndpoints.result = FSUCCESS;
+		functionsContext.activeEndpoints.numExpectedMsgs = 0;
+		///	Register RPC Context Data (containing RPC SessionId and RPC callbacks for response and notification) related to the specific request.
+		functionsContext.activeEndpoints.rpcContext = *rpcContextData;
+		/// Register a ServiceAgent listener on event ZB_ZDO_ACTIVE_EP_DESC_CONFIRM in GalZbIf
+		pGalZb->registerListener(ZB_ZDO_ACTIVE_EP_DESC_CONFIRM,
+				(void *) (&getActiveEndPoints_CbW));
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->debug("getActiveEndPoints started");
+#endif
+		// Active End Points request on node identified by nwk_addr
+		pGalZb->ZDO_ACTIVE_EP_DESC_request(nwk_addr, nwk_addr);
+		/// Increase number of expected messages 
+		functionsContext.activeEndpoints.numExpectedMsgs++;
+		// In case an asynch request is considered, RPC response Callback has to be invoked
+		if (functionsContext.activeEndpoints.rpcContext.getRPCNotifyCb()
+				!= NULL) {
+			/*
+			 #ifdef DEBUG_ACTIVE_SA
+			 pLogger->info("getActiveEndPoints - getRPCNotifyCb() != NULL = asynch request");
+			 #endif
+			 */
+			RPCReqStatus rpcReqStatus(End, FSUCCESS, AGENT_SUCCESS, true);
+			CALL_RESPONSE (rpcContextData)(NULL, rpcContextData->getSessionId(),
+					&rpcReqStatus);
+		}
+	} else {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("getActiveEndPoints - A getActiveEndPoints is already running");
+#endif
+		pthread_mutex_unlock(&mux);
+		// RPC response Callback
+		RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED, AGENT_BUSY);
+		CALL_RESPONSE (rpcContextData)(NULL, rpcContextData->getSessionId(),
+				&rpcReqStatus);
+		return AGENT_BUSY;
+	}
+	pthread_mutex_unlock(&mux);
+	return AGENT_SUCCESS;
+}
+
+/**
+ Public method ServiceAgent getActiveEndPoints_CbW
+ This is a static member function, used as a wrapper to callback to the non-static member getActiveEndPoints_Cb.
+ In particular, it is called by GalZbIf::ZDO_ACTIVE_EP_DESC_confirm.
+
+ @param status Success or Error status related to the request.
+ @param nwk_addr Short address of the device of interest.
+ @param active_ep_count Number of active endpoints available on the device identified by nwk_addr.
+ @param active_ep_list Pointer to the endpoint list.
+ @return Void.
+ */
+template<class T>
+void ServiceAgent<T>::getActiveEndPoints_CbW(uchar status, ushort nwk_addr,
+		uchar active_ep_count, uchar *active_ep_list) {
+	ServiceAgent* sAgent = ServiceAgent<T>::Instance();
+
+#ifdef DEBUG_ACTIVE_SA
+	if (sAgent->debugEnabled == true)
+	printf("\nServiceAgent::getActiveEndPoints_CbW\n");
+#endif
+
+	sAgent->getActiveEndPoints_Cb(status, nwk_addr, active_ep_count,
+			active_ep_list);
+}
+
+/**
+ Protected method ServiceAgent getActiveEndPoints_Cb
+ This method relates to getActiveEndPoints callback function.
+
+ @param status Success or Error status related to the request.
+ @param nwk_addr Short address of the device of interest.
+ @param active_ep_count Number of active endpoints available on the device identified by nwk_addr.
+ @param active_ep_list Pointer to the endpoint list.
+ @return Void.
+ */
+template<class T>
+void ServiceAgent<T>::getActiveEndPoints_Cb(uchar status, ushort nwk_addr,
+		uchar active_ep_count, uchar *active_ep_list) {
+	Node *node;
+
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("getActiveEndPoints_Cb - node %04X", nwk_addr);
+#endif
+
+	assert(pGalDb != NULL);
+
+	functionsContext.activeEndpoints.numExpectedMsgs--;
+
+	if (status != ZB_ZDO_SUCCESS) {
+
+		pLogger->error("getActiveEndPoints_Cb - ERROR returned by ZDO_ACTIVE_EP_DESC_confirm");
+
+		functionsContext.activeEndpoints.result = FFAILED;
+
+		if (functionsContext.activeEndpoints.numExpectedMsgs == 0) {
+			pLogger->info("getActiveEndPoints_Cb - getActiveEndPoints failed");
+
+			// Unregister listener
+			pGalZb->unregisterListener(ZB_ZDO_ACTIVE_EP_DESC_CONFIRM,
+					(void *) (&getActiveEndPoints_CbW));
+
+			// Remove timer related to getActiveEndPoints
+			functionsContext.activeEndpoints.killTimer();
+
+			// getActiveEndPoints Completed
+			functionsContext.activeEndpoints.unlock();
+		}
+
+		if (functionsContext.activeEndpoints.rpcContext.getRPCNotifyCb()
+				!= NULL) {
+			RPCReqStatus rpcReqStatus(functionsContext.activeEndpoints,
+					ACTIVE_EP_ERROR);
+
+			FCALL_NOTIFY (functionsContext.activeEndpoints)(NULL,
+					&rpcReqStatus);
+		} else {
+			// RPC response Callback
+			RPCReqStatus rpcReqStatus(functionsContext.activeEndpoints,
+					ACTIVE_EP_ERROR);
+			FCALL_RESPONSE (functionsContext.activeEndpoints)(NULL,
+					functionsContext.activeEndpoints.rpcContext.getSessionId(),
+					&rpcReqStatus);
+		}
+		return;
+	}
+
+	// Lookup the node 
+	node = pGalDb->findNodeByNwkAddr(nwk_addr);
+
+	if (node == NULL) {
+
+		pLogger->error("getActiveEndPoints_Cb - INTERNAL ERROR: an active endpoints confirm for a nonexistent node %04X has been received", (int)nwk_addr);
+
+		functionsContext.activeEndpoints.result = FFAILED;
+
+		if (functionsContext.activeEndpoints.numExpectedMsgs == 0) {
+			pLogger->info("getActiveEndPoints_Cb - getActiveEndPoints failed");
+
+			// Unregister listener
+			pGalZb->unregisterListener(ZB_ZDO_ACTIVE_EP_DESC_CONFIRM,
+					(void *) (&getActiveEndPoints_CbW));
+
+			// Remove timer related to getActiveEndPoints
+			functionsContext.activeEndpoints.killTimer();
+			// getActiveEndPoints Completed
+			functionsContext.activeEndpoints.unlock();
+		}
+
+		if (functionsContext.activeEndpoints.rpcContext.getRPCNotifyCb()
+				!= NULL) {
+			RPCReqStatus rpcReqStatus(functionsContext.activeEndpoints,
+					NONEXISTENTENT_NODE);
+
+			FCALL_NOTIFY (functionsContext.activeEndpoints)(NULL,
+					&rpcReqStatus);
+		} else {
+			// RPC response Callback
+			RPCReqStatus rpcReqStatus(functionsContext.activeEndpoints,
+					NONEXISTENTENT_NODE);
+			FCALL_RESPONSE (functionsContext.activeEndpoints)(NULL,
+					functionsContext.activeEndpoints.rpcContext.getSessionId(),
+					&rpcReqStatus);
+		}
+
+		return;
+	}
+
+	// Clear data obtained in previous requests
+	pGalDb->clearEndPointList(node);
+	pGalDb->clearSimpleDescrList(node);
+
+	/// The specific endpoints are added to the endpoint list related to the node identified by nwk_addr parameter.
+	for (int i = 0; i < active_ep_count; i++) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("getActiveEndPoints - active endpoint : %d",(int)active_ep_list[i]);
+#endif
+		// Add the endpoint to the endpoint list.
+		pGalDb->addEndPoint(node, (int) active_ep_list[i]);
+	}
+	if (active_ep_count == 0) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("getActiveEndPoints - active endpoints : None");
+#endif
+	}
+
+	if (functionsContext.activeEndpoints.numExpectedMsgs == 0) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->debug("getActiveEndPoints - getActiveEndPoints completed (node %04X)",(int)nwk_addr);
+#endif
+
+		// Unregister listener
+		pGalZb->unregisterListener(ZB_ZDO_ACTIVE_EP_DESC_CONFIRM,
+				(void *) (&getActiveEndPoints_CbW));
+
+		// Remove timer related to getActiveEndPoints
+		functionsContext.activeEndpoints.killTimer();
+		// getActiveEndPoints completed
+		functionsContext.activeEndpoints.unlock();
+
+		if (functionsContext.activeEndpoints.rpcContext.getRPCNotifyCb()
+				!= NULL) {
+#ifdef DEBUG_ACTIVE_SA
+			if (this->debugEnabled == true)
+			pLogger->debug("getActiveEndPoints - Procedure completed send asynch notification");
+#endif
+			RPCReqStatus rpcReqStatus(functionsContext.activeEndpoints,
+					AGENT_SUCCESS);
+			FCALL_NOTIFY (functionsContext.activeEndpoints)(node,
+					&rpcReqStatus);
+		} else {
+			pLogger->debug("getActiveEndPoints - Procedure completed send synch response");
+			// RPC response Callback
+			RPCReqStatus rpcReqStatus(functionsContext.activeEndpoints,
+					AGENT_SUCCESS);
+
+			FCALL_RESPONSE (functionsContext.activeEndpoints)(node,
+					functionsContext.activeEndpoints.rpcContext.getSessionId(),
+					&rpcReqStatus);
+		}
+
+	}
+}
+
+/**
+ Public method ServiceAgent getServiceDescriptor
+ This method allows requesting the service descriptor related to a specific node (identified by its short address) and endpoint.
+
+ @param nwk_addr Short address of the device of interest.
+ @param end_point Endpoint identifier from which to obtain the required service descriptor.
+ @param rpcContextData RPC context data.
+ @return Description of returned value.
+ */
+template<class T>
+int ServiceAgent<T>::getServiceDescriptor(unsigned long int timeout,
+		ushort nwk_addr, uchar end_point,
+		ServiceDescriptorCtxt *rpcContextData) {
+	pthread_mutex_lock(&mux);
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("getServiceDescriptor - node %04X - endpoint %02X", nwk_addr, end_point);
+#endif
+	//if (pGalZb->getGalStatus() != GAL_SS_RUNNING){
+	if (pGalZb->getGWStatus() != GW_RUNNING) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("getServiceDescriptor - Error GAL_NOT_RUNNING");
+#endif
+		pthread_mutex_unlock(&mux);
+		RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED, GAL_NOT_RUNNING);
+		CALL_RESPONSE (rpcContextData)(NULL, NOT_RUNNING,
+				rpcContextData->getSessionId(), &rpcReqStatus);
+		return GAL_NOT_RUNNING;
+	}
+	if (functionsContext.getServiceDescriptor.lock()) {
+		// If a superDiscovery or an Inquiry is running (refer to DiscoveryAgent) -> getServiceDescriptor not allowed
+		// Moreover, if ServiceDescriptor is running -> superDiscovery or Inquiry are not allowed.
+		// ---> At the moment, the check is considered only within the same agent -> cross agent approach should be considered
+
+		// getServiceDescriptor is not running: start getServiceDescriptor 
+		assert(pGalDb != NULL);
+
+		// Timer creation management
+		if (timeout > 0x00000000 && timeout != 0xffffffff) {
+
+			// Convert timeout from milliseconds to seconds (ceil)
+			timeout = timeout / 1000 + ((timeout % 1000) ? 1 : 0);
+
+			///	Set the timer for stopping the getServiceDescriptor process
+			functionsContext.getServiceDescriptor.fTimeout = (int) timeout;
+#ifdef DEBUG_ACTIVE_SA
+			if (this->debugEnabled == true)
+			pLogger->info("getServiceDescriptor - timeout value = %d (sec)", functionsContext.getServiceDescriptor.fTimeout);
+#endif
+			if (!functionsContext.getServiceDescriptor.setTimer(&timerThread,
+					this, &ServiceAgent::onServiceDescriptor)) {
+				pLogger->error("getServiceDescriptor - ERROR creating timer!");
+				functionsContext.getServiceDescriptor.unlock(Canceled);
+				pthread_mutex_unlock(&mux);
+				RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED,
+						TIMER_ERROR);
+				CALL_RESPONSE (rpcContextData)(NULL, ERROR_ON_SETTING_TIMER,
+						rpcContextData->getSessionId(), &rpcReqStatus);
+				return TIMER_ERROR;
+			}
+		} else {
+			/// If timeout value is 0xffffffff (infinite amount of time) or 0x00000000 do not use timer
+			pLogger->info("getServiceDescriptor - timeout value infinite or zero - timer disabled");
+		}
+
+		functionsContext.getServiceDescriptor.result = FSUCCESS;
+		functionsContext.getServiceDescriptor.numExpectedMsgs = 0;
+		functionsContext.getServiceDescriptor.rpcContext = *rpcContextData;
+
+		/// Register a ServiceAgent listener on event ZB_ZDO_SIMPLE_DESC_CONFIRM in GalZbIf
+		pGalZb->registerListener(ZB_ZDO_SIMPLE_DESC_CONFIRM,
+				(void *) (&getServiceDescriptor_CbW));
+
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->debug("getServiceDescriptor started");
+#endif
+
+		/// Simple Descriptor request on node identified by nwk_addr	
+		pGalZb->ZDO_SIMPLE_DESC_request(nwk_addr, nwk_addr, end_point);
+
+		/// Increase number of expected messages 
+		functionsContext.getServiceDescriptor.numExpectedMsgs++;
+
+		// In case an asynch request is considered, RPC response Callback has to be invoked
+		if (functionsContext.getServiceDescriptor.rpcContext.getRPCNotifyCb()
+				!= NULL) {
+			RPCReqStatus rpcReqStatus(End, FSUCCESS, AGENT_SUCCESS, true);
+			CALL_RESPONSE (rpcContextData)(NULL, FSUCCESS,
+					rpcContextData->getSessionId(), &rpcReqStatus);
+		}
+	} else {
+		pthread_mutex_unlock(&mux);
+		pLogger->info("getServiceDescriptor - A getServiceDescriptor is already running");
+		// RPC response Callback
+		RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED, AGENT_BUSY);
+		CALL_RESPONSE (rpcContextData)(NULL, ALREADY_CALLED,
+				rpcContextData->getSessionId(), &rpcReqStatus);
+		return AGENT_BUSY;
+	}
+	pthread_mutex_unlock(&mux);
+	return AGENT_SUCCESS;
+}
+
+/**
+ Public method ServiceAgent getServiceDescriptor_CbW
+ This is a static member function, used as a wrapper to callback to the non-static member getServiceDescriptor_Cb.
+ In particular, it is called by GalZbIf::ZDO_SIMPLE_DESC_confirm.
+
+ @param status Success or Error status related to the request.
+ @param nwk_addr Short address of the device of interest.
+ @param simple_desc Pointer to the returned service descriptor data structure.
+ @return Void.
+ */
+template<class T>
+void ServiceAgent<T>::getServiceDescriptor_CbW(uchar status, ushort nwk_addr,
+		ZB_SIMPLE_DESC *simple_desc) {
+	ServiceAgent* sAgent = ServiceAgent<T>::Instance();
+
+#ifdef DEBUG_ACTIVE_SA
+	if (sAgent->debugEnabled == true)
+	printf("\nServiceAgent::getServiceDescriptor_CbW\n");
+#endif
+
+	sAgent->getServiceDescriptor_Cb(status, nwk_addr, simple_desc);
+}
+
+/**
+ Protected method ServiceAgent getServiceDescriptor_Cb
+ This method relates to getServiceDescriptor callback function.
+
+ @param status Success or Error status related to the request.
+ @param nwk_addr Short address of the device of interest.
+ @param simple_desc Pointer to the returned service descriptor data structure.
+ @return Void.
+ */
+template<class T>
+void ServiceAgent<T>::getServiceDescriptor_Cb(uchar status, ushort nwk_addr,
+		ZB_SIMPLE_DESC *simple_desc) {
+	Node *node;
+
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("getServiceDescriptor_Cb - node %04X", nwk_addr);
+#endif
+
+	assert(pGalDb != NULL);
+
+	functionsContext.getServiceDescriptor.numExpectedMsgs--;
+
+	if (status != ZB_ZDO_SUCCESS) {
+		pLogger->error("getServiceDescriptor_Cb - ERROR returned by ZDO_SIMPLE_DESC_confirm - %02x",status);
+
+		functionsContext.getServiceDescriptor.result = FFAILED;
+
+		if (functionsContext.getServiceDescriptor.numExpectedMsgs == 0) {
+			pLogger->info("getServiceDescriptor_Cb - getServiceDescriptor failed");
+
+			// Unregister listener
+			pGalZb->unregisterListener(ZB_ZDO_SIMPLE_DESC_CONFIRM,
+					(void *) (&getServiceDescriptor_CbW));
+
+			// Remove timer related to getServiceDescriptor
+			functionsContext.getServiceDescriptor.killTimer();
+			// getNodedescriptor Completed
+			functionsContext.getServiceDescriptor.unlock();
+		}
+
+		if (functionsContext.getServiceDescriptor.rpcContext.getRPCNotifyCb()
+				!= NULL) {
+			RPCReqStatus rpcReqStatus(functionsContext.getServiceDescriptor,
+					SERVICE_DESCRIPTOR_ERROR);
+			FCALL_NOTIFY (functionsContext.getServiceDescriptor)(NULL,
+					NOT_SPECIFIED_ENDPOINT, &rpcReqStatus);
+		} else {
+			// RPC response Callback
+			RPCReqStatus rpcReqStatus(functionsContext.getServiceDescriptor,
+					SERVICE_DESCRIPTOR_ERROR);
+			FCALL_RESPONSE (functionsContext.getServiceDescriptor)(NULL,
+					NOT_SPECIFIED_ENDPOINT,
+					functionsContext.getServiceDescriptor.rpcContext.getSessionId(),
+					&rpcReqStatus);
+		}
+		return;
+	}
+
+	// Lookup the node 
+	node = pGalDb->findNodeByNwkAddr(nwk_addr);
+
+	if (node == NULL) {
+		pLogger->error("getServiceDescriptor_Cb - INTERNAL ERROR: arrived a simple desc confirm for a unexistent node %04X", (int)nwk_addr);
+
+		functionsContext.getServiceDescriptor.result = FFAILED;
+
+		if (functionsContext.getServiceDescriptor.numExpectedMsgs == 0) {
+			pLogger->info("getServiceDescriptor_Cb - getServiceDescriptor failed");
+
+			// Unregister listener
+			pGalZb->unregisterListener(ZB_ZDO_SIMPLE_DESC_CONFIRM,
+					(void *) (&getServiceDescriptor_CbW));
+
+			// Remove timer related to getServiceDescriptor
+			functionsContext.getServiceDescriptor.killTimer();
+			// getServiceDescriptor Completed
+			functionsContext.getServiceDescriptor.unlock();
+		}
+
+		if (functionsContext.getServiceDescriptor.rpcContext.getRPCNotifyCb()
+				!= NULL) {
+			RPCReqStatus rpcReqStatus(functionsContext.getServiceDescriptor,
+					NONEXISTENTENT_NODE);
+			FCALL_NOTIFY (functionsContext.getServiceDescriptor)(NULL,
+					NOT_SPECIFIED_ENDPOINT, &rpcReqStatus);
+		} else {
+			// RPC response Callback
+			RPCReqStatus rpcReqStatus(functionsContext.getServiceDescriptor,
+					NONEXISTENTENT_NODE);
+			FCALL_RESPONSE (functionsContext.getServiceDescriptor)(NULL,
+					NOT_SPECIFIED_ENDPOINT,
+					functionsContext.getServiceDescriptor.rpcContext.getSessionId(),
+					&rpcReqStatus);
+		}
+
+		return;
+	}
+
+	// Clear the previously stored simple descriptor related to the specific node and endpoint.
+	pGalDb->clearSimpleDescr(node, (int) simple_desc->ep);
+
+	SimpleDescriptor * sd = new SimpleDescriptor();
+
+	sd->end_point = simple_desc->ep;
+	sd->profile_id = simple_desc->app_profile_id;
+	sd->device_id = simple_desc->app_device_id;
+	sd->device_ver = (int) simple_desc->app_device_ver;
+	sd->complex_desc_available = GET_BIT(simple_desc->reserved, 5);
+	sd->user_desc_available = GET_BIT(simple_desc->reserved, 6);
+
+	for (int i = 0; i < simple_desc->app_in_cluster_count; i++) {
+		sd->input_cluster.push_back(simple_desc->app_in_cluster_list[i]);
+	}
+	for (int i = 0; i < simple_desc->app_out_cluster_count; i++) {
+		sd->output_cluster.push_back(simple_desc->app_out_cluster_list[i]);
+		//pLogger->debug("ServiceAgent::getServiceDescriptor_Cb -- output cluster %d",simple_desc->app_out_cluster_list[i]);
+	}
+
+	pGalDb->addSimpleDescr(node, sd);
+
+	if (functionsContext.getServiceDescriptor.numExpectedMsgs == 0) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->debug("getServiceDescriptor_Cb - getServiceDescriptor completed (node %04X)",(int)nwk_addr);
+#endif
+
+		// Unregister listener
+		pGalZb->unregisterListener(ZB_ZDO_SIMPLE_DESC_CONFIRM,
+				(void *) (&getServiceDescriptor_CbW));
+
+		// Remove timer related to getServiceDescriptor
+		functionsContext.getServiceDescriptor.killTimer();
+		// getServiceDescriptor completed
+		functionsContext.getServiceDescriptor.unlock();
+
+		if (functionsContext.getServiceDescriptor.rpcContext.getRPCNotifyCb()
+				!= NULL) {
+			RPCReqStatus rpcReqStatus(functionsContext.getServiceDescriptor,
+					AGENT_SUCCESS);
+			FCALL_NOTIFY (functionsContext.getServiceDescriptor)(node,
+					(int) sd->end_point, &rpcReqStatus);
+		} else {
+			// RPC response Callback
+			RPCReqStatus rpcReqStatus(functionsContext.getServiceDescriptor,
+					AGENT_SUCCESS);
+			FCALL_RESPONSE (functionsContext.getServiceDescriptor)(node,
+					(int) sd->end_point,
+					functionsContext.getServiceDescriptor.rpcContext.getSessionId(),
+					&rpcReqStatus);
+		}
+	}
+
+	return;
+}
+
+template<class T>
+int ServiceAgent<T>::getnodebindingRequest(unsigned long int timeout,
+		short destAddr, int startIndex, GetnodebindingCtxt *rpcContextData) {
+	pthread_mutex_lock(&mux);
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("getnodebindingRequest");
+#endif
+	if (pGalZb->getGWStatus() != GW_RUNNING) {
+
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("getnodebindingRequest - Error GAL_NOT_RUNNING");
+#endif
+		pthread_mutex_unlock(&mux);
+		RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED, GAL_NOT_RUNNING);
+		CALL_RESPONSE (rpcContextData)(0, 0, 0, NULL,
+				rpcContextData->getSessionId(), &rpcReqStatus);
+		return GAL_NOT_RUNNING;
+	}
+	if (functionsContext.getnodebindingRequest.lock()) {
+		assert(pGalDb != NULL);
+		// Timer creation management
+		if (timeout > 0x00000000 && timeout != 0xffffffff) {
+			// Convert timeout from milliseconds to seconds (ceil)
+			timeout = timeout / 1000 + ((timeout % 1000) ? 1 : 0);
+			///	Set the timer for stopping the getServiceDescriptor process
+			functionsContext.getnodebindingRequest.fTimeout = (int) timeout;
+#ifdef DEBUG_ACTIVE_SA
+			if (this->debugEnabled == true)
+			pLogger->info("getnodebindingRequest - timeout value = %d (sec)", functionsContext.getnodebindingRequest.fTimeout);
+#endif
+			if (!functionsContext.getnodebindingRequest.setTimer(&timerThread,
+					this, &ServiceAgent::onGetnodebindingRequestExpired)) {
+				pLogger->error("getnodebindingRequest - ERROR creating timer!");
+				functionsContext.getnodebindingRequest.unlock(Canceled);
+				pthread_mutex_unlock(&mux);
+				RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED,
+						TIMER_ERROR);
+				CALL_RESPONSE (rpcContextData)(0, 0, 0, NULL,
+						rpcContextData->getSessionId(), &rpcReqStatus);
+				return TIMER_ERROR;
+			}
+		} else
+			pLogger->info("getnodebindingRequest - timeout value infinite or zero - timer disabled");
+
+		functionsContext.getnodebindingRequest.result = FSUCCESS;
+		functionsContext.getnodebindingRequest.numExpectedMsgs = 0;
+		functionsContext.getnodebindingRequest.rpcContext = *rpcContextData;
+
+		/// Register a ServiceAgent listener
+		pGalZb->registerListener(ZB_ZDP_MGMT_BIND_RESPONSE,
+				(void *) (&getnodebinding_CbW));
+
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->debug("getnodebindingRequest started");
+#endif
+		// Send the message
+		pGalZb->ZDP_MGMT_BIND_Request(destAddr, startIndex);
+		// Increase number of expected messages
+		functionsContext.getnodebindingRequest.numExpectedMsgs++;
+		// In case an asynch request is considered, RPC response Callback has to be invoked
+		if (functionsContext.getnodebindingRequest.rpcContext.getRPCNotifyCb()
+				!= NULL) {
+			RPCReqStatus rpcReqStatus(End, FSUCCESS, AGENT_SUCCESS, true);
+			CALL_RESPONSE (rpcContextData)(0, 0, 0, NULL,
+					rpcContextData->getSessionId(), &rpcReqStatus);
+		}
+	} else {
+		pthread_mutex_unlock(&mux);
+		pLogger->info("getnodebindingRequest - A getnodebindingRequest is already running");
+		// RPC response Callback
+		RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED, AGENT_BUSY);
+		CALL_RESPONSE (rpcContextData)(0, 0, 0, NULL,
+				rpcContextData->getSessionId(), &rpcReqStatus);
+		return AGENT_BUSY;
+	}
+	pthread_mutex_unlock(&mux);
+	return AGENT_SUCCESS;
+}
+
+template<class T>
+void ServiceAgent<T>::getnodebinding_CbW(uchar status,
+		ushort bindingTableEntries, ushort startIndex,
+		ushort bindingTableListCount, ZB_BIND_STRUCT *bindingtableList) {
+	ServiceAgent* sAgent = ServiceAgent<T>::Instance();
+#ifdef DEBUG_ACTIVE_SA
+	if (sAgent->debugEnabled == true)
+	printf("\nServiceAgent::getnodebinding_CbW\n");
+#endif
+
+	sAgent->getnodebinding_Cb(status, bindingTableEntries, startIndex,
+			bindingTableListCount, bindingtableList);
+}
+
+template<class T>
+void ServiceAgent<T>::getnodebinding_Cb(uchar status,
+		ushort bindingTableEntries, ushort startIndex,
+		ushort bindingTableListCount, ZB_BIND_STRUCT *bindingtableList) {
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("getnodebinding_Cb");
+#endif
+	assert(pGalDb != NULL);
+	functionsContext.getnodebindingRequest.numExpectedMsgs--;
+	if (status != ZB_ZDO_SUCCESS) {
+		pLogger->error("getnodebinding_Cb - ERROR returned - %02x",status);
+		functionsContext.getnodebindingRequest.result = FFAILED;
+		if (functionsContext.getnodebindingRequest.numExpectedMsgs == 0) {
+			pLogger->info("getnodebinding_Cb - getServiceDescriptor failed");
+			// Unregister listener
+			pGalZb->unregisterListener(ZB_ZDP_MGMT_BIND_RESPONSE,
+					(void *) (&getnodebinding_CbW));
+			// Remove timer related to getServiceDescriptor
+			functionsContext.getnodebindingRequest.killTimer();
+			// getNodedescriptor Completed
+			functionsContext.getnodebindingRequest.unlock();
+		}
+		if (functionsContext.getnodebindingRequest.rpcContext.getRPCNotifyCb()
+				!= NULL) {
+			RPCReqStatus rpcReqStatus(functionsContext.getnodebindingRequest,
+					GETNODEBINDING_ERROR);
+			FCALL_NOTIFY (functionsContext.getnodebindingRequest)(0, 0, 0, NULL,
+					&rpcReqStatus);
+		} else {
+			RPCReqStatus rpcReqStatus(functionsContext.getnodebindingRequest,
+					GETNODEBINDING_ERROR);
+			FCALL_RESPONSE (functionsContext.getnodebindingRequest)(0, 0, 0,
+					NULL,
+					functionsContext.getnodebindingRequest.rpcContext.getSessionId(),
+					&rpcReqStatus);
+		}
+		return;
+	}
+	//Status is success, just return it!
+	if (functionsContext.getnodebindingRequest.numExpectedMsgs == 0) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->debug("getnodebinding_Cb - getnodebinding completed");
+#endif
+		// Unregister listener
+		pGalZb->unregisterListener(ZB_ZDP_MGMT_BIND_RESPONSE,
+				(void *) (&getnodebinding_CbW));
+		functionsContext.getnodebindingRequest.killTimer();
+		functionsContext.getnodebindingRequest.unlock();
+		if (functionsContext.getnodebindingRequest.rpcContext.getRPCNotifyCb()
+				!= NULL) {
+			RPCReqStatus rpcReqStatus(functionsContext.getnodebindingRequest,
+					AGENT_SUCCESS);
+			FCALL_NOTIFY (functionsContext.getnodebindingRequest)(
+					bindingTableEntries, startIndex, bindingTableListCount,
+					bindingtableList, &rpcReqStatus);
+		} else {
+			RPCReqStatus rpcReqStatus(functionsContext.getnodebindingRequest,
+					AGENT_SUCCESS);
+			FCALL_RESPONSE (functionsContext.getnodebindingRequest)(
+					bindingTableEntries, startIndex, bindingTableListCount,
+					bindingtableList,
+					functionsContext.getnodebindingRequest.rpcContext.getSessionId(),
+					&rpcReqStatus);
+		}
+	}
+	return;
+}
+
+template<class T>
+int ServiceAgent<T>::bindRequest(unsigned long int timeout,
+		ZB_BIND_STRUCT bindParams, BindCtxt *rpcContextData) {
+	Node * tmpNode;
+	ushort network_addr;
+
+	pthread_mutex_lock(&mux);
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("bindRequest - params: srcAddr %08X, src_ep %02X, clusterID %04X, dstAddr %16X, dst_ep %02X",
+			bindParams.src_addr,bindParams.src_ep,bindParams.cluster_id,bindParams.dst_addr,bindParams.dst_ep );
+#endif
+	if (pGalZb->getGWStatus() != GW_RUNNING) {
+
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("bindRequest - Error GAL_NOT_RUNNING");
+#endif
+		pthread_mutex_unlock(&mux);
+		RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED, GAL_NOT_RUNNING);
+		CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+				&rpcReqStatus);
+		return GAL_NOT_RUNNING;
+	}
+	if (!functionsContext.bindRequest.lock()) {
+		pLogger->info("bindRequest - A bindRequest is already running - overwriting!!!");
+		/*
+		 // RPC response Callback
+		 RPCReqStatus rpcReqStatus (NotAvailable, FNOT_STARTED,AGENT_BUSY);
+		 CALL_RESPONSE (rpcContextData)
+		 (rpcContextData -> getSessionId (), &rpcReqStatus);
+		 return AGENT_BUSY;
+		 */
+	} else {
+		// Register a ServiceAgent listener
+		pGalZb->registerListener(ZB_ZDP_BIND_RESPONSE,
+				(void *) (&bindRequest_CbW));
+	}
+	assert(pGalDb != NULL);
+	// Timer creation management
+	if (timeout > 0x00000000 && timeout != 0xffffffff) {
+		// Convert timeout from milliseconds to seconds (ceil)
+		timeout = timeout / 1000 + ((timeout % 1000) ? 1 : 0);
+		///	Set the timer for stopping the getServiceDescriptor process
+		functionsContext.bindRequest.fTimeout = (int) timeout;
+#ifdef DEBUG_ACTIVE_SA
+		if (this->debugEnabled == true)
+		pLogger->info("bindRequest - timeout value = %d (sec)", functionsContext.bindRequest.fTimeout);
+#endif
+		if (!functionsContext.bindRequest.setTimer(&timerThread, this,
+				&ServiceAgent::onBindRequestExpired)) {
+			pLogger->error("bindRequest - ERROR creating timer!");
+			functionsContext.bindRequest.unlock(Canceled);
+			pthread_mutex_unlock(&mux);
+			RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED, TIMER_ERROR);
+			CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+					&rpcReqStatus);
+			// Unregister a ServiceAgent listener
+			pGalZb->unregisterListener(ZB_ZDP_BIND_RESPONSE,
+					(void *) (&bindRequest_CbW));
+			return TIMER_ERROR;
+		}
+	} else
+		pLogger->info("bindRequest - timeout value infinite or zero - timer disabled");
+
+	functionsContext.bindRequest.result = FSUCCESS;
+	functionsContext.bindRequest.numExpectedMsgs = 0;
+	functionsContext.bindRequest.rpcContext = *rpcContextData;
+
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("bindRequest started");
+#endif
+	//Get the shortAddress
+	tmpNode = pGalDb->findNodeByIEEEAddr(bindParams.src_addr);
+	if (tmpNode != NULL) {
+		network_addr = tmpNode->get_nwk_addr();
+		// Send the message
+		pGalZb->ZDP_BIND_request(network_addr, bindParams.src_addr,
+				bindParams.src_ep, bindParams.cluster_id, bindParams.dst_addr,
+				bindParams.dst_ep);
+		// Increase number of expected messages
+		functionsContext.bindRequest.numExpectedMsgs++;
+		// In case an asynch request is considered, RPC response Callback has to be invoked
+		if (functionsContext.bindRequest.rpcContext.getRPCNotifyCb() != NULL) {
+			RPCReqStatus rpcReqStatus(End, FSUCCESS, AGENT_SUCCESS, true);
+			CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+					&rpcReqStatus);
+		}
+	} else {
+		pthread_mutex_unlock(&mux);
+		pLogger->info("bindRequest - Entry in DB not found for this node! Please discover it first!");
+		// RPC response Callback
+		RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED, AGENT_BUSY);
+		CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+				&rpcReqStatus);
+		// Unregister a ServiceAgent listener
+		pGalZb->unregisterListener(ZB_ZDP_BIND_RESPONSE,
+				(void *) (&bindRequest_CbW));
+		return AGENT_BUSY;
+	}
+	pthread_mutex_unlock(&mux);
+	return AGENT_SUCCESS;
+}
+
+template<class T>
+void ServiceAgent<T>::bindRequest_CbW(uchar status)
+//ZB_BIND_STRUCT bindRsp)
+		{
+	ServiceAgent* sAgent = ServiceAgent<T>::Instance();
+#ifdef DEBUG_ACTIVE_SA
+	if (sAgent->debugEnabled == true)
+	printf("\nServiceAgent::bindRequest_CbW\n");
+#endif
+
+	sAgent->bindRequest_Cb(status);
+}
+
+template<class T>
+void ServiceAgent<T>::bindRequest_Cb(uchar status) {
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("bindRequest_Cb");
+#endif
+	assert(pGalDb != NULL);
+	functionsContext.bindRequest.numExpectedMsgs--;
+	if (status != ZB_ZDO_SUCCESS) {
+		pLogger->error("bindRequest_Cb - ERROR returned - %02x",status);
+		functionsContext.bindRequest.result = FFAILED;
+		if (functionsContext.bindRequest.numExpectedMsgs == 0) {
+			pLogger->info("bindRequest_Cb - binding failed");
+			// Unregister listener
+			pGalZb->unregisterListener(ZB_ZDP_BIND_RESPONSE,
+					(void *) (&bindRequest_CbW));
+			// Remove timer related to getServiceDescriptor
+			functionsContext.bindRequest.killTimer();
+			// getNodedescriptor Completed
+			functionsContext.bindRequest.unlock();
+		}
+		if (functionsContext.bindRequest.rpcContext.getRPCNotifyCb() != NULL) {
+			RPCReqStatus rpcReqStatus(functionsContext.bindRequest, BIND_ERROR);
+			FCALL_NOTIFY (functionsContext.bindRequest)(&rpcReqStatus);
+		} else {
+			RPCReqStatus rpcReqStatus(functionsContext.bindRequest, BIND_ERROR);
+			FCALL_RESPONSE (functionsContext.bindRequest)(
+					functionsContext.bindRequest.rpcContext.getSessionId(),
+					&rpcReqStatus);
+		}
+		return;
+	}
+	//Status is success, just return it!
+	if (functionsContext.bindRequest.numExpectedMsgs == 0) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->debug("bindRequest_Cb - bindRequest completed");
+#endif
+		// Unregister listener
+		pGalZb->unregisterListener(ZB_ZDP_BIND_RESPONSE,
+				(void *) (&bindRequest_CbW));
+		functionsContext.bindRequest.killTimer();
+		functionsContext.bindRequest.unlock();
+		if (functionsContext.bindRequest.rpcContext.getRPCNotifyCb() != NULL) {
+			RPCReqStatus rpcReqStatus(functionsContext.bindRequest,
+					AGENT_SUCCESS);
+			FCALL_NOTIFY (functionsContext.bindRequest)(&rpcReqStatus);
+		} else {
+			RPCReqStatus rpcReqStatus(functionsContext.bindRequest,
+					AGENT_SUCCESS);
+			FCALL_RESPONSE (functionsContext.bindRequest)(
+					functionsContext.bindRequest.rpcContext.getSessionId(),
+					&rpcReqStatus);
+		}
+	}
+	return;
+}
+
+template<class T>
+int ServiceAgent<T>::unbindRequest(unsigned long int timeout,
+		ZB_BIND_STRUCT bindParams, UnbindCtxt *rpcContextData) {
+	Node * tmpNode;
+	ushort network_addr;
+
+	pthread_mutex_lock(&mux);
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("unbindRequest - params: srcAddr %08X, src_ep %02X, clusterID %04X, dstAddr %16X, dst_ep %02X",
+			bindParams.src_addr,bindParams.src_ep,bindParams.cluster_id,bindParams.dst_addr,bindParams.dst_ep );
+#endif
+	if (pGalZb->getGWStatus() != GW_RUNNING) {
+
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("unbindRequest - Error GAL_NOT_RUNNING");
+#endif
+		pthread_mutex_unlock(&mux);
+		RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED, GAL_NOT_RUNNING);
+		CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+				&rpcReqStatus);
+		return GAL_NOT_RUNNING;
+	}
+	if (functionsContext.unbindRequest.lock()) {
+		assert(pGalDb != NULL);
+		// Timer creation management
+		if (timeout > 0x00000000 && timeout != 0xffffffff) {
+			// Convert timeout from milliseconds to seconds (ceil)
+			timeout = timeout / 1000 + ((timeout % 1000) ? 1 : 0);
+			///	Set the timer for stopping the getServiceDescriptor process
+			functionsContext.unbindRequest.fTimeout = (int) timeout;
+#ifdef DEBUG_ACTIVE_SA
+			if (this->debugEnabled == true)
+			pLogger->info("unbindRequest - timeout value = %d (sec)", functionsContext.unbindRequest.fTimeout);
+#endif
+			if (!functionsContext.unbindRequest.setTimer(&timerThread, this,
+					&ServiceAgent::onUnbindRequestExpired)) {
+				pLogger->error("unbindRequest - ERROR creating timer!");
+				functionsContext.unbindRequest.unlock(Canceled);
+				pthread_mutex_unlock(&mux);
+				RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED,
+						TIMER_ERROR);
+				CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+						&rpcReqStatus);
+				return TIMER_ERROR;
+			}
+		} else
+			pLogger->info("unbindRequest - timeout value infinite or zero - timer disabled");
+
+		functionsContext.unbindRequest.result = FSUCCESS;
+		functionsContext.unbindRequest.numExpectedMsgs = 0;
+		functionsContext.unbindRequest.rpcContext = *rpcContextData;
+
+		/// Register a ServiceAgent listener
+		pGalZb->registerListener(ZB_ZDP_UNBIND_RESPONSE,
+				(void *) (&unbindRequest_CbW));
+
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->debug("unbindRequest started");
+#endif
+		//Get the shortAddress
+		tmpNode = pGalDb->findNodeByIEEEAddr(bindParams.src_addr);
+		if (tmpNode != NULL) {
+			network_addr = tmpNode->get_nwk_addr();
+			// Send the message
+			pGalZb->ZDP_UNBIND_request(network_addr, bindParams.src_addr,
+					bindParams.src_ep, bindParams.cluster_id,
+					bindParams.dst_addr, bindParams.dst_ep);
+			// Increase number of expected messages
+			functionsContext.unbindRequest.numExpectedMsgs++;
+			// In case an asynch request is considered, RPC response Callback has to be invoked
+			if (functionsContext.unbindRequest.rpcContext.getRPCNotifyCb()
+					!= NULL) {
+				RPCReqStatus rpcReqStatus(End, FSUCCESS, AGENT_SUCCESS, true);
+				CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+						&rpcReqStatus);
+			}
+		} else {
+			pthread_mutex_unlock(&mux);
+			pLogger->info("unbindRequest - Entry in DB not found for this node! Please discover it first!");
+			// RPC response Callback
+			RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED, AGENT_BUSY);
+			CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+					&rpcReqStatus);
+			return AGENT_BUSY;
+		}
+	} else {
+		pthread_mutex_unlock(&mux);
+		pLogger->info("unbindRequest - A unbindRequest is already running");
+		// RPC response Callback
+		RPCReqStatus rpcReqStatus(NotAvailable, FNOT_STARTED, AGENT_BUSY);
+		CALL_RESPONSE (rpcContextData)(rpcContextData->getSessionId(),
+				&rpcReqStatus);
+		return AGENT_BUSY;
+	}
+	pthread_mutex_unlock(&mux);
+	return AGENT_SUCCESS;
+}
+
+template<class T>
+void ServiceAgent<T>::unbindRequest_CbW(uchar status) {
+	ServiceAgent* sAgent = ServiceAgent<T>::Instance();
+#ifdef DEBUG_ACTIVE_SA
+	if (sAgent->debugEnabled == true)
+	printf("\nServiceAgent::unbindRequest_CbW\n");
+#endif
+
+	sAgent->unbindRequest_Cb(status);
+}
+
+template<class T>
+void ServiceAgent<T>::unbindRequest_Cb(uchar status) {
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("unbindRequest_Cb");
+#endif
+	assert(pGalDb != NULL);
+	functionsContext.unbindRequest.numExpectedMsgs--;
+	if (status != ZB_ZDO_SUCCESS) {
+		pLogger->error("unbindRequest_Cb - ERROR returned - %02x",status);
+		functionsContext.unbindRequest.result = FFAILED;
+		if (functionsContext.unbindRequest.numExpectedMsgs == 0) {
+			pLogger->info("unbindRequest_Cb - getServiceDescriptor failed");
+			// Unregister listener
+			pGalZb->unregisterListener(ZB_ZDP_UNBIND_RESPONSE,
+					(void *) (&unbindRequest_CbW));
+			// Remove timer related to getServiceDescriptor
+			functionsContext.unbindRequest.killTimer();
+			// getNodedescriptor Completed
+			functionsContext.unbindRequest.unlock();
+		}
+		if (functionsContext.unbindRequest.rpcContext.getRPCNotifyCb()
+				!= NULL) {
+			RPCReqStatus rpcReqStatus(functionsContext.unbindRequest,
+					UNBIND_ERROR);
+			FCALL_NOTIFY (functionsContext.unbindRequest)(&rpcReqStatus);
+		} else {
+			RPCReqStatus rpcReqStatus(functionsContext.unbindRequest,
+					UNBIND_ERROR);
+			FCALL_RESPONSE (functionsContext.unbindRequest)(
+					functionsContext.unbindRequest.rpcContext.getSessionId(),
+					&rpcReqStatus);
+		}
+		return;
+	}
+	//Status is success, just return it!
+	if (functionsContext.unbindRequest.numExpectedMsgs == 0) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->debug("unbindRequest_Cb - unbindRequest completed");
+#endif
+		// Unregister listener
+		pGalZb->unregisterListener(ZB_ZDP_UNBIND_RESPONSE,
+				(void *) (&unbindRequest_CbW));
+		functionsContext.unbindRequest.killTimer();
+		functionsContext.unbindRequest.unlock();
+		if (functionsContext.unbindRequest.rpcContext.getRPCNotifyCb()
+				!= NULL) {
+			RPCReqStatus rpcReqStatus(functionsContext.unbindRequest,
+					AGENT_SUCCESS);
+			FCALL_NOTIFY (functionsContext.unbindRequest)(&rpcReqStatus);
+		} else {
+			RPCReqStatus rpcReqStatus(functionsContext.unbindRequest,
+					AGENT_SUCCESS);
+			FCALL_RESPONSE (functionsContext.unbindRequest)(
+					functionsContext.unbindRequest.rpcContext.getSessionId(),
+					&rpcReqStatus);
+		}
+	}
+	return;
+}
+
+/**
+ Public method ServiceAgent activeEndPointsDiscovery
+ This method allows discovering the active endpoints (i.e. services) list within all nodes in the ZigBee network. In particular, an active
+ endpoints request is performed for each previously discovered node. Out-of-date nodes list should be avoided.
+ TO BE MODIFIED.
+
+ @param void Void.
+ @return Status.
+ */
+template<class T>
+int ServiceAgent<T>::activeEndPointsDiscovery() {
+	Node* node;
+	ushort nwk_addr;
+
+	if (pGalZb->getGWStatus() != GW_RUNNING) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("activeEndPointsDiscovery - Error GAL_NOT_RUNNING");
+#endif
+		return GAL_E_NOT_RUNNING;
+	}
+
+	pthread_mutex_lock(&mux);
+
+	if (functionsContext.activeEndpointsDiscovery.lock()) {
+		// If a superDiscovery or an Inquiry is running (refer to DiscoveryAgent) -> activeEndPointsDiscovery not allowed
+		// Moreover, if activeEndPointsDiscovery is running -> superDiscovery or Inquiry are not allowed.
+		// ---> At the moment, the check is considered only within the same agent -> cross agent approach should be considered
+
+		// activeEndPointsDiscovery is not running: start activeEndPointsDiscovery 
+		assert(pGalDb != NULL);
+
+		/// Set the timer for stopping the discovery process
+		if (!functionsContext.activeEndpointsDiscovery.setTimer(&timerThread,
+				this, &ServiceAgent::onActiveEndpointsDiscovery)) {
+			pLogger->error("activeEndPointsDiscovery - ERROR creating timer!");
+			functionsContext.activeEndpointsDiscovery.unlock(Canceled);
+			pthread_mutex_unlock(&mux);
+			return TIMER_ERROR;
+		}
+		functionsContext.activeEndpointsDiscovery.result = FSUCCESS;
+		functionsContext.activeEndpointsDiscovery.numExpectedMsgs = 0;
+
+		///	Register a ServiceAgent listener on event ZB_ZDO_ACTIVE_EP_DESC_CONFIRM in GalZbIf
+		pGalZb->registerListener(ZB_ZDO_ACTIVE_EP_DESC_CONFIRM,
+				(void *) (&activeEndPointsDiscovery_CbW));
+
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->debug("activeEndPointsDiscovery started");
+#endif
+
+		///	Set number of expected messages to the number of nodes in the network
+		functionsContext.activeEndpointsDiscovery.numExpectedMsgs =
+				pGalDb->getNodesCount();
+
+		for (node = pGalDb->getFirstNode(); node != NULL;
+				node = pGalDb->getNextNode(node)) {
+			node->dump();
+			nwk_addr = node->get_nwk_addr();
+			//	Active End Points request on node identified by nwk_addr
+			pGalZb->ZDO_ACTIVE_EP_DESC_request(nwk_addr, nwk_addr);
+			usleep(PACETIME);
+		}
+	} else {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("activeEndPointsDiscovery - A activeEndPointsDiscovery is already running");
+#endif
+		pthread_mutex_unlock(&mux);
+		return -1;
+	}
+	pthread_mutex_unlock(&mux);
+	return 0;
+}
+
+/**
+ Public method ServiceAgent activeEndPointsDiscovery_CbW
+ This is a static member function, used as a wrapper to callback to the non-static member activeEndPointsDiscovery_Cb.
+ In particular, it is called by GalZbIf::ZDO_ACTIVE_EP_DESC_confirm.
+
+ @param status Success or Error status related to the request.
+ @param nwk_addr Short address of the device of interest.
+ @param active_ep_count Number of active endpoints available on the device identified by nwk_addr.
+ @param active_ep_list Pointer to the endpoint list.
+ @return Void.
+ */
+template<class T>
+void ServiceAgent<T>::activeEndPointsDiscovery_CbW(uchar status,
+		ushort nwk_addr, uchar active_ep_count, uchar *active_ep_list) {
+	ServiceAgent* sAgent = ServiceAgent<T>::Instance();
+
+#ifdef DEBUG_ACTIVE_SA
+	if (sAgent->debugEnabled == true)
+	printf("\nServiceAgent::activeEndPointsDiscovery_CbW\n");
+#endif
+
+	sAgent->activeEndPointsDiscovery_Cb(status, nwk_addr, active_ep_count,
+			active_ep_list);
+}
+
+/**
+ Protected method ServiceAgent activeEndPointsDiscovery_Cb
+ This method relates to activeEndPointsDiscovery callback function.
+ TO BE MODIFIED.
+
+ @param status Success or Error status related to the request.
+ @param nwk_addr Short address of the device of interest.
+ @param active_ep_count Number of active endpoints available on the device identified by nwk_addr.
+ @param active_ep_list Pointer to the endpoint list.
+ @return Void.
+ */
+template<class T>
+void ServiceAgent<T>::activeEndPointsDiscovery_Cb(uchar status, ushort nwk_addr,
+		uchar active_ep_count, uchar *active_ep_list) {
+	Node *node;
+
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("activeEndPointsDiscovery_Cb - node %04X", nwk_addr);
+#endif
+
+	assert(pGalDb != NULL);
+
+	functionsContext.activeEndpointsDiscovery.numExpectedMsgs--;
+
+	if (status != ZB_ZDO_SUCCESS) {
+		pLogger->error("activeEndPointsDiscovery_Cb - ERROR returned by ZDO_ACTIVE_EP_DESC_confirm");
+
+		functionsContext.activeEndpointsDiscovery.result = FFAILED;
+
+		if (functionsContext.activeEndpointsDiscovery.numExpectedMsgs == 0) {
+
+			pLogger->error("activeEndPointsDiscovery_Cb - activeEndPointsDiscovery failed");
+
+			// Unregister listener
+			pGalZb->unregisterListener(ZB_ZDO_ACTIVE_EP_DESC_CONFIRM,
+					(void *) (&activeEndPointsDiscovery_CbW));
+
+			// Remove timer related to activeEndPointsDiscovery_
+			functionsContext.activeEndpointsDiscovery.killTimer();
+
+			// activeEndPointsDiscovery Completed
+			functionsContext.activeEndpointsDiscovery.unlock();
+		}
+		return;
+	}
+
+	// lookup the node 
+	node = pGalDb->findNodeByNwkAddr(nwk_addr);
+
+	if (node == NULL) {
+		pLogger->error("activeEndPointsDiscovery_Cb - INTERNAL ERROR: arrived a active endpoints confirm for a unexistent node %04X", (int)nwk_addr);
+
+		functionsContext.activeEndpointsDiscovery.result = FFAILED;
+
+		if (functionsContext.activeEndpointsDiscovery.numExpectedMsgs == 0) {
+
+			pLogger->info("activeEndPointsDiscovery_Cb - activeEndPointsDiscovery failed");
+
+			// Unregister listener
+			pGalZb->unregisterListener(ZB_ZDO_ACTIVE_EP_DESC_CONFIRM,
+					(void *) (&activeEndPointsDiscovery_CbW));
+
+			// Remove timer related to activeEndPointsDiscovery
+			functionsContext.activeEndpointsDiscovery.killTimer();
+
+			// activeEndPointsDiscovery Completed
+			functionsContext.activeEndpointsDiscovery.unlock();
+		}
+		return;
+	}
+	//Reset the old information
+	pGalDb->clearEndPointList(node);
+	pGalDb->clearSimpleDescrList(node);
+	//Store the new setting
+	int i = 0;
+	// The specific endpoints are added to the endpoint list related to the node identified by nwk_addr parameter
+	for (i = 0; i < active_ep_count; i++) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("activeEndPointsDiscovery_Cb - active endpoint : %d",(int)active_ep_list[i]);
+#endif
+		// Add the endpoint to the endpoint list.
+		pGalDb->addEndPoint(node, (int) active_ep_list[i]);
+	}
+
+	if (functionsContext.activeEndpointsDiscovery.numExpectedMsgs == 0) {
+
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->debug("activeEndPointsDiscovery_Cb - activeEndPointsDiscovery completed (node %04X)",(int)nwk_addr);
+#endif
+
+		// Unregister listener
+		pGalZb->unregisterListener(ZB_ZDO_ACTIVE_EP_DESC_CONFIRM,
+				(void *) (&activeEndPointsDiscovery_CbW));
+
+		// Remove timer related to activeEndPointsDiscovery
+		functionsContext.activeEndpointsDiscovery.killTimer();
+
+		// activeEndPointsDiscovery completed
+		functionsContext.activeEndpointsDiscovery.unlock();
+	}
+
+	return;
+}
+
+/**
+ Public method ServiceAgent serviceDescriptorsDiscovery
+ This method allows retrieving the service descriptor for all the active endpoints (i.e. services) within all nodes in the 
+ ZigBee network. In particular, a simple descriptor request is performed for each previously discovered endpoint within each node.
+ Out-of-date nodes list and active endpoints lists should be avoided.
+ TO BE MODIFIED.
+
+ @param void Void.
+ @return Status.
+ */
+template<class T>
+int ServiceAgent<T>::serviceDescriptorsDiscovery() {
+	Node* node;
+	ushort nwk_addr;
+	std::list<int> epList;
+	std::list<int>::iterator ep_it;
+
+	if (pGalZb->getGWStatus() != GW_RUNNING) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->debug("ServiceAgent::serviceDescriptorsDiscovery - Error GAL_E_NOT_RUNNING");
+#endif
+		return GAL_E_NOT_RUNNING;
+	}
+
+	pthread_mutex_lock(&mux);
+
+	if (functionsContext.serviceDescriptorsDiscovery.lock()) {
+		// If a superDiscovery or an Inquiry is running (refer to DiscoveryAgent) -> serviceDescriptorsDiscovery not allowed
+		// Moreover, if serviceDescriptorsDiscovery is running -> superDiscovery or Inquiry are not allowed.
+		// ---> At the moment, the check is considered only within the same agent -> cross agent approach should be considered
+
+		// serviceDescriptorsDiscovery is not running: start serviceDescriptorsDiscovery 
+		assert(pGalDb != NULL);
+
+		///	Set the timer for stopping the discovery process
+		if (!functionsContext.serviceDescriptorsDiscovery.setTimer(&timerThread,
+				this, &ServiceAgent::onServiceDescriptorsDiscovery)) {
+			pLogger->error("ServiceAgent::serviceDescriptorsDiscovery - ERROR creating timer");
+			functionsContext.serviceDescriptorsDiscovery.unlock(Canceled);
+			pthread_mutex_unlock(&mux);
+			return TIMER_ERROR;
+		}
+
+		functionsContext.serviceDescriptorsDiscovery.result = FSUCCESS;
+		functionsContext.serviceDescriptorsDiscovery.numExpectedMsgs = 0;
+
+		/// Register a ServiceAgent listener on event ZB_ZDO_SIMPLE_DESC_CONFIRM in GalZbIf
+		pGalZb->registerListener(ZB_ZDO_SIMPLE_DESC_CONFIRM,
+				(void *) (&serviceDescriptorsDiscovery_CbW));
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->debug("serviceDescriptorsDiscovery- ServiceAgent::serviceDescriptorsDiscovery started");
+#endif
+
+		for (node = pGalDb->getFirstNode(); node != NULL;
+				node = pGalDb->getNextNode(node)) {
+			epList = pGalDb->getEndPointList(node);
+
+			/// The number of expected messages is increased by the number of endpoints related to the node considered
+			functionsContext.serviceDescriptorsDiscovery.numExpectedMsgs +=
+					epList.size();
+		}
+
+		for (node = pGalDb->getFirstNode(); node != NULL;
+				node = pGalDb->getNextNode(node)) {
+			node->dump();
+			nwk_addr = node->get_nwk_addr();
+
+			epList = pGalDb->getEndPointList(node);
+
+			for (ep_it = epList.begin(); ep_it != epList.end(); ep_it++) {
+#ifdef DEBUG_ACTIVE_SA
+				pLogger->debug("serviceDescriptorsDiscovery - Endpoint - %d",(*ep_it));
+#endif
+				/// Simple Descriptor request on node identified by nwk_addr	
+				pGalZb->ZDO_SIMPLE_DESC_request(nwk_addr, nwk_addr, *ep_it);
+				usleep(PACETIME);
+			}
+		}
+	} else {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("serviceDescriptorsDiscovery - A serviceDescriptorsDiscovery is already running");
+#endif
+		pthread_mutex_unlock(&mux);
+		return -1;
+	}
+	pthread_mutex_unlock(&mux);
+	return 0;
+}
+
+/**
+ Public method ServiceAgent serviceDescriptorsDiscovery_CbW
+ This is a static member function, used as a wrapper to callback to the non-static member serviceDescriptorsDiscovery_Cb.
+ In particular, it is called by GalZbIf::ZDO_SIMPLE_DESC_confirm.
+
+ @param status Success or Error status related to the request.
+ @param nwk_addr Short address of the device of interest.
+ @param simple_desc Pointer to the returned service descriptor data structure.
+ @return Void.
+ */
+template<class T>
+void ServiceAgent<T>::serviceDescriptorsDiscovery_CbW(uchar status,
+		ushort nwk_addr, ZB_SIMPLE_DESC *simple_desc) {
+	ServiceAgent* sAgent = ServiceAgent<T>::Instance();
+#ifdef DEBUG_ACTIVE_SA
+	if (sAgent->debugEnabled == true)
+	printf("\nServiceAgent::serviceDescriptorsDiscovery_CbW\n");
+#endif
+	sAgent->serviceDescriptorsDiscovery_Cb(status, nwk_addr, simple_desc);
+}
+
+/**
+ Protected method ServiceAgent serviceDescriptorsDiscovery_Cb
+ This method relates to serviceDescriptorsDiscovery callback function.
+
+ @param status Success or Error status related to the request.
+ @param nwk_addr Short address of the device of interest.
+ @param simple_desc Pointer to the returned service descriptor data structure.
+ @return Void.
+ */
+template<class T>
+void ServiceAgent<T>::serviceDescriptorsDiscovery_Cb(uchar status,
+		ushort nwk_addr, ZB_SIMPLE_DESC *simple_desc) {
+	Node *node;
+
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("serviceDescriptorsDiscovery_Cb - ServiceAgent::serviceDescriptorsDiscovery_Cb");
+#endif
+	assert(pGalDb != NULL);
+
+	functionsContext.serviceDescriptorsDiscovery.numExpectedMsgs--;
+
+	if (status != ZB_ZDO_SUCCESS) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->debug("serviceDescriptorsDiscovery_Cb - ERROR: returned by ZDO_SIMPLE_DESC_confirm");
+#endif
+
+		functionsContext.serviceDescriptorsDiscovery.result = FFAILED;
+
+		if (functionsContext.serviceDescriptorsDiscovery.numExpectedMsgs == 0) {
+			pLogger->warn("serviceDescriptorsDiscovery_Cb - serviceDescriptorsDiscovery failed");
+			// Unregister listener
+			pGalZb->unregisterListener(ZB_ZDO_SIMPLE_DESC_CONFIRM,
+					(void *) (&serviceDescriptorsDiscovery_CbW));
+
+			// Remove timer related to serviceDescriptorsDiscovery
+			functionsContext.serviceDescriptorsDiscovery.killTimer();
+
+			// serviceDescriptorsDiscovery Completed
+			functionsContext.serviceDescriptorsDiscovery.unlock();
+		}
+		return;
+	}
+
+	// lookup the node 
+	node = pGalDb->findNodeByNwkAddr(nwk_addr);
+
+	if (node == NULL) {
+		pLogger->warn("serviceDescriptorsDiscovery_Cb -INTERNAL ERROR: arrived a simple desc confirm for a unexistent node %05d!", (int)nwk_addr);
+
+		functionsContext.serviceDescriptorsDiscovery.result = FFAILED;
+
+		if (functionsContext.serviceDescriptorsDiscovery.numExpectedMsgs == 0) {
+			pLogger->warn("serviceDescriptorsDiscovery_Cb - serviceDescriptorsDiscovery failed");
+			// Unregister listener
+			pGalZb->unregisterListener(ZB_ZDO_SIMPLE_DESC_CONFIRM,
+					(void *) (&serviceDescriptorsDiscovery_CbW));
+
+			// Remove timer related to serviceDescriptorsDiscovery
+			functionsContext.serviceDescriptorsDiscovery.killTimer();
+
+			// serviceDescriptorsDiscovery Completed
+			functionsContext.serviceDescriptorsDiscovery.unlock();
+		}
+		return;
+	}
+
+	// Clear the previously stored simple descriptor related to the specific node and endpoint.
+	pGalDb->clearSimpleDescr(node, (int) simple_desc->ep);
+
+	SimpleDescriptor * sd = new SimpleDescriptor();
+
+	sd->end_point = simple_desc->ep;
+	sd->profile_id = simple_desc->app_profile_id;
+	sd->device_id = simple_desc->app_device_id;
+	sd->device_ver = (int) simple_desc->app_device_ver;
+	sd->complex_desc_available = GET_BIT(simple_desc->reserved, 5);
+	sd->user_desc_available = GET_BIT(simple_desc->reserved, 6);
+
+	for (int i = 0; i < simple_desc->app_in_cluster_count; i++) {
+		sd->input_cluster.push_back(simple_desc->app_in_cluster_list[i]);
+	}
+	for (int i = 0; i < simple_desc->app_out_cluster_count; i++) {
+		sd->output_cluster.push_back(simple_desc->app_out_cluster_list[i]);
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->debug("serviceDescriptorsDiscovery_Cb - output cluster %d",simple_desc->app_out_cluster_list[i]);
+#endif
+	}
+
+	pGalDb->addSimpleDescr(node, sd);
+
+	if (functionsContext.serviceDescriptorsDiscovery.numExpectedMsgs == 0) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->debug("serviceDescriptorsDiscovery_Cb - serviceDescriptorsDiscovery completed (node %05d)",(int)nwk_addr);
+#endif
+
+		// Unregister listener
+		pGalZb->unregisterListener(ZB_ZDO_SIMPLE_DESC_CONFIRM,
+				(void *) (&serviceDescriptorsDiscovery_CbW));
+
+		// Remove timer related to serviceDescriptorsDiscovery
+		functionsContext.serviceDescriptorsDiscovery.killTimer();
+
+		// serviceDescriptorsDiscovery completed
+		functionsContext.serviceDescriptorsDiscovery.unlock();
+	}
+
+	return;
+}
+
+template<class T>
+int ServiceAgent<T>::getCurrentServices(int *services) {
+	int j = 0;
+	for (int i = 0; i <= ENDPOINT_240; i++)
+		// Check whether endpoint is allocated
+		if (servicesTable.count(i) != 0)
+			services[j++] = i;
+	return j;
+}
+
+/**
+ Public method ServiceAgent addService
+ This method allows adding a new service and specifying its functionalities through a service descriptor. In particular, a new endpoint 
+ identifier is allocated (the first available endpoint is considered if no one is specified) and inserted in the servicesTable.
+
+ @param serviceDesc Pointer to the service descriptor data structure concerning new service to be allocated.
+ @param rpcContextData RPC context data.
+ @return The number of the allocated endpoint.
+ */
+template<class T>
+int ServiceAgent<T>::addService(SimpleDescriptor *serviceDesc,
+		RPCContext<T, addServiceResponseCb> *rpcContextData) {
+	int endpoint = NOT_SPECIFIED_ENDPOINT;
+	serviceEntry *e;
+
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("addService");
+#endif
+
+	pthread_mutex_lock(&mux);
+	//First check if the gateway is already running
+	if (pGalZb->getGWStatus() == GW_RUNNING) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("addService - Error GW_RUNNING");
+#endif
+		// RPC response Callback
+		RPCReqStatus rpcReqStatus(NotAvailable, FFAILED, INVALID_GW_STATUS);
+		CALL_RESPONSE (rpcContextData)(NULL, rpcContextData->getSessionId(),
+				&rpcReqStatus);
+		pthread_mutex_unlock(&mux);
+		return GW_RUNNING;
+	}
+	//Check if we still have endPoint available to be assigned!
+	if (servicesTable.size()
+			== (MAX_NUM_ENDPOINTS + servicesTable.count(ALL_ENDPOINTS))) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("addService - No available endpoint!");
+#endif
+		pthread_mutex_unlock(&mux);
+		if (rpcContextData != NULL) {
+			if (rpcContextData->getRPCResponseCb() != NULL) {
+				RPCReqStatus rpcReqStatus(End, FFAILED, NO_AVAILABLE_ENDPOINT);
+				CALL_RESPONSE (rpcContextData)(NULL,
+						rpcContextData->getSessionId(), &rpcReqStatus);
+			} else {
+				pLogger->warn("addService - (A) - RPCResponseCb == NULL");
+			}
+		}
+		return NO_AVAILABLE_ENDPOINT;
+	}
+	//Check if the user has specified a desired endPoint
+	if (serviceDesc->end_point == 0) {
+		//No endPoint specified, so get the first one available (If no one available return ERROR)
+		for (int i = ENDPOINT_001;
+				i <= ENDPOINT_240 && endpoint == NOT_SPECIFIED_ENDPOINT; i++)
+			// Check whether endpoint is available.
+			if (servicesTable.count(i) == 0)
+				endpoint = i; // it exit since the condition endpoint == NOT_SPECIFIED_ENDPOINT is not verified anymore!
+	} else {
+		// "serviceDesc->end_point" is the desired valued, check if it is available
+		if (servicesTable.count(serviceDesc->end_point) == 0)
+			endpoint = serviceDesc->end_point;
+		else {
+			//Return an error since that endPoint is already assigned!
+#ifdef DEBUG_ACTIVE_SA
+			pLogger->info("addService - endpoint already assigned!");
+#endif
+			pthread_mutex_unlock(&mux);
+			if (rpcContextData != NULL) {
+				if (rpcContextData->getRPCResponseCb() != NULL) {
+					RPCReqStatus rpcReqStatus(End, FFAILED,
+							NO_AVAILABLE_ENDPOINT);
+					CALL_RESPONSE (rpcContextData)(NULL,
+							rpcContextData->getSessionId(), &rpcReqStatus);
+				} else
+					pLogger->warn("addService - (A) - RPCResponseCb == NULL");
+			}
+			return NO_AVAILABLE_ENDPOINT;
+		}
+	}
+
+	// Create Simple Descriptor 
+	e = &servicesTable[endpoint];
+
+	// Assign endpoint
+	e->simpleDesc.end_point = endpoint;
+
+	e->simpleDesc.profile_id = serviceDesc->profile_id;
+	e->simpleDesc.device_id = serviceDesc->device_id;
+	e->simpleDesc.device_ver = serviceDesc->device_ver;
+	e->simpleDesc.complex_desc_available = serviceDesc->complex_desc_available;
+	e->simpleDesc.user_desc_available = serviceDesc->user_desc_available;
+
+	std::list<int>::iterator it;
+	for (it = serviceDesc->input_cluster.begin();
+			it != serviceDesc->input_cluster.end(); it++) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("addService - input cluster = %02X",(*it));
+#endif
+		servicesTable[endpoint].simpleDesc.input_cluster.push_back((*it));
+	}
+
+	for (it = serviceDesc->output_cluster.begin();
+			it != serviceDesc->output_cluster.end(); it++) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("addService - output cluster = %02X",(*it));
+#endif
+		servicesTable[endpoint].simpleDesc.output_cluster.push_back((*it));
+	}
+
+	// Update the Service Simple Descriptor table in the GAL database
+	if (this->pGalDb->setServicesSD(&(servicesTable[endpoint].simpleDesc))
+			== -1)
+		pLogger->fatal("addService - setServicesSD Error");
+
+	pthread_mutex_unlock(&mux);
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->info("addService - allocated endpoint %d",endpoint);
+#endif
+	if (rpcContextData != NULL) {
+		if (rpcContextData->getRPCResponseCb() != NULL) {
+			RPCReqStatus rpcReqStatus(End, FSUCCESS, AGENT_SUCCESS);
+			CALL_RESPONSE (rpcContextData)(&servicesTable[endpoint].simpleDesc,
+					rpcContextData->getSessionId(), &rpcReqStatus);
+		} else {
+			pLogger->warn("addService - (B) - RPCResponseCb == NULL");
+		}
+	}
+	return AGENT_SUCCESS;
+}
+
+template<class T>
+bool ServiceAgent<T>::isEndpointAvailable(int endpoint) {
+	typename std::map<int, serviceEntry>::iterator it;
+
+	it = servicesTable.find(endpoint);
+	if (it == servicesTable.end()) { // Note: this state should be unreachable!
+			// No entries found!
+#ifdef DEBUG_ACTIVE_SA
+			pLogger->debug("isEndpointAvailable - Endpoint %d NOT available",endpoint);
+#endif
+		return false;
+	} else {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->debug("isEndpointAvailable - Endpoint %d available",endpoint);
+#endif
+		return true;
+	}
+}
+
+/**
+ Public method ServiceAgent removeService
+ This method allows removing a specific allocated service from servicesTable
+
+ @param endpoint Number of the endpoint of interest.
+ @return Status.
+ */
+template<class T>
+int ServiceAgent<T>::removeService(int endpoint) {
+	typename std::map<int, serviceEntry>::iterator it;
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("removeService");
+#endif
+	//First check if the gateway is already running
+	if (pGalZb->getGWStatus() == GW_RUNNING) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("removeService - Error GW_RUNNING");
+#endif
+		return -1;
+	}
+	pthread_mutex_lock(&mux);
+	it = servicesTable.find(endpoint);
+	if (it == servicesTable.end()) {
+		// No entries found!
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("removeService - No entries found");
+#endif
+		pthread_mutex_unlock(&mux);
+		return -2;
+	}
+	// Update the Service Simple Descriptor table in the GAL database
+	if (this->pGalDb->removeServicesSD(&(servicesTable[endpoint].simpleDesc))
+			== -1)
+		pLogger->fatal("removeService - removeServicesSD not found!");
+	// Remove entry
+	servicesTable.erase(it);
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->info("removeService - endpoint %d removed",endpoint);
+#endif
+	///	If servicesTable is empty, unregister a ServiceAgent listener on event ZB_APSDE_DATA_INDICATION in GalZbIf.
+	if (servicesTable.size() == 0) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->debug("removeService - serviceTable is empty -> unregister listener");
+#endif
+		pGalZb->unregisterListener(ZB_APSDE_DATA_INDICATION,
+				(void *) (&messageReceived_CbW));
+		dataListenerRegistered = FALSE;
+	}
+	pthread_mutex_unlock(&mux);
+	return 0;
+}
+
+/**
+ Public method ServiceAgent getFirstService
+ This method allows return the first allocated service present in the list
+
+ @return Status.
+ */
+template<class T>
+int ServiceAgent<T>::getFirstService() {
+	typename std::map<int, serviceEntry>::iterator it;
+	it = servicesTable.begin();
+	return (*it).first;
+}
+
+/**
+ Public method ServiceAgent createCallback
+ This method allows creating a WSN connection on a specific service or on all services defined in the local node. In particular, a
+ RCP listener is registered: this will be invoked on ZigBee message reception.
+
+ @param endpoint Number of the endpoint of interest.
+ @param rpcContextData RPC context data.
+ @return Status.
+ */
+template<class T>
+AgentError ServiceAgent<T>::createCallback(int endpoint,
+		CreateCallbackCtxt *rpcContextData) {
+	typename std::map<int, serviceEntry>::iterator it;
+	ServiceAgent* sAgent = ServiceAgent<T>::Instance();
+
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("createCallback - endpoint %d",endpoint);
+#endif
+	pthread_mutex_lock(&mux);
+
+	if (endpoint == ALL_ENDPOINTS && servicesTable.count(endpoint) == 0) {
+		// Create entry ALL_ENDPOINTS
+		servicesTable[endpoint].listener.features = AGO_NONE;
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->debug("createCallback - create entry ALL_ENDPOINTS");
+#endif
+	}
+
+	it = servicesTable.find(endpoint);
+	if (it == servicesTable.end()) {
+		// No entries found! We cannot allocate a listener to a SimpleDescriptor that doesn't exist
+		pLogger->error("createCallback - ERROR - Endpoint not registered");
+		pthread_mutex_unlock(&mux);
+		if (rpcContextData->getRPCResponseCb() != NULL) {
+			RPCReqStatus rpcReqStatus(End, FFAILED, ENDPOINT_NOT_REGISTERED);
+			CALL_RESPONSE (rpcContextData)(endpoint,
+					rpcContextData->getSessionId(), &rpcReqStatus);
+		} else {
+			pLogger->warn("createCallback - (a) - RPCResponseCb == NULL");
+		}
+		return ENDPOINT_NOT_REGISTERED;
+	}
+
+	///	Set Connection Status to ACTIVE - Even if an entry is present in servicesTable, received ZigBee Messages will not be forwarded to the RPC Module until a "connection" is explicitly created
+	if (!servicesTable[endpoint].listener.lock()) {
+		// NB: Only one RPC module can be registered on a specific endpoint!! However, at RPC layer multiple connections on the same endpoint can be considered.
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->warn("createCallback - EndPoint %d - connection previously created -> overwrite!", endpoint);
+#endif
+	}
+	servicesTable[endpoint].listener.rpcContext = *rpcContextData;
+	///	If the serviceTables contains only the connection that has just been created, a ServiceAgent listener on event ZB_APSDE_DATA_INDICATION in GalZbIf has to be registered.
+	if (servicesTable.size() > 0) {
+#ifdef DEBUG_ACTIVE_SA
+		if (sAgent->debugEnabled == true)
+		pLogger->debug("createCallback - Register ServiceAgent Data Listener on event ZB_APSDE_DATA_INDICATION");
+#endif
+		if (dataListenerRegistered == FALSE) {
+			pGalZb->registerListener(ZB_APSDE_DATA_INDICATION,
+					(void *) (&messageReceived_CbW));
+			dataListenerRegistered = TRUE;
+		}
+	} else {
+		if (sAgent->debugEnabled == true)
+			pLogger->debug("createCallback - WARNING: ServiceAgent DataListener ZB_APSDE_DATA_INDICATION not registered!");
+	}
+	pthread_mutex_unlock(&mux);
+	if (rpcContextData->getRPCResponseCb() != NULL) {
+		RPCReqStatus rpcReqStatus(End, FSUCCESS, AGENT_SUCCESS);
+		CALL_RESPONSE (rpcContextData)(endpoint, rpcContextData->getSessionId(),
+				&rpcReqStatus);
+	} else {
+		pLogger->warn("createCallback - RPCResponseCb is NULL, couldn't send a response");
+	}
+	return AGENT_SUCCESS;
+}
+
+template<class T>
+AgentError ServiceAgent<T>::createCallback(Callback *cb,
+		CreateCallbackCtxt *rpcContextData) {
+	typename std::map<int, serviceEntry>::iterator it;
+	ServiceAgent* sAgent = ServiceAgent<T>::Instance();
+	int endpoint;
+
+	pthread_mutex_lock(&mux);
+	// AddressSpecification
+	if (cb->filter.addressSpec.isDefined
+			&& cb->filter.addressSpec.isAPSDestinationEndpointDefined)
+		endpoint = cb->filter.addressSpec.APSDestinationEndpoint;
+	else
+		endpoint = ALL_ENDPOINTS;
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->info("createCallback - Internal Id = %d", cb->internalId);
+	pLogger->info("createCallback - endpoint %d",endpoint);
+#endif
+
+	if (endpoint == ALL_ENDPOINTS && servicesTable.count(endpoint) == 0) {
+		servicesTable[endpoint].customizedCallbackslistener.features = AGO_NONE;
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->debug("createCallback - create entry ALL_ENDPOINTS");
+#endif
+	}
+
+	it = servicesTable.find(endpoint);
+	if (it == servicesTable.end()) {
+		pthread_mutex_unlock(&mux);
+		pLogger->error("createCallback - ERROR Endpoint not registered");
+		if (rpcContextData->getRPCResponseCb() != NULL) {
+			RPCReqStatus rpcReqStatus(End, FFAILED, ENDPOINT_NOT_REGISTERED);
+			CALL_RESPONSE (rpcContextData)(endpoint,
+					rpcContextData->getSessionId(), &rpcReqStatus);
+		} else {
+			pLogger->warn("createCallback - (a) - RPCResponseCb == NULL");
+		}
+		return ENDPOINT_NOT_REGISTERED;
+	}
+
+	///	Set Connection Status to ACTIVE - Even if an entry is present in servicesTable, received ZigBee Messages will not be forwarded to the RPC Module until a "connection" is explicitly created
+	if (!servicesTable[endpoint].customizedCallbackslistener.lock()) {
+		pLogger->warn("createCallback - customized callbacks already defined for endpoint %d",
+				servicesTable[endpoint].customizedCallbacks.size(),
+				endpoint);
+	}
+	// Manage customized callbacks
+	if (cb != NULL) {
+		servicesTable[endpoint].customizedCallbacks.push_back(*cb);
+		pLogger->info("createCallback - new callback (endpoint %d) added in customizedCallbacks list (counter=%d)",
+				endpoint, servicesTable[endpoint].customizedCallbacks.size());
+
+		servicesTable[endpoint].customizedCallbackslistener.rpcContext =
+				*rpcContextData;
+	} else {
+		pthread_mutex_unlock(&mux);
+		pLogger->error("createCallback - cb == NULL");
+		if (rpcContextData->getRPCResponseCb() != NULL) {
+			RPCReqStatus rpcReqStatus(End, FFAILED, ENDPOINT_NOT_REGISTERED);
+			CALL_RESPONSE (rpcContextData)(endpoint,
+					rpcContextData->getSessionId(), &rpcReqStatus);
+		} else {
+			pLogger->warn("createCallback - (b) - RPCResponseCb == NULL");
+		}
+		return AGENT_ERROR;
+	}
+
+	///	If the serviceTables contains only the connection that has just been created, a ServiceAgent listener on event ZB_APSDE_DATA_INDICATION in GalZbIf has to be registered.
+	if (servicesTable.size() > 0) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("createCallback - Register ServiceAgent Data Listener on event ZB_APSDE_DATA_INDICATION");
+#endif
+		if (dataListenerRegistered == FALSE) {
+			pGalZb->registerListener(ZB_APSDE_DATA_INDICATION,
+					(void *) (&messageReceived_CbW));
+			dataListenerRegistered = TRUE;
+		}
+	} else {
+		if (sAgent->debugEnabled == true)
+			pLogger->debug("createCallback - WARNING: servicesTable.size is zero, ServiceAgent DataListener ZB_APSDE_DATA_INDICATION not registered!");
+	}
+	if (rpcContextData->getRPCResponseCb() != NULL) {
+		RPCReqStatus rpcReqStatus(End, FSUCCESS, AGENT_SUCCESS);
+		CALL_RESPONSE (rpcContextData)(endpoint, rpcContextData->getSessionId(),
+				&rpcReqStatus);
+	} else {
+		pLogger->warn("createCallback - (c) - RPCResponseCb == NULL");
+	}
+	pthread_mutex_unlock(&mux);
+	return AGENT_SUCCESS;
+}
+
+/**
+ Public method ServiceAgent deleteCallback
+ This method allows removing a WSN connection on a specific service or on all services defined in the local node.
+ An asynchronous response is sent
+
+ @param endpoint Number of the endpoint of interest.
+ @param rpcContextData RPC context data.
+ @return Status.
+ */
+
+template<class T>
+int ServiceAgent<T>::deleteCallback(int endpoint,
+		DeleteCallbackCtxt *rpcContextData) {
+	typename std::map<int, serviceEntry>::iterator it;
+
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("deleteCallback - endpoint %d",endpoint);
+#endif
+	pthread_mutex_lock(&mux);
+
+	it = servicesTable.find(endpoint);
+	if (it == servicesTable.end()) { // Note: this state should be unreachable!
+			// No entries found!
+		pLogger->error("deleteCallback - ERROR Endpoint not registered");
+		pthread_mutex_unlock(&mux);
+		if (rpcContextData->getRPCResponseCb() != NULL) {
+			RPCReqStatus rpcReqStatus(End, FFAILED, ENDPOINT_NOT_REGISTERED);
+			CALL_RESPONSE (rpcContextData)(endpoint,
+					rpcContextData->getSessionId(), &rpcReqStatus);
+		} else {
+			pLogger->warn("deleteCallback - (a) - RPCResponseCb == NULL");
+		}
+		return ENDPOINT_NOT_REGISTERED;
+	}
+
+	if (!servicesTable[endpoint].listener.unlock(Idle)) // Note: this state should be unreachable!
+			{
+		pLogger->error("deleteCallback - EndPoint %d - no listener previously registered on this specific EndPoint (WARNING)", endpoint);
+
+		pthread_mutex_unlock(&mux);
+		if (rpcContextData->getRPCResponseCb() != NULL) {
+			RPCReqStatus rpcReqStatus(End, FFAILED, NO_ACTIVE_WSN_CONNECTIONS);
+			CALL_RESPONSE (rpcContextData)(endpoint,
+					rpcContextData->getSessionId(), &rpcReqStatus);
+		} else {
+			pLogger->warn("deleteCallback - (b) - RPCResponseCb == NULL");
+		}
+		return NO_ACTIVE_WSN_CONNECTIONS;
+	}
+
+	pthread_mutex_unlock(&mux);
+	if (rpcContextData->getRPCResponseCb() != NULL) {
+		RPCReqStatus rpcReqStatus(End, FSUCCESS, AGENT_SUCCESS);
+		CALL_RESPONSE (rpcContextData)(endpoint, rpcContextData->getSessionId(),
+				&rpcReqStatus);
+	} else {
+		pLogger->warn("deleteCallback - (c) - RPCResponseCb == NULL");
+	}
+	return AGENT_SUCCESS;
+}
+
+template<class T>
+int ServiceAgent<T>::deleteCustomizedCallback(int internalId,
+		DeleteCallbackCtxt *rpcContextData) {
+	typename std::map<int, serviceEntry>::iterator it;
+
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("deleteCustomizedCallback - internalId %d", internalId);
+#endif
+	pthread_mutex_lock(&mux);
+
+	int serviceId = 0;
+	std::list<Callback>::iterator itCbList;
+	bool cbFound = false;
+
+	for (int i = ENDPOINT_001; i <= ENDPOINT_240; i++) {
+		if (cbFound)
+			break;
+		/*
+		 #ifdef DEBUG_ACTIVE_SA
+		 pLogger->debug("deleteCustomizedCallback - i = %d", i);
+		 #endif
+		 */
+		if (servicesTable.count(i) != 0) {
+			serviceId = i;
+#ifdef DEBUG_ACTIVE_SA
+			pLogger->debug("deleteCustomizedCallback - Considering serviceId %d", serviceId);
+#endif
+			if (servicesTable[serviceId].customizedCallbackslistener.isLocked()) {
+#ifdef DEBUG_ACTIVE_SA
+				pLogger->info("deleteCustomizedCallback - customized callback was registered on endpoint %d",serviceId);
+#endif
+				for (itCbList =
+						servicesTable[serviceId].customizedCallbacks.begin();
+						itCbList
+								!= servicesTable[serviceId].customizedCallbacks.end();
+						itCbList++) {
+#ifdef DEBUG_ACTIVE_SA
+					pLogger->info("deleteCustomizedCallback - filter internal id = %d",(*itCbList).internalId);
+#endif
+					if ((*itCbList).internalId == internalId) {
+						cbFound = true;
+#ifdef DEBUG_ACTIVE_SA
+						pLogger->info("deleteCustomizedCallback - filter internal id %d found!", internalId);
+#endif
+						// Remove the callback
+						servicesTable[serviceId].customizedCallbacks.erase(
+								itCbList);
+						// if equals to zero, unlock the listener
+						if (servicesTable[serviceId].customizedCallbacks.empty()) {
+							servicesTable[serviceId].customizedCallbackslistener.unlock();
+						}
+						// Send a notification
+						if (rpcContextData->getRPCResponseCb() != NULL) {
+							RPCReqStatus rpcReqStatus(End, FSUCCESS,
+									AGENT_SUCCESS);
+							CALL_RESPONSE (rpcContextData)(serviceId,
+									rpcContextData->getSessionId(),
+									&rpcReqStatus);
+						} else {
+							pLogger->warn("deleteCustomizedCallback - RPCResponseCb is NULL");
+						}
+					}
+				}
+			}
+			/* else {
+			 #ifdef DEBUG_ACTIVE_SA
+			 pLogger->info("deleteCustomizedCallback -  customized callback was NOT registered on endpoint %d",serviceId);
+			 #endif
+			 }
+			 */
+		}
+	}
+	if (cbFound == false) {
+		// Send a notification
+		if (rpcContextData->getRPCResponseCb() != NULL) {
+			RPCReqStatus rpcReqStatus(End, FFAILED, NO_CUSTOMIZED_FILTER_FOUND);
+			CALL_RESPONSE (rpcContextData)(internalId,
+					rpcContextData->getSessionId(), &rpcReqStatus);
+		} else {
+			pLogger->warn("deleteCustomizedCallback - RPCResponseCb is NULL");
+		}
+		pthread_mutex_unlock(&mux);
+		return AGENT_ERROR;
+	}
+	pthread_mutex_unlock(&mux);
+	return AGENT_SUCCESS;
+}
+
+/**
+ Public method ServiceAgent messageReceived_CbW
+ This is a static member function, used as a wrapper to callback to the non-static member messageReceived_Cb.
+ In particular, it is called by GalZbIf::APSDE_DATA_indication (when a ZigBee message is received).
+
+ @param dst_addr_mode Destination address mode.
+ @param dst_addr Destination address of the received message.
+ @param dst_ep Destination endpoint of the received message.
+ @param src_addr_mode Source address mode.
+ @param src_addr Source address of the received message.
+ @param src_ep Source endpoint of the received message.
+ @param profile_id Profile identifier considered in the received message.
+ @param cluster_id Cluster identifier considered in the received message.
+ @param asdu_len APS Service Data Unit length of the received message.
+ @param asdu APS Service Data Unit of the received message.
+ @param was_broadcast It indicates whether the trasmission was broadcast or not.
+ @param sec_status Security Status value.
+ @return Void.
+ */
+template<class T>
+void ServiceAgent<T>::messageReceived_CbW(uchar dst_addr_mode, uchar *dst_addr,
+		uchar dst_ep, uchar src_addr_mode, uchar *src_addr, uchar src_ep,
+		ushort profile_id, ushort cluster_id, ushort asdu_len, uchar *asdu,
+		uchar was_broadcast, uchar sec_status) {
+	ServiceAgent* sAgent = ServiceAgent<T>::Instance();
+	/*
+	 #ifdef DEBUG_ACTIVE_SA
+	 if (sAgent->debugEnabled == true)
+	 printf("ServiceAgent::messageReceived_CbW");
+	 #endif
+	 */
+	sAgent->messageReceived_Cb(dst_addr_mode, dst_addr, dst_ep, src_addr_mode,
+			src_addr, src_ep, profile_id, cluster_id, asdu_len, asdu,
+			was_broadcast, sec_status);
+	return;
+}
+
+/**
+ Public method ServiceAgent messageReceived_Cb
+ This method relates to the messageReceived callback function. In particular, the received ZigBee message can stored in the msgCache
+ if a WSN connection on the specific message destination endpoint has been created. However, the message can also be buffered in the cache
+ if a WSN connection is active on servicesTable entry "ALL_ENPOINTS".
+
+ @param dst_addr_mode Destination address mode.
+ @param dst_addr Destination address of the received message.
+ @param dst_ep Destination endpoint of the received message.
+ @param src_addr_mode Source address mode.
+ @param src_addr Source address of the received message.
+ @param src_ep Source endpoint of the received message.
+ @param profile_id Profile identifier considered in the received message.
+ @param cluster_id Cluster identifier considered in the received message.
+ @param asdu_len APS Service Data Unit length of the received message.
+ @param asdu APS Service Data Unit of the received message.
+ @param was_broadcast It indicates whether the trasmission was broadcast or not.
+ @param sec_status Security Status value.
+ @return Void.
+ */
+template<class T>
+void ServiceAgent<T>::messageReceived_Cb(uchar dst_addr_mode, uchar *dst_addr,
+		uchar dst_ep, uchar src_addr_mode, uchar *src_addr_p, uchar src_ep,
+		ushort profile_id, ushort cluster_id, ushort asdu_len, uchar *asdu,
+		uchar was_broadcast, uchar sec_status) {
+	Node * nodeFound; //, * tmpNode;
+	uchar tmpUchar_p[8]; // This parameter will contain the correct sourceAddress to use (eventually swapped)!
+	uchar* tmpIEEEAddrPointer;
+	ushort tmpShortAddr;
+	ushort nwkAddrToPing;
+	//ushort msgLength;
+
+	pthread_mutex_lock(&mux);
+	// Check if there are active end points available for the incoming message
+	if (servicesTable.count((int) dst_ep) == 0 && dst_ep != BROADCAST_ENDPOINT) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->warn("messageReceived_Cb - WARNING: No active service for the received message");
+#endif
+		pthread_mutex_unlock(&mux);
+		return;
+	}
+
+	switch (src_addr_mode) {
+	case ZB_AM_DIRECT_EX:
+		tmpUchar_p[0] = src_addr_p[0];
+		tmpUchar_p[1] = src_addr_p[1];
+		tmpUchar_p[2] = src_addr_p[2];
+		tmpUchar_p[3] = src_addr_p[3];
+		tmpUchar_p[4] = src_addr_p[4];
+		tmpUchar_p[5] = src_addr_p[5];
+		tmpUchar_p[6] = src_addr_p[6];
+		tmpUchar_p[7] = src_addr_p[7];
+		nodeFound = pGalDb->findNodeByIEEEAddr(tmpUchar_p);
+		break;
+	case ZB_AM_DIRECT:
+		tmpShortAddr = (src_addr_p[1] << 8) + src_addr_p[0];
+		nodeFound = pGalDb->findNodeByNwkAddr(tmpShortAddr);
+		if (nodeFound != NULL) {
+			//Pass from shortAddress to IEEEAddress
+			tmpIEEEAddrPointer = nodeFound->get_ieee_addr();
+			//Store the new value!
+			tmpUchar_p[0] = tmpIEEEAddrPointer[0];
+			tmpUchar_p[1] = tmpIEEEAddrPointer[1];
+			tmpUchar_p[2] = tmpIEEEAddrPointer[2];
+			tmpUchar_p[3] = tmpIEEEAddrPointer[3];
+			tmpUchar_p[4] = tmpIEEEAddrPointer[4];
+			tmpUchar_p[5] = tmpIEEEAddrPointer[5];
+			tmpUchar_p[6] = tmpIEEEAddrPointer[6];
+			tmpUchar_p[7] = tmpIEEEAddrPointer[7];
+			// Set the new sourceAddressMode
+			src_addr_mode = ZB_AM_DIRECT_EX;
+		}
+		break;
+	default:
+		nodeFound = NULL;
+		break;
+	}
+	if (nodeFound == NULL) {
+		nwkAddrToPing = (src_addr_p[1] << 8) + src_addr_p[0];
+		if (src_addr_mode == ZB_AM_DIRECT) {
+			// Trigger the discovery of the considered node
+			if ((this->autoDiscoveryUnknownNodeFeature != 0)
+					&& (!(profile_id == 0x0000
+							&& (cluster_id == 0x0013 || cluster_id == 0x8034)))) //0x8034 is a LeaveAnnouncement, 0x0013 is a NLME-JOIN.Indication
+					{
+				//#ifdef DEBUG_ACTIVE_SA
+				if (debugEnabled == true)
+					pLogger->debug("messageReceived_Cb - Ping the unknown node 0x%04x (Message discarded)",nwkAddrToPing);
+				//#endif
+				//pGalZb->registerListener(ZB_ZDO_IEEE_ADDR_CONFIRM,(void *) (&pDAgent->IeeeAddrConfirm_CbW));
+				pGalZb->ZDO_IEEE_ADDR_request(nwkAddrToPing,
+						ZDO_REQ_TYPE_EX_RES, 0);
+				usleep(PACETIME);
+			} else {
+				// Since we received an incoming message with shortAddress as sourceAddress, we cannot delivery the message to the upper layer!
+				//#ifdef DEBUG_ACTIVE_SA
+				if (debugEnabled == true)
+					pLogger->debug("messageReceived_Cb - Node 0x%04x unknown (autoDiscovery disabled) - DISCARDED!",nwkAddrToPing);
+				//#endif
+			}
+			pthread_mutex_unlock(&mux);
+			return;
+		} else {
+			// With Freescale we shall never enter here: case of an incoming message with sourceAddress==IEEEAddress instead of a short!
+#ifdef DEBUG_ACTIVE_SA
+			if (debugEnabled == true)
+			pLogger->debug("messageReceived_Cb - Node %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x unknown - DISCARDED!",
+					src_addr_p[0],src_addr_p[1],src_addr_p[2],src_addr_p[3],src_addr_p[4],src_addr_p[5],src_addr_p[6],src_addr_p[7]);
+#endif
+			pthread_mutex_unlock(&mux);
+			return;
+		}
+	}
+	if (debugEnabled == true) {
+		timeval tp;
+		gettimeofday(&tp, NULL);
+		pLogger->debug("[%lu.%06lu] - messageReceived_Cb - Received message from 0x%04x",tp.tv_sec,tp.tv_usec, nodeFound->get_nwk_addr());
+	}
+	if (nodeFound->getIsActive() == false
+			&& nodeFound->get_nwk_addr() != pGalDb->root->get_nwk_addr()) {
+		// Node alive (it just sent a message) but not active yet, force a MTMG_LQI_Req
+#ifdef DEBUG_ACTIVE_SA
+		if (debugEnabled == true)
+		pLogger->debug("messageReceived_Cb - Push this node to announce through a MGMT_LQI");
+#endif
+		nodeFound->setKANodeTimer(nodeFound->getKANodeTimer() - 2000); //2000 >> KAthreshold
+	}
+	// ************ dest Endpoint = BROADCAST_ENDPOINT ****************
+	// ************************ S T A R T *****************************
+	if ((int) dst_ep == BROADCAST_ENDPOINT) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("messageReceived_Cb - Message received on BROADCAST_ENDPOINT");
+#endif
+		Message *broadcastMsg;
+		broadcastMsg = new Message();
+
+		broadcastMsg->setDstAddrMode(dst_addr_mode);
+		broadcastMsg->setDstAddr(dst_addr);
+		broadcastMsg->setDstEp(dst_ep);
+		broadcastMsg->setSrcAddrMode(src_addr_mode);
+		broadcastMsg->setSrcAddr(tmpUchar_p);
+		broadcastMsg->setSrcNwkAddr(nodeFound->get_nwk_addr());
+		broadcastMsg->setSrcEp(src_ep);
+		broadcastMsg->setProfileId(profile_id);
+		broadcastMsg->setClusterId(cluster_id);
+		broadcastMsg->setPayload(asdu, asdu_len);
+		broadcastMsg->setMsgId(msgIdCounter);
+
+		for (int i = ENDPOINT_001; i <= ENDPOINT_240; i++) {
+			// Check if the end point is allocated
+			if (servicesTable.count(i) != 0) {
+				if (servicesTable[i].listener.isLocked()) {
+					///	The message is cached in a specific FIFO list, according to Destination End Point value.
+					// Refer to the registered callback function.
+#ifdef DEBUG_ACTIVE_SA
+					pLogger->info("messageReceived_Cb - callback function - endpoint %d",i);
+#endif
+					// RPC notify Callback
+					RPCReqStatus rpcReqStatus(Running, FSUCCESS, AGENT_SUCCESS);
+					FCALL_NOTIFY (servicesTable [i].listener)(i, broadcastMsg,
+							&rpcReqStatus);
+				}
+				//Manage customized callbacks
+				if (servicesTable[i].customizedCallbackslistener.isLocked()) {
+#ifdef DEBUG_ACTIVE_SA
+					pLogger->info("messageReceived_Cb - (a) -  customized callback was registered "
+							"on endpoint %d",i);
+#endif
+					this->messageFilter(broadcastMsg, i);
+				}
+			}
+		}
+		//free(broadcastMsg->getPayload(&msgLength));
+		delete (broadcastMsg);
+
+		// Check whether a WSN connection on ALL_ENDPOINTS has been created. If so, the message is cached in the proper FIFO list.
+		if (servicesTable[ALL_ENDPOINTS].listener.isLocked()) {
+			Message *genBroadcastMsg;
+
+			genBroadcastMsg = new Message();
+
+			genBroadcastMsg->setDstAddrMode(dst_addr_mode);
+			genBroadcastMsg->setDstAddr(dst_addr);
+			genBroadcastMsg->setDstEp(dst_ep);
+			genBroadcastMsg->setSrcAddrMode(src_addr_mode);
+			genBroadcastMsg->setSrcAddr(tmpUchar_p);
+			genBroadcastMsg->setSrcNwkAddr(nodeFound->get_nwk_addr());
+			genBroadcastMsg->setSrcEp(src_ep);
+			genBroadcastMsg->setProfileId(profile_id);
+			genBroadcastMsg->setClusterId(cluster_id);
+			genBroadcastMsg->setPayload(asdu, asdu_len);
+
+			genBroadcastMsg->setMsgId(msgIdCounter);
+
+			// Refer to the registered callback function.
+#ifdef DEBUG_ACTIVE_SA
+			pLogger->debug("messageReceived_Cb - callback function");
+#endif
+			// RPC notify Callback
+			RPCReqStatus rpcReqStatus(Running, FSUCCESS, AGENT_SUCCESS);
+			FCALL_NOTIFY (servicesTable[ALL_ENDPOINTS].listener)(
+					(int) genBroadcastMsg->getDstEp(), genBroadcastMsg,
+					&rpcReqStatus);
+			//free(genBroadcastMsg->getPayload(&msgLength));
+			delete (genBroadcastMsg);
+		}
+
+		if (servicesTable[ALL_ENDPOINTS].customizedCallbackslistener.isLocked()) {
+			Message *genBroadcastMsgcc;
+
+			genBroadcastMsgcc = new Message();
+
+			genBroadcastMsgcc->setDstAddrMode(dst_addr_mode);
+			genBroadcastMsgcc->setDstAddr(dst_addr);
+			genBroadcastMsgcc->setDstEp(dst_ep);
+			genBroadcastMsgcc->setSrcAddrMode(src_addr_mode);
+			genBroadcastMsgcc->setSrcAddr(tmpUchar_p);
+			genBroadcastMsgcc->setSrcNwkAddr(nodeFound->get_nwk_addr());
+			genBroadcastMsgcc->setSrcEp(src_ep);
+			genBroadcastMsgcc->setProfileId(profile_id);
+			genBroadcastMsgcc->setClusterId(cluster_id);
+			genBroadcastMsgcc->setPayload(asdu, asdu_len);
+
+			genBroadcastMsgcc->setMsgId(msgIdCounter);
+
+			pLogger->info("messageReceived_Cb - (b) -  customized callback was registered "
+					"on ALL_ENDPOINTS");
+
+			this->messageFilter(genBroadcastMsgcc, ALL_ENDPOINTS);
+			//free(genBroadcastMsgcc->getPayload(&msgLength));
+			delete (genBroadcastMsgcc);
+		}
+
+		// msgIdCounter value is increased (if it is equal to MAX_MSG_ID_COUNTER_VALUE, msgIdCounter has to be set to 0)
+		msgIdCounter++;
+		if (msgIdCounter == MAX_MSG_ID_COUNTER_VALUE) {
+			msgIdCounter = 0;
+#ifdef DEBUG_ACTIVE_SA
+			pLogger->warn("messageReceived_Cb - msgIdCounter set to 0");
+#endif
+		}
+		pthread_mutex_unlock(&mux);
+		return;
+	}
+	// ************ dest Endpoint = BROADCAST_ENDPOINT ****************
+	// ************************* E N D ********************************
+
+	// ************ dest Endpoint ! = BROADCAST_ENDPOINT ******************
+	// ************************* S T A R T ********************************
+	if (!servicesTable[(int) dst_ep].listener.isLocked()
+			&& !servicesTable[ALL_ENDPOINTS].listener.isLocked()
+			&& !servicesTable[(int) dst_ep].customizedCallbackslistener.isLocked()
+			&& !servicesTable[ALL_ENDPOINTS].customizedCallbackslistener.isLocked()) {
+		// Return except it is end point zero!
+		if (dst_ep != 0x00) {
+#ifdef DEBUG_ACTIVE_SA
+			pLogger->warn("messageReceived_Cb - No specified connection for end point %d",(int)dst_ep);
+#endif
+			pthread_mutex_unlock(&mux);
+			return;
+		} else {
+#ifdef DEBUG_ACTIVE_SA
+			pLogger->debug("messageReceived_Cb - End point 0 not managed here");
+#endif
+		}
+	}
+
+	// Verify if there is an existing end point active to handle this message
+	if (servicesTable[(int) dst_ep].listener.isLocked()
+			|| servicesTable[(int) dst_ep].customizedCallbackslistener.isLocked()) {
+		Message *msg;
+		msg = new Message();
+		msg->setDstAddrMode(dst_addr_mode);
+		msg->setDstAddr(dst_addr);
+		msg->setDstEp(dst_ep);
+		msg->setSrcAddrMode(src_addr_mode);
+		msg->setSrcAddr(tmpUchar_p);
+		msg->setSrcNwkAddr(nodeFound->get_nwk_addr());
+		msg->setSrcEp(src_ep);
+		msg->setProfileId(profile_id);
+		msg->setClusterId(cluster_id);
+		msg->setPayload(asdu, asdu_len);
+		msg->setMsgId(msgIdCounter);
+
+		///	The message is cached in a specific FIFO list, according to Destination End Point value.
+		storeMsg(msg, (int) dst_ep);
+		// Refer to the registered callback function.
+		if (servicesTable[(int) dst_ep].listener.isLocked()) {
+			// RPC notify Callback
+			RPCReqStatus rpcReqStatus(Running, FSUCCESS, AGENT_SUCCESS);
+			FCALL_NOTIFY (servicesTable[(int)dst_ep].listener)(
+					(int) msg->getDstEp(), msg, &rpcReqStatus);
+		}
+
+		if (servicesTable[(int) dst_ep].customizedCallbackslistener.isLocked()) {
+			pLogger->info("messageReceived_Cb - (d) -  customized callback was registered "
+					"on endpoint %d",(int)dst_ep);
+			this->messageFilter(msg, (int) dst_ep);
+		}
+	}
+
+	// Check whether a WSN connection on ALL_ENDPOINTS has been created. If so, the message is cached in the proper FIFO list.
+	if (servicesTable[ALL_ENDPOINTS].listener.isLocked()) {
+		Message *genMsg;
+		genMsg = new Message();
+
+		genMsg->setDstAddrMode(dst_addr_mode);
+		genMsg->setDstAddr(dst_addr);
+		genMsg->setDstEp(dst_ep);
+		genMsg->setSrcAddrMode(src_addr_mode);
+		genMsg->setSrcAddr(tmpUchar_p);
+		genMsg->setSrcNwkAddr(nodeFound->get_nwk_addr());
+		genMsg->setSrcEp(src_ep);
+		genMsg->setProfileId(profile_id);
+		genMsg->setClusterId(cluster_id);
+		genMsg->setPayload(asdu, asdu_len);
+		genMsg->setMsgId(msgIdCounter);
+
+		storeMsg(genMsg, ALL_ENDPOINTS);
+
+		// Refer to the registered callback function.
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->debug("messageReceived_Cb - callback function");
+#endif
+		// RPC notify Callback
+		RPCReqStatus rpcReqStatus(Running, FSUCCESS, AGENT_SUCCESS);
+		FCALL_NOTIFY (servicesTable[ALL_ENDPOINTS].listener)(
+				(int) genMsg->getDstEp(), genMsg, &rpcReqStatus);
+	}
+
+	if (servicesTable[ALL_ENDPOINTS].customizedCallbackslistener.isLocked()) {
+		Message *genMsgcc;
+		genMsgcc = new Message();
+		genMsgcc->setDstAddrMode(dst_addr_mode);
+		genMsgcc->setDstAddr(dst_addr);
+		genMsgcc->setDstEp(dst_ep);
+		genMsgcc->setSrcAddrMode(src_addr_mode);
+		genMsgcc->setSrcAddr(tmpUchar_p);
+		genMsgcc->setSrcNwkAddr(nodeFound->get_nwk_addr());
+		genMsgcc->setSrcEp(src_ep);
+		genMsgcc->setProfileId(profile_id);
+		genMsgcc->setClusterId(cluster_id);
+		genMsgcc->setPayload(asdu, asdu_len);
+		genMsgcc->setMsgId(msgIdCounter);
+
+		pLogger->info("messageReceived_Cb - customized callback registered on ALL_ENDPOINTS");
+		this->messageFilter(genMsgcc, ALL_ENDPOINTS);
+
+		//free(genMsgcc->getPayload(&msgLength));
+		delete (genMsgcc);
+	}
+
+	// msgIdCounter value is increased (if it is equal to MAX_MSG_ID_COUNTER_VALUE, msgIdCounter has to be set to 0)
+	msgIdCounter++;
+	if (msgIdCounter == MAX_MSG_ID_COUNTER_VALUE) {
+		msgIdCounter = 0;
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->warn("messageReceived_Cb - msgIdCounter set to 0");
+#endif
+	}
+	pthread_mutex_unlock(&mux);
+	return;
+}
+
+template<class T>
+void ServiceAgent<T>::messageFilter(Message *msg, int serviceId) {
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->info("messageFilter");
+#endif
+
+	bool matchFound = true;
+
+	std::list<Callback>::iterator it;
+
+	for (it = servicesTable[serviceId].customizedCallbacks.begin();
+			it != servicesTable[serviceId].customizedCallbacks.end(); it++) {
+		matchFound = true;
+		pLogger->info("messageFilter - filter internal id =% d",(*it).internalId);
+
+		// MessageSpecification elements
+		if ((*it).filter.messageSpec.isAPSClusterGroupDefined) {
+			if ((*it).filter.messageSpec.APSClusterGroup.compare("ZDP") == 0) {
+				if (msg->getSrcEp() != 0x00) {
+					pLogger->info("messageFilter - srcEndpoint = 0x%x != 0x00 - This is not a ZDP Msg",
+							msg->getSrcEp());
+					matchFound = false;
+				}
+				pLogger->info("messageFilter - cluster group ZDP - Match = %x",matchFound);
+			} else if ((*it).filter.messageSpec.APSClusterGroup.compare("ZCL")
+					== 0) {
+				if (msg->getSrcEp() == 0x00) {
+					pLogger->info("messageFilter - srcEndpoint = 0x%x == 0x00 - This is not a ZCL Msg",
+							msg->getSrcEp());
+					matchFound = false;
+				}
+				pLogger->info("messageFilter - cluster group ZCL - Match = %x",matchFound);
+			} else if ((*it).filter.messageSpec.APSClusterGroup.compare(
+					"Discovery") == 0) {
+				pLogger->info("messageFilter - cluster group Discovery");
+				bool localMatch = false;
+
+				if (msg->getSrcEp() != 0x00) {
+					pLogger->info("messageFilter - srcEndpoint = 0x%x != 0x00 - This is not a Discovery Msg",
+							msg->getSrcEp());
+					matchFound = false;
+				} else {
+					pLogger->info("messageFilter - Cluster Id IM = %d (%04x) ",
+							msg->getClusterId(), msg->getClusterId());
+
+					for (int c = 0; c < DISCOVERY_CLUSTERS_LIST_LEN; c++) {
+						pLogger->info("messageFilter - Discovery Cluster Id considered = %x",Discovery_clusters[c]);
+						if (Discovery_clusters[c] == msg->getClusterId()) {
+							localMatch = true;
+							pLogger->info("messageFilter - localMatch - cluster Id %x = cluster Id %x within the Discovery group",
+									msg->getClusterId(), Discovery_clusters[c]);
+							break;
+						}
+					}
+					if (!localMatch) {
+						matchFound = false;
+					}
+				}
+
+			} else if ((*it).filter.messageSpec.APSClusterGroup.compare("ing")
+					== 0) {
+				pLogger->info("messageFilter - APSClusterGroup - ing not supported");
+			} else if ((*it).filter.messageSpec.APSClusterGroup.compare(
+					"NWK_Management") == 0) {
+				pLogger->info("messageFilter - APSClusterGroup - NWK_Management not supported");
+			}
+		}
+
+		// AddressSpecification elements
+		if ((*it).filter.addressSpec.isDefined) {
+			if ((*it).filter.addressSpec.isNWKSourceAddressDefined) {
+				// Consider the nwk address of the incoming message
+				ushort nwkSrcAddr_IM = msg->getSrcNwkAddr();
+				// Consider the nwk address defined in the filter
+				ushort nwkSrcAddr_F = (*it).filter.addressSpec.NWKSourceAddress;
+				pLogger->info("messageFilter - nwkSrcAddr IM = %04x -- nwkSrcAddr Filter = %04x",
+						nwkSrcAddr_IM, nwkSrcAddr_F);
+
+				if (!((nwkSrcAddr_IM == nwkSrcAddr_F)
+						|| (nwkSrcAddr_F == 0xffff))) {
+					pLogger->info("messageFilter - (nwkSrcAddr IM = %04x) != (nwkSrcAddr Filter = %04x) -- NO MATCH",
+							nwkSrcAddr_IM, nwkSrcAddr_F);
+					matchFound = false;
+				}
+			}
+		}
+
+		if (matchFound) {
+			RPCReqStatus rpcReqStatus(Running, FSUCCESS, AGENT_SUCCESS);
+			FCALL_NOTIFY (servicesTable[serviceId].customizedCallbackslistener)(
+					(*it).internalId, msg, &rpcReqStatus);
+		}
+
+	}
+
+	pLogger->info("messageFilter - end");
+}
+
+/**
+ Protected method ServiceAgent storeMsg
+ This method stores the received ZigBee message in the cache msgCache.
+
+ @param msg ZigBee message received.
+ @param serviceId Message destination service identifier.
+ @return Void.
+ */
+template<class T>
+void ServiceAgent<T>::storeMsg(Message *msg, int serviceId) {
+	//ushort msgLength;
+	pthread_mutex_lock(&msgCacheMux);
+
+	msgCache[serviceId].push_back(msg);
+	if (msgCache[serviceId].size() > maxMsgCacheSize) {
+#ifdef DEBUG_ACTIVE_SA
+		if (debugEnabled == true)
+		pLogger->warn("storeMsg - Replacing oldest element");
+#endif
+		//free((msgCache[serviceId].front())->getPayload(&msgLength));
+		delete (msgCache[serviceId].front());
+		msgCache[serviceId].pop_front();
+	}
+
+	pthread_mutex_unlock(&msgCacheMux);
+}
+
+/**
+ Public method ServiceAgent getLastRxMsg
+ This method allows retrieving the last received message related to a specific service defined in the local node. The entry ALL_ENDPOINTS
+ (i.e. all services) can be considered as well.
+
+ @param serviceId Service identifier.
+ @param rpcContextData RPC context data.
+ @return Void.
+ */
+template<class T>
+int ServiceAgent<T>::getLastRxMsg(int serviceId,
+		RPCContext<T, getLastRxMsgResponseCb> *rpcContextData) {
+	if (msgCache[serviceId].empty()) {
+		pLogger->info("getLastRxMsg - Service Id = %d cache empty",serviceId);
+		if (rpcContextData != NULL) {
+			// RPC response Callback
+			RPCReqStatus rpcReqStatus(End, FFAILED, MSG_CACHE_EMPTY);
+			CALL_RESPONSE (rpcContextData)(NULL, rpcContextData->getSessionId(),
+					&rpcReqStatus);
+		}
+		return MSG_CACHE_EMPTY;
+	} else {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->debug("getLastRxMsg - endPoint = %d (cache size = %d)", serviceId, msgCache[serviceId].size());
+#endif
+		if (rpcContextData != NULL) {
+			// RPC response Callback
+			RPCReqStatus rpcReqStatus(End, FSUCCESS, AGENT_SUCCESS);
+			/* OLD
+			 CALL_RESPONSE (rpcContextData)
+			 (msgCache[serviceId].back(),
+			 rpcContextData -> getSessionId (),
+			 &rpcReqStatus);
+			 */
+			// NEW - 26-01-2012
+			CALL_RESPONSE (rpcContextData)(msgCache[serviceId].front(),
+					rpcContextData->getSessionId(), &rpcReqStatus);
+			delete (msgCache[serviceId].front());
+#ifdef DEBUG_ACTIVE_SA
+			pLogger->debug("getLastRxMsg - removed the oldest msg (cache size = %d)", msgCache[serviceId].size());
+#endif
+		}
+		return AGENT_SUCCESS;
+	}
+}
+
+/**
+ Public method ServiceAgent send
+ This method provides an interface to send specific ZigBee messages.
+
+ @param msg ZigBee message to be sent.
+ @param status the confirm status code
+ @param txTime the network tx time
+ @return Void.
+ */
+template<class T>
+int ServiceAgent<T>::send(Message *msg, unsigned char &status,
+		unsigned &txTime) {
+	uchar dst_addr_mode;
+	uchar *dst_addr;
+	uchar dst_ep;
+	ushort profile_id;
+	ushort cluster_id;
+	uchar src_ep;
+	ushort asdu_len;
+	uchar *asdu;
+	uchar tx_options;
+	uchar radius;
+	uchar tempToSwapAddr;
+	uchar ieeeAddrInv[8];
+	int i = 0;
+
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("send");
+#endif
+
+	Node * tmpNode;
+	ushort network_addr;
+	//uchar macaddr_ch[8];
+
+	if (pGalZb->getGWStatus() != GW_RUNNING) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("send - Error GAL_NOT_RUNNING");
+#endif
+		// Return Error Code
+		return GAL_NOT_RUNNING;
+	}
+
+	if (msg == NULL) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("send - Message is null");
+#endif
+		// Return Error Code
+		return SENDING_MSG_ERROR;
+	}
+
+	pthread_mutex_lock(&mux);
+	//Get all the information from Message
+	dst_addr_mode = msg->getDstAddrMode();
+	dst_addr = msg->getDstAddr(NULL);
+	dst_ep = msg->getDstEp();
+	profile_id = msg->getProfileId();
+	cluster_id = msg->getClusterId();
+	src_ep = msg->getSrcEp();
+	asdu = msg->getPayload(&asdu_len);
+	tx_options = msg->getTxSettings();
+	radius = msg->getMaxHopsNumber();
+
+	//Set the status and the txTime to return (those are parameters takes as arguments!!!)
+	status = ZB_ZDO_SUCCESS;
+	txTime = time(NULL);
+	timeval tp;
+	gettimeofday(&tp, NULL);
+
+	if (dst_addr_mode == ZB_AM_DIRECT) {
+		//ShortAddress - Swap it!
+		tempToSwapAddr = dst_addr[0];
+		dst_addr[0] = dst_addr[1];
+		dst_addr[1] = tempToSwapAddr;
+		memcpy(&network_addr, dst_addr, sizeof(short));
+		//#ifdef DEBUG_ACTIVE_SA
+		if (debugEnabled == true)
+			printf("[%lu.%06lu] - send APSDE_DATA_request to 0x%04x\n",
+					tp.tv_sec, tp.tv_usec, network_addr);
+		//#endif
+		pGalZb->APSDE_DATA_request(dst_addr_mode, dst_addr, dst_ep, profile_id,
+				cluster_id, src_ep, asdu_len, asdu, tx_options, radius);
+		// Check if we know this shortAddr
+		tmpNode = pGalDb->findNodeByNwkAddr(network_addr);
+		if (tmpNode == NULL) {
+			// Node unknown, we have to ping it!
+			if (this->autoDiscoveryUnknownNodeFeature == 0) {
+#ifdef DEBUG_ACTIVE_SA
+				if (debugEnabled == true)
+				pLogger->debug("send - autoDiscoveryUnknownNodes feature disabled");
+#endif
+				pthread_mutex_unlock(&mux);
+				return AGENT_SUCCESS;
+			}
+			// Send a ping!
+			if (debugEnabled == true)
+				pLogger->debug("send - Node 0x%02x%02x not recognized by GAL, ping this node!",dst_addr[1],dst_addr[0]);
+			//pGalZb->registerListener(ZB_ZDO_IEEE_ADDR_CONFIRM,(void *) (&pDAgent->IeeeAddrConfirm_CbW));
+			pGalZb->ZDO_IEEE_ADDR_request(network_addr, ZDO_REQ_TYPE_EX_RES, 0);
+			usleep(PACETIME);
+		}
+	} else {
+		//IEEE_Address
+		tmpNode = pGalDb->findNodeByIEEEAddr(dst_addr);
+		if (tmpNode != NULL) {
+			// Node present into DB, proceed with the conversion!
+			dst_addr_mode = ZB_AM_DIRECT;
+			network_addr = tmpNode->get_nwk_addr();
+			memcpy(dst_addr, &network_addr, sizeof(short));
+			//#ifdef DEBUG_ACTIVE_SA
+			if (debugEnabled == true)
+				printf("[%lu.%06lu] - send APSDE_DATA_request to 0x%02x%02x\n",
+						tp.tv_sec, tp.tv_usec, dst_addr[1], dst_addr[0]);
+			//#endif
+			//Send the message
+			pGalZb->APSDE_DATA_request(dst_addr_mode, dst_addr, dst_ep,
+					profile_id, cluster_id, src_ep, asdu_len, asdu, tx_options,
+					radius);
+			pthread_mutex_unlock(&mux);
+			return AGENT_SUCCESS;
+		}
+		// Node not found, send it as it is but we need to discovery its shortAddress (but we need to invert the IEEE_Address)
+		for (i = 7; i >= 0; i--)
+			ieeeAddrInv[7 - i] = dst_addr[i];
+		if (debugEnabled == true) {
+			printf(
+					"[%lu.%06lu] - Send APSDE_DATA_request to 0x%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+					tp.tv_sec, tp.tv_usec, ieeeAddrInv[0], ieeeAddrInv[1],
+					ieeeAddrInv[2], ieeeAddrInv[3], ieeeAddrInv[4],
+					ieeeAddrInv[5], ieeeAddrInv[6], ieeeAddrInv[7]);
+		}
+		pGalZb->APSDE_DATA_request(dst_addr_mode, ieeeAddrInv, dst_ep,
+				profile_id, cluster_id, src_ep, asdu_len, asdu, tx_options,
+				radius);
+		if (this->autoDiscoveryUnknownNodeFeature == 0) {
+#ifdef DEBUG_ACTIVE_SA
+			if (debugEnabled == true)
+			pLogger->debug("send - autoDiscoveryUnknownNodes feature disabled");
+#endif
+			pthread_mutex_unlock(&mux);
+			return AGENT_SUCCESS;
+		}
+		// We shall Send a ping but we can't!
+		if (debugEnabled == true)
+			pLogger->debug("send - autoDiscoveryUnknownNodes cannot work (ShortAddr unknown for 0x%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x)",
+					ieeeAddrInv[0],ieeeAddrInv[1],ieeeAddrInv[2],ieeeAddrInv[3],ieeeAddrInv[4],ieeeAddrInv[5],ieeeAddrInv[6],ieeeAddrInv[7]);
+	}
+	pthread_mutex_unlock(&mux);
+	return AGENT_SUCCESS;
+}
+
+template<class T>
+void ServiceAgent<T>::autoMatchDescriptorRsp_CbW(ushort src_addr,
+		ushort profile_id, uchar nicl, ushort *icllist, uchar nocl,
+		ushort *ocllist) {
+	ServiceAgent* sAgent = ServiceAgent<T>::Instance();
+
+#ifdef DEBUG_ACTIVE_SA
+	if (sAgent->debugEnabled == true)
+	printf("\nServiceAgent::autoMatchDescriptorRsp_CbW\n");
+#endif
+
+	sAgent->autoMatchDescriptorRsp_Cb(src_addr, profile_id, nicl, icllist, nocl,
+			ocllist);
+}
+
+/**
+ Protected method ServiceAgent activeEndPointsDiscovery_Cb
+ This method relates to activeEndPointsDiscovery callback function.
+ TO BE MODIFIED.
+
+ @param status Success or Error status related to the request.
+ @param nwk_addr Short address of the device of interest.
+ @param active_ep_count Number of active endpoints available on the device identified by nwk_addr.
+ @param active_ep_list Pointer to the endpoint list.
+ @return Void.
+ */
+template<class T>
+void ServiceAgent<T>::autoMatchDescriptorRsp_Cb(ushort src_addr,
+		ushort profile_id, uchar nicl, ushort *icllist, uchar nocl,
+		ushort *ocllist) {
+#ifdef DEBUG_ACTIVE_SA
+	pLogger->debug("autoMatchDescriptorRsp_Cb");
+#endif
+
+	uchar status;
+	ushort nwk_addr;
+	uchar match_len;
+	uchar *match_list;
+
+	// ------------------------------------------
+	std::list<int> matchList;
+	std::list<int>::iterator ml_it;
+	int matchlength = 0;
+
+	std::list<int>::iterator localICL_it;
+	std::list<int>::iterator localOCL_it;
+
+	///	Match criterion - to each simple descriptor
+	///	1)	Check that the ProfileID field (profile_id parameter) matches the application profile identifier field of the simple descriptor
+	///	1a)	If not -> match is unsuccessful, perform no further matching -> NEXT SIMPLE DESCRIPTOR
+
+	///	1b)	If ProfileIDs match-> go to 2)
+	///	2)	Check whether the match criteria contains a list of input clusters
+	///	2a)	list is present -> check that at least one of the considered cluster IDs matches one of the input cluster IDs of the local simple descriptor
+	///		  - at least one match	-> note EndPoint id and perform no further matching (for that specific simple descriptor) - MATCH SUCCESSFUL -> NEXT SIMPLE 	DESCRIPTOR
+	///		  - no match		-> go to 3)
+	///	2b)	list is not present ->	go to 3)
+	///	3)	Check whether the match criteria contains a list of output clusters
+	///	3a)	If a list is present -> check that at least one of the considered cluster IDs matches one of the output cluster IDs of the local simple descriptors
+	///		  - at least one match	-> note EndPoint id - MATCH SUCCESSFUL -> NEXT SIMPLE DESCRIPTOR
+	///		  - no match		-> MATCH UNSUCCESSFUL -> NEXT SIMPLE DESCRIPTOR
+	///	3b)	list is not present -> MATCH UNSUCCESSFUL -> NEXT SIMPLE DESCRIPTOR
+
+	// Calculate number of registered EPs = servicesTable size - 1 (in case the special EP ALL_ENDPOINTS is registered -> in fact, EP ALL_ENDPOINTS is not a real ZigBee EP)
+	int numOfRegisteredEPs = servicesTable.size()
+			- servicesTable.count(ALL_ENDPOINTS);
+	int EPcount = 0;
+	int matchFound = 0;
+
+	if ((int) nicl == 0 && (int) nocl == 0) {
+		pLogger->warn("autoMatchDescriptorRsp_Cb - Bad msg received! WARN");
+		return;
+	}
+
+	for (int i = ENDPOINT_001;
+			i <= ENDPOINT_240 && EPcount < numOfRegisteredEPs; i++) {
+		// Check whether endpoint is registered
+		if (servicesTable.count(i) != 0) {
+			EPcount++;
+
+			// STEP 1)
+			if (servicesTable[i].simpleDesc.profile_id != (int) profile_id) {
+				// STEP 1a)
+#ifdef DEBUG_ACTIVE_SA
+				pLogger->info("autoMatchDescriptorRsp_Cb - EndPoint= %d  - ProfileID check unsuccessful -> NEXT SIMPLE DESCRIPTOR",i);
+#endif
+				continue;
+			}
+
+			// STEP 1b)	-->  STEP 2)
+
+			// Reset matchFound flag
+			matchFound = 0;
+
+			if ((int) nicl != 0) {
+				// STEP 2a)
+				for (int j = 0; j < (int) nicl && matchFound == 0; j++) {
+
+					for (localICL_it =
+							servicesTable[i].simpleDesc.input_cluster.begin();
+							localICL_it
+									!= servicesTable[i].simpleDesc.input_cluster.end()
+									&& matchFound == 0; localICL_it++) {
+						if ((*localICL_it) == (int) icllist[j]) {
+#ifdef DEBUG_ACTIVE_SA
+							pLogger->info("autoMatchDescriptorRsp_Cb - EndPoint= %d  - Match successful",i);
+#endif
+							matchFound = 1;
+						}
+					}
+				}
+
+				if (matchFound != 0) {
+					// STEP 2a) - at least one match
+					// Increase Match length Variable and update MatchList
+					matchlength++;
+					matchList.push_back(i);
+#ifdef DEBUG_ACTIVE_SA
+					pLogger->info("autoMatchDescriptorRsp_Cb - EndPoint= %d  - Match successful (matchlength = %d) -> NEXT SIMPLE DESCRIPTOR", i, matchlength);
+#endif
+					continue;
+				}
+				// STEP 2a) - no match
+#ifdef DEBUG_ACTIVE_SA
+				pLogger->info("autoMatchDescriptorRsp_Cb - EndPoint= %d  - No Match on inputCluster list",i);
+#endif
+			} else {
+				// STEP 2b)
+#ifdef DEBUG_ACTIVE_SA
+				pLogger->info("autoMatchDescriptorRsp_Cb - Match criterion - input cluster list empty");
+#endif
+			}
+
+			// STEP 3)
+			if ((int) nocl != 0) {
+				// STEP 3a)
+				for (int j = 0; j < (int) nocl && matchFound == 0; j++) {
+
+					for (localOCL_it =
+							servicesTable[i].simpleDesc.output_cluster.begin();
+							localOCL_it
+									!= servicesTable[i].simpleDesc.output_cluster.end()
+									&& matchFound == 0; localOCL_it++) {
+						if ((*localOCL_it) == (int) ocllist[j]) {
+#ifdef DEBUG_ACTIVE_SA
+							pLogger->info("autoMatchDescriptorRsp_Cb - EndPoint= %d  - Match successful",i);
+#endif
+							matchFound = 1;
+						}
+					}
+				}
+
+				if (matchFound != 0) {
+					// STEP 3a) - at least one match
+					// Increase Match length Variable and update MatchList
+					matchlength++;
+					matchList.push_back(i);
+#ifdef DEBUG_ACTIVE_SA
+					pLogger->info("autoMatchDescriptorRsp_Cb - EndPoint= %d  - Match successful (matchlength = %d) -> NEXT SIMPLE DESCRIPTOR", i, matchlength);
+#endif
+					continue;
+				}
+				// STEP 3a) - no match
+#ifdef DEBUG_ACTIVE_SA
+				pLogger->info("autoMatchDescriptorRsp_Cb - EndPoint= %d  - No Match on inputCluster list - Match unsuccessful -> NEXT SIMPLE DESCRIPTOR",i);
+#endif
+			} else {
+				// STEP 3b)
+#ifdef DEBUG_ACTIVE_SA
+				pLogger->info("autoMatchDescriptorRsp_Cb - Match criterion - output cluster list empty -> NEXT SIMPLE DESCRIPTOR");
+#endif
+			}
+		}
+	}
+
+	// If the above procedures one or more matches -> construct Match_Desc_rsp; otherwise, return
+	if (matchlength == 0) {
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("autoMatchDescriptorRsp_Cb - No Match - Match unsuccessful -> return");
+#endif
+		return;
+	}
+
+	status = ZB_ZDO_SUCCESS;
+	nwk_addr = src_addr;
+	match_len = (uchar) matchlength;
+	match_list = (uchar *) malloc(matchlength * sizeof(uchar));
+
+	int pos = 0;
+	for (ml_it = matchList.begin();
+			ml_it != matchList.end() && pos < matchlength; ml_it++) {
+		match_list[pos] = (uchar) (*ml_it);
+#ifdef DEBUG_ACTIVE_SA
+		pLogger->info("autoMatchDescriptorRsp_Cb - Build match list = add EndPoint= %d",(*ml_it));
+#endif
+	}
+	pGalZb->ZDO_MATCH_DESC_response(status, nwk_addr, match_len, match_list);
+
+	free(match_list);
+}
+
+/**
+ Protected method ServiceAgent initTimers
+ Timers initialization.
+
+ @param void Void.
+ @return Status.
+ */
+template<class T>
+int ServiceAgent<T>::initTimers(void) {
+	ThreadPoolAttr attr;
+
+	TPAttrInit(&attr);
+	TPAttrSetMaxThreads(&attr, SA_MAX_THREADS);
+	TPAttrSetMinThreads(&attr, SA_MIN_THREADS);
+	TPAttrSetJobsPerThread(&attr, SA_JOBS_PER_THREAD);
+	TPAttrSetIdleTime(&attr, SA_THREAD_IDLE_TIME);
+
+#ifdef NEW_VERSION
+	TPAttrSetMaxJobsTotal(&attr, SA_MAX_JOBS_TOTAL);
+#endif
+
+	if (ThreadPoolInit(&threadPool, &attr) != 0) {
+		return -1;
+	}
+	TimerThreadInit(&timerThread, &threadPool);
+	return 0;
+}
+
+template<class T>
+void ServiceAgent<T>::onActiveEndpoints() {
+	pthread_mutex_lock(&mux);
+	pLogger->info("onTimer - getActiveEndPoints_Cb - getActiveEndPoints canceled (Failed)");
+	///	Set result
+	functionsContext.activeEndpoints.result = FFAILED;
+	///	Unregister listener
+	pGalZb->unregisterListener(ZB_ZDO_ACTIVE_EP_DESC_CONFIRM,
+			(void *) (&getActiveEndPoints_CbW));
+	///	Set getActiveEndPoints function state to Canceled
+	functionsContext.activeEndpoints.unlock(Canceled);
+	pthread_mutex_unlock(&mux);
+	if (functionsContext.activeEndpoints.rpcContext.getRPCNotifyCb() != NULL) {
+		RPCReqStatus rpcReqStatus(functionsContext.activeEndpoints,
+				TIMER_EXPIRED);
+		FCALL_NOTIFY (functionsContext.activeEndpoints)(NULL, &rpcReqStatus);
+	} else {
+		RPCReqStatus rpcReqStatus(functionsContext.activeEndpoints,
+				TIMER_EXPIRED);
+		FCALL_RESPONSE (functionsContext.activeEndpoints)(NULL,
+				functionsContext.activeEndpoints.rpcContext.getSessionId(),
+				&rpcReqStatus);
+	}
+}
+
+template<class T>
+void ServiceAgent<T>::onServiceDescriptor() {
+	pthread_mutex_lock(&mux);
+	pLogger->info("onTimer - getServiceDescriptor_Cb - getServiceDescriptor canceled (Failed)");
+	///	Set result
+	functionsContext.getServiceDescriptor.result = FFAILED;
+	///	Unregister listener
+	pGalZb->unregisterListener(ZB_ZDO_SIMPLE_DESC_CONFIRM,
+			(void *) (&getServiceDescriptor_CbW));
+	///	Set getServiceDescriptor function state to Canceled
+	functionsContext.getServiceDescriptor.unlock(Canceled);
+	pthread_mutex_unlock(&mux);
+	if (functionsContext.getServiceDescriptor.rpcContext.getRPCNotifyCb()
+			!= NULL) {
+		RPCReqStatus rpcReqStatus(functionsContext.getServiceDescriptor,
+				TIMER_EXPIRED);
+		FCALL_NOTIFY (functionsContext.getServiceDescriptor)(NULL,
+				NOT_SPECIFIED_ENDPOINT, &rpcReqStatus);
+	} else {
+		RPCReqStatus rpcReqStatus(functionsContext.getServiceDescriptor,
+				TIMER_EXPIRED);
+		FCALL_RESPONSE (functionsContext.getServiceDescriptor)(NULL,
+				NOT_SPECIFIED_ENDPOINT,
+				functionsContext.getServiceDescriptor.rpcContext.getSessionId(),
+				&rpcReqStatus);
+	}
+}
+
+template<class T>
+void ServiceAgent<T>::onGetnodebindingRequestExpired() {
+	pthread_mutex_lock(&mux);
+	pLogger->info("onGetnodebindingRequestExpired - BindRequest canceled (Failed)");
+	///	Set result
+	functionsContext.getnodebindingRequest.result = FFAILED;
+	///	Unregister listener
+	pGalZb->unregisterListener(ZB_ZDP_MGMT_BIND_RESPONSE,
+			(void *) (&getnodebinding_CbW));
+	///	Set getServiceDescriptor function state to Canceled
+	functionsContext.getnodebindingRequest.unlock(Canceled);
+	pthread_mutex_unlock(&mux);
+	if (functionsContext.getnodebindingRequest.rpcContext.getRPCNotifyCb()
+			!= NULL) {
+		RPCReqStatus rpcReqStatus(functionsContext.getnodebindingRequest,
+				TIMER_EXPIRED);
+		FCALL_NOTIFY (functionsContext.getnodebindingRequest)(0, 0, 0, NULL,
+				&rpcReqStatus);
+	} else {
+		RPCReqStatus rpcReqStatus(functionsContext.getnodebindingRequest,
+				TIMER_EXPIRED);
+		FCALL_RESPONSE (functionsContext.getnodebindingRequest)(0, 0, 0, NULL,
+				functionsContext.getnodebindingRequest.rpcContext.getSessionId(),
+				&rpcReqStatus);
+	}
+}
+
+template<class T>
+void ServiceAgent<T>::onBindRequestExpired() {
+	//ZB_BIND_STRUCT bindParams;
+	pthread_mutex_lock(&mux);
+	pLogger->info("onBindRequestExpired - BindRequest canceled (Failed)");
+	///	Set result
+	functionsContext.bindRequest.result = FFAILED;
+	///	Unregister listener
+	pGalZb->unregisterListener(ZB_ZDP_BIND_RESPONSE,
+			(void *) (&bindRequest_CbW));
+	///	Set getServiceDescriptor function state to Canceled
+	functionsContext.bindRequest.unlock(Canceled);
+	pthread_mutex_unlock(&mux);
+	if (functionsContext.bindRequest.rpcContext.getRPCNotifyCb() != NULL) {
+		RPCReqStatus rpcReqStatus(functionsContext.bindRequest, TIMER_EXPIRED);
+		FCALL_NOTIFY (functionsContext.bindRequest)(&rpcReqStatus);
+	} else {
+		RPCReqStatus rpcReqStatus(functionsContext.bindRequest, TIMER_EXPIRED);
+		FCALL_RESPONSE (functionsContext.bindRequest)(
+				functionsContext.bindRequest.rpcContext.getSessionId(),
+				&rpcReqStatus);
+	}
+}
+
+template<class T>
+void ServiceAgent<T>::onUnbindRequestExpired() {
+	pthread_mutex_lock(&mux);
+	pLogger->info("onUnbindRequestExpired - UnbindRequest canceled (Failed)");
+	///	Set result
+	functionsContext.unbindRequest.result = FFAILED;
+	///	Unregister listener
+	pGalZb->unregisterListener(ZB_ZDP_UNBIND_RESPONSE,
+			(void *) (&unbindRequest_CbW));
+	///	Set getServiceDescriptor function state to Canceled
+	functionsContext.unbindRequest.unlock(Canceled);
+	pthread_mutex_unlock(&mux);
+	if (functionsContext.unbindRequest.rpcContext.getRPCNotifyCb() != NULL) {
+		RPCReqStatus rpcReqStatus(functionsContext.unbindRequest,
+				TIMER_EXPIRED);
+		FCALL_NOTIFY (functionsContext.unbindRequest)(&rpcReqStatus);
+	} else {
+		RPCReqStatus rpcReqStatus(functionsContext.unbindRequest,
+				TIMER_EXPIRED);
+		FCALL_RESPONSE (functionsContext.unbindRequest)(
+				functionsContext.unbindRequest.rpcContext.getSessionId(),
+				&rpcReqStatus);
+	}
+}
+
+template<class T>
+void ServiceAgent<T>::onActiveEndpointsDiscovery() {
+	pthread_mutex_lock(&mux);
+	pLogger->debug("ServiceAgent::activeEndPointsDiscovery_Cb - activeEndPointsDiscovery canceled (Failed)");
+	/// Set result
+	functionsContext.activeEndpointsDiscovery.result = FFAILED;
+	/// Unregister listener
+	pGalZb->unregisterListener(ZB_ZDO_ACTIVE_EP_DESC_CONFIRM,
+			(void *) (&activeEndPointsDiscovery_CbW));
+	/// Set activeEndPointsDiscovery function state to Canceled
+	functionsContext.activeEndpointsDiscovery.unlock(Canceled);
+	pthread_mutex_unlock(&mux);
+}
+
+template<class T>
+void ServiceAgent<T>::onServiceDescriptorsDiscovery() {
+	pthread_mutex_lock(&mux);
+	pLogger->debug("ServiceAgent::serviceDescriptorsDiscovery_Cb - serviceDescriptorsDiscovery canceled (Failed)");
+	/// Set result
+	functionsContext.serviceDescriptorsDiscovery.result = FFAILED;
+	/// Unregister listener
+	pGalZb->unregisterListener(ZB_ZDO_SIMPLE_DESC_CONFIRM,
+			(void *) (&activeEndPointsDiscovery_CbW));
+	/// Set serviceDescriptorsDiscovery function state to Canceled
+	functionsContext.serviceDescriptorsDiscovery.unlock(Canceled);
+	pthread_mutex_unlock(&mux);
+}

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CServiceAgent.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CServiceAgent.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CServiceAgent.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,480 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef SERVICEAGENT_H
+#define SERVICEAGENT_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "ThreadPool.h"
+#include "TimerThread.h"
+
+#include "GalZbIf.h"
+#include "CMessage.h"
+#include "ZbNetDb.h"
+#include "CDebug.h"
+#include "Agents.h"
+
+#include "CDiscoveryAgent.h"			
+
+#include "ConfigurationRepository.h"
+
+/**
+ Service Agent is organized in macrofunctions, i.e.  getActiveEPs, getServiceDescriptor, ...
+ Each macrofunction is identified by a unique ID (please refer to the following ID list).
+ This unique ID is used as a key in associative arrays containing macrofunction context (e.g. the status
+ of the macrofunction, number of expected messages, ...) or the RPC listeners registered on the specific function.
+ Specific macrofunctions have been defined only for internal use (e.g. internal request to start a Discovery Agent Inquiry, ...)
+ */
+#define SA_GET_ACTIVE_EPS					1
+#define SA_GET_SERVICE_DESCRIPTOR				2
+#define SA_GET_NODE_SERVICE_DESCRIPTORs				3
+#define SA_ACTIVE_ENDPOINTS_DISCOVERY				4
+#define SA_SERVICE_DESCRIPTORS_DISCOVERY			5
+#define SA_SEND							6
+
+// Macrofunctions defined only for internal use
+#define SA_INTERNAL_START_INQUIRY_REQUEST			10
+#define SA_INTERNAL_IEEE_ADDRESS_REQUEST			11
+
+// The default configuration 
+#define CALL_DA_GET_IEEE_ADDRESS_DISABLED			0
+// -> defaultEndPoint in case no value is specified
+#define DEFAULT_END_POINT_NOT_SPECIFIED				8
+
+/**
+ Allmost all macrofunctions ( GetNodeDescriptor, GetPowerDescriptor and SuperService ) use a timeout: once it has expired, the related function
+ is terminated with a failure result (i.e. function not properly ended).
+ In some cases, different values are used depending on ZigBee platform (Integration, TI-Chipcon,... ) used.
+ */
+
+#define SA_INTERNAL_START_INQUIRY_REQUEST_DEFAULT_TIMEOUT	10
+#define CALL_DA_GET_IEEE_ADDRESS_REQUEST_DEFAULT_TIMEOUT	5
+
+/// Integration Associates (IA)
+//#define SA_GET_ACTIVE_EPS_TIMEOUT_IA				15
+//#define SA_GET_SERVICE_DESCRIPTOR_TIMEOUT_IA			15
+//#define SA_GET_NODE_SERVICE_DESCRIPTORs_TIMEOUT_IA		30
+//#define SA_ACTIVE_ENDPOINTS_DISCOVERY_TIMEOUT_IA		50		
+//#define SA_SERVICE_DESCRIPTORS_DISCOVERY_TIMEOUT_IA		50	
+#define SA_GET_ACTIVE_EPS_TIMEOUT_IA				6
+#define SA_GET_SERVICE_DESCRIPTOR_TIMEOUT_IA			6
+#define SA_GET_NODE_SERVICE_DESCRIPTORs_TIMEOUT_IA		20
+#define SA_ACTIVE_ENDPOINTS_DISCOVERY_TIMEOUT_IA		30		
+#define SA_SERVICE_DESCRIPTORS_DISCOVERY_TIMEOUT_IA		30	
+
+/// Texas Instruments - Chipcon (TICC)
+#define SA_GET_ACTIVE_EPS_TIMEOUT_TICC				6
+#define SA_GET_SERVICE_DESCRIPTOR_TIMEOUT_TICC			6
+#define SA_GET_NODE_SERVICE_DESCRIPTORS_TIMEOUT_TICC		20
+#define SA_ACTIVE_ENDPOINTS_DISCOVERY_TIMEOUT_TICC		30
+#define SA_SERVICE_DESCRIPTORS_DISCOVERY_TIMEOUT_TICC		30
+//TODO Modify the last 3 constants
+
+/**
+ Dummy service descriptor - This is used when a new service is added (and a specific endpoint is allocated) 
+ without requiring a specific service descriptor.
+ */
+#define DUMMY_PROFILE_ID					0
+#define DUMMY_DEVICE_ID						0
+#define DUMMY_DEVICE_VER					0
+#define DUMMY_COMPLEX_DESC_AVAILABLE				0
+#define DUMMY_USER_DESC_AVAILABLE				0
+#define DUMMY_INPUT_CLUSTER_1					0
+#define DUMMY_INPUT_CLUSTER_2					1
+#define DUMMY_INPUT_CLUSTER_3					2
+#define DUMMY_OUTPUT_CLUSTER_1					0
+#define DUMMY_OUTPUT_CLUSTER_2					1
+#define DUMMY_OUTPUT_CLUSTER_3					2
+
+/**
+ Set of constants used in public method addService.
+ */
+#define ENDPOINT_001						1
+#define ENDPOINT_240						240
+#define NOT_SPECIFIED_ENDPOINT				-1
+#define NOT_RUNNING							-2
+#define ERROR_ON_SETTING_TIMER				-3
+#define ALREADY_CALLED						-4
+#define MAX_NUM_ENDPOINTS					240
+
+/**
+ Set of constants used in servicesTable
+ */
+#define BROADCAST_ENDPOINT					255	
+
+#define ALL_ENDPOINTS						256
+
+/**
+ Set of constants used for received message cache
+ */
+#define MAX_MSG_CACHE_SIZE_DEFAULT				10
+#define MAX_MSG_ID_COUNTER_VALUE				2147483647	// Maximum value allowed for msgIdCounter
+
+/**
+ Set of generic constants used in ServiceAgent
+ */
+#define TRUE							1
+#define FALSE							0
+
+/**
+ Set of constants used in thread management.
+ */
+#define SA_MAX_THREADS						10
+#define SA_MIN_THREADS						10	
+#define SA_JOBS_PER_THREAD					10
+#define SA_THREAD_IDLE_TIME 					5000
+#define SA_MAX_JOBS_TOTAL 					10
+
+template<class T>
+class ServiceAgent {
+
+public:
+	//	function pointers types related to RPC callbacks (concerning getActiveEndPoints)
+	typedef void * (T::*activeEndPointsResponseCb)(Node *node, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void * (T::*activeEndPointsNotifyCb)(Node *node,
+			RPCReqStatus *rpcReqStatus);
+
+	///	function pointers types related to RPC callbacks (concerning addService)
+	typedef void * (T::*addServiceResponseCb)(SimpleDescriptor *serviceDesc,
+			int sessionId, RPCReqStatus *rpcReqStatus);
+
+	//	function pointers types related to RPC callbacks (concerning createCallback)
+	typedef void * (T::*createCallbackResponseCb)(int endpoint, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void * (T::*deleteCallbackResponseCb)(int endpoint, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void * (T::*messageReceivedNotifyCb)(int destEP, Message *message,
+			RPCReqStatus *rpcReqStatus);
+
+	//	function pointers types related to RPC callbacks (concerning getLastRxMsg)
+	typedef void * (T::*getLastRxMsgResponseCb)(Message *message, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	//	function pointers types related to RPC callbacks (concerning getServiceDescriptor)
+	typedef void * (T::*serviceDescriptorResponseCb)(Node *node, int endpoint,
+			int sessionId, RPCReqStatus *rpcReqStatus);
+
+	typedef void * (T::*serviceDescriptorNotifyCb)(Node *node, int endpoint,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void * (T::*getnodebindingResponseCb)(ushort bindingTableEntries,
+			ushort startIndex, ushort bindingTableListCount,
+			ZB_BIND_STRUCT *bindingtableList, int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void * (T::*getnodebindingNotifyCb)(ushort bindingTableEntries,
+			ushort startIndex, ushort bindingTableListCount,
+			ZB_BIND_STRUCT *bindingtableList, RPCReqStatus *rpcReqStatus);
+
+	typedef void * (T::*bindResponseCb)(int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void * (T::*bindNotifyCb)(RPCReqStatus *rpcReqStatus);
+
+	typedef void * (T::*unbindResponseCb)(int sessionId,
+			RPCReqStatus *rpcReqStatus);
+
+	typedef void * (T::*unbindNotifyCb)(RPCReqStatus *rpcReqStatus);
+
+	typedef RPCContext<T, addServiceResponseCb> AddServiceCtxt;
+
+	typedef RPCContext<T, activeEndPointsResponseCb, activeEndPointsNotifyCb> ActiveEndPointsCtxt;
+
+	typedef RPCContext<T, createCallbackResponseCb, messageReceivedNotifyCb> CreateCallbackCtxt;
+
+	typedef RPCContext<T, deleteCallbackResponseCb> DeleteCallbackCtxt;
+
+	typedef RPCContext<T, getLastRxMsgResponseCb> GetLastRxMsgCtxt;
+
+	typedef RPCContext<T, serviceDescriptorResponseCb, serviceDescriptorNotifyCb> ServiceDescriptorCtxt;
+
+	typedef RPCContext<T, getnodebindingResponseCb, getnodebindingNotifyCb> GetnodebindingCtxt;
+
+	typedef RPCContext<T, bindResponseCb, bindNotifyCb> BindCtxt;
+
+	typedef RPCContext<T, unbindResponseCb, unbindNotifyCb> UnbindCtxt;
+
+public:
+	// Constructors
+
+	// Destructor
+	~ServiceAgent();
+
+	// Functions: modifiers (set), selectors (get)
+
+	// Pattern Singleton
+	static ServiceAgent *Instance(void);
+
+	void init();
+
+	int addZDOService(RPCContext<T, addServiceResponseCb> *rpcContextData);
+	int addDefaultService(RPCContext<T, addServiceResponseCb> *rpcContextData);
+
+	/// Macrofunction getActiveEndPoints -- public methods: getActiveEndPoints 
+	int getActiveEndPoints(unsigned long int timeout, ushort nwk_addr,
+			ActiveEndPointsCtxt *rpcContextData);
+
+	static void getActiveEndPoints_CbW(uchar status, ushort nwk_addr,
+			uchar active_ep_count, uchar *active_ep_list);
+
+	/// Macrofunction getServiceDescriptor -- public methods: getServiceDescriptor 
+	int getServiceDescriptor(unsigned long int timeout, ushort nwk_addr,
+			uchar end_point, ServiceDescriptorCtxt *rpcContextData);
+
+	static void getServiceDescriptor_CbW(uchar status, ushort nwk_addr,
+			ZB_SIMPLE_DESC *simple_desc);
+
+	/// Macrofunction getNodeServiceDescriptors -- public methods: getServiceDescriptor 
+	int getNodeServiceDescriptors(ushort nwk_addr);
+
+	int getnodebindingRequest(unsigned long int timeout, short destAddr,
+			int startIndex, GetnodebindingCtxt *rpcContextData);
+
+	static void getnodebinding_CbW(uchar status, ushort bindingTableEntries,
+			ushort startIndex, ushort bindingTableListCount,
+			ZB_BIND_STRUCT *bindingtableList);
+
+	void getnodebinding_Cb(uchar status, ushort bindingTableEntries,
+			ushort startIndex, ushort bindingTableListCount,
+			ZB_BIND_STRUCT *bindingtableList);
+
+	int bindRequest(unsigned long int timeout, ZB_BIND_STRUCT bindParams,
+			BindCtxt *rpcContextData);
+
+	static void bindRequest_CbW(uchar status);
+
+	int unbindRequest(unsigned long int timeout, ZB_BIND_STRUCT bindParams,
+			UnbindCtxt *rpcContextData);
+
+	static void unbindRequest_CbW(uchar status);
+
+	/// Macrofunction activeEndPointsDiscovery -- public methods: activeEndPointsDiscovery.
+	int activeEndPointsDiscovery();
+
+	static void activeEndPointsDiscovery_CbW(uchar status, ushort nwk_addr,
+			uchar active_ep_count, uchar *active_ep_list);
+
+	//TODO	Define function pointers types related to RPC callbacks (concerning activeEndPointsDiscovery)
+
+	/// Macrofunction serviceDescriptorDiscovery -- public methods: serviceDescriptorDiscovery.
+	int serviceDescriptorsDiscovery();
+
+	static void serviceDescriptorsDiscovery_CbW(uchar status, ushort nwk_addr,
+			ZB_SIMPLE_DESC *simple_desc);
+
+	//TODO	Define function pointers types related to RPC callbacks (concerning serviceDescriptorsDiscovery)
+
+	int getCurrentServices(int *services);
+
+	/// Services Management
+	int addService(SimpleDescriptor *serviceDesc,
+			AddServiceCtxt *rpcContextData);
+
+	//--
+	bool isEndpointAvailable(int endpoint);
+
+	int removeService(int endpoint);
+
+	int getFirstService();
+
+	AgentError createCallback(int endpoint, CreateCallbackCtxt *rpcContextData);
+
+	AgentError createCallback(Callback *cb, CreateCallbackCtxt *rpcContextData);
+
+	int deleteCallback(int endpoint, DeleteCallbackCtxt *rpcContextData);
+
+	int deleteCustomizedCallback(int internalId,
+			DeleteCallbackCtxt *rpcContextData);
+
+	/// Data management
+	static void messageReceived_CbW(uchar dst_addr_mode, uchar *dst_addr,
+			uchar dst_ep, uchar src_addr_mode, uchar *src_addr, uchar src_ep,
+			ushort profile_id, ushort cluster_id, ushort asdu_len, uchar *asdu,
+			uchar was_broadcast, uchar sec_status);
+
+	int getLastRxMsg(int serviceId, GetLastRxMsgCtxt *rpcContextData);
+
+	int send(Message *msg, uchar &confirmStatus, unsigned &txTime);
+
+	/// Automatic Response
+	static void autoMatchDescriptorRsp_CbW(ushort src_addr, ushort profile_id,
+			uchar nicl, ushort *icllist, uchar nocl, ushort *ocllist);
+
+	/// Pointers to other GAL Agents
+	//DiscoveryAgent<ServiceAgent> *pDAgent;
+
+	// iterators:
+	// Attributes visible by scope of instantiation and use
+
+protected:
+
+	/// Constructor (pattern Singleton)
+	ServiceAgent();
+
+	/// Macrofunction getActiveEndPoints -- protected method: getActiveEndPoints_Cb */
+	void getActiveEndPoints_Cb(uchar status, ushort nwk_addr,
+			uchar active_ep_count, uchar *active_ep_list);
+
+	/// Macrofunction getServiceDescriptor -- protected method: getServiceDescriptor_Cb */
+	void getServiceDescriptor_Cb(uchar status, ushort nwk_addr,
+			ZB_SIMPLE_DESC *simple_desc);
+
+	void getnodebindingRequest_Cb(ushort bindingTableEntries, ushort startIndex,
+			ushort bindingTableListCount, ZB_BIND_STRUCT *bindingtableList,
+			uchar status);
+
+	void bindRequest_Cb(uchar status);
+
+	void unbindRequest_Cb(uchar status);
+
+	///	Macrofunction getNodeServiceDescriptors -- protected methods: getNodeServiceDescriptors_Cb 
+	void getNodeServiceDescriptors_Cb(uchar status, ushort nwk_addr,
+			ZB_SIMPLE_DESC *simple_desc);
+
+	/// Macrofunction activeEndPointsDiscovery -- public methods: activeEndPointsDiscovery_Cb.
+	void activeEndPointsDiscovery_Cb(uchar status, ushort nwk_addr,
+			uchar active_ep_count, uchar *active_ep_list);
+
+	/// Macrofunction serviceDescriptorDiscovery -- public methods: serviceDescriptorsDiscovery_Cb.
+	void serviceDescriptorsDiscovery_Cb(uchar status, ushort nwk_addr,
+			ZB_SIMPLE_DESC *simple_desc);
+
+	/// Data management
+	void messageReceived_Cb(uchar dst_addr_mode, uchar *dst_addr, uchar dst_ep,
+			uchar src_addr_mode, uchar *src_addr, uchar src_ep,
+			ushort profile_id, ushort cluster_id, ushort asdu_len, uchar *asdu,
+			uchar was_broadcast, uchar sec_status);
+
+	void messageFilter(Message *msg, int serviceId);
+
+	void storeMsg(Message *msg, int serviceId);
+
+	/// Automatic Response
+	void autoMatchDescriptorRsp_Cb(ushort src_addr, ushort profile_id,
+			uchar nicl, ushort *icllist, uchar nocl, ushort *ocllist);
+
+	/// Timers management
+	int initTimers(void);
+
+	void onActiveEndpoints();
+	void onServiceDescriptor();
+	void onGetnodebindingRequestExpired();
+	void onBindRequestExpired();
+	void onUnbindRequestExpired();
+	void onActiveEndpointsDiscovery();
+	void onServiceDescriptorsDiscovery();
+
+	typedef void *TIMERPROC;
+
+	///	Pointer to GalZbIf object
+	GalZbIf *pGalZb;
+
+	///	Pointer to Gal database (refer to ZbNetDb class)
+	ZbNetDb *pGalDb;
+
+	///	Pointer to a Debug object -> logger
+	Debug *pLogger;
+
+	/// To enable/disable Debug (default value is 0)
+	bool debugEnabled;
+
+	/// To enable/disable the automatic discovery of unknown devices
+	int autoDiscoveryUnknownNodeFeature;
+
+private:
+	// Local attributes
+
+	// Pattern Singleton
+	static ServiceAgent instance;
+
+	///	Mutex
+	pthread_mutex_t mux;
+	pthread_mutex_t msgCacheMux;
+
+	///	Thread management
+	ThreadPool threadPool;
+	TimerThread timerThread;
+
+	struct fContexts {
+		fContext<T, ServiceAgent, activeEndPointsResponseCb,
+				activeEndPointsNotifyCb> activeEndpoints;
+
+		fContext<T, ServiceAgent, serviceDescriptorResponseCb,
+				serviceDescriptorNotifyCb> getServiceDescriptor;
+
+		fContext<T, ServiceAgent, getnodebindingResponseCb,
+				getnodebindingNotifyCb> getnodebindingRequest;
+
+		fContext<T, ServiceAgent, bindResponseCb, bindNotifyCb> bindRequest;
+
+		fContext<T, ServiceAgent, unbindResponseCb, unbindNotifyCb> unbindRequest;
+
+		fContext<T, ServiceAgent> activeEndpointsDiscovery;
+		fContext<T, ServiceAgent> serviceDescriptorsDiscovery;
+
+		fContexts(GalZbIf::FeatureControl *fc) :
+				activeEndpoints(fc, AGO_GET_ACTIVE_EPS), getServiceDescriptor(
+						fc, AGO_GET_SERVICE_DESC), getnodebindingRequest(fc,
+						AGO_MGMT_BIND_REQUEST), bindRequest(fc,
+						AGO_BIND_REQUEST), unbindRequest(fc,
+						AGO_UNBIND_REQUEST), activeEndpointsDiscovery(fc,
+						AGO_ACT_EPS_DISCOVERY | AGO_SERVICE_DESC_DISCOVERY
+								| AGO_GET_SERVICE_DESC | AGO_GET_ACTIVE_EPS), serviceDescriptorsDiscovery(
+						fc,
+						AGO_SERVICE_DESC_DISCOVERY | AGO_ACT_EPS_DISCOVERY
+								| AGO_GET_SERVICE_DESC | AGO_GET_ACTIVE_EPS) {
+		}
+
+	} functionsContext;
+
+	///	serviceEntry is the struct containing a pointer to a service descriptor and a pointer to a static member function of a generic Agent or RPC listener.
+	struct serviceEntry {
+		SimpleDescriptor simpleDesc;
+		fContext<T, ServiceAgent, createCallbackResponseCb,
+				messageReceivedNotifyCb> listener;
+
+		std::list<Callback> customizedCallbacks;
+		fContext<T, ServiceAgent, createCallbackResponseCb,
+				messageReceivedNotifyCb> customizedCallbackslistener;
+
+		serviceEntry() :
+				listener(GalZbIf::Instance()->getFeatureControl(), AGO_NONE), customizedCallbackslistener(
+						GalZbIf::Instance()->getFeatureControl(), AGO_NONE) {
+		}
+	};
+
+	///	The map servicesTable contains serviceEntry structs related to specific endpoints and is used to manage connections between the local node and remote nodes.
+	std::map<int, serviceEntry> servicesTable;
+
+	///	The attribute dataListenerRegistered is set to TRUE if a ServiceAgent callback has been already registered on event ZB_APSDE_DATA_INDICATION (in GalZbIf), FALSE otherwise.
+	int dataListenerRegistered;
+
+	///	Received message can be cached in FIFO lists (according to msgCacheEnabled value), one for each active connection.
+	std::map<int, std::list<Message *> > msgCache;
+
+	///	msgIdCounter is a counter used to uniquely identify each received ZigBee message	
+	int msgIdCounter;
+
+	///	The attribute msgCacheEnabled determines whether received messages are to be cached or not.
+	//int msgCacheEnabled;
+	///	maxMsgCacheSize is the maximum allowed size of the message cache
+	size_t maxMsgCacheSize;
+
+};
+
+#import "CServiceAgent.cpp"
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CTrustCenterAgent.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CTrustCenterAgent.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CTrustCenterAgent.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,1131 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+/**
+ * @brief CTrustCenterAgent. Trust Center Agent Implementation.
+ */
+
+#warning NOTE
+/*
+ -Facendo un po' di hacking, mi sono accorto che non sono accettati piu' di DA_MAX_THREADS (ora a 10...) che faccio se non ho piu' timeout-slot a disposizione ? Butto fuori ?
+ -__int64 e' un estensione non standard, come long long, quindi non possiamo usarla, perche' sara' difficile che sia supportata dal videotelefono http://www.thescripts.com/forum/thread63790.html
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include "CTrustCenterAgent.h"
+#include "zigbee.h"
+#include "ConfigurationRepository.h"
+#include "StaticACLLoader.h"
+
+//Actual variables is in header file, this is just an extern reference
+///static singleton instance of TrustCenterAgent
+template<class T>
+TrustCenterAgent<T> *TrustCenterAgent<T>::pInstance = NULL;
+
+///debug boject pointer for static methods
+Debug *staticDebug = NULL;
+
+string state;
+
+/**
+ Constructor
+ TrustCenterAgent constructor. It is a protected method (pattern Singleton)
+ */
+template<class T>
+TrustCenterAgent<T>::TrustCenterAgent() {
+
+	_pLogger = new Debug("TrustCenterAgent");
+	staticDebug = _pLogger;
+	_pLogger->setDebugLevel(DEBUGGING);
+	_pLogger->setDebugMode(DBG_ENABLED);
+	_pLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+	_pLogger->enableDebugOuput(DBG_SCREEN);
+
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+	_pLogger->debug ( "TrustCenterAgent Constructor\n" );
+#endif
+	//accessing singleton configuration repository
+	_conf = ConfigurationRepository::instance();
+
+	if (_conf == NULL) {
+		_pLogger->fatal ( "Missing configuration repository." );
+	}
+
+// instantiate local access control list and loading it from the configuration repository
+	_acl = new ACL();
+
+	/*
+	 // Boris BEGIN 27122007
+	 // load TC_AGENT
+	 state = _conf->getparam ( "TC_AGENT" );
+
+
+	 if ( state.empty() )
+	 {
+	 _pLogger->fatal ( "Missing TC_AGENT in configuration repository" );
+	 }
+
+	 if ( state.compare ( "true" ) ==0 )
+	 {
+	 }
+	 else if ( state.compare ( "false" ) ==0 )
+	 {
+	 //               this->~TrustCenterAgent();
+	 }
+	 else
+	 {
+	 _pLogger->fatal ( "invalid/missing TC_AGENT [%s]. Legal values are [true,false]",state.c_str() );
+	 }
+
+	 // Boris END 27122007
+	 */
+
+//load TC_JOINREQUESTPROCESSING
+	string jrp = _conf->getstring("tc:joinrequestprocessing", "");
+
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+	_pLogger->debug ( "TC: loaded jrp param [%s]",jrp.c_str() );
+#endif
+
+	if (jrp.empty()) {
+		_pLogger->fatal ( "Missing TC_JOINREQUESTPROCESSING in configuration repository" );
+	}
+
+	if (jrp.compare("true") == 0) {
+		this->setJoinReqProcessing(true);
+	} else if (jrp.compare("false") == 0) {
+		this->setJoinReqProcessing(false);
+	} else {
+		_pLogger->fatal ( "invalid/missing TC_JOINREQUESTPROCESSING [%s]. Legal values are [true,false]",jrp.c_str() );
+	}
+
+//load TC_LEAVENOTIFICATIONPROCESSING
+	string lnp = _conf->getstring("tc:leavenotificationprocessing", "");
+
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+	_pLogger->debug ( "TC: loaded lnp param [%s]",lnp.c_str() );
+#endif
+	if (jrp.empty()) {
+		_pLogger->fatal ( "Missing TC_LEAVENOTIFICATIONPROCESSING in configuration repository" );
+	}
+
+	if (lnp.compare("true") == 0) {
+		this->setLeaveNotifProcessing(true);
+	} else if (lnp.compare("false") == 0) {
+		this->setLeaveNotifProcessing(false);
+	} else {
+		_pLogger->fatal ( "invalid/missing TC_LEAVENOTIFICATIONPROCESSING [%s]. Legal values are [true,false]",lnp.c_str() );
+	}
+
+//load acl file name (only if needed)
+
+	if (this->_confparam_joinRequestProcessing) {
+
+		string aclfilename = _conf->getstring("tc:aclfilename", "");
+
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+		_pLogger->debug ( "TC: loaded acl filename [%s]",aclfilename.c_str() );
+#endif
+
+		if (aclfilename.empty()) {
+			_pLogger->fatal ( "Missing TC_ACLFILENAME in configuration repository" );
+		}
+
+		if (!StaticACLLoader::load(aclfilename.c_str(), _acl)) {
+			_pLogger->fatal ( "Missing acl file [%s] or acl file error",aclfilename.c_str() );
+		}
+
+	}
+
+//load TC_APPSECURITYTIMEOUTPERIOD
+	int appsectimeout = _conf->getint("tc:appsecuritytimeoutperiod", -1);
+
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+	_pLogger->debug ( "TC: loaded appsectimeout [%d]", appsectimeout);
+#endif
+
+	if (appsectimeout == -1) {
+		_pLogger->fatal ( "Missing TC_APPSECURITYTIMEOUTPERIOD in configuration repository" );
+	}
+
+	// 	loaded_appsectimeout=loaded_appsectimeout;
+
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+	_pLogger->debug ( "TC: setting App sec Timeoutperiod to [%d] milliseconds", appsectimeout );
+#endif
+	this->setAPSSecTimeOutPeriod_msec(appsectimeout);
+
+//load TC_NETWORKKEY
+	string nwk = _conf->getstring("tc:networkkey", "");
+
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+	_pLogger->debug ( "TC: loaded TC_NETWORKKEY [%s]",nwk.c_str() );
+#endif
+
+	if (nwk.empty()) {
+// Boris 04022008 change from fatal to debug BEGIN
+//		_pLogger->fatal ( "Missing TC_NETWORKKEY in configuration repository" );
+		_pLogger->debug ( "Missing, invalid or ZERO TC_NETWORKKEY in configuration repository, Trust Center and Security are DISABLED !!!" );
+// Boris 04022008 change from fatal to debug END
+	} else {
+		uchar *loadedkey = StaticACLLoader::parseBytes(nwk, NWK_KEY_SIZE);
+
+		if (loadedkey == NULL) {
+			_pLogger->fatal ( "wrong TC_NETWORKKEY format in configuration repository" );
+		} else {
+			this->setNetworkKey(loadedkey);
+		}
+
+	}
+
+//instantiate network node list
+	_anl = new NodeMap();
+
+//Boris Moltchanov 06122007 per impostare l'indirizzo del coordinatore stesso
+//load TC_IEEE_ADDRESS
+	string tc_ieee_addr = _conf->getstring("tc:ieee_address", "");
+
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+	_pLogger->debug ( "TC: loaded TC_IEEE_ADDRESS [%s]",tc_ieee_addr.c_str() );
+#endif
+
+	if (tc_ieee_addr.empty()) {
+		_pLogger->fatal ( "Missing TC_IEEE_ADDRESS in configuration repository" );
+	} else {
+		uchar *loadedtcieeeaddress = StaticACLLoader::parseBytes(tc_ieee_addr,
+				IEEE_RAWADDRESS_SIZE);
+
+		if (loadedtcieeeaddress == NULL) {
+			_pLogger->fatal ( "wrong TC_IEEE_ADDRESS format in configuration repository" );
+		} else {
+			// _anl->addNode(new NodeMapItem(0,loadedtcieeeaddress,0,0,FALSE));
+			_anl->addNode(new NodeMapItem(loadedtcieeeaddress));
+			this->setIEEEAddr(loadedtcieeeaddress);
+		}
+	}
+
+	// get singleton instance of GalZbIf
+	_pGalZb = GalZbIf::Instance();
+
+	int ret = initTimers();
+
+	// initiate timers
+	if (ret != TCA_TIMER_SUCCESS) {
+		_pLogger->fatal ( "Cannot initialize Timers !" );
+	}
+}
+
+/**
+ TrustCenterAgent destructor.
+ */
+template<class T>
+TrustCenterAgent<T>::~TrustCenterAgent() {
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+	_pLogger->debug ( "TrustCenterAgent Destructor\n" );
+#endif
+
+	ThreadPoolShutdown (&threadPool);
+
+	delete _acl;
+	delete _anl;
+	delete _pLogger;
+}
+
+/**
+ Public method TrustCenterAgent *Instance(void)
+ (pattern Singleton)
+ @return Singleton instance of TrustCenterAgent class.
+ */
+template<class T>
+TrustCenterAgent<T> *TrustCenterAgent<T>::Instance(void) {
+	if (pInstance == NULL) {
+		pInstance = new TrustCenterAgent;
+	}
+	return pInstance;
+}
+
+/**
+ Protected method TrustCenterAgent init
+ TrustCenterAgent initializations
+ */
+template<class T>
+void TrustCenterAgent<T>::init() {
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+	_pLogger->debug ( "TrustCenterAgent init\n" );
+#endif
+
+//register JOIN INDICATION and UPDATE DEVICE to the galzbif
+// Boris BEGIN 27122007
+//if (state.compare ( "true" ) == 0)
+	/*
+	 {
+	 _pGalZb->registerListener ( ZB_NLME_JOIN_INDICATION, ( void * ) ( &joinIndication_CbW ) );
+
+	 _pGalZb->registerListener ( ZB_APSME_UPDATE_DEVICE_INDICATION, ( void * ) ( &updateDeviceIndication_CbW ) );
+	 }
+	 */
+// Boris END 27122007
+// Boris 31012008 To set the Network key into Coordinator from mainconf BEGIN
+	uchar *tmpkey = this->getNetworkKey();
+	bool key;
+	for (int i = 0; i < NWK_KEY_SIZE; i++) {
+		if (tmpkey[i] != 0x00)
+			key = TRUE;
+	}
+	if (key) {
+		_pLogger->debug ( "loaded TC_NETWORKKEY [%x]",tmpkey[0] );
+		_pGalZb->registerListener(ZB_NLME_JOIN_INDICATION,
+				(void *) (&joinIndication_CbW));
+		_pGalZb->registerListener(ZB_APSME_UPDATE_DEVICE_INDICATION,
+				(void *) (&updateDeviceIndication_CbW));
+
+		ZB_TRANSPORT_KEY_DATA tcdata;
+		uchar tmpaddr[IEEE_RAWADDRESS_SIZE];
+		/*
+		 uchar *tmpkey = this->getNetworkKey();
+		 for ( int i=0;i<NWK_KEY_SIZE;i++ )
+		 {
+		 tmpkey[i] = this->_networkKey[i];
+		 }
+		 */
+		tcdata.nwk_key.key_seq_num = 0;
+		tcdata.nwk_key.nwk_key = tmpkey;
+		tcdata.nwk_key.use_parent = false;
+		for (int i = 0; i < IEEE_RAWADDRESS_SIZE; i++) {
+			tmpaddr[i] = 0;
+		}
+		tcdata.nwk_key.parent_ieee_addr = tmpaddr;
+
+		uchar *parentaddr = this->getIEEEAddr();
+		for (int i = 0; i < IEEE_RAWADDRESS_SIZE; i++) {
+			tmpaddr[i] = parentaddr[i];
+		}
+
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+		_pLogger->debug ( "TrustCenterAgent IEEE Address 0x%x-0x%x-0x%x-0x%x-0x%x-0x%x-0x%x-0x%x\n",tmpaddr[0],tmpaddr[1],tmpaddr[2],tmpaddr[3],tmpaddr[4],tmpaddr[5],tmpaddr[6],tmpaddr[7] );
+#endif
+
+#ifndef DONOTUSEACTUALCALLS
+		this->_pGalZb->APSME_TRANSPORT_KEY_request(tmpaddr,
+				TC_TRANSPORTKEYTYPE_networkkey, &tcdata);
+#endif
+	}
+// Boris 31012008 To set the Network key into Coordinator from mainconf END
+
+// #warning modifica temporanea
+// 	_pGalZb->ZDO_IEEE_ADDR_request ( 1, ZDO_REQ_TYPE_EX_RES, 0 );
+}
+
+/**
+ joinRequestProcessing modifier
+ @param value
+ */
+template<class T>
+void TrustCenterAgent<T>::setJoinReqProcessing(bool value) {
+	this->_confparam_joinRequestProcessing = value;
+
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+	_pLogger->debug ( "TrustCenterAgent::setJoinReqProcessing - joinRequestProcessing = %d ", this->_confparam_joinRequestProcessing );
+#endif
+}
+
+/**
+ joinRequestProcessing accessor
+ @return joinRequestProcessing
+ */
+template<class T>
+bool TrustCenterAgent<T>::getJoinReqProcessing() {
+	return this->_confparam_joinRequestProcessing;
+}
+
+/// Contains actions to be performet upon a join indication
+template<class T>
+void TrustCenterAgent<T>::joinIndication_Cb(ushort nwk_addr, uchar *ieee_addr,
+		uchar capability_info, uchar secure_join) {
+
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+	_pLogger->debug ( "TrustCenterAgent JoinIndication_Cb: nwk_addr %d,...\n",nwk_addr );
+#endif
+
+	this->loginNode(ZB_NLME_JOIN_INDICATION, ieee_addr, nwk_addr,
+			capability_info, secure_join, NULL);
+
+}
+
+/**
+ Protected method TrustCenterAgent initTimers
+ Timers initialization.
+
+ @return TCA_TIMER_ERROR, in case of error or TCA_TIMER_SUCCESS if everything is ok
+ */
+template<class T>
+int TrustCenterAgent<T>::initTimers() {
+	ThreadPoolAttr attr;
+
+	TPAttrInit(&attr);
+	TPAttrSetMaxThreads(&attr, DA_MAX_THREADS);
+	TPAttrSetMinThreads(&attr, DA_MIN_THREADS);
+	TPAttrSetJobsPerThread(&attr, DA_JOBS_PER_THREAD);
+	TPAttrSetIdleTime(&attr, DA_THREAD_IDLE_TIME);
+
+#ifdef NEW_VERSION
+	TPAttrSetMaxJobsTotal ( &attr, DA_MAX_JOBS_TOTAL );
+#endif
+
+	if (ThreadPoolInit(&_threadPool, &attr) != 0) {
+		return TCA_TIMER_ERROR;
+	}
+	return TCA_TIMER_SUCCESS;
+}
+
+/**
+ Protected method TrustCenterAgent setTimer
+ Create a new timer.
+
+ @param timer_id Timer identifier.
+ @param time Timeout value, in milliseconds
+ @param callback Pointer to a callback function (static method).
+ @return Timer thread pointer.
+ */
+template<class T>
+unsigned int *TrustCenterAgent<T>::setTimeout(int timer_id, int time_msec,
+		void *callback) {
+	int eventId;
+	int res;
+
+//Upnp timers have such a bad granularity !
+	int time_sec = time_msec / 1000;
+
+	TimerThread *timer;
+
+	timer_data_t *data = new timer_data_t;
+
+	data->timer_id = timer_id;
+	data->agentPtr = this;
+
+	TPJobInit(&_job, timer_CbW, (void *) data);
+
+	TPJobSetFreeFunction(&_job, (free_routine) free_upnp_timeout_W);
+	TPJobSetPriority(&_job, MED_PRIORITY);
+
+	timer = (TimerThread *) malloc(sizeof(TimerThread));
+
+	// 	printf ( "\nTrustCenterAgent::setTimer - timer_id = %d\n", timer_id );
+
+	res = TimerThreadInit(timer, &_threadPool);
+	if (res != 0) {
+//This code should be unreachable! (this behavior is protected in the loginNode function)
+		_pLogger->fatal ( "cannot init timer for node %d",timer_id );
+		return NULL;
+	}
+
+	res = TimerThreadSchedule(timer, time_sec, REL_SEC, &_job, SHORT_TERM,
+			&eventId);
+
+	if (res != 0) {
+//This code should be unreachable! (this behavior is protected in the loginNode function)
+		_pLogger->fatal ( "cannot init timer for node %d",timer_id );
+		return NULL;
+	}
+
+	data->timer = (unsigned int *) timer;
+	data->eventId = eventId;
+
+	return (unsigned int *) timer;
+}
+
+/**
+ Protected method TrustCenterAgent killTimer
+ Cancel a specific timer thread, thus avoiding timeout expiration.
+
+
+ @internal function, use killTimer instead
+
+ @param timer Timer thread pointer.
+ @param eventId Identifier of the event to remove.
+ @return TCA_TIMER_SUCCESS or TCA_TIMER_ERROR , in case of error
+ */
+template<class T>
+int TrustCenterAgent<T>::killTimer_internal(unsigned int *timer, int eventId) {
+
+	ThreadPoolJob tempJob;
+	TimerThread *currentTimer;
+
+	currentTimer = (TimerThread *) timer;
+
+	if (TimerThreadShutdown(currentTimer) != 0) {
+		// 		printf ( "\nTrustCenterAgent::killTimer - Error in TimerThreadShutdown\n" );
+		_pLogger->error ( "Error in TimerThreadShutdown" );
+
+	}
+
+//Seems to work withouth this ... this function always return error , maybe shutdown is enough ...
+	if (TimerThreadRemove(currentTimer, eventId, &tempJob) != 0) {
+
+		_pLogger->warn ( "expected warn in TimerThreadRemove" );
+		// 		printf ( "\nTrustCenterAgent::killTimer - \n" );
+
+	}
+
+	return TCA_TIMER_SUCCESS;
+}
+
+/**
+ Protected method TrustCenterAgent onTimer
+ This Method is called on timeout expiration.
+
+ @param timer_id Timer thread identifier.
+ */
+template<class T>
+void TrustCenterAgent<T>::onTimer(unsigned int timer_id) {
+
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+	_pLogger->debug ( "TimeOutExpired for node %d ",timer_id );
+#endif
+
+	//Timeout Expired, send leave
+
+	/*	std::map <int, NodeMapItem *>::iterator iter = _pendingnodes.find ( timer_id );
+
+	 if ( iter == _pendingnodes.end() )
+	 {
+	 #ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+	 _pLogger->debug ( "TimeOutExpired  node %d, but node was not supposed to expire! ",timer_id );
+	 #endif
+	 //do nothing
+	 return;
+	 }
+
+	 NodeMapItem *returned = iter->second;*/
+
+//I kill the timer to destroy the timer thread and free memory
+	this->killTimer(timer_id);
+
+	NodeMapItem *returned = this->getPendingNodeItem(timer_id);
+
+	if (returned == NULL) {
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+		_pLogger->debug ( "TimeOutExpired  node %d, but node was not supposed to expire! ",timer_id );
+#endif
+//do nothing
+		return;
+	}
+
+// #warning ATTENZIONE ! METTERE IL NWK ADDRESS VERO
+	this->sendLeaveRequest(returned->getLongAddr(), returned->getParentAddr());
+
+	delete returned;
+	_pendingnodes.erase(timer_id);
+}
+
+/**
+ Protected method TrustCenterAgent free_upnp_timeout_W
+ This is a static member function, used as a wrapper to callback to the non-static member free_upnp_timeout.
+ This function is called by upnp library routines.
+
+ @param event Event pointer.
+ @return Void.
+ */
+template<class T>
+void TrustCenterAgent<T>::free_upnp_timeout_W(void *event) {
+	// 	printf ( "\nTrustCenterAgent::free_upnp_timeout_W\n" );
+	TrustCenterAgent* tcAgent = TrustCenterAgent<T>::Instance();
+	tcAgent->free_upnp_timeout(event);
+}
+
+/**
+ Protected method TrustCenterAgent free_upnp_timeout
+ Implements free function called by upnp library routines.
+
+ @param event Event pointer.
+ @return Void.
+ */
+template<class T>
+void TrustCenterAgent<T>::free_upnp_timeout(void *event) {
+	// 	printf ( "\nTrustCenterAgent::free_upnp_timeout\n" );
+//nothing here ?
+}
+
+/**
+ Protected method TrustCenterAgent timer_CbW
+ This is a static member function, used as a wrapper to callback to the non-static member timer_Cb.
+ This function is called on timeout expiration.
+
+ @param input Timer data.
+ @return Void.
+ */
+template<class T>
+void *TrustCenterAgent<T>::timer_CbW(void *input) {
+	TrustCenterAgent* tcAgent = TrustCenterAgent<T>::Instance();
+	tcAgent->timer_Cb(input);
+	return NULL;
+}
+
+/**
+ Protected method TrustCenterAgent timer_Cb
+ Implements callback to be called on timeout expiration.
+
+ @param input Timer data.
+ @return Void.
+ */
+template<class T>
+void *TrustCenterAgent<T>::timer_Cb(void *input) {
+	timer_data_t *data;
+	data = (timer_data_t *) input;
+	data->agentPtr->onTimer(data->timer_id);
+	delete data;
+	return NULL;
+}
+
+/// Access control list selector
+template<class T>
+ACL *TrustCenterAgent<T>::getACL() {
+	return this->_acl;
+}
+
+/**
+ This method is called when access is granted to a node, either from WSN-C or local access control list
+ @param n - contains info about the granted access node
+ */
+template<class T>
+void TrustCenterAgent<T>::joinGranted(NodeMapItem *n) {
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+	_pLogger->debug ( "TrustCenterAgent Authorized node [%s]\n",n->toString().c_str() );
+
+#endif
+	//I add the node to the authorized node list
+	_anl->addNode(n);
+
+	//send the transport key to the granted node
+	this->sendTransportKey(n);
+}
+
+/// Authorized node list selector
+template<class T>
+NodeMap *TrustCenterAgent<T>::getANL() {
+	return _anl;
+}
+
+/// Network key modifier
+template<class T>
+void TrustCenterAgent<T>::setNetworkKey(uchar *nwk) {
+	for (int i = 0; i < NWK_KEY_SIZE; i++) {
+		_networkKey[i] = nwk[i];
+	}
+}
+
+/// Network key selector
+template<class T>
+uchar *TrustCenterAgent<T>::getNetworkKey() {
+	return _networkKey;
+}
+
+/// apsSecurityTimeOutPeriod parameter modifier and selector (Management agent is used) @return the appSecurityTimeOutPeriod , in seconds
+template<class T>
+int TrustCenterAgent<T>::getAPSSecTimeOutPeriod_msec() {
+	return this->_apsSecurityTimeOutPeriod_msec;
+}
+
+// param value the appSecurityTimeOutPeriod to be set, in seconds
+template<class T>
+void TrustCenterAgent<T>::setAPSSecTimeOutPeriod_msec(int value) {
+	this->_apsSecurityTimeOutPeriod_msec = value;
+}
+
+/// leaveNotificationProcessing parameter selector
+template<class T>
+bool TrustCenterAgent<T>::getLeaveNotifProcessing() {
+	return this->_confparam_leaveNotificationProcessing;
+}
+
+/// leaveNotificationProcessing parameter modifier
+template<class T>
+void TrustCenterAgent<T>::setLeaveNotifProcessing(bool value) {
+	this->_confparam_leaveNotificationProcessing = value;
+}
+
+// Boris 31012008 to set and get its own IEEE address BEGIN
+template<class T>
+void TrustCenterAgent<T>::setIEEEAddr(uchar *addr) {
+	for (int i = 0; i < IEEE_RAWADDRESS_SIZE; i++) {
+		_ieeeAddr[i] = addr[i];
+	}
+
+}
+
+template<class T>
+uchar *TrustCenterAgent<T>::getIEEEAddr() {
+	return _ieeeAddr;
+}
+
+// Boris 31012008 to set and get its own IEEE address END
+
+///Sends netwrok key to target node
+template<class T>
+void TrustCenterAgent<T>::sendTransportKey(NodeMapItem *n) {
+
+//TODO should I register ASPME_TRANSPORT_KEY_confirm ? It is possible ... This would add the possibility to receive that event and do something if the event is not received ....
+
+//note by Riccardo. Because of how the ZB_TRANSPORT_KEY_DATA is done, I'm forced to do this, but beware: this is not a thread-safe behavior if the _pGalZb object in the future will be made non-blocking
+
+	ZB_TRANSPORT_KEY_DATA tcdata;
+	uchar tmpkey[NWK_KEY_SIZE];
+	uchar tmpaddr[IEEE_RAWADDRESS_SIZE];
+
+	tcdata.nwk_key.key_seq_num = 0;
+	for (int i = 0; i < NWK_KEY_SIZE; i++) {
+		tmpkey[i] = this->_networkKey[i];
+	}
+
+	tcdata.nwk_key.nwk_key = tmpkey;
+
+	tcdata.nwk_key.use_parent = n->getHasParent();
+
+	if (n->getHasParent()) {
+
+		uchar *parentaddr = n->getParentAddr();
+
+		for (int i = 0; i < IEEE_RAWADDRESS_SIZE; i++) {
+			tmpaddr[i] = parentaddr[i];
+		}
+	}
+
+	else {
+		for (int i = 0; i < IEEE_RAWADDRESS_SIZE; i++) {
+			tmpaddr[i] = 0;
+		}
+	}
+
+	tcdata.nwk_key.parent_ieee_addr = tmpaddr;
+
+#ifndef DONOTUSEACTUALCALLS
+	this->_pGalZb->APSME_TRANSPORT_KEY_request(n->getLongAddr(),
+			TC_TRANSPORTKEYTYPE_networkkey, &tcdata);
+#endif
+
+#ifdef DONOTUSEACTUALCALLS
+#warning ACTUAL CALL DISABLED HERE
+#endif
+
+}
+
+/// Contains actions to be performet upon an update device indication
+template<class T>
+void TrustCenterAgent<T>::updateDeviceIndication_Cb(uchar *src_ieee_addr,
+		uchar *dev_ieee_addr, uchar status, ushort dev_nwk_addr) {
+
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+	_pLogger->debug ( "update indication CB" );
+
+#endif
+
+//if status == New join -> tratto come una join indication
+// APSME_UPDATE_DEVICE_indication_STATUS_SECURED_JOIN
+// APSME_UPDATE_DEVICE_indication_STATUS_UNSECURED_JOIN
+
+	if (status == APSME_UPDATE_DEVICE_indication_STATUS_SECURED_JOIN) {
+
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+		_pLogger->debug ( "update SECURE JOIN" );
+#endif
+
+		this->loginNode(ZB_APSME_UPDATE_DEVICE_INDICATION, dev_ieee_addr,
+				dev_nwk_addr, 0, true, src_ieee_addr);
+	} else if (status == APSME_UPDATE_DEVICE_indication_STATUS_UNSECURED_JOIN) {
+
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+		_pLogger->debug ( "update UNSECURE JOIN" );
+#endif
+
+		this->loginNode(ZB_APSME_UPDATE_DEVICE_INDICATION, dev_ieee_addr,
+				dev_nwk_addr, 0, false, src_ieee_addr);
+
+	} else if (status == APSME_UPDATE_DEVICE_indication_STATUS_LEFT) {
+
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+		_pLogger->debug ( "Update REMOVING node %d",dev_nwk_addr );
+#endif
+
+		_anl->removeNode(dev_ieee_addr);
+
+	} else {
+		_pLogger->warn ( "update discarded, status in UNDEFINED value" );
+	}
+}
+
+/**
+ Static callback for the update event
+ */
+template<class T>
+void TrustCenterAgent<T>::updateDeviceIndication_CbW(uchar *src_ieee_addr,
+		uchar *dev_ieee_addr, uchar status, ushort dev_nwk_addr) {
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+	staticDebug->debug ( "TrustCenterAgent updateDeviceIndication_CbW\n" );
+#endif
+
+//TODO should I check if the parent (src_ieee_addr) is authorized ? It should be, but I can check as additional security measure...
+
+	TrustCenterAgent *tca = TrustCenterAgent<T>::Instance();
+
+	tca->updateDeviceIndication_Cb(src_ieee_addr, dev_ieee_addr, status,
+			dev_nwk_addr);
+
+}
+
+/**
+ Static callback for the join indication event
+ */
+template<class T>
+void TrustCenterAgent<T>::joinIndication_CbW(ushort nwk_addr, uchar *ieee_addr,
+		uchar capability_info, uchar secure_join) {
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+	staticDebug->debug ( "TrustCenterAgent JoinIndication_CbW: nwk_addr %d,...\n",nwk_addr );
+#endif
+
+	TrustCenterAgent *tca = TrustCenterAgent<T>::Instance();
+
+	tca->joinIndication_Cb(nwk_addr, ieee_addr, capability_info, secure_join);
+}
+
+///internal function, to be called in case of joinIndication_Cb or updateDeviceIndication_Cb or other login events
+template<class T>
+void TrustCenterAgent<T>::loginNode(int loginType, uchar *ieee_addr,
+		ushort nwk_addr, uchar capability_info, uchar secure_join,
+		uchar *parent_addr) {
+
+//I verify if parent is not in anl
+	if (parent_addr != NULL) {
+		if (!_anl->isPresent(parent_addr)) {
+			_pLogger->warn ( "Warning parent of node %d is not authorized!!! ",nwk_addr );
+
+			_pLogger->warn ( "Node address 0x%x-0x%x-0x%x-0x%x-0x%x-0x%x-0x%x-0x%x",ieee_addr[0],ieee_addr[1],ieee_addr[2],ieee_addr[3],ieee_addr[4],ieee_addr[5],ieee_addr[6],ieee_addr[7] );
+
+			_pLogger->warn ( "Parent address 0x%x-0x%x-0x%x-0x%x-0x%x-0x%x-0x%x-0x%x",parent_addr[0],parent_addr[1],parent_addr[2],parent_addr[3],parent_addr[4],parent_addr[5],parent_addr[6],parent_addr[7] );
+
+		}
+	}
+
+	if (this->_confparam_joinRequestProcessing) {
+		//use local ACL, do not interrogate WSN-C
+		//verify locally, I do not add to pending nodes listener
+
+		if (this->_acl->isPresent(ieee_addr)) {
+			//node locally allowed
+			NodeMapItem n(nwk_addr, ieee_addr, capability_info, secure_join,
+					FALSE);
+
+			n.setParentAddr(parent_addr);
+
+			if (parent_addr != NULL) {
+				n.setHasParent(true);
+			} else {
+				n.setHasParent(false);
+			}
+			this->joinGranted(&n);
+		} else {
+			//node locally not allowed
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+			_pLogger->debug ( "TrustCenterAgent Node locally NOT authorized. Sending Leave!\n" );
+
+			_pLogger->debug ( "addr 0x%x-0x%x-0x%x-0x%x-0x%x-0x%x-0x%x-0x%x",ieee_addr[0],ieee_addr[1],ieee_addr[2],ieee_addr[3],ieee_addr[4],ieee_addr[5],ieee_addr[6],ieee_addr[7] );
+#endif
+
+			this->sendLeaveRequest(ieee_addr, parent_addr);
+		}
+	} else {
+//here authorization needed by WSN-C
+		NodeMapItem *tmp = this->getPendingNodeItem(nwk_addr);
+
+		if (tmp != NULL) {
+			_pLogger->warn ( "Received request by node 0x%4x while TCA was already waiting for a WSN-C response about that guy!\n",nwk_addr );
+			return;
+		}
+
+		if (_pendingnodes.size() < DA_MAX_THREADS) {
+			//interrogate WSN-C
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+			_pLogger->debug ( "TrustCenterAgent asking permission to WSN-C!\n" );
+
+			_pLogger->debug ( "should I authorize addr 0x%x-0x%x-0x%x-0x%x-0x%x-0x%x-0x%x-0x%x, nwk addr %d ? ",ieee_addr[0],ieee_addr[1],ieee_addr[2],ieee_addr[3],ieee_addr[4],ieee_addr[5],ieee_addr[6],ieee_addr[7],nwk_addr );
+
+			_pLogger->debug ( "Activating timer for node %d (%d milliseconds)\n",nwk_addr,this->getAPSSecTimeOutPeriod_msec() );
+#endif
+
+		} else {
+			_pLogger->warn ( "Maximum numer of pending nodes reached. Ignoring request from node %d \n",nwk_addr );
+
+			// RPC notify Callback
+			if (functionsContext.join.rpcContext.getRPCNotifyCb() != NULL) {
+				RPCReqStatus *rpcReqStatus = new RPCReqStatus(Running, FFAILED,
+						PENDING_NODES_NUMBER_OVERFLOW);
+				FCALL_NOTIFY (functionsContext.join)(loginType, NULL,
+						rpcReqStatus);
+				delete (rpcReqStatus);
+			}
+
+			return;
+		}
+
+		NodeMapItem *n = new NodeMapItem(nwk_addr, ieee_addr, capability_info,
+				secure_join, TRUE);
+
+		n->setParentAddr(parent_addr);
+
+		if (parent_addr != NULL) {
+			n->setHasParent(true);
+		} else {
+			n->setHasParent(false);
+		}
+
+		unsigned int *descript = this->setTimeout(nwk_addr,
+				this->getAPSSecTimeOutPeriod_msec(), (TIMERPROC) NULL);
+
+		if (descript == NULL) {
+//since the maximum number of nodes is fixed, this code should be unreachable
+			_pLogger->fatal ( "Maximum number of timeouts exceeded for node with nwk_addr %d",nwk_addr );
+			return;
+		}
+
+		// RPC notify Callback
+		if (functionsContext.join.rpcContext->getRPCNotifyCb() != NULL) {
+			RPCReqStatus *rpcReqStatus = new RPCReqStatus(Running, FSUCCESS,
+					AGENT_SUCCESS);
+			FCALL_NOTIFY (functionsContext.join)(loginType, n, rpcReqStatus);
+			delete (rpcReqStatus);
+		}
+
+//add the node to the pending node map, using nwk address as key
+
+//launch timer
+
+// I use the network address nwk as key for the timers. According to Claudio the nwk address is reserved, so this is not a proble,
+
+		n->setTimerDescriptor(descript);
+
+		_pendingnodes[nwk_addr] = n;
+	}
+
+}
+
+/**
+ Send Leave request to node with addrees addr
+ @param addr ieee address of the node
+ */
+template<class T>
+void TrustCenterAgent<T>::sendLeaveRequest(uchar *addr, uchar *parentaddr) {
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+	_pLogger->debug ( "Sending leave request to node 0x%x-0x%x-0x%x-0x%x-0x%x-0x%x-0x%x-0x%x  ",addr[0],addr[1],addr[2],addr[3],addr[4],addr[5],addr[6],addr[7],parentaddr[0],parentaddr[1],parentaddr[2],parentaddr[3],parentaddr[4],parentaddr[5],parentaddr[6],parentaddr[7] );
+#endif
+
+	_pLogger->warn ( "ATTENTION ! I'm sending the APSME_REMOVE instead of MGMT_LEAVE_request!!! This is legal, but you should be aware about this!" );
+
+#ifndef DONOTUSEACTUALCALLS
+
+	_pGalZb->APSME_REMOVE_DEVICE_request(parentaddr, addr
+
+	);
+#endif
+
+#ifdef DONOTUSEACTUALCALLS
+#warning ACTUAL CALL DISABLED HERE
+#endif
+
+}
+
+/**
+ Callback. This event is received when the WSNC authorize node with nwk address addr. It can either be positive (granted) or negative (denied).
+ */
+template<class T>
+int TrustCenterAgent<T>::FromWSNC_Authorization_cb(
+		ushort addr, bool granted,
+		RPCContext<T, fromWSNC_AuthorizationResponseCb> *rpcContextData
+		) {
+
+//anyways, I kill the timeout timer ...
+
+	if (granted) {
+
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+		_pLogger->debug ( "Node %d authorized from wsn-C",addr );
+#endif
+
+		this->killTimer(addr);
+
+		NodeMapItem *returned = this->getPendingNodeItem(addr);
+
+		if (returned != NULL) {
+			this->joinGranted(returned);
+
+			_pLogger->info ( "FromWSNC_Authorization_cb - joinGranted called" );
+
+			// RPC response Callback									//TODO Add check on getRPCResponseCb != NULL ?
+			RPCReqStatus *rpcReqStatus = new RPCReqStatus(End, FSUCCESS,
+					AGENT_SUCCESS);
+			((fromWSNC_AuthorizationResponseCb) (rpcContextData->getRPCResponseCb()))(
+					addr, granted, rpcContextData, rpcReqStatus);
+			delete (rpcReqStatus);
+
+		} else {
+//Unreachable code
+
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+			_pLogger->debug ( "wsn-c GRANTED access to node %d, but I don't know anything about this node! ",addr );
+#endif
+
+			// RPC response Callback									//TODO Add check on getRPCResponseCb != NULL ?
+			RPCReqStatus *rpcReqStatus = new RPCReqStatus(End, FFAILED,
+					WSNC_AUTH_FOR_NONEXISTENTENT_NODE);
+			((fromWSNC_AuthorizationResponseCb) (rpcContextData->getRPCResponseCb()))(
+					addr, granted, rpcContextData, rpcReqStatus);
+			delete (rpcReqStatus);
+
+			_pLogger->error ( "Critical error, unreachable code" );
+
+			return WSNC_AUTH_FOR_NONEXISTENTENT_NODE;
+
+		}
+
+// I remove it from the pending nodes, but I don't erase it from memory: it will go in the anl
+		_pendingnodes.erase(addr);
+	} else {
+
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+		_pLogger->debug ( "Node %d not authorized from wsn-C",addr );
+#endif
+
+		this->killTimer( /*returned->getTimerDescriptor(),*/addr);
+
+		NodeMapItem *returned = this->getPendingNodeItem(addr);
+
+		if (returned != NULL) {
+			this->sendLeaveRequest(returned->getLongAddr(),
+					returned->getParentAddr());
+			delete returned;
+
+			_pLogger->info ( "FromWSNC_Authorization_cb - sendLeaveRequest called" );
+			// RPC response Callback									//TODO Add check on getRPCResponseCb != NULL
+			RPCReqStatus *rpcReqStatus = new RPCReqStatus(End, FSUCCESS,
+					AGENT_SUCCESS);
+			((fromWSNC_AuthorizationResponseCb) (rpcContextData->getRPCResponseCb()))(
+					addr, granted, rpcContextData, rpcReqStatus);
+			delete (rpcReqStatus);
+
+		} else {
+//Unreachable code
+
+			_pLogger->error ( "wsn-c denied access to node %d, but I don't know anything about this node! ",addr );
+
+			// RPC response Callback									//TODO Add check on getRPCResponseCb != NULL ?
+			RPCReqStatus *rpcReqStatus = new RPCReqStatus(End, FFAILED,
+					WSNC_AUTH_FOR_NONEXISTENTENT_NODE);
+			((fromWSNC_AuthorizationResponseCb) (rpcContextData->getRPCResponseCb()))(
+					addr, granted, rpcContextData, rpcReqStatus);
+			delete (rpcReqStatus);
+
+			return WSNC_AUTH_FOR_NONEXISTENTENT_NODE;
+		}
+
+		_pendingnodes.erase(addr);
+	}
+
+	return AGENT_SUCCESS;
+
+}
+
+template<class T>
+NodeMapItem *TrustCenterAgent<T>::getPendingNodeItem(ushort addr) {
+
+	std::map<int, NodeMapItem *>::iterator iter = _pendingnodes.find(addr);
+
+	if (iter == _pendingnodes.end()) {
+//do nothing
+		return NULL;
+	}
+
+	NodeMapItem *returned = iter->second;
+
+	return returned;
+
+}
+
+template<class T>
+int TrustCenterAgent<T>::killTimer(int eventID) {
+
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+	_pLogger->debug ( "killing timer for node %d",eventID );
+#endif
+
+	NodeMapItem *ret = this->getPendingNodeItem(eventID);
+
+	if (ret == NULL) {
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+		_pLogger->debug ( "killing timer for node %d failed, node already expired somewhere else ... ",eventID );
+#endif
+		return TRUE;
+	}
+
+	return this->killTimer_internal(ret->getTimerDescriptor(), eventID);
+}
+
+template<class T>
+void TrustCenterAgent<T>::TMPPUBLICsendLeaveRequest(uchar *longaddr,
+		uchar *parentaddr) {
+
+	_pLogger->warn ( " Sending external Leave request to node" );
+
+	_pLogger->warn ( "long 0x%x-0x%x-0x%x-0x%x-0x%x-0x%x-0x%x-0x%x",longaddr[0],longaddr[1],longaddr[2],longaddr[3],longaddr[4],longaddr[5],longaddr[6],longaddr[7] );
+	this->sendLeaveRequest(longaddr, parentaddr);
+}
+
+template<class T>
+int TrustCenterAgent<T>::registerRPCListener(
+		RPCContext<T, registerRPCListenerResponseCb> *rpcContextData) {
+#ifdef DEBUG_ACTIVE_TRUSTCENTERAGENT
+	_pLogger->debug ( "registerRPCListener" );
+#endif
+
+	//if ( _pGalZb->getGalStatus() != GAL_SS_RUNNING )
+	if (_pGalZb->getGWStatus() != GW_RUNNING) {
+		_pLogger->info ( "registerRPCListener - Error GAL_NOT_RUNNING" );
+
+		// RPC response Callback
+		RPCReqStatus *rpcReqStatus = new RPCReqStatus(NotAvailable,
+				FNOT_STARTED, GAL_NOT_RUNNING);
+		((registerRPCListenerResponseCb) (rpcContextData->getRPCResponseCb()))(
+				rpcContextData, rpcReqStatus);
+		delete (rpcReqStatus);
+
+		// Return Error Code
+		return GAL_NOT_RUNNING;
+	}
+
+	///	Register RPC Context Data (containing RPC SessionId and RPC callbacks for response and notification) related to the specific request.
+	if (functionsContext.join.fState != Idle) {
+		_pLogger->warn ( "registerRPCListener - RPC callbacks previously registered -> overwrite! (WARNING)" );
+	}
+	functionsContext.join.rpcContext = *rpcContextData;
+	functionsContext.join.fState = Running;
+
+	// RPC response Callback						//TODO Add check on getRPCResponseCb != NULL ?
+	RPCReqStatus *rpcReqStatus = new RPCReqStatus(Running, FSUCCESS,
+			AGENT_SUCCESS);
+	((registerRPCListenerResponseCb) (rpcContextData->getRPCResponseCb()))(
+			rpcContextData, rpcReqStatus);
+	delete (rpcReqStatus);
+
+	return AGENT_SUCCESS;
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CTrustCenterAgent.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CTrustCenterAgent.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/CTrustCenterAgent.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,486 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef TRUSTCENTERAGENT_H
+#define TRUSTCENTERAGENT_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "ThreadPool.h"
+#include "TimerThread.h"
+
+#include "GalZbIf.h"
+#include "CMessage.h"
+#include "ZbNetDb.h"
+#include "CDebug.h"
+
+#include "Agents.h"
+#include "ACL.h"
+
+#include "ConfigurationRepository.h"
+
+///DEBUG_ACTIVE_TRUSTCENTERAGENT: if uncommented, masks out debug messages from the code
+//#define DEBUG_ACTIVE_TRUSTCENTERAGENT
+
+///Timer error return code
+#define TCA_TIMER_ERROR (-1)
+///Timer error return code
+#define TCA_TIMER_SUCCESS (1)
+
+//Enable thie variable DONOTUSEACTUALCALLS in the Makefile, to avoid the use of actual HW callBacks
+//DONOTUSEACTUALCALLS
+
+/**
+ Set of ZigBee related constants used in Trust Center Agent, expressed in number of bytes
+ */
+//FIXME per Pastrone era 8 l'ho messa a 16 come sul documento, va bene ?
+#define NWK_KEY_SIZE 16
+
+/*
+ Set of constants used in thread management.
+ */
+///Maximum number of Threads in the ThreadPool
+#define DA_MAX_THREADS					10
+///Minimum number of Threads in the ThreadPool
+#define DA_MIN_THREADS					10
+///Number of threads Jobs
+#define DA_JOBS_PER_THREAD				10
+///Thread idle time
+#define DA_THREAD_IDLE_TIME 				5000
+// #define DA_MAX_JOBS_TOTAL 				10*/
+
+//FIXME next definitions should be moved to zigbee.h
+
+///definition for the the TC_TRANSPORTKEYTYPE field
+#define TC_TRANSPORTKEYTYPE_masterkey 0
+///definition for the the TC_TRANSPORTKEYTYPE field
+#define TC_TRANSPORTKEYTYPE_networkkey 1
+///definition for the the TC_TRANSPORTKEYTYPE field
+#define TC_TRANSPORTKEYTYPE_applicationmasterkey 2
+///definition for the the TC_TRANSPORTKEYTYPE field
+#define TC_TRANSPORTKEYTYPE_applicationlinkkey 3
+
+///definition of the APSME_UPDATE_DEVICE_indication_STATUS code
+#define APSME_UPDATE_DEVICE_indication_STATUS_SECURED_JOIN 0x00
+///definition of the APSME_UPDATE_DEVICE_indication_STATUS code
+#define APSME_UPDATE_DEVICE_indication_STATUS_UNSECURED_JOIN 0x01
+///definition of the APSME_UPDATE_DEVICE_indication_STATUS code
+#define APSME_UPDATE_DEVICE_indication_STATUS_LEFT 0x02
+
+/**
+ TrustCenter Agent includes several functions, i.e. Device Join management,...
+ Each macrofunction is identified by a unique ID (please refer to the following ID list).
+ This unique ID is used as a key in associative arrays containing macrofunction context i.e.
+ the RPC listeners registered on the specific function.
+ */
+#define TC_DEVICE_JOIN					1
+
+/**
+ TrustCenterAgent class, singleton object.
+ */
+template<class T>
+class TrustCenterAgent {
+public:
+	// --- RPC callbacks ---------------------------
+	typedef void * (T::*registerRPCListenerResponseCb)(int sessionId,
+			RPCReqStatus *rpcReqStatus);
+	typedef void * (T::*deviceJoinIndicationNotifyCb)(int eventType,
+			NodeMapItem *joiningNode, RPCReqStatus *rpcReqStatus);
+	typedef void * (T::*fromWSNC_AuthorizationResponseCb)(ushort addr,
+			bool granted, int sessionId, RPCReqStatus *rpcReqStatus);
+
+public:
+
+	//////////////////////////////////////
+	// PUBLIC constructors and related
+	//////////////////////////////////////
+
+	/**
+	 TrustCenterAgent destructor.
+	 */
+	~TrustCenterAgent();
+
+	/**
+	 Public method TrustCenterAgent *Instance(void)
+	 (pattern Singleton)
+	 @return Singleton instance of TrustCenterAgent class.
+	 */
+	static TrustCenterAgent *Instance();
+
+	//////////////////////////////////////
+	// PUBLIC modifiers (set), selectors (get)
+	//////////////////////////////////////
+
+	/// Network key modifier
+	void setNetworkKey(uchar *nwk);
+
+	/// Network key selector
+	uchar *getNetworkKey();
+
+// Boris 31012008 added to set and get IEEE address if TC itself BEGIN
+	void setIEEEAddr(uchar *addr);
+
+	uchar *getIEEEAddr();
+// Boris 31012008 added to set and get IEEE address if TC itself END
+
+	/**
+	 joinRequestProcessing modifier
+	 @param value
+	 */
+	void setJoinReqProcessing(bool value);
+
+	/**
+	 joinRequestProcessing selector
+	 @return joinRequestProcessing
+	 */
+	bool getJoinReqProcessing();
+
+	/// leaveNotificationProcessing parameter modifier
+	void setLeaveNotifProcessing(bool value);
+
+	/// leaveNotificationProcessing parameter selector
+	bool getLeaveNotifProcessing();
+
+	/// Access control list selector
+	ACL *getACL();
+
+	/// Authorized node list selector
+	NodeMap *getANL();
+
+	//Commented out unused stuff
+
+	/*		/// nwkAllFresh parameter modifier and selector (Management agent is used)
+	 void getNwkAllFresh (
+	 );
+	 static void getNwkAllFresh_CbW (
+	 uchar status,
+	 uchar attr
+	 );
+	 void setNwkAllFresh (
+	 int value
+	 );
+	 static void setNwkAllFresh_CbW (
+	 uchar status,
+	 uchar attr
+	 );
+
+	 /// permitJoin parameter modifier and selector (Management agent is used)
+	 void getPermitJoin (
+	 );
+	 static void getPermitJoin_CbW (
+	 uchar status,
+	 uchar attr
+	 );
+	 void setPermitJoin (
+	 int value
+	 );
+	 static void setPermitJoin_CbW (
+	 uchar status,
+	 uchar attr
+	 );
+	 */
+
+	/// apsSecurityTimeOutPeriod parameter modifier and selector (Management agent is used) @return the appSecurityTimeOutPeriod , milliseconds
+	int getAPSSecTimeOutPeriod_msec();
+
+	// param value the appSecurityTimeOutPeriod to be set, in milliseconds
+	void setAPSSecTimeOutPeriod_msec(int msecs);
+
+	/// RPC listener registration
+	int registerRPCListener(
+			RPCContext<T, registerRPCListenerResponseCb> *rpcContextData);
+
+	//////////////////////////////////////
+	//PUBLIC callbacks/events/commands
+	//////////////////////////////////////
+
+	/**
+	 Static callback for the join indication event
+	 */
+	static void joinIndication_CbW(ushort nwk_addr, uchar *ieee_addr,
+			uchar capability_info, uchar secure_join);
+
+	/**
+	 Static callback for the update event
+	 */
+	static void updateDeviceIndication_CbW(uchar *src_ieee_addr,
+			uchar *dev_ieee_addr, uchar status, ushort dev_nwk_addr);
+
+	/**
+	 Callback. This event is received when the WSNC authorize node with nwk address addr. It can either be positive (granted) or negative (denied).
+	 */
+	//void FromWSNC_Authorization_cb ( 
+	int FromWSNC_Authorization_cb(ushort addr, bool granted,
+			RPCContext<T, fromWSNC_AuthorizationResponseCb> *rpcContextData
+			);
+
+	/**
+	 Return item from the pending node lists (Nodes wiating for authorization from wsn-c)
+	 @return null, if pending node is missing
+	 */
+	NodeMapItem *getPendingNodeItem(ushort addr);
+
+	void TMPPUBLICsendLeaveRequest(uchar *longaddr, uchar *parentaddr);
+
+	/**
+	 Protected method TrustCenterAgent init
+	 TrustCenterAgent initialization: macrofunction context is initialized.
+	 */
+	void init();
+
+protected:
+
+	//////////////////////////////////////
+	// PROTECTED constructors and related
+	//////////////////////////////////////
+
+	/**
+	 Constructor
+	 TrustCenterAgent constructor. It is a protected method (pattern Singleton)
+	 */
+	TrustCenterAgent();
+
+	//////////////////////////////////////
+	//PROTECTED callbacks/events/commands
+	//////////////////////////////////////
+
+	/// Contains actions to be performet upon a join indication
+	void joinIndication_Cb(ushort nwk_addr, uchar *ieee_addr,
+			uchar capability_info, uchar secure_join);
+
+//		/// nwkAllFresh parameter modifier and selector (Management agent is used)
+// 		void getNwkAllFresh_Cb (
+// 		    uchar status,
+// 		    uchar attr
+// 		);
+
+// 		void setNwkAllFresh_Cb (
+// 		    uchar status,
+// 		    uchar attr
+// 		);
+
+	/// Contains actions to be performet upon an update device indication
+	void updateDeviceIndication_Cb(uchar *src_ieee_addr, uchar *dev_ieee_addr,
+			uchar status, ushort dev_nwk_addr);
+
+//		/// Transport key
+// 		void transportKey_Cb();
+
+	//////////////////////////////////////
+	// PROTECTED timer management functions
+	//////////////////////////////////////
+
+	// used for Timers management
+	typedef void *TIMERPROC;
+
+	typedef struct {
+		int timer_id;
+		unsigned int *timer;
+		int eventId;
+		TrustCenterAgent *agentPtr;
+	}
+	// used for Timers management
+	timer_data_t;
+
+	/**
+	 Protected method TrustCenterAgent initTimers
+	 Timers initialization.
+
+	 @return TCA_TIMER_ERROR, in case of error or TCA_TIMER_SUCCESS if everything is ok
+	 */
+	int initTimers();
+
+	/**
+	 Protected method TrustCenterAgent setTimeout
+	 Create a new timer.
+
+	 @param timer_id Timer identifier.
+	 @param time Timeout value, in milliseconds
+	 @param callback Pointer to a callback function (static method).
+	 @return Timer thread pointer.
+	 */
+	unsigned int *setTimeout(int timer_id, int time, void *callback);
+
+	/**
+
+	 Protected method TrustCenterAgent killTimer
+	 Cancel a specific timer thread, thus avoiding timeout expiration.
+
+	 @param eventId Identifier of the event to remove.
+	 @return Status.
+	 */
+	int killTimer(int eventID);
+
+	/**
+
+	 Protected method TrustCenterAgent killTimer
+	 Cancel a specific timer thread, thus avoiding timeout expiration.
+
+	 @internal function, use killTimer instead 
+
+
+	 @param timer Timer thread pointer.
+	 @param eventId Identifier of the event to remove.
+	 @return Status.
+	 */
+	int killTimer_internal(unsigned int *timer, int eventID);
+
+	/**
+	 Protected method TrustCenterAgent onTimer
+	 This Method is called on timeout expiration.
+
+	 @param timer_id Timer thread identifier.
+	 @return Void..
+	 */
+	void onTimer(unsigned int timer_id);
+
+//commented out by Riccardo: withouth these, the tests run anyway :)
+	/**
+	 Protected method TrustCenterAgent free_upnp_timeout_W
+	 This is a static member function, used as a wrapper to callback to the non-static member free_upnp_timeout.
+	 This function is called by upnp library routines.
+
+	 @param event Event pointer.
+	 @return Void.
+	 */
+	static void free_upnp_timeout_W(void *event);
+
+	/**
+	 Protected method TrustCenterAgent free_upnp_timeout
+	 Implements free function called by upnp library routines.
+
+	 @param event Event pointer.
+	 @return Void.
+	 */
+	void free_upnp_timeout(void *event);
+
+	/**
+	 Protected method TrustCenterAgent timer_CbW
+	 This is a static member function, used as a wrapper to callback to the non-static member timer_Cb.
+	 This function is called on timeout expiration.
+
+	 @param input Timer data.
+	 */
+	static void *timer_CbW(void *input);
+
+	/**
+	 Protected method TrustCenterAgent timer_Cb
+	 Implements callback to be called on timeout expiration.
+
+	 @param input Timer data.
+	 */
+	void *timer_Cb(void *input);
+
+private:
+	//////////////////////////////////////
+	// PRIVATE local attributes
+	//////////////////////////////////////
+
+	// Pattern Singleton, unique TrustCenterAgent
+	static TrustCenterAgent *pInstance;
+
+	/// Thread management
+	ThreadPool _threadPool;
+	ThreadPoolJob _job;
+
+	// Struct used to store functions context data
+
+	/*		enum fState_t { Idle, Running, Canceled, End};
+	 struct fContext
+	 {
+	 fState_t functionState;
+	 int result;					/// Fcontext - result -> allowed values: FSUCCESS, FFAILED
+	 int numExpectedMsgs;
+	 int fTimeout;					/// Fcontext - fTimeout -> function timeout value (please refer to the method setTimer)
+	 timer_data_t *timerData;
+	 };
+	 //		/// Map containing functions context data
+	 ;*/
+
+	// Struct used to store functions context data
+	struct {
+		fContext<T, TrustCenterAgent, void *, deviceJoinIndicationNotifyCb> join;
+	} functionsContext;
+
+	//Map  of Nodes waiting for access reply
+	std::map<int, NodeMapItem *> _pendingnodes;
+
+	///local access control list
+	ACL *_acl;
+
+	///Map containing all currently joined (trusted) nodes
+	NodeMap *_anl;
+
+	//////////////////////////////////////
+	// PRIVATE local conf param
+	//////////////////////////////////////
+
+	/// joinRequestProcessing (allowed values: TRUE, FALSE) - variable defining the join policy of the Trust Center. If TRUE, the Trust center will not interrogate the WSN-C. Instead it will use local ACL
+	bool _confparam_joinRequestProcessing;
+
+	/// leaveNotificationProcessing (allowed values: TRUE, FALSE) - variable defining the leave notification policy of the Trust Center
+	bool _confparam_leaveNotificationProcessing;
+
+	// nwkAllFresh is a start-up parameter - NIB attribute of the node
+	//int nwkAllFresh;
+
+	// permitJoin is a start-up parameter - refer to PermitDuration, a MAC PIB attribute of the node
+	//int permitJoin;
+
+	/// apsSecurityTimeOutPeriod is a APS PIB attribute
+	int _apsSecurityTimeOutPeriod_msec;
+
+	//TODO not used, so far.
+	uchar TC_IEEEAddr[8];
+	//TODO not used, so far.
+	ushort TC_ShortAddr;
+
+	uchar _networkKey[NWK_KEY_SIZE];
+
+// Boris 31012008 added for the address if TC itself BEGIN
+	uchar _ieeeAddr[IEEE_RAWADDRESS_SIZE];
+// Boris 31012008 added for the address if TC itself END
+
+	//////////////////////////////////////
+	// PRIVATE methods
+	//////////////////////////////////////
+
+	/**
+	 This method is called when access is granted to a node, either from WSN-C or local access control list
+	 @param n - contains info about the granted access node
+	 */
+	void joinGranted(NodeMapItem *n);
+
+	///pointer to configuration repository
+	ConfigurationRepository *_conf;
+
+	///Sends netwrok key to target node
+	void sendTransportKey(NodeMapItem *n);
+
+	///internal function, to be called in case of joinIndication_Cb or updateDeviceIndication_Cb or other login events
+	void loginNode(int loginType, uchar *addr, ushort dev_addr,
+			uchar capability_info, uchar secure_join, uchar *parent_addr);
+
+	/**
+	 Send Leave request to node with addrees addr
+	 @param addr ieee address of the node
+	 */
+	void sendLeaveRequest(uchar *addr, uchar *parentaddr);
+
+	/// Pointer to GalZbIf object
+	GalZbIf *_pGalZb;
+
+	/// Pointer to a Debug object -> logger
+	Debug *_pLogger;
+
+};
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ConfigurationRepository.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ConfigurationRepository.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ConfigurationRepository.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,89 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "ConfigurationRepository.h"
+
+///see included header file
+ConfigurationRepository::ConfigurationRepository(string filename) {
+	pthread_mutex_init(&mux, NULL);
+	ini = NULL;
+	_filename = filename;
+}
+
+///see included header file
+ConfigurationRepository::~ConfigurationRepository() {
+#ifdef CONFIGURATION_REPOSITORY_DEBUG
+	delete _pLogger;
+#endif
+	iniparser_freedict(ini);
+}
+
+///see included header file
+bool ConfigurationRepository::load() {
+	pthread_mutex_lock(&mux);
+	ini = iniparser_load(_filename.c_str());
+	if (ini != NULL) {
+		pthread_mutex_unlock(&mux);
+		return true;
+	} else {
+		pthread_mutex_unlock(&mux);
+		return false;
+	}
+}
+
+int ConfigurationRepository::getint(const char *key, int notfound) {
+	pthread_mutex_lock(&mux);
+	int returnValue = iniparser_getint(ini, key, notfound);
+	pthread_mutex_unlock(&mux);
+	return returnValue;
+}
+
+const char *ConfigurationRepository::getstring(const char *key,
+		const char *def) {
+	pthread_mutex_lock(&mux);
+	const char *returnValue = iniparser_getstring(ini, key, (char *) def);
+	pthread_mutex_unlock(&mux);
+	return returnValue;
+}
+
+void ConfigurationRepository::getHexArray(const char *key, const char *def,
+		uchar *array, int len) {
+	pthread_mutex_lock(&mux);
+	const char *tmpString = iniparser_getstring(ini, key, (char *) def);
+	pthread_mutex_unlock(&mux);
+
+	int *tmpValue;
+	tmpValue = (int*) malloc(len * sizeof(int));
+
+	for (int i = 0; i < len; i++) {
+		sscanf(tmpString, "%x", &tmpValue[i]);
+		(tmpString) += 5;
+	}
+	for (int c = 0; c < len; c++)
+		array[c] = (uchar) tmpValue[c];
+
+	free(tmpValue);
+}
+
+ConfigurationRepository GBL_staticconfref("");
+
+ConfigurationRepository *ConfigurationRepository::instance(string filename) {
+	GBL_staticconfref = ConfigurationRepository(filename);
+
+	return &GBL_staticconfref;
+}
+
+ConfigurationRepository *ConfigurationRepository::instance() {
+	return &GBL_staticconfref;
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ConfigurationRepository.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ConfigurationRepository.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ConfigurationRepository.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,72 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef _CONFIGURATION_REPOSITORY_H_INCLUDED_
+#define _CONFIGURATION_REPOSITORY_H_INCLUDED_
+
+#include <string>
+#include <map>
+#include "CDebug.h"
+#include "iniparser.h"
+
+#include "TimerThread.h"
+
+using namespace std;
+
+typedef unsigned char uchar;
+
+///	Character to comment out line
+#define CONFCOMMENTTERMINATOR '#'
+
+///	Character to separate parameter name and value
+#define CONFEQUALTERMINATOR '='
+
+///	String-based configuration class
+
+class ConfigurationRepository {
+public:
+	///	Return instance of configuration (singleton pattern)
+	static ConfigurationRepository *instance(string filename);
+	static ConfigurationRepository *instance();
+
+	/**
+	 default constructor
+	 @param filename - configuration file
+	 */
+	ConfigurationRepository(string filename);
+
+	///	Default destructor
+	~ConfigurationRepository();
+
+	///	It loads the parameters from the file
+	bool load();
+
+	///
+
+	int getint(const char *key, int notfound);
+	const char *getstring(const char *key, const char *def);
+
+	void getHexArray(const char *key, const char *def, uchar *array, int len);
+
+	//TODO		Add 	getdouble	getboolean
+	double getdouble(const char *key, double notfound);
+
+	int getboolean(const char *key, int notfound);
+
+private:
+	dictionary *ini;
+	string _filename;
+	string _firmwareVersion;
+
+	///	Mutex
+	pthread_mutex_t mux;
+};
+
+#endif
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/Doxyfile
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/Doxyfile (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/Doxyfile Fri Oct 19 18:37:43 2012
@@ -1,0 +1,1315 @@
+# Doxyfile 1.5.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file that 
+# follow. The default is UTF-8 which is also the encoding used for all text before 
+# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into 
+# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of 
+# possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = zbgw2006
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = 1
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = 
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of 
+# source files, where putting all generated files in the same directory would 
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, 
+# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, 
+# Italian, Japanese, Japanese-en (Japanese with English messages), Korean, 
+# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, 
+# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is 
+# used as the annotated text. Otherwise, the brief description is used as-is. 
+# If left blank, the following values are used ("$name" is automatically 
+# replaced with the name of the entity): "The $name class" "The $name widget" 
+# "The $name file" "is" "provides" "specifies" "contains" 
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
+# inherited members of a class in the documentation of that class as if those 
+# members were ordinary class members. Constructors, destructors and assignment 
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip.
+
+STRIP_FROM_PATH        = /home/tomasi/
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like the Qt-style comments (thus requiring an 
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member 
+# documentation.
+
+DETAILS_AT_TOP         = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
+# a new page for each member. If set to NO, the documentation of a member will 
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 8
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
+# sources only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 
+# sources only. Doxygen will then generate output that is more tailored for Java. 
+# For instance, namespaces will be presented as packages, qualified scopes 
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to 
+# include (a tag file for) the STL sources as input, then you should 
+# set this tag to YES in order to let doxygen match functions declarations and 
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. 
+# func(std::string) {}). This also make the inheritance and collaboration 
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories 
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
+# doxygen should invoke to get the current version for each file (typically from the 
+# version control system). Doxygen will invoke the program by executing (via 
+# popen()) the command <command> <input-file>, where <command> is the value of 
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
+# provided by doxygen. Whatever the program writes to standard output 
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for 
+# functions that are documented, but have no documentation for their parameters 
+# or return value. If set to NO (the default) doxygen will only warn about 
+# wrong or incomplete parameter documentation, but not about the absence of 
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text. Optionally the format may contain 
+# $version, which will be replaced by the version of the file (if it could 
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = .
+
+# This tag can be used to specify the character encoding of the source files that 
+# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default 
+# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. 
+# See http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
+
+FILE_PATTERNS          = *.c \
+                         *.cc \
+                         *.cxx \
+                         *.cpp \
+                         *.c++ \
+                         *.d \
+                         *.java \
+                         *.ii \
+                         *.ixx \
+                         *.ipp \
+                         *.i++ \
+                         *.inl \
+                         *.h \
+                         *.hh \
+                         *.hxx \
+                         *.hpp \
+                         *.h++ \
+                         *.idl \
+                         *.odl \
+                         *.cs \
+                         *.php \
+                         *.php3 \
+                         *.inc \
+                         *.m \
+                         *.mm \
+                         *.dox \
+                         *.py \
+                         *.C \
+                         *.CC \
+                         *.C++ \
+                         *.II \
+                         *.I++ \
+                         *.H \
+                         *.HH \
+                         *.H++ \
+                         *.CS \
+                         *.PHP \
+                         *.PHP3 \
+                         *.M \
+                         *.MM \
+                         *.PY \
+                         *.C \
+                         *.H \
+                         *.tlh \
+                         *.diff \
+                         *.patch \
+                         *.moc \
+                         *.xpm \
+                         *.dox
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = yes
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                = 
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
+# directories that are symbolic links (a Unix filesystem feature) are excluded 
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories. Note that the wildcards are matched 
+# against the file with absolute path, so to exclude all test directories 
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       = 
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names 
+# (namespaces, classes, functions, etc.) that should be excluded from the output. 
+# The symbol name can be a fully qualified name, a word, or if the wildcard * is used, 
+# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
+
+INPUT_FILTER           = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis.  Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match.  The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
+# is applied to all files.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default) 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.  Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code 
+# will point to the HTML generated by the htags(1) tool instead of doxygen 
+# built-in source browser. The htags tool is part of GNU's global source 
+# tagging system (see http://www.gnu.org/software/global/global.html). You 
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = yes
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. To prevent a macro definition from being 
+# undefined via #undef or recursively expanded use the := operator 
+# instead of the = operator.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse 
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = zbgw2006.tag
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
+# or super classes. Setting the tag to NO turns the diagrams off. Note that 
+# this option is superseded by the HAVE_DOT option below. This is only a 
+# fallback. It is recommended to install and use dot, since it yields more 
+# powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc 
+# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to 
+# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to 
+# specify the directory where the mscgen tool resides. If left empty the tool is assumed to 
+# be found in the default search path.
+
+MSCGEN_PATH            = 
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
+# generate a call dependency graph for every global function or class method. 
+# Note that enabling this option will significantly increase the time of a run. 
+# So in most cases it will be better to enable call graphs for selected 
+# functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
+# generate a caller dependency graph for every global function or class method. 
+# Note that enabling this option will significantly increase the time of a run. 
+# So in most cases it will be better to enable caller graphs for selected 
+# functions only using the \callergraph command.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
+# then doxygen will show the dependencies a directory has on other directories 
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of 
+# nodes that will be shown in the graph. If the number of nodes in a graph 
+# becomes larger than this value, doxygen will truncate the graph, which is 
+# visualized by representing a node as a red box. Note that doxygen will always 
+# show the root nodes and its direct children regardless of this setting.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
+# background. This is disabled by default, which results in a white background. 
+# Warning: Depending on the platform used, enabling this option may lead to 
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to 
+# read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
+# files in one run (i.e. multiple -o and -T options on the command line). This 
+# makes dot run faster, but since only newer versions of dot (>1.8.10) 
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/GWManagement.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/GWManagement.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/GWManagement.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,305 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include "GWManagement.h"
+
+//**************************************************************************
+//*************  GWManagementMessages  ******************************************
+//**************************************************************************
+
+GWManagementMessages GWManagementMessages::instance;
+
+/**
+ Constructor
+
+ @param void Void.
+ @return Void.
+ */
+
+GWManagementMessages::GWManagementMessages() {
+	ConfigurationRepository *_conf = ConfigurationRepository::instance();
+	// We load the configuration from the ConfigurationManager
+	this->debugEnabled = _conf->getint("main:debugEnabled", false);
+
+	pLogger = new Debug("GWManagementMessages");
+	pLogger->setDebugMode(this->debugEnabled);
+	//pLogger->setDebugMode(DBG_ENABLED);			
+	//pLogger->setDebugMode(DBG_DISABLED);
+	pLogger->setDebugLevel(DEBUGGING);
+	pLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+	pLogger->enableDebugOuput(DBG_SCREEN);
+	//pLogger->enableDebugOuput(DBG_LOGFILE);		
+
+#ifdef DEBUG_ACTIVE_GWERR
+	pLogger->debug("Constructor");
+#endif
+
+	this->init();
+}
+
+/**
+ Destructor
+
+ @param void Void.
+ @return Void.
+ */
+
+GWManagementMessages::~GWManagementMessages() {
+#ifdef DEBUG_ACTIVE_GWERR
+	pLogger->debug("Destructor");
+#endif
+
+	delete pLogger;
+}
+
+GWManagementMessages *GWManagementMessages::Instance(void) {
+	return &instance;
+}
+
+/**
+ Public method GWManagementMessages init
+ It deals with object initialization.
+
+ @param void Void.
+ @return Void.
+ */
+
+void GWManagementMessages::init() {
+#ifdef DEBUG_ACTIVE_GWERR
+	pLogger->debug("init");
+#endif
+
+	// Generic GW Success
+	this->setErrorMessage(GW_SUCCESS, GW_SUCCESS_ED);
+
+	// GW Errors
+	this->setErrorMessage(GW_GEN_ERROR, GW_GEN_ERROR_ED);
+	this->setErrorMessage(GW_UNKNOWN_ERROR, GW_UNKNOWN_ERROR_ED);
+	this->setErrorMessage(GW_STATUS_UNKNOWN_ERROR, GW_STATUS_UNKNOWN_ERROR_ED);
+	this->setErrorMessage(GW_ZNP_INITIALIZATION_FAILED,
+			GW_ZNP_INITIALIZATION_FAILED_ED);
+	this->setErrorMessage(GW_ZNP_START_FAILED, GW_ZNP_START_FAILED_ED);
+
+	// GW States Description
+	this->setStateDescMessage(GW_STOPPED, GW_STOPPED_D);
+	this->setStateDescMessage(GW_ZNP_SERIAL_INITIALIZED,
+			GW_ZNP_SERIAL_INITIALIZED_D);
+	this->setStateDescMessage(GW_STARTING, GW_STARTING_D);
+	this->setStateDescMessage(GW_RUNNING, GW_RUNNING_D);
+	this->setStateDescMessage(GW_ERROR, GW_ERROR_D);
+}
+
+/**
+ Public method GWManagementMessages setErrorMessage
+ It is a modifier method: it allows setting errorMessage map.
+
+ @param errorId Return code.
+ @param errorDesc Human readable description related to return code errorId.
+ @return Void.
+ */
+
+void GWManagementMessages::setErrorMessage(int errorId,
+		const char * errorDesc) {
+#ifdef DEBUG_ACTIVE_AGENTERR
+	pLogger->debug("setErrorMessage - Error Code = %d - Error Description = %s", errorId, errorDesc);
+#endif
+	this->errorMessages[errorId] = errorDesc;
+}
+
+/**
+ Public method GWManagementMessages getErrorMessage
+ It is a selector method: it allows retrieving the error description related to a specific return code.
+
+ @param errorId Return code whose description is required.
+ @return Error description.
+ */
+
+const char * GWManagementMessages::getErrorMessage(int errorId) {
+	std::map<int, const char*>::iterator it;
+
+	it = this->errorMessages.find(errorId);
+	if (it == this->errorMessages.end()) {
+		pLogger->error("getErrorMessage - No Error Description for errorId = %d -> return Error Description = %s", errorId, this->errorMessages[GW_UNKNOWN_ERROR]);
+		return this->errorMessages[GW_UNKNOWN_ERROR];
+	}
+#ifdef DEBUG_ACTIVE_AGENTERR
+	pLogger->info("getErrorMessage - Error Code = %d - Error Description = %s", errorId, this->errorMessages[errorId]);
+#endif
+	return this->errorMessages[errorId];
+}
+
+void GWManagementMessages::setStateDescMessage(int stateCode,
+		const char * stateDesc) {
+#ifdef DEBUG_ACTIVE_AGENTERR
+	pLogger->debug("setStateDescMessage - GW State  = %d - State Description = %s", stateCode, stateDesc);
+#endif
+	this->statesDescMessages[stateCode] = stateDesc;
+}
+
+const char * GWManagementMessages::getStateDescMessage(int stateCode) {
+	std::map<int, const char*>::iterator it;
+
+	it = this->statesDescMessages.find(stateCode);
+	if (it == this->statesDescMessages.end()) {
+		pLogger->error("getStateDescMessage - No state description for GW State Code = %d -> return Error = %s", stateCode, this->getErrorMessage(GW_STATUS_UNKNOWN_ERROR));
+		return this->getErrorMessage(GW_STATUS_UNKNOWN_ERROR);
+	}
+#ifdef DEBUG_ACTIVE_AGENTERR
+	pLogger->info("getStateDescMessage - GW State Code = %d - GW State Description = %s", stateCode, this->statesDescMessages[stateCode]);
+#endif
+	return this->statesDescMessages[stateCode];
+}
+
+//**************************************************************************
+//*************  GwDescriptor  *********************************************
+//**************************************************************************
+
+/**
+ Constructor
+
+ @param void Void.
+ @return Void.
+ */
+
+GwDescriptor::GwDescriptor(
+/*	int resType,
+ int identifier,
+ int param,
+ std::string *uri*/
+) {
+	ConfigurationRepository *_conf = ConfigurationRepository::instance();
+	// We load the configuration from the ConfigurationManager
+	this->debugEnabled = _conf->getint("main:debugEnabled", false);
+
+	pLogger = new Debug("GwDescriptor");
+	pLogger->setDebugMode(this->debugEnabled);
+	//pLogger->setDebugMode(DBG_ENABLED);		
+	//pLogger->setDebugMode(DBG_DISABLED);
+	pLogger->setDebugLevel(DEBUGGING);
+	pLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+	pLogger->enableDebugOuput(DBG_SCREEN);
+	//pLogger->enableDebugOuput(DBG_LOGFILE);	
+
+#ifdef DEBUG_ACTIVE_GWDESC
+	pLogger->debug("Constructor");
+#endif
+
+	pGWManagementMsgs = GWManagementMessages::Instance();
+
+	this->init();
+}
+
+/**
+ Destructor
+
+ @param void Void.
+ @return Void.
+ */
+
+GwDescriptor::~GwDescriptor() {
+#ifdef DEBUG_ACTIVE_GWDESC
+	pLogger->debug("Destructor");
+#endif
+
+	delete pGWManagementMsgs;
+	delete pLogger;
+}
+
+/**
+ Public method GwDescriptor init
+
+ @param void Void.
+ @return Void.
+ */
+
+void GwDescriptor::init() {
+#ifdef DEBUG_ACTIVE_GWDESC
+	pLogger->debug("init");
+#endif
+
+	this->firmwareVersion = std::string(ZIGBEE_GW_FIRMWARE_VERSION);
+	this->timeStamp = std::string("");
+}
+
+void GwDescriptor::setWSNId(const char *id) {
+	this->wsnId = std::string(id);
+}
+
+std::string GwDescriptor::getWSNId() {
+	return this->wsnId;
+}
+
+void GwDescriptor::setGwState(int state) {
+	this->gwState = state;
+	this->gwStateDesc = std::string(
+			pGWManagementMsgs->getStateDescMessage(state));
+	this->setTimeStamp();
+
+}
+
+int GwDescriptor::getGwState() {
+	return this->gwState;
+}
+
+std::string GwDescriptor::getGwStateDescription() {
+	return this->gwStateDesc;
+}
+
+void GwDescriptor::setErrorCode(int code) {
+	this->errorCode = code;
+	this->errorCodeDesc = std::string(
+			pGWManagementMsgs->getErrorMessage(errorCode));
+}
+
+int GwDescriptor::getErrorCode() {
+	return this->errorCode;
+}
+
+std::string GwDescriptor::getErrorCodeDescription() {
+	return this->errorCodeDesc;
+}
+
+std::string GwDescriptor::getFirmwareVersion() {
+	return this->firmwareVersion;
+}
+
+void GwDescriptor::setTimeStamp() {
+	char tmp_str[DATETIME_BUFFER_SIZE];
+	time_t rawtime;
+	struct tm * timeinfo;
+
+	time(&rawtime);
+	timeinfo = localtime(&rawtime);
+
+	this->timeStamp.clear();
+
+	sprintf(tmp_str, "%04d-%02d-%02dT%02d:%02d:%02d%s",
+			timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday,
+			timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec,
+			REFERENCE_TIME_ZONE_DESIGNATOR);
+	tmp_str[strlen(tmp_str)] = '\0';
+	this->timeStamp += tmp_str;
+
+#ifdef DEBUG_ACTIVE_GWDESC
+	pLogger->debug("setTimeStamp - %s",this->timeStamp.c_str());
+#endif
+}
+
+std::string GwDescriptor::getTimeStamp() {
+	return this->timeStamp;
+}

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/GWManagement.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/GWManagement.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/GWManagement.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,199 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef _GW_MANAGEMENT_H_
+#define _GW_MANAGEMENT_H_
+
+#include "ConfigurationRepository.h"
+#include "CDebug.h"
+#include <map>
+#include <time.h>
+
+#define REFERENCE_TIME_ZONE_DESIGNATOR	"+01:00"
+#define ZIGBEE_GW_FIRMWARE_VERSION VERSION
+/// GW EVENTS CONSTANTS
+#define GW_STATUS_CHANGED_EVENT				0x010001
+#define DATETIME_BUFFER_SIZE				26
+
+//TODO		GAL States to be removed -> replace with GW States
+///	GAL States
+#define GAL_SS_STOPPED		0
+#define GAL_SS_STARTUP		1
+#define GAL_SS_RUNNING		2
+#define GAL_SS_ERROR		3
+
+//TODO Descrivere stati...
+
+///	GW States
+#define GW_STOPPED			0
+#define GW_ZNP_SERIAL_INITIALIZED	1
+#define GW_STARTING			2			
+#define GW_RUNNING			3
+#define GW_ERROR			4
+
+/// GW States Description
+#define GW_STOPPED_D			"GW Stopped"
+#define GW_ZNP_SERIAL_INITIALIZED_D	"GW ZigBee Network Processor initialized"
+#define GW_STARTING_D			"GW is starting (ZigBee Network Processor configuration)"			
+#define GW_RUNNING_D			"GW successfully started"
+#define GW_ERROR_D			"GW Error"
+
+/**
+ GW Error Codes
+ */
+// GW Success
+#define	GW_SUCCESS				0	
+
+// GW Error codes
+#define	GW_GEN_ERROR				1	// Generic GW error
+#define	GW_UNKNOWN_ERROR			2	// Unknown GW State
+#define	GW_STATUS_UNKNOWN_ERROR			3	// Unknown GW State
+#define	GW_ZNP_INITIALIZATION_FAILED		4	// ZigBee Network Processor initialization failed
+#define	GW_ZNP_START_FAILED			5	// ZigBee Network Processor start failed
+
+/**
+ GW Error Messages		(ED stands for Error Description)
+ */
+// Generic Agent Errors Descriptions
+#define	GW_SUCCESS_ED				""
+#define	GW_GEN_ERROR_ED				"Generic GW error"
+#define	GW_UNKNOWN_ERROR_ED			"Unknown GW error"
+#define	GW_STATUS_UNKNOWN_ERROR_ED		"Unknown GW State"
+#define	GW_ZNP_INITIALIZATION_FAILED_ED		"ZigBee Network Processor initialization failed"
+#define	GW_ZNP_START_FAILED_ED			"GAL not running"
+
+//**************************************************************************
+//*************  GWErrorMessages  ******************************************
+//**************************************************************************
+
+class GWManagementMessages {
+
+public:
+
+	// Pattern Singleton
+	static GWManagementMessages *Instance(void);
+
+	///	Destructor:
+	~GWManagementMessages();
+
+	// Functions: modifiers (set), selectors (get)
+	void init();
+
+	///	Management Messages map modifier and selector 
+	void setErrorMessage(int errorId, const char * errorDesc);
+
+	const char *getErrorMessage(int errorId);
+
+	///	statesDescMessages map modifier and selector 
+	void setStateDescMessage(int stateCode, const char * stateDesc);
+
+	const char *getStateDescMessage(int stateCode);
+
+	// itterators:
+	// Attributes visible by scope of instantiation and use
+
+protected:
+
+	///	Constructor (pattern Singleton)
+	GWManagementMessages();
+
+	// Attributes visible to descendents
+
+	///	Pointer to a Debug object -> logger
+	Debug *pLogger;
+
+	/// To enable/disable Debug (default value is 0)
+	bool debugEnabled;
+
+private:
+	// Local attributes
+
+	// Pattern Singleton
+	static GWManagementMessages instance;
+
+	///	Map containing error messages related to all agents. For each error code, a text concerning error description is stored.
+	std::map<int, const char*> errorMessages;
+
+	///	Map containing description messages concerning GW states
+	std::map<int, const char*> statesDescMessages;
+
+};
+
+//**************************************************************************
+//*************  GwDescriptor  *********************************************
+//**************************************************************************
+
+class GwDescriptor {
+
+public:
+	///	Constructors:
+	GwDescriptor();
+
+	///	Destructor:
+	~GwDescriptor();
+
+	///	Functions: modifiers (set), selectors (get)
+	void init();
+
+	void setGwState(int state);
+
+	int getGwState();
+
+	void setWSNId(const char *id);
+
+	std::string getWSNId();
+
+	std::string getGwStateDescription();
+
+	void setErrorCode(int code);
+
+	int getErrorCode();
+
+	std::string getErrorCodeDescription();
+
+	std::string getTimeStamp();
+
+	std::string getFirmwareVersion();
+
+	// itterators:
+	// Attributes visible by scope of instantiation and use
+
+protected:
+
+	void setTimeStamp();
+
+	// Attributes visible to descendents
+
+	std::string wsnId;
+	int gwState;
+	std::string gwStateDesc;
+	int errorCode;
+	std::string errorCodeDesc;
+	std::string firmwareVersion;
+	std::string timeStamp;
+
+	///	Pointer to a Debug object -> logger
+	Debug *pLogger;
+
+	/// To enable/disable Debug (default value is 0)
+	bool debugEnabled;
+
+	GWManagementMessages *pGWManagementMsgs;
+
+private:
+	// Local attributes
+
+};
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+#endif
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/GalZbIf.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/GalZbIf.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/GalZbIf.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,2249 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <arpa/inet.h>
+#include "winport.h"
+#include <pthread.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stdio.h>
+#endif
+
+#include "ZbNetDb.h"
+#include "GalZbIf.h"
+#include "zigbee_utils.h"
+#include "CDiscoveryAgent.h"
+//#include "zigbee_log.h"
+#include "ConfigurationRepository.h"
+
+GalZbIf GalZbIf::instance;
+ushort maxTCKeyTableSize = 9; //By default Ember can be set up to 12 entries!
+
+GalZbIf::FeatureControl::FeatureControl() {
+	lockedFeatures = 0;
+}
+
+bool GalZbIf::FeatureControl::lock(unsigned long features) {
+	if (features & lockedFeatures)
+		return false;
+
+	lockedFeatures |= features;
+
+	return true;
+}
+
+void GalZbIf::FeatureControl::unlock(unsigned long features) {
+	lockedFeatures &= ~features;
+}
+
+/**
+ Constructor
+ GalZbIf constructor.
+
+ @param void  Void.
+ @return Void.
+ */
+
+GalZbIf::GalZbIf() {
+	// Init mutex
+	pthread_mutex_init(&mux, NULL);
+
+	simple_desc_count = 0; //TODO	Move to Management Agent
+	count_expected_confirm = 0;
+
+	profile_id = 0x0104;
+	device_id = 0x0001;
+	ScanChannels = 0x00100000;
+
+	/*
+	 // init localShortAddress
+	 this->localShortAddress = 0x0000;
+	 this->localShortAddressUc[0] = 0x00;
+	 this->localShortAddressUc[1] = 0x00;
+	 */
+	// Initialize the SecurityLevel
+	this->securityLevel = 0;
+
+	// Init number of ZDO_Start_Request attempts
+	this->zdoStartAttempts = 0;
+
+	// Init isFirstStart -> TRUE
+	this->isFirstStart = TRUE;
+
+	// By default we use the EZSP stack
+	this->isEZSPstackRunning = TRUE;
+
+	//
+	this->lastSDSet = NULL;
+	//
+	this->tcKT_setIndex = 0;
+	this->tcKT_eraseIndex = 0;
+	this->currentTCKeyTableEntryIndex = 0;
+	this->erasePhase = true;
+	this->setPhase = false;
+}
+
+/**
+ Destructor
+ GalZbIf destructor.
+
+ @param void Void.
+ @return Void.
+ */
+
+GalZbIf::~GalZbIf() {
+
+#ifdef DEBUG_ACTIVE_GALZB
+	printf("GalZbIf - Desctructor\n");
+#endif
+
+	// Clear listeners map
+	std::map<int, std::list<void*> >::const_iterator iter;
+	std::list<void*> tmpList;
+	std::list<void*>::iterator tmpList_it;
+	for (iter = listeners.begin(); iter != listeners.end(); ++iter) {
+		tmpList = iter->second;
+		tmpList.clear();
+	}
+	listeners.clear();
+
+	delete pLogger;
+}
+
+/**
+ Public method GalZbIf *Instance(void)
+ (pattern Singleton)
+
+ @param void Void.
+ @return Instance of GalZbIf class.
+ */
+
+GalZbIf *GalZbIf::Instance(void) {
+	return &instance;
+}
+
+GalZbIf::FeatureControl *GalZbIf::getFeatureControl(void) {
+	return &featureControl;
+}
+
+void GalZbIf::init() {
+	ConfigurationRepository *_conf = ConfigurationRepository::instance();
+	// We load the configuration from the ConfigurationManager
+	this->debugEnabled = _conf->getint("main:debugEnabled", false);
+
+	// Debug
+	pLogger = new Debug("GalZbIf");
+	pLogger->setDebugMode(this->debugEnabled);
+	//pLogger->setDebugMode(DBG_ENABLED);
+	pLogger->setDebugLevel(DEBUGGING);
+	pLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+	pLogger->enableDebugOuput(DBG_SCREEN);
+
+	this->setGWStatus(GW_STOPPED, GW_SUCCESS);
+}
+
+/**
+ Public method GalZbIf LoadConfig
+
+ Read GAL configuration file
+
+ @param filename Description of first function argument.
+ @return Status.
+ */
+
+int GalZbIf::LoadConfig(const char *filename) {
+	pthread_mutex_lock(&mux);
+
+	ConfigurationRepository *_conf = ConfigurationRepository::instance();
+
+	platform = _conf->getint("main:platform", 0);
+
+	this->apscMaxWindowSize = _conf->getint("main:apscMaxWindowSize", 1);
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("LoadConfig - apscMaxWindowSize = %d", this->apscMaxWindowSize);
+#endif
+
+	this->apsInterframeDelay = _conf->getint("main:apsInterframeDelay", 100);
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("LoadConfig - apsInterframeDelay = %d", this->apsInterframeDelay);
+#endif
+
+	pthread_mutex_unlock(&mux);
+	return 0;
+}
+
+/**
+ Public method GalZbIf SaveConfig
+ Save GAL configuration file
+
+ @param filename Configuration file name.
+ @return Status.
+ */
+
+int GalZbIf::SaveConfig(const char *filename) {
+	return 0;
+}
+
+/**
+ Public method GalZbIf registerListener
+ This method is used by Agents to register a callback on a specific event (e.g. the reception of a IEEE Address confirm, ...).
+ When a specific event occurs, the registered callbacks are invoked.
+
+ @param eventType Event type (refer to codes defined in zigbee_ser.h).
+ @param listener Event listener (i.e. agent callback function).
+ @return Status.
+ */
+
+int GalZbIf::registerListener(int eventType, void *listener) {
+
+	if (listeners[eventType].empty()) {
+		/*
+		 #ifdef DEBUG_ACTIVE_GALZB
+		 pLogger->debug("registerListener - Map empty");
+		 #endif
+		 */
+	}
+	listeners[eventType].push_back(listener);
+	/*
+	 #ifdef DEBUG_ACTIVE_GALZB
+	 pLogger->debug("registerListener - listener registered");
+	 #endif
+	 */
+	return 0;
+}
+
+/**
+ Public method GalZbIf unregisterListener
+ This method allows unregistering listeners for specific events.
+
+ @param eventType Event type (refer to codes defined in zigbee_ser.h).
+ @param listener Event listener (i.e. agent callback function).
+ @return Status.
+ */
+int GalZbIf::unregisterListener(int eventType, void *listener) {
+	/*TODO: Are we sure listeners[eventType] always exists?? We could use the code below:
+	 std::map <int, std::list <void*> >::iterator it;
+	 it=listeners.find(eventType);
+	 if (it == NULL || listeners[eventType].empty())
+	 return -1;
+	 */
+	if (listeners[eventType].empty())
+		return (-1);
+	// Remove the listener
+	listeners[eventType].remove(listener);
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("unregisterListener - listener removed");
+#endif
+	return 0;
+}
+
+/**
+ Public method GalZbIf getDb
+ This method allows retrieving a pointer to the used ZbNetDb object.
+
+ @param void Void.
+ @return Instance of ZbNetDb class.
+ */
+
+ZbNetDb* GalZbIf::getDb(void) {
+
+	return &(this->db);
+}
+
+/**
+ Public method GalZbIf Start
+
+ Starts the GAL. This method must be called before calling any other metod, apart LoadConfig()
+ During startup GW moves through the following states: GW_STOPPED -> GW_ZNP_SERIAL_INITIALIZED -> GW_STARTING -> GW_RUNNING
+ In case of failure the GW goes in state GW_ERROR.
+
+ @param void Void.
+ @return Status.
+ */
+
+int GalZbIf::Start(void) {
+	ZbNetDb *pGalDb;
+	ConfigurationRepository *_conf = ConfigurationRepository::instance();
+	int resetOptions = 0x00;
+
+	// Get the current StartupAttributeSetIndex used
+	int currentSASIndex = db.getCurrentStartupAttributeSetIndex();
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("Start - currentSASIndex = %d",currentSASIndex);
+#endif
+	this->currentSAS = db.getStartupAttributeInfo(currentSASIndex);
+	if (this->currentSAS == NULL) {
+		pLogger->fatal("Start - currentSAS = NULL");
+	}
+	this->setGWStatus(GW_STARTING, GW_SUCCESS);
+
+	pGalDb = getDb();
+
+	this->securityLevel = (this->currentSAS)->_securityLevel;
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->info("Start - Security level = %d",this->securityLevel);
+#endif
+
+	/*
+	 this->isTCKeyTableDefined = (this->currentSAS)->_isTCKeyTableDefined;
+	 #ifdef DEBUG_ACTIVE_GALZB
+	 pLogger->info("Start - isTCKeyTableDefined = %d",this->isTCKeyTableDefined);
+	 #endif
+	 */
+
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("Start - Starting ZNP - ZDO Reset");
+#endif
+
+	int generateRandomIEEEAddr = _conf->getint(
+			"DefaultStartupAttributeSet:freescaleMACAddressValue", 0);
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->info("Start - generateRandomIEEEAddr = %d",generateRandomIEEEAddr);
+#endif
+
+	// Configure the reset options
+	resetOptions |= 0x01; // restartGWafterReset enable
+	if (pGalDb->getStartModeSetting() == 0x00) {
+		//0 - StartupSetMode=0x18 (CommissioningMode) AND StartupControlMode=0x00 (Association) --> To be used the first time, when the network is created
+		resetOptions |= 0x02; //Use CommissioningMode
+	} else if (pGalDb->getStartModeSetting() == 0x01) {
+		//1 - StartupSetMode=0x00 (use NVM) AND StartupControlMode=0x04 (SilentStart) --> To be used at running time
+		resetOptions |= 0x10; //use SilentStartMode
+	} else if (pGalDb->getStartModeSetting() == 0x02) {
+		//2 - StartupSetMode=0x18 (CommissioningMode) AND StartupControlMode=0x04 (SilentStart) --> To be used for TC Replacement
+		resetOptions |= 0x02; //Use CommissioningMode
+		resetOptions |= 0x10; //use SilentStartMode
+	}
+	// call a real Freescale dongle reset!
+	resetOptions |= 0x04;
+	if (generateRandomIEEEAddr == 1)
+		resetOptions |= 0x08; // generateRandomIEEEAddr true!
+
+	// Call the reset function
+	ZDO_RESET_request(resetOptions);
+	return 0;
+}
+
+int GalZbIf::ZbIfConnect_W(const char *device) {
+	int returnValue;
+	const char *param = device;
+	char _name[41];
+	char _value[41];
+	char ch;
+
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("ZbIfConnect");
+#endif
+
+	//Check and set if we're using a EZSP stack (by default set to NO)
+	isEZSPstackRunning = false;
+	while (param) {
+		if (sscanf(param, "%40[^=]%c%40s", _name, &ch, _value) != 3) {
+			return -1;
+		}
+		if (strcmp("dongle", _name) == 0) {
+			if (strncmp("ezsp", _value, 4) == 0) {
+				isEZSPstackRunning = true;
+#ifdef DEBUG_ACTIVE_GALZB
+				pLogger->debug("ZbIfConnect - EZSP dongle selected");
+#endif
+			}
+			break;
+		}
+		param++;
+	}
+
+	returnValue = this->ZBIFConnect(device);
+
+	if (returnValue < 0) {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->error("ZbIfConnect - ERROR: cannot connect to the ZigBee device");
+#endif
+		this->setGWStatus(GW_ERROR, GW_ZNP_INITIALIZATION_FAILED);
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("ZbIfConnect - ZigBee device connected");
+#endif
+		this->setGWStatus(GW_ZNP_SERIAL_INITIALIZED, GW_SUCCESS);
+	}
+
+	return this->getGWStatus();
+}
+
+int GalZbIf::ZbIfDisconnect_W(void) {
+#ifdef DEBUG_ACTIVE_GALZB
+	printf("GalZbIf::ZbIfDisconnect_W\n");
+#endif
+	this->ZBIFDisconnect();
+	this->setGWStatus(GW_STOPPED, GW_SUCCESS);
+	return this->getGWStatus();
+}
+
+/**
+ Public method GalZbIf getGalStatus
+ This method allows retrieving current GAL status.
+
+ @param void Void.
+ @return GAL status.
+ */
+
+int GalZbIf::getGalStatus(void) {
+
+	return this->gwStatus;
+}
+
+int GalZbIf::getGWStatus(void) {
+
+	return this->gwStatus;
+}
+
+int GalZbIf::setGWStatus(int gwStatus, int errorCode) {
+	return this->setGWStatus(gwStatus, errorCode, 0x00);
+}
+
+int GalZbIf::setGWStatus(int gwStatus, int errorCode, uchar commandStatus) {
+
+	this->gwStatus = gwStatus;
+	this->GW_STATUS_CHANGED_event(errorCode, commandStatus);
+	return this->gwStatus;
+}
+
+/*
+ ushort GalZbIf::getLocalNwkAddress_us() {
+ return this->localShortAddress;
+ }
+
+ uchar* GalZbIf::getLocalNwkAddress_uc() {
+ return this->localShortAddressUc;
+ }
+
+
+ uchar* GalZbIf::getLocalIEEEAddress_uc() {
+ return this->localIEEEAddress;
+ }
+ */
+
+/**
+ Protected method GalZbIf ZDO_RESET_confirm
+
+ @param status Status value.
+ @return Void.
+ */
+
+void GalZbIf::ZDO_RESET_confirm(uchar status, uchar restartGW //1=Restart, 0=just init
+		) {
+	ZbNetDb *pGalDb;
+
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("ZDO_RESET_confirm - status %02x, restartGw %02x",status,restartGW);
+#endif
+
+	// Get the current StartupAttributeSetIndex used
+	int currentSASIndex = db.getCurrentStartupAttributeSetIndex();
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("ZDO_RESET_confirm - currentSASIndex = %d",currentSASIndex);
+#endif
+	this->currentSAS = db.getStartupAttributeInfo(currentSASIndex);
+	if (this->currentSAS == NULL) {
+		pLogger->fatal("ZDO_RESET_confirm - currentSAS = NULL");
+	}
+	this->setGWStatus(GW_STARTING, GW_SUCCESS);
+
+	this->securityLevel = (this->currentSAS)->_securityLevel;
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->info("ZDO_RESET_confirm - Security level = %d",this->securityLevel);
+#endif
+	// Send a notification
+	if (!listeners[ZB_ZDO_RESET_CONFIRM].empty()) {
+		std::map<int, std::list<void*> >::const_iterator currEventListeners;
+		std::list<void*> tempList;
+		std::list<void*>::iterator iter;
+		currEventListeners = listeners.find(ZB_ZDO_RESET_CONFIRM);
+		tempList = currEventListeners->second;
+		for (iter = tempList.begin(); iter != tempList.end(); iter++) {
+			((ZB_ZDO_RESET_CONFIRM_Listener) (*iter))(status);
+		}
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("Map Listeners for ZDO_RESET_confirm empty");
+#endif
+	}
+	if (status == ZB_ZDO_SUCCESS) {
+		if (restartGW == 0x01) {
+			//TODO: A better way shall be to alert cRestBroker that the reset has concluded so that it can perform the autorun() procedure!
+			ZB_NODE_DESC g_node_desc;
+			ZB_Init_NODE_DESC(&g_node_desc);
+			g_node_desc.logical_type = (this->currentSAS)->deviceType;
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("ZDO_RESET_confirm - Device type = %d",(this->currentSAS)->deviceType);
+#endif
+			g_node_desc.complx_desc_avail = 0;
+			g_node_desc.user_desc_avail = 0;
+			g_node_desc.reserved = 0;
+			g_node_desc.aps_flags = 0;
+			g_node_desc.freq_band = 0x08; //was 0x1F
+			g_node_desc.mac_cap = 0x8E; //was 0x4F
+			g_node_desc.manifact_code = 0x03F0; //was 0
+			g_node_desc.max_buf_size = 0x70; //was 0x70
+			g_node_desc.max_transf_size = 0;
+			g_node_desc.server_mask = 0;
+
+			APSME_SET_request(ZB_ATTR_CONFIG_NODE_DESCRIPTOR,
+					sizeof(g_node_desc), (uchar *) &g_node_desc);
+		} else {
+			this->setGWStatus(GW_ZNP_SERIAL_INITIALIZED, GW_SUCCESS);
+			// Initialize the gateway (included all the variables and classes)
+			pGalDb = getDb();
+			//Save the root local node!
+			pGalDb->clearAllButRoot();
+			printf(
+					"\n*************\nGateway initialized (waiting for startup) - StartupMode = 0x%02x\n*************\n",
+					pGalDb->getStartModeSetting());
+		}
+	}
+}
+
+/**
+ Protected method GalZbIf ZDO_END_DEVICE_BIND_confirm
+
+ @param status Status value.
+ @return Void.
+ */
+
+void GalZbIf::ZDO_END_DEVICE_BIND_confirm(uchar status) {
+	if (status == ZB_ZDO_SUCCESS) {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("Binding succeded" );
+#endif
+	} else {
+		pLogger->debug("Binding returned status = 0x%02x", status);
+	}
+}
+
+void GalZbIf::ZDP_MGMT_BIND_Response(uchar status, ushort bindingTableEntries,
+		ushort StartIndex, ushort BindingTableListCount,
+		ZB_BIND_STRUCT *BindingTableList) {
+	if (status == ZB_ZDO_SUCCESS) {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("ZDP_MGMT_BIND_Response succeed" );
+#endif
+	} else {
+		pLogger->debug("ZDP_MGMT_BIND_Response returned status = 0x%02x", status);
+	}
+	if (!listeners[ZB_ZDP_MGMT_BIND_RESPONSE].empty()) {
+		std::map<int, std::list<void*> >::const_iterator currEventListeners;
+		std::list<void*> tempList;
+		std::list<void*>::iterator iter;
+
+		currEventListeners = listeners.find(ZB_ZDP_MGMT_BIND_RESPONSE);
+		tempList = currEventListeners->second;
+		// Send to the listeners
+		for (iter = tempList.begin(); iter != tempList.end(); iter++) {
+			((ZB_ZDP_MGMT_BIND_Response_Listener) (*iter))(status,
+					bindingTableEntries, StartIndex, BindingTableListCount,
+					BindingTableList);
+		}
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("Map Listeners empty");
+#endif
+	}
+	return;
+}
+
+void GalZbIf::ZDP_BIND_response(uchar status) {
+	if (status == ZB_ZDO_SUCCESS) {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("Bind_Confirm succeed" );
+#endif
+	} else {
+		pLogger->debug("Bind_Confirm  returned status = 0x%02x", status);
+	}
+	if (!listeners[ZB_ZDP_BIND_RESPONSE].empty()) {
+		std::map<int, std::list<void*> >::const_iterator currEventListeners;
+		std::list<void*> tempList;
+		std::list<void*>::iterator iter;
+
+		currEventListeners = listeners.find(ZB_ZDP_BIND_RESPONSE);
+		tempList = currEventListeners->second;
+		// Send to the listeners
+		for (iter = tempList.begin(); iter != tempList.end(); iter++) {
+			((ZB_ZDP_BIND_response_Listener) (*iter))(status);
+		}
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("Map Listeners empty");
+#endif
+	}
+	return;
+}
+
+void GalZbIf::ZDP_UNBIND_response(uchar status) {
+	if (status == ZB_ZDO_SUCCESS) {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("Unbind_response succeed" );
+#endif
+	} else {
+		pLogger->debug("Unbind_response  returned status = 0x%02x", status);
+	}
+	if (!listeners[ZB_ZDP_UNBIND_RESPONSE].empty()) {
+		std::map<int, std::list<void*> >::const_iterator currEventListeners;
+		std::list<void*> tempList;
+		std::list<void*>::iterator iter;
+
+		currEventListeners = listeners.find(ZB_ZDP_UNBIND_RESPONSE);
+		tempList = currEventListeners->second;
+		// Send to the listeners
+		for (iter = tempList.begin(); iter != tempList.end(); iter++) {
+			((ZB_ZDP_UNBIND_response_Listener) (*iter))(status);
+		}
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("Map Listeners empty");
+#endif
+	}
+	return;
+}
+
+void GalZbIf::MGMT_PERMIT_JOINING_response(uchar status) {
+	if (status == ZB_ZDO_SUCCESS) {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("Permit Joining succeed" );
+#endif
+	} else {
+		pLogger->debug("Permit Joining  returned status = 0x%02x", status);
+	}
+
+	if (!listeners[ZB_MGMT_PERMIT_JOINING_RESPONSE].empty()) {
+		std::map<int, std::list<void*> >::const_iterator currEventListeners;
+		std::list<void*> tempList;
+		std::list<void*>::iterator iter;
+
+		currEventListeners = listeners.find(ZB_MGMT_PERMIT_JOINING_RESPONSE);
+		tempList = currEventListeners->second;
+
+		for (iter = tempList.begin(); iter != tempList.end(); iter++) {
+			((ZB_MGMT_PERMIT_JOINING_response_Listener) (*iter))(status);
+		}
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("Map Listeners empty");
+#endif
+	}
+
+	return;
+}
+
+void GalZbIf::MGMT_LEAVE_response(uchar status) {
+	if (status == ZB_ZDO_SUCCESS) {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("GalZbIf::Leave response succeeded. " );
+#endif
+	} else
+		pLogger->debug("Leave response  returned status = 0x%02x", status);
+
+	if (!listeners[ZB_MGMT_LEAVE_RESPONSE].empty()) {
+		std::map<int, std::list<void*> >::const_iterator currEventListeners;
+		std::list<void*> tempList;
+		std::list<void*>::iterator iter;
+
+		currEventListeners = listeners.find(ZB_MGMT_LEAVE_RESPONSE);
+		tempList = currEventListeners->second;
+
+		for (iter = tempList.begin(); iter != tempList.end(); iter++) {
+			((ZB_MGMT_LEAVE_response_Listener) (*iter))(status);
+		}
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("Map Listeners empty");
+#endif
+	}
+	return;
+}
+
+void GalZbIf::MGMT_LEAVE_confirm(uchar *ieee_addr, uchar rejoin) {
+	Node * srcNode;
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("GalZbIf::MGMT_LEAVE_confirm");
+#endif
+	srcNode = this->db.findNodeByIEEEAddr(ieee_addr); //srcNode = pGalDb->findNodeByIEEEAddr
+	if (srcNode == NULL) {
+		// Node not found: it was probably already deleted in GAL's database (then OK, just ignore)
+		/*
+		 #ifdef DEBUG_ACTIVE_GALZB
+		 pLogger->debug("Node %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x not found (already deleted by MGMT_LQI_Rsp)",ieee_addr[0],ieee_addr[1],ieee_addr[2],ieee_addr[3],
+		 ieee_addr[4],ieee_addr[5],ieee_addr[6],ieee_addr[7]);
+		 #endif
+		 */
+		return;
+	}
+	// Set the timeout to this particular value so that the keepAlive algorithm will declare the node dead to the upper layer
+	srcNode->setKANodeTimer(0xFFFFFFFC);
+}
+
+int GalZbIf::setSimpleDescriptor(void) {
+	unsigned char simple_descr[255];
+	int simple_descr_size = 0;
+
+	SimpleDescriptor *sd;
+
+	memset(simple_descr, 0, sizeof(unsigned char) * 255);
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("setSimpleDescriptor");
+#endif
+	if (lastSDSet == NULL) {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("setSimpleDescriptor - getFirstSD");
+#endif
+		sd = this->db.getFirstServicesSD();
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("setSimpleDescriptor - getNextSD");
+#endif
+		sd = this->db.getNextServicesSD(lastSDSet);
+	}
+
+	lastSDSet = sd;
+
+	if (sd == NULL) {
+		return -1;
+	} else {
+		//Prepare the next SimpleDescriptor to set
+		simple_descr[0] = sd->end_point; // endpoint value
+#ifdef DEBUG_ACTIVE_GALZB
+				pLogger->debug("setSimpleDescriptor - endpoint %d",simple_descr[0]);
+#endif
+		simple_descr[1] = LSB_USHORT(sd->profile_id);
+		simple_descr[2] = MSB_USHORT(sd->profile_id);
+		simple_descr[3] = LSB_USHORT(sd->device_id);
+		simple_descr[4] = MSB_USHORT(sd->device_id);
+		simple_descr[5] = sd->device_ver; // version flags (was 0)
+		// Input clusters
+		simple_descr[6] = sd->input_cluster.size(); //input cluster count
+		// Output clusters
+		simple_descr[7] = sd->output_cluster.size(); //output cluster count
+		simple_descr_size = 8;
+		//input cluster list
+		std::list<int>::iterator it;
+		for (it = sd->input_cluster.begin(); it != sd->input_cluster.end();
+				it++) {
+			simple_descr[simple_descr_size++] = LSB_USHORT((*it));
+			simple_descr[simple_descr_size++] = MSB_USHORT((*it));
+		}
+		// Output cluster list
+		for (it = sd->output_cluster.begin(); it != sd->output_cluster.end();
+				it++) {
+			simple_descr[simple_descr_size++] = LSB_USHORT((*it));
+			simple_descr[simple_descr_size++] = MSB_USHORT((*it));
+		}
+		APSME_SET_request(ZB_ATTR_CONFIG_SIMPLE_DESCRIPTOR, simple_descr_size,
+				simple_descr);
+	}
+	return 0;
+}
+
+void GalZbIf::APSME_GET_confirm(uchar status, uchar attr, uchar length,
+		uchar * value) {
+	ZbNetDb *pGalDb;
+
+	if (status != ZB_ZDO_SUCCESS) {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->warn("ERROR: attribute 0x%02X - status = 0x%02X", attr, status);
+#endif
+		return;
+	}
+
+	switch (platform) {
+	case 0: // ----- INTEGRATION ---------------------------------
+	{
+		pLogger->fatal("This dongle is not supported anymore!");
+	}
+		break;
+
+	case 1: // ----- zsdio/EZSP/freescale ---------------------------------
+	{
+
+		if (attr == ZB_ATTR_GET_CHANNEL_MASK) {
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_GET_confirm: ZB_ATTR_GET_CHANNEL_MASK" );
+#endif
+			// Store the Channel mask
+			assignedChannelMask = value[0];
+			ZbNetDb *pGalDb = getDb();
+			StartupAttributeInfo* sasInfo = pGalDb->getStartupAttributeInfo(
+					pGalDb->getCurrentStartupAttributeSetIndex());
+			if (assignedChannelMask >= 11 && assignedChannelMask <= 26) {
+				// Shift the bit 1 by "n" positions!
+				sasInfo->channelMask = 1 << assignedChannelMask;
+			} else {
+				pLogger->error("APSME_GET_confirm - invalid channel mask returned: %d",assignedChannelMask);
+				exit(0);
+				return;
+			}
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_GET_confirm: Channel mask assigned = %d",value[0]);
+#endif
+			/*
+			 switch (assignedChannelMask) {
+			 case 26:
+			 sasInfo->channelMask = 0x04000000;
+			 break;
+			 case 25:
+			 sasInfo->channelMask = 0x02000000;
+			 break;
+			 case 24:
+			 sasInfo->channelMask = 0x01000000;
+			 break;
+			 case 23:
+			 sasInfo->channelMask = 0x00800000;
+			 break;
+			 case 22:
+			 sasInfo->channelMask = 0x00400000;
+			 break;
+			 case 21:
+			 sasInfo->channelMask = 0x00200000;
+			 break;
+			 case 20:
+			 sasInfo->channelMask = 0x00100000;
+			 break;
+			 case 19:
+			 sasInfo->channelMask = 0x00080000;
+			 break;
+			 case 18:
+			 sasInfo->channelMask = 0x00040000;
+			 break;
+			 case 17:
+			 sasInfo->channelMask = 0x00020000;
+			 break;
+			 case 16:
+			 sasInfo->channelMask = 0x00010000;
+			 break;
+			 case 15:
+			 sasInfo->channelMask = 0x00008000;
+			 break;
+			 case 14:
+			 sasInfo->channelMask = 0x00004000;
+			 break;
+			 case 13:
+			 sasInfo->channelMask = 0x00002000;
+			 break;
+			 case 12:
+			 sasInfo->channelMask = 0x00001000;
+			 break;
+			 case 11:
+			 sasInfo->channelMask = 0x00000800;
+			 break;
+			 default:
+			 pLogger->error("APSME_GET_confirm - invalid channel mask returned: %d",assignedChannelMask);
+			 exit(0);
+			 break;
+			 }
+			 #ifdef DEBUG_ACTIVE_GALZB
+			 pLogger->debug("APSME_GET_confirm: Channel mask assigned = %d",value[0]);
+			 #endif
+			 */
+			// Last (but not least), ask for the GAL's IEEEAddress
+			APSME_GET_request (ZB_ATTR_GET_EUI64);
+		} else if (attr == ZB_ATTR_GET_EUI64) {
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_GET_confirm: ZB_ATTR_GET_EUI64" );
+#endif
+			pGalDb = getDb();
+			// Store the ROOT IEEEAddress
+			uchar tmpIEEEAddr[8];
+			for (int c = 0; c < 8; c++) {
+				tmpIEEEAddr[c] = (uchar) value[7 - c];
+			}
+			pGalDb->root->set_ieee_addr(tmpIEEEAddr);
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("\n\nRoot node: IEEEAddress Set!");
+#endif
+			// Trigger StartGatewayDevice Response or Event, GWStatusChanged Event
+			this->setGWStatus(GW_RUNNING, GW_SUCCESS);
+			// Make fake internal Device Announcement Indication (this is not triggered by an actual low level ZigBee message)
+			this->ZDO_DEVICE_ANNCE_indication(pGalDb->root->get_nwk_addr(),
+					tmpIEEEAddr, 0xCF);
+			if ((this->currentSAS)->deviceType == ZB_END_DEVICE) {
+				// End device so poll for data
+				NLME_SYNC_request(1); // Sync & Track
+			}
+			// Force the root node to restart the keepAliveAlgorithm
+			if (pGalDb->root != NULL) {
+#ifdef DEBUG_ACTIVE_GALZB
+				pLogger->debug("ZDO_RESET_confirm - Forced local node to run KeepAlive algorithm");
+#endif
+				pGalDb->root->setKANodeTimer(
+						pGalDb->root->getKANodeTimer() - 2000); //2000 >> KAthreshold
+			}
+			/*
+			 // Last but not least, check if there are activeEndPoints not set yet (available only for NVM!)
+			 if (pGalDb->getStartModeSetting() == 0x01){
+			 ZDO_ACTIVE_EP_DESC_request(localShortAddress, localShortAddress);
+			 }
+			 */
+			// We are now operational, announce it!
+			printf(
+					"\n************\nDevice started (GAL shortAddr = 0x%04x - GAL IEEE address = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x - Channel Mask = %d)\n************\n",
+					pGalDb->root->get_nwk_addr(), tmpIEEEAddr[0],
+					tmpIEEEAddr[1], tmpIEEEAddr[2], tmpIEEEAddr[3],
+					tmpIEEEAddr[4], tmpIEEEAddr[5], tmpIEEEAddr[6],
+					tmpIEEEAddr[7], assignedChannelMask);
+			// Reset the deadingNodeList in CDiscoveryAgent (this was the only place where I've found an easy way to clean it) :-(
+			DiscoveryAgent<GalZbIf> *pDAgent;
+			pDAgent = DiscoveryAgent<GalZbIf>::Instance();
+		} else {
+			pLogger->fatal("Received a APSME_GET_confirm from an unsupported attribute: %02x", attr);
+		}
+	}
+		break;
+	}
+}
+
+/**
+ Protected method GalZbIf APSME_SET_confirm
+
+ @param status Status value.
+ @param attr Attribute code.
+ @return Void.
+ */
+
+void GalZbIf::APSME_SET_confirm(uchar status, uchar attr) {
+
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("APSME_SET_confirm");
+#endif
+
+	if (status != ZB_ZDO_SUCCESS) {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->warn("ERROR: setting attribute 0x%02x - status = 0x%02X", attr, status);
+#endif
+		return;
+	}
+
+	switch (platform) {
+	case 0: // ----- INTEGRATION ---------------------------------
+	{
+		switch (attr) {
+		case ZIB_CONFIG_NODE_DESCRIPTOR: //	ZIB_CONFIG_NODE_DESCRIPTOR =
+		{
+			unsigned char buff[30];
+			uchar *p;
+
+			// Have successfully Set the Node Descriptor.
+			// Build the mode & params descriptor
+			p = buff;
+
+			*p++ = (uchar) ScanChannels;
+			*p++ = (uchar) (ScanChannels >> 8);
+			*p++ = (uchar) (ScanChannels >> 16);
+			*p++ = (uchar) (ScanChannels >> 24);
+			//memcpy(p, ExtendedPanId, sizeof(ExtendedPanId)); p += sizeof(ExtendedPanId);
+			memcpy(p, (this->currentSAS)->extendedPANId,
+					sizeof((this->currentSAS)->extendedPANId));
+			p += sizeof((this->currentSAS)->extendedPANId);
+
+			*p++ = 2; // Protocol Version
+			*p++ = 1; // Stack Profile
+			*p++ = 5; // Scan Duration
+			*p++ = 0; // Security Level
+
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("Setting the Mode Descriptor" );
+#endif
+
+			APSME_SET_request(ZIB_CONFIG_NWK_MODE_AND_PARAMS, p - buff, buff);
+		}
+			break;
+
+		case ZIB_CONFIG_NWK_MODE_AND_PARAMS: //	ZIB_CONFIG_NWK_MODE_AND_PARAMS =
+		{
+			unsigned char simple_descr[14];
+			//ushort profile_id = 0x0104;
+			ushort profile_id = 0x0F04;
+			ushort device_id = 0x0001;
+
+			//		configures EP #1
+			simple_descr[0] = 10; // gives 1 for endpoint
+
+			simple_descr[1] = LSB_USHORT(profile_id);
+			simple_descr[2] = MSB_USHORT(profile_id);
+
+			simple_descr[3] = LSB_USHORT(device_id);
+			simple_descr[4] = MSB_USHORT(device_id);
+
+			simple_descr[5] = 0; // version flags
+
+			simple_descr[6] = 1; // switch input cluster count
+			simple_descr[7] = LSB_USHORT(2); // cluster 1 is input
+			simple_descr[8] = MSB_USHORT(2);
+
+			simple_descr[9] = 2; // switch output cluster count
+			simple_descr[10] = LSB_USHORT(3); // cluster 0 is output
+			simple_descr[11] = MSB_USHORT(3);
+			simple_descr[12] = LSB_USHORT(4); // cluster 1 is output
+			simple_descr[13] = MSB_USHORT(4);
+
+			APSME_SET_request(ZIB_CONFIG_SIMPLE_DESCRIPTOR, 14, simple_descr);
+			simple_desc_count++;
+
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("Setting the Simple Descriptor");
+#endif
+		}
+			break;
+
+		case ZIB_CONFIG_SIMPLE_DESCRIPTOR: //	ZIB_CONFIG_SIMPLE_DESCRIPTOR =
+		{
+			simple_desc_count--;
+			if (simple_desc_count == 0) {
+				if ((this->currentSAS)->deviceType == ZB_COORDINATOR) {
+#ifdef DEBUG_ACTIVE_GALZB
+					pLogger->debug("Starting the Network");
+#endif
+				} else {
+#ifdef DEBUG_ACTIVE_GALZB
+					pLogger->debug("Joining a Network");
+#endif
+				}
+				// Increase the counter of ZDO Start attempts
+				this->zdoStartAttempts++;
+
+				ZDO_START_request();
+			}
+		}
+			break;
+
+		default: {
+			pLogger->warn("Unknown Attribute");
+		}
+		}
+	}
+		break;
+
+	case 1: // ----- zsdio/EZSP/freescale/microSD --------------------
+	{
+		switch (attr) {
+
+		case ZB_ATTR_CONFIG_NODE_DESCRIPTOR: // ZB_ATTR_CONFIG_NODE_DESCRIPTOR =
+		{
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_SET_confirm: ZB_ATTR_CONFIG_NODE_DESCRIPTOR");
+#endif
+			ushort panid = 0xFFFF;
+			panid = htozs((this->currentSAS)->PANId);
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_SET_confirm - Setting PanId %04x",panid);
+#endif
+			APSME_SET_request(ZB_ATTR_CONFIG_PANID, sizeof(panid),
+					(uchar *) &panid);
+		}
+			break;
+
+		case ZB_ATTR_CONFIG_PANID: //	ZB_ATTR_CONFIG_PANID =
+		{
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_SET_confirm: ZB_ATTR_CONFIG_PANID" );
+#endif
+			if (this->isFirstStart) {
+				std::list<int> endPoints;
+				std::list<int>::iterator iter;
+				// Set the SimpleDescriptor
+#ifdef DEBUG_ACTIVE_GALZB
+				pLogger->debug("APSME_SET_confirm: Setting a Simple Descriptor");
+#endif
+				if (setSimpleDescriptor() == -1) {
+					pLogger->fatal("APSME_SET_confirm: ERROR - At least one SimpleDescriptor shall be present!" );
+				}
+			} else {
+
+#ifdef DEBUG_ACTIVE_GALZB
+				pLogger->debug("GAlZbIf - sai.extendedPANId = [%02x %02x %02x %02x %02x %02x %02x %02x]",(this->currentSAS)->extendedPANId[0],
+						(this->currentSAS)->extendedPANId[1],(this->currentSAS)->extendedPANId[2],
+						(this->currentSAS)->extendedPANId[3], (this->currentSAS)->extendedPANId[4],
+						(this->currentSAS)->extendedPANId[5], (this->currentSAS)->extendedPANId[6],
+						(this->currentSAS)->extendedPANId[7]);
+#endif
+				APSME_SET_request(ZB_ATTR_CONFIG_EXTENDEDPANID, 8,
+						(this->currentSAS)->extendedPANId);
+
+			}
+		}
+			break;
+
+		case ZB_ATTR_CONFIG_SIMPLE_DESCRIPTOR: {
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_SET_confirm: ZB_ATTR_CONFIG_SIMPLE_DESCRIPTOR");
+#endif
+			// Set the SimpleDescriptor
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_SET_confirm - Set additional Simple Descriptors");
+#endif
+			if (setSimpleDescriptor() == -1) {
+#ifdef DEBUG_ACTIVE_GALZB
+				pLogger->debug("APSME_SET_confirm: DONE, set the ExtendedPanId");
+#endif
+				//Enter here only when all the SimpleDescriptor are set!
+#ifdef DEBUG_ACTIVE_GALZB
+				pLogger->debug("GAlZbIf - sai.extendedPANId = [%02x %02x %02x %02x %02x %02x %02x %02x]",(this->currentSAS)->extendedPANId[0],
+						(this->currentSAS)->extendedPANId[1],(this->currentSAS)->extendedPANId[2],
+						(this->currentSAS)->extendedPANId[3], (this->currentSAS)->extendedPANId[4],
+						(this->currentSAS)->extendedPANId[5], (this->currentSAS)->extendedPANId[6],
+						(this->currentSAS)->extendedPANId[7]);
+#endif
+				APSME_SET_request(ZB_ATTR_CONFIG_EXTENDEDPANID, 8,
+						(this->currentSAS)->extendedPANId);
+			}
+		}
+			break;
+
+		case ZB_ATTR_CONFIG_EXTENDEDPANID: //	ZB_ATTR_CONFIG_EXTENDEDPANID =
+		{
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_SET_confirm: ZB_ATTR_CONFIG_EXTENDEDPANID" );
+#endif
+			this->startupControl = (this->currentSAS)->StartupControl;
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_SET_confirm - startupControl = %x",this->startupControl);
+#endif
+			APSME_SET_request(ZB_ATTR_CONFIG_STARTUPCONTROL, 1,
+					(uchar *) &startupControl);
+		}
+			break;
+
+		case ZB_ATTR_CONFIG_STARTUPCONTROL: {
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_SET_confirm: ZB_ATTR_CONFIG_STARTUPCONTROL");
+#endif
+			if (this->isFirstStart) {
+				APSME_SET_request(ZB_ATTR_CONFIG_FRAGMENT_WINDOW_SIZE, 2,
+						(uchar *) &apscMaxWindowSize);
+			} else {
+				if (this->securityLevel == 5) {
+					uchar policy_value = 0x51;
+					policy_value = htozl(policy_value);
+					APSME_SET_request(ZB_TC_KEY_REQUEST_POLICY, 1,
+							&policy_value);
+				} else {
+					unsigned long channel_mask = (this->currentSAS)->channelMask;
+
+#ifdef DEBUG_ACTIVE_GALZB
+					pLogger->debug("Channel mask is %08x", (int) channel_mask);
+#endif
+					channel_mask = htozl(channel_mask);
+					APSME_SET_request(ZB_ATTR_CONFIG_CHANNEL_MASK,
+							sizeof(channel_mask), (uchar *) &channel_mask);
+				}
+			}
+		}
+			break;
+
+		case ZB_ATTR_CONFIG_FRAGMENT_WINDOW_SIZE: //	ZB_ATTR_CONFIG_FRAGMENT_WINDOW_SIZE =
+		{
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_SET_confirm: ZB_ATTR_CONFIG_FRAGMENT_WINDOW_SIZE" );
+#endif
+			APSME_SET_request(ZB_ATTR_CONFIG_FRAGMENT_DELAY_MS, 2,
+					(uchar *) &apsInterframeDelay);
+		}
+			break;
+
+		case ZB_ATTR_CONFIG_FRAGMENT_DELAY_MS: //	ZB_ATTR_CONFIG_FRAGMENT_DELAY_MS =
+		{
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_SET_confirm: ZB_ATTR_CONFIG_FRAGMENT_DELAY_MS");
+#endif
+			int sec = this->securityLevel;
+			sec = htozl(sec);
+			APSME_SET_request(ZB_ATTR_CONFIG_SECURITY, 1, (uchar *) &sec);
+		}
+			break;
+
+		case ZB_ATTR_CONFIG_SECURITY: //	ZB_ATTR_CONFIG_SECURITY =
+		case ZB_ATTR_CONFIG_SECURITY_LEVEL: //	ZB_ATTR_CONFIG_SECURITY_LEVEL =
+		{
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_SET_confirm: ZB_ATTR_CONFIG_SECURITY or ZB_ATTR_CONFIG_SECURITY_LEVEL");
+#endif
+
+			if (this->securityLevel == 5) {
+				uchar policy_value = 0x51;
+				policy_value = htozl(policy_value);
+				APSME_SET_request(ZB_TC_KEY_REQUEST_POLICY, 1, &policy_value);
+			} else {
+				unsigned long channel_mask = (this->currentSAS)->channelMask;
+#ifdef DEBUG_ACTIVE_GALZB
+				pLogger->debug("Channel mask is %08x", (int) channel_mask);
+#endif
+				channel_mask = htozl(channel_mask);
+				APSME_SET_request(ZB_ATTR_CONFIG_CHANNEL_MASK,
+						sizeof(channel_mask), (uchar *) &channel_mask);
+			}
+		}
+			break;
+
+		case ZB_TC_KEY_REQUEST_POLICY: //	ZB_TC_KEY_REQUEST_POLICY =
+		{
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_SET_confirm: ZB_TC_KEY_REQUEST_POLICY");
+#endif
+			int policy_value1 = 0x61;
+			policy_value1 = htozl(policy_value1);
+			APSME_SET_request(ZB_APP_KEY_REQUEST_POLICY, 1,
+					(uchar *) &policy_value1);
+		}
+			break;
+
+		case ZB_APP_KEY_REQUEST_POLICY: //	ZB_APP_KEY_REQUEST_POLICY =
+		{
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_SET_confirm: ZB_APP_KEY_REQUEST_POLICY");
+#endif
+			int policy_value2 = 0x01;
+			policy_value2 = htozl(policy_value2);
+			APSME_SET_request(0x00, 1, (uchar *) &policy_value2); //0x00=EZSP_TRUST_CENTER_POLICY
+		}
+			break;
+
+		case 0x00: //	EZSP_TRUST_CENTER_POLICY
+		{
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_SET_confirm: EZSP_TRUST_CENTER_POLICY");
+#endif
+
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_SET_confirm - preconfiguredLinkKey = [%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x]",
+					(this->currentSAS)->preconfiguredLinkKey[0],(this->currentSAS)->preconfiguredLinkKey[1],(this->currentSAS)->preconfiguredLinkKey[2],(this->currentSAS)->preconfiguredLinkKey[3],
+					(this->currentSAS)->preconfiguredLinkKey[4],(this->currentSAS)->preconfiguredLinkKey[5],(this->currentSAS)->preconfiguredLinkKey[6],(this->currentSAS)->preconfiguredLinkKey[7],
+					(this->currentSAS)->preconfiguredLinkKey[8],(this->currentSAS)->preconfiguredLinkKey[9],(this->currentSAS)->preconfiguredLinkKey[10],(this->currentSAS)->preconfiguredLinkKey[11],
+					(this->currentSAS)->preconfiguredLinkKey[12],(this->currentSAS)->preconfiguredLinkKey[13],(this->currentSAS)->preconfiguredLinkKey[14],(this->currentSAS)->preconfiguredLinkKey[15]);
+#endif
+			APSME_SET_request(ZB_ATTR_PRECONF_TC_LINK_KEY, 16,
+					(this->currentSAS)->preconfiguredLinkKey);
+		}
+			break;
+
+		case ZB_ATTR_PRECONF_TC_LINK_KEY: {
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_SET_confirm: ZB_ATTR_PRECONF_TC_LINK_KEY");
+#endif
+
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_SET_confirm - sai.networkKey = [%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x]",
+					(this->currentSAS)->networkKey[0],(this->currentSAS)->networkKey[1],(this->currentSAS)->networkKey[2],(this->currentSAS)->networkKey[3],
+					(this->currentSAS)->networkKey[4],(this->currentSAS)->networkKey[5],(this->currentSAS)->networkKey[6],(this->currentSAS)->networkKey[7],
+					(this->currentSAS)->networkKey[8],(this->currentSAS)->networkKey[9],(this->currentSAS)->networkKey[10],(this->currentSAS)->networkKey[11],
+					(this->currentSAS)->networkKey[12],(this->currentSAS)->networkKey[13],(this->currentSAS)->networkKey[14],(this->currentSAS)->networkKey[15]);
+#endif
+			APSME_SET_request(ZB_ATTR_NWK_KEY, 16,
+					(this->currentSAS)->networkKey);
+		}
+			break;
+
+		case ZB_ATTR_NWK_KEY: {
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_SET_confirm: ZB_ATTR_NWK_KEY");
+#endif
+			if (db.getTCKeyTableSize() > 0) {
+				maxTCKeyTableSize = db.getTCKeyTableSize();
+				if (this->isFirstStart) {
+					ushort value = maxTCKeyTableSize;
+#ifdef DEBUG_ACTIVE_GALZB
+					pLogger->debug("APSME_SET_confirm - Key Table size  = %d",value );
+#endif
+					APSME_SET_request(ZB_ATTR_KEY_TABLE_SIZE, 2,
+							(uchar *) &value);
+				} else {
+					if (this->initTCKeyTable() == -1) {
+						pLogger->fatal("APSME_SET_confirm: ERROR in initTCKeyTable!" );
+					}
+				}
+			} else {
+				unsigned long channel_mask = (this->currentSAS)->channelMask;
+#ifdef DEBUG_ACTIVE_GALZB
+				pLogger->debug("Channel mask is %08x", (int) channel_mask);
+#endif
+				channel_mask = htozl(channel_mask);
+				APSME_SET_request(ZB_ATTR_CONFIG_CHANNEL_MASK,
+						sizeof(channel_mask), (uchar *) &channel_mask);
+			}
+		}
+			break;
+
+		case ZB_ATTR_KEY_TABLE_SIZE: {
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_SET_confirm: ZB_ATTR_KEY_TABLE_SIZE");
+#endif
+			if (this->initTCKeyTable() == -1) {
+				pLogger->fatal("APSME_SET_confirm: ERROR in initTCKeyTable!" );
+			}
+		}
+			break;
+
+		case ZB_ATTR_KEY_TABLE_ENTRY: {
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_SET_confirm: ZB_ATTR_KEY_TABLE_ENTRY");
+#endif
+			if (this->initTCKeyTable() == -1) {
+				//initTCKeyTable operation completed!
+#ifdef DEBUG_ACTIVE_GALZB
+				pLogger->debug("APSME_SET_confirm: TCLinkKeyTable initialized!");
+#endif
+				unsigned long channel_mask = (this->currentSAS)->channelMask;
+#ifdef DEBUG_ACTIVE_GALZB
+				pLogger->debug("Ready to send channel mask is %08x", (int) channel_mask);
+#endif
+				channel_mask = htozl(channel_mask);
+				APSME_SET_request(ZB_ATTR_CONFIG_CHANNEL_MASK,
+						sizeof(channel_mask), (uchar *) &channel_mask);
+			}
+		}
+			break;
+
+		case ZB_ATTR_CONFIG_CHANNEL_MASK: {
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("APSME_SET_confirm: ZB_ATTR_CONFIG_CHANNEL_MASK");
+#endif
+			// Increase the counter of ZDO Start attempts
+			this->zdoStartAttempts++;
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("Start a ZigBee Network");
+#endif
+			// Call the start network procedure
+			ZDO_START_request();
+		}
+			break;
+
+		default: {
+			pLogger->warn("Unknown Attribute");
+		}
+		}
+	}
+		break;
+
+	default: {
+		pLogger->warn("Unknown platform!");
+	}
+		break;
+	}
+
+	return;
+}
+
+/**
+ Protected method GalZbIf ZDO_START_confirm
+
+
+
+ @param status Status value.
+ @param nwk_addr Node network address.
+ @return Void.
+ */
+
+void GalZbIf::ZDO_START_confirm(uchar status, ushort nwk_addr) {
+
+	// Set isFirstStart to FALSE in case we are running a EZSP stack since we will skip some parts in case of future restarts
+	if (isEZSPstackRunning)
+		this->isFirstStart = FALSE;
+
+	if (status != ZB_ZDO_SUCCESS) {
+
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->error("ZDO_START_confirm - Start Failed 0x%02x", status);
+#endif
+
+		// Restart operation should be considered only for a limited amount of times
+		if (this->zdoStartAttempts > MAX_ZDO_START_REQUEST_ATTEMPTS) {
+			// Send a reset to stop the dongle!
+			ZDO_RESET_request(0x04); //0x04 execute the reset at the low level!
+			// Report the error!
+			if ((this->currentSAS)->deviceType == ZB_COORDINATOR) {
+#ifdef DEBUG_ACTIVE_GALZB
+				pLogger->debug("ZDO_START_confirm - Start Failed (attempts %02x)! - deviceType was COORDINATOR ",this->zdoStartAttempts);
+#endif
+				this->setGWStatus(GW_ERROR, 11, status);
+			} else {
+#ifdef DEBUG_ACTIVE_GALZB
+				pLogger->debug("ZDO_START_confirm - Start Failed (attempts %02x)! - deviceType was ROUTER or END_DEVICE ",this->zdoStartAttempts);
+#endif
+				this->setGWStatus(GW_ERROR, 10, status);
+			}
+			// Reset the counter of ZDO Start attempts
+			this->zdoStartAttempts = 0;
+		} else {
+			// Increase the counter of ZDO Start attempts
+			this->zdoStartAttempts++;
+			// restart the dongle
+			ZDO_START_request();
+		}
+	} else {
+		ZbNetDb *pGalDb = getDb();
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("ZDO_START_confirm - Status=0x%02x, nwk_addr=0x%04X", status, nwk_addr);
+#endif
+		// Create a new root node and assign it!
+		Node * root = new Node(nwk_addr);
+		if (pGalDb->setRoot(root) == -1) {
+			uchar tmpIEEEAddr[8];
+			memcpy(tmpIEEEAddr, pGalDb->root->get_ieee_addr(), 8);
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("ZDO_START_confirm - Root node (0x%04x,%02x:%02x:%02x:%02x:%02x:%02x:%02x) already present,fine!",pGalDb->root->get_nwk_addr(),tmpIEEEAddr[0],tmpIEEEAddr[1],tmpIEEEAddr[2],tmpIEEEAddr[3],tmpIEEEAddr[4],tmpIEEEAddr[5],tmpIEEEAddr[6],tmpIEEEAddr[7]);
+#endif
+			//exit(0);
+		}
+		// Reset the counter of ZDO Start attempts
+		this->zdoStartAttempts = 0;
+		// Ask for the GAL's Channel mask
+		APSME_GET_request (ZB_ATTR_GET_CHANNEL_MASK);
+	}
+	return;
+}
+
+/**
+ Protected method GalZbIf NLME_SYNC_confirm
+
+ @param status Status value.
+ @return Void.
+ */
+
+void GalZbIf::NLME_SYNC_confirm(uchar status) {
+	if (status != ZB_ZDO_SUCCESS) {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->warn("Sync failed");
+#endif
+
+	}
+	return;
+}
+
+/**
+ Protected method GalZbIf NLME_SYNC_indication
+
+ @param void Void.
+ @return Void.
+ */
+
+void GalZbIf::NLME_SYNC_indication(void) {
+	pLogger->debug("CZbIf::NLME_SYNC_indication");
+}
+
+/**
+ Protected method GalZbIf ZDO_IEEE_ADDR_confirm
+
+ @param status Success or Error status related to the request.
+ @param ieee_addr IEEE address of the device of interest.
+ @param nwk_addr Short address of the device of interest.
+ @param num_assoc_dev Number of associated devices to the remote device of interest.
+ @param start_index Starting index into the list of associated devices.
+ @param nwk_addr_assoc_dev_list The list of short addresses related to the associated devices.
+ @return Void.
+ */
+
+void GalZbIf::ZDO_IEEE_ADDR_confirm(uchar status, uchar *ieee_addr,
+		ushort nwk_addr, uchar num_assoc_dev, uchar start_index,
+		ushort *nwk_addr_assoc_dev_list) {
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("GalZbIf::ZDO_IEEE_ADDR_confirm");
+#endif
+
+	// Update the timeout information related to the source address
+	uchar src_addr_mode = 0x03; //This is a IEEEAddress
+	manageNodeTimeouts(src_addr_mode, ieee_addr);
+
+	if (!listeners[ZB_ZDO_IEEE_ADDR_CONFIRM].empty()) {
+		std::map<int, std::list<void*> >::const_iterator currEventListeners;
+		std::list<void*> tempList;
+		std::list<void*>::iterator iter;
+
+		currEventListeners = listeners.find(ZB_ZDO_IEEE_ADDR_CONFIRM);
+		tempList = currEventListeners->second;
+
+		for (iter = tempList.begin(); iter != tempList.end(); iter++) {
+			((ZDO_IEEE_ADDR_confirm_Listener) (*iter))(status, ieee_addr,
+					nwk_addr, num_assoc_dev, start_index,
+					nwk_addr_assoc_dev_list);
+		}
+
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("Map Listeners empty");
+#endif
+	}
+	return;
+}
+
+void GalZbIf::ZB_MGMT_LQI_response(uchar srcAddrMode, uchar* src_addr,
+		uchar * asdu) {
+
+	uchar status;
+	uchar NeighborTableEntries;
+	uchar StartIndex;
+	uchar NeighborTableListCount;
+	ZB_NEIGHBOR_TABLE_LIST *NeighborTableList;
+
+	int c = 0;
+
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("ZB_MGMT_LQI_response from 0x%02x%02x",src_addr[1],src_addr[0]);
+#endif
+	// Update the timer as first thing!
+	manageNodeTimeouts(srcAddrMode, src_addr);
+	// Send the message to the respective callbacks
+	if (!listeners[ZB_MGMT_LQI_RESPONSE].empty()) {
+		std::map<int, std::list<void*> >::const_iterator currEventListeners;
+		std::list<void*> tempList;
+		std::list<void*>::iterator iter;
+
+		currEventListeners = listeners.find(ZB_MGMT_LQI_RESPONSE);
+		tempList = currEventListeners->second;
+
+		// Set all the values...
+		//tsNum = asdu[0]; //not used...
+		c = 1;
+		status = asdu[c++];
+		NeighborTableEntries = asdu[c++];
+		StartIndex = asdu[c++];
+		NeighborTableListCount = asdu[c++];
+		if (NeighborTableListCount == 0)
+			NeighborTableList = NULL;
+		else {
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("ZB_MGMT_LQI_response - NeighborTableListCount %x",NeighborTableListCount);
+#endif
+			NeighborTableList = (ZB_NEIGHBOR_TABLE_LIST *) malloc(
+					NeighborTableListCount * sizeof(ZB_NEIGHBOR_TABLE_LIST));
+
+			int i = 0;
+			for (i = 0; i < NeighborTableListCount; i++) {
+				memcpy(NeighborTableList[i].ExtendedPANId, asdu + c,
+						IEEE_ADDR_LEN);
+				swap_bytes(NeighborTableList[i].ExtendedPANId, IEEE_ADDR_LEN);
+				memcpy(NeighborTableList[i].ExtendedAddress,
+						asdu + c + IEEE_ADDR_LEN, IEEE_ADDR_LEN);
+				swap_bytes(NeighborTableList[i].ExtendedAddress, IEEE_ADDR_LEN);
+				c += IEEE_ADDR_LEN * 2;
+				NeighborTableList[i].NetworkAddress = asdu[c]
+						+ (asdu[c + 1] << 8);
+				c += 2;
+#ifdef DEBUG_ACTIVE_GALZB
+				pLogger->debug("ZB_MGMT_LQI_response - nkwAddr %04x",NeighborTableList[i].NetworkAddress);
+#endif
+				NeighborTableList[i].devTypeRxOnRelation = asdu[c++]; //correct: it takes all together "DevType, RxOnWhenIdle and RelationShip"!)
+				NeighborTableList[i].PermitJoining = asdu[c++];
+				NeighborTableList[i].Depth = asdu[c++];
+				NeighborTableList[i].LQI = asdu[c++];
+
+#ifdef DEBUG_ACTIVE_GALZB
+				pLogger->debug("ZB_MGMT_LQI_response - ieee_addr = %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
+						(int)(NeighborTableList[i].ExtendedAddress[0]), (int)(NeighborTableList[i].ExtendedAddress[1]), (int)(NeighborTableList[i].ExtendedAddress[2]),
+						(int)(NeighborTableList[i].ExtendedAddress[3]), (int)(NeighborTableList[i].ExtendedAddress[4]), (int)(NeighborTableList[i].ExtendedAddress[5]),
+						(int)(NeighborTableList[i].ExtendedAddress[6]), (int)(NeighborTableList[i].ExtendedAddress[7]) );
+#endif
+			}
+		}
+		// Call the listeners...
+		for (iter = tempList.begin(); iter != tempList.end(); iter++) {
+			((ZB_MGMT_LQI_RESPONSE_Listener) (*iter))(srcAddrMode, src_addr,
+					status, NeighborTableEntries, StartIndex,
+					NeighborTableListCount, NeighborTableList);
+		}
+		free(NeighborTableList);
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("Map Listeners empty for ZB_MGMT_LQI_response");
+#endif
+	}
+	return;
+}
+/**
+ Protected method GalZbIf ZDO_NWK_ADDR_confirm
+
+ @param status Success or Error status related to the request.
+ @param ieee_addr IEEE address of the device of interest.
+ @param nwk_addr Short address of the device of interest.
+ @param num_assoc_dev Number of associated devices to the remote device of interest.
+ @param start_index Starting index into the list of associated devices.
+ @param nwk_addr_assoc_dev_list The list of short addresses related to the associated devices.
+ @return Void.
+ */
+
+void GalZbIf::ZDO_NWK_ADDR_confirm(uchar status, uchar *ieee_addr,
+		ushort nwk_addr, uchar num_assoc_dev, uchar start_index,
+		ushort *nwk_addr_assoc_dev_list) {
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("GalZbIf::ZDO_NWK_ADDR_confirm");
+#endif
+
+	if (!listeners[ZB_ZDO_NWK_ADDR_CONFIRM].empty()) {
+		/*
+		 #ifdef DEBUG_ACTIVE_GALZB
+		 pLogger->debug("Map Listeners not empty");
+		 #endif
+		 */
+		std::map<int, std::list<void*> >::const_iterator currEventListeners;
+		std::list<void*> tempList;
+		std::list<void*>::iterator iter;
+
+		currEventListeners = listeners.find(ZB_ZDO_NWK_ADDR_CONFIRM);
+		tempList = currEventListeners->second;
+
+		for (iter = tempList.begin(); iter != tempList.end(); iter++) {
+			((ZDO_NWK_ADDR_confirm_Listener) (*iter))(status, ieee_addr,
+					nwk_addr, num_assoc_dev, start_index,
+					nwk_addr_assoc_dev_list);
+		}
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("Map Listeners empty");
+#endif
+	}
+
+	return;
+}
+
+/**
+ Protected method GalZbIf ZDO_NODE_DESC_confirm
+
+ @param status Success or Error status related to the request.
+ @param nwk_addr Short address of the device of interest.
+ @param node_descr  Pointer to the returned node descriptor data structure.
+ @return Void.
+ */
+
+void GalZbIf::ZDO_NODE_DESC_confirm(uchar status, ushort nwk_addr,
+		ZB_NODE_DESC *node_descr) {
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("GalZbIf::ZDO_NODE_DESC_confirm");
+#endif
+
+	if (!listeners[ZB_ZDO_NODE_DESC_CONFIRM].empty()) {
+		/*
+		 #ifdef DEBUG_ACTIVE_GALZB
+		 pLogger->debug("Map Listeners not empty");
+		 #endif
+		 */
+		std::map<int, std::list<void*> >::const_iterator currEventListeners;
+		std::list<void*> tempList;
+		std::list<void*>::iterator iter;
+
+		currEventListeners = listeners.find(ZB_ZDO_NODE_DESC_CONFIRM);
+		tempList = currEventListeners->second;
+
+		for (iter = tempList.begin(); iter != tempList.end(); iter++) {
+			((ZDO_NODE_DESC_confirm_Listener) (*iter))(status, nwk_addr,
+					node_descr);
+		}
+
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("Map Listeners empty");
+#endif
+	}
+
+#define GET_BIT(a, bit_no) (((a) >> (bit_no)) & 0x01)
+
+	return;
+}
+
+/**
+ Protected method GalZbIf ZDO_POWER_DESC_confirm
+
+ @param status Success or Error status related to the request.
+ @param nwk_addr Short address of the device of interest.
+ @param power_descr  Pointer to the returned power descriptor data structure.
+ @return Void.
+ */
+
+void GalZbIf::ZDO_POWER_DESC_confirm(uchar status, ushort nwk_addr,
+		ZB_POWER_DESC *power_descr) {
+
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("GalZbIf::ZDO_POWER_DESC_confirm");
+#endif
+
+	if (!listeners[ZB_ZDO_POWER_DESC_CONFIRM].empty()) {
+		/*
+		 #ifdef DEBUG_ACTIVE_GALZB
+		 pLogger->debug("Map Listeners not empty");
+		 #endif
+		 */
+		std::map<int, std::list<void*> >::const_iterator currEventListeners;
+		std::list<void*> tempList;
+		std::list<void*>::iterator iter;
+
+		currEventListeners = listeners.find(ZB_ZDO_POWER_DESC_CONFIRM);
+		tempList = currEventListeners->second;
+
+		for (iter = tempList.begin(); iter != tempList.end(); iter++) {
+			((ZDO_POWER_DESC_confirm_Listener) (*iter))(status, nwk_addr,
+					power_descr);
+		}
+
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("Map Listeners empty");
+#endif
+	}
+	return;
+}
+
+/**
+ Protected method GalZbIf ZDO_SIMPLE_DESC_confirm
+
+ @param status Success or Error status related to the request.
+ @param nwk_addr Short address of the device of interest.
+ @param simple_desc Pointer to the returned service descriptor data structure.
+ @return Void.
+ */
+
+void GalZbIf::ZDO_SIMPLE_DESC_confirm(uchar status, ushort nwk_addr,
+		ZB_SIMPLE_DESC *simple_desc) {
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("GalZbIf::ZDO_SIMPLE_DESC_confirm");
+#endif
+
+	if (!listeners[ZB_ZDO_SIMPLE_DESC_CONFIRM].empty()) {
+		/*
+		 #ifdef DEBUG_ACTIVE_GALZB
+		 pLogger->debug("Map Listeners not empty");
+		 #endif
+		 */
+		std::map<int, std::list<void*> >::const_iterator currEventListeners;
+		std::list<void*> tempList;
+		std::list<void*>::iterator iter;
+
+		currEventListeners = listeners.find(ZB_ZDO_SIMPLE_DESC_CONFIRM);
+		tempList = currEventListeners->second;
+
+		for (iter = tempList.begin(); iter != tempList.end(); iter++) {
+			((ZDO_SIMPLE_DESC_confirm_Listener) (*iter))(status, nwk_addr,
+					simple_desc);
+		}
+
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("Map Listeners empty");
+#endif
+	}
+}
+
+/**
+ Protected method GalZbIf ZDO_ACTIVE_EP_DESC_confirm
+
+ @param status Success or Error status related to the request.
+ @param nwk_addr Short address of the device of interest.
+ @param active_ep_count Number of active endpoints available on the device identified by nwk_addr.
+ @param active_ep_list Pointer to the endpoint list.
+ @return Void.
+ */
+
+void GalZbIf::ZDO_ACTIVE_EP_DESC_confirm(uchar status, ushort nwk_addr,
+		uchar active_ep_count, uchar *active_ep_list) {
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("GalZbIf::ZDO_ACTIVE_EP_DESC_confirm");
+#endif
+	if (!listeners[ZB_ZDO_ACTIVE_EP_DESC_CONFIRM].empty()) {
+		std::map<int, std::list<void*> >::const_iterator currEventListeners;
+		std::list<void*> tempList;
+		std::list<void*>::iterator iter;
+
+		currEventListeners = listeners.find(ZB_ZDO_ACTIVE_EP_DESC_CONFIRM);
+		tempList = currEventListeners->second;
+
+		for (iter = tempList.begin(); iter != tempList.end(); iter++) {
+			((ZDO_ACTIVE_EP_DESC_confirm_Listener) (*iter))(status, nwk_addr,
+					active_ep_count, active_ep_list);
+		}
+
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("Map Listeners empty");
+#endif
+	}
+
+	return;
+}
+
+/**
+ Protected method GalZbIf ZDO_DEVICE_ANNCE_indication
+
+ @param nwk_addr
+ @param ieee_addr
+ @param capability
+ @return Void.
+ */
+
+void GalZbIf::ZDO_DEVICE_ANNCE_indication(ushort nwk_addr, uchar *ieee_addr,
+		uchar capability) {
+	ZbNetDb *pGalDb;
+
+	if (this->gwStatus != GW_RUNNING)
+		// Ignore any incoming messages until the GAL is up!
+		return;
+
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("***** ZDO_DEVICE_ANNCE_indication - ShortAddress: %04x ******",nwk_addr);
+#endif
+
+	if (!listeners[ZB_ZDO_DEVICE_ANNCE_INDICATION].empty()) {
+		std::map<int, std::list<void*> >::const_iterator currEventListeners;
+		std::list<void*> tempList;
+		std::list<void*>::iterator iter;
+
+		currEventListeners = listeners.find(ZB_ZDO_DEVICE_ANNCE_INDICATION);
+		tempList = currEventListeners->second;
+
+		for (iter = tempList.begin(); iter != tempList.end(); iter++) {
+			((ZB_ZDO_DEVICE_ANNCE_indication_Listener) (*iter))(nwk_addr,
+					ieee_addr, capability);
+		}
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("Map Listeners empty");
+#endif
+		// Whatever a listener is present or not, a new node shall be created!
+		pGalDb = getDb();
+		pGalDb->nodeAnnounce(nwk_addr, ieee_addr, capability);
+	}
+}
+
+void GalZbIf::ZIGBEE_STACK_STATUS_indication(uchar status) {
+
+	switch (status) {
+	case 0x90:
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("ZIGBEE_STACK_STATUS_indication - EVENT - EMBER_NETWORK_UP");
+#endif
+		break;
+	case 0x91:
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("ZIGBEE_STACK_STATUS_indication - EVENT - EMBER_NETWORK_DOWN");
+#endif
+		break;
+	case 0x94:
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("ZIGBEE_STACK_STATUS_indication - EVENT - EMBER_JOIN_FAILED");
+#endif
+		break;
+	case 0x98:
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("ZIGBEE_STACK_STATUS_indication - EVENT - EMBER_CANNOT_JOIN_AS_ROUTER");
+#endif
+		break;
+	case 0x9A:
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("ZIGBEE_STACK_STATUS_indication - EVENT - EMBER_PAN_ID_CHANGED");
+#endif
+		break;
+
+	default:
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("ZIGBEE_STACK_STATUS_indication - EVENT - status %x", status);
+#endif
+		break;
+	}
+	if (status == 0x91) //EMBER_NETWORK_DOWN
+			{
+		this->setGWStatus(GW_ERROR, 500);
+	}
+}
+
+/**
+ Protected method GalZbIf APSDE_DATA_confirm
+
+ @param dst_addr_mode Destination address mode.
+ @param dst_addr Message destination address.
+ @param dst_ep Message destination endpoint.
+ @param src_ep Message source endpoint.
+ @param status Status.
+ @return Void.
+ */
+
+void GalZbIf::APSDE_DATA_confirm(uchar dst_addr_mode, uchar *dst_addr,
+		uchar dst_ep, uchar src_ep, uchar status) {
+	if (status != ZB_ZDO_SUCCESS) {
+		/* TODO: what to do here? */
+	}
+	return;
+}
+
+void GalZbIf::APSDE_DATA_indication_Dummy(uchar dst_addr_mode, uchar *dst_addr,
+		uchar dst_ep, uchar src_addr_mode, uchar *src_addr, uchar src_ep,
+		ushort profile_id, ushort cluster_id, ushort asdu_len, uchar *asdu,
+		uchar was_broadcast, uchar sec_status) {
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("GalZbIf::APSDE_DATA_indication_Dummy");
+#endif
+
+	this->APSDE_DATA_indication(dst_addr_mode, dst_addr, dst_ep, src_addr_mode,
+			src_addr, src_ep, profile_id, cluster_id, asdu_len, asdu,
+			was_broadcast, sec_status);
+
+}
+
+void GalZbIf::manageNodeTimeouts(uchar src_addr_mode, uchar *src_addr) {
+	Node * srcNode;
+	struct timeval tv;
+	time_t curtime;
+	ZbNetDb *pGalDb;
+	ushort shortAddr;
+	/*
+	 #ifdef DEBUG_ACTIVE_GALZB
+	 pLogger->debug("manageNodeTimeouts");
+	 #endif
+	 */
+	pGalDb = getDb();
+	// Update the timeout information related to the source address
+	if (src_addr_mode == 0x02) {
+		shortAddr = (src_addr[1] << 8) + src_addr[0];
+		srcNode = pGalDb->findNodeByNwkAddr(shortAddr);
+	} else if (src_addr_mode == 0x03) {
+		srcNode = pGalDb->findNodeByIEEEAddr(src_addr);
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("manageNodeTimeouts - src_addr_mode not valid - operation aborted");
+#endif
+		return;
+	}
+	if (srcNode == NULL) {
+		//Node not present yet into ZbNetDb (it will be inserted later on by another procedure)
+		if (src_addr_mode == 0x02) {
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("manageNodeTimeouts - node 0x%04x not inserted yet, nothing to do then!",(src_addr[1] << 8) + src_addr[0]);
+#endif
+		} else {
+#ifdef DEBUG_ACTIVE_GALZB
+			pLogger->debug("manageNodeTimeouts - node 0x%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x not inserted yet, nothing to do then!",src_addr[0], src_addr[1],
+					src_addr[2],src_addr[3],src_addr[4],src_addr[5],src_addr[6],src_addr[7]);
+#endif
+		}
+		return;
+	}
+	gettimeofday(&tv, NULL);
+	curtime = tv.tv_sec; //get the seconds
+	srcNode->setKANodeTimer((long) curtime);
+#ifdef DEBUG_ACTIVE_GALZB
+	if (this->debugEnabled)
+	pLogger->debug("manageNodeTimeouts - timer updated for node 0x%04x!",srcNode->get_nwk_addr());
+#endif
+}
+
+/**
+ Protected method GalZbIf APSDE_DATA_indication
+
+ @param dst_addr_mode Destination address mode.
+ @param dst_addr Destination address of the received message.
+ @param dst_ep Destination endpoint of the received message.
+ @param src_addr_mode Source address mode.
+ @param src_addr Source address of the received message.
+ @param src_ep Source endpoint of the received message.
+ @param profile_id Profile identifier considered in the received message.
+ @param cluster_id Cluster identifier considered in the received message.
+ @param asdu_len APS Service Data Unit length of the received message.
+ @param asdu APS Service Data Unit of the received message.
+ @param was_broadcast It indicates whether the trasmission was broadcast or not.
+ @param sec_status Security Status value.
+ @return Void.
+ */
+
+void GalZbIf::APSDE_DATA_indication(uchar dst_addr_mode, uchar *dst_addr,
+		uchar dst_ep, uchar src_addr_mode, uchar *src_addr, uchar src_ep,
+		ushort profile_id, ushort cluster_id, ushort asdu_len, uchar *asdu,
+		uchar was_broadcast, uchar sec_status) {
+	ZbNetDb *pGalDb;
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("GalZbIf::APSDE_DATA_indication");
+#endif
+
+	pGalDb = getDb();
+	if (this->gwStatus != GW_RUNNING)
+		// Ignore any incoming messages until the GAL is up!
+		return;
+	//#ifdef DEBUG_ACTIVE_GALZB
+	if (this->debugEnabled) {
+		printf("GalZbIf::APSDE_DATA_indication - Message from ");
+		if (dst_addr_mode == ZB_AM_DIRECT) {
+			printf("%02x%02x, ", src_addr[1], src_addr[0]);
+		} else if (dst_addr_mode == ZB_AM_DIRECT_EX)
+			printf("%s (printed in reverse order), ", src_addr);
+		printf("EndPoint %02x, profId %04x, clusId %04x, payload ", dst_ep,
+				profile_id, cluster_id);
+		int i;
+		for (i = 0; i < asdu_len; i++) {
+			printf("%02X ", asdu[i]);
+		}
+		printf("\n");
+	}
+	//#endif
+	// Update the timeout information related to the source address
+	manageNodeTimeouts(src_addr_mode, src_addr);
+	if (!listeners[ZB_APSDE_DATA_INDICATION].empty()) {
+
+		std::map<int, std::list<void*> >::const_iterator currEventListeners;
+		std::list<void*> tempList;
+		std::list<void*>::iterator iter;
+
+		currEventListeners = listeners.find(ZB_APSDE_DATA_INDICATION);
+		tempList = currEventListeners->second;
+
+		uchar tmpShortAddrr[2];
+		tmpShortAddrr[0] = LSB_USHORT(pGalDb->root->get_nwk_addr());
+		tmpShortAddrr[1] = MSB_USHORT(pGalDb->root->get_nwk_addr());
+
+		for (iter = tempList.begin(); iter != tempList.end(); iter++) {
+			((APSDE_DATA_indication_Listener) (*iter))(0x02, tmpShortAddrr,
+					dst_ep, src_addr_mode, src_addr, src_ep, profile_id,
+					cluster_id, asdu_len, asdu, was_broadcast, sec_status);
+		}
+	} else {
+//#ifdef DEBUG_ACTIVE_GALZB
+		//pLogger->debug("Map Listeners empty for ZB_APSDE_DATA_INDICATION");
+		printf("Map Listeners empty for ZB_APSDE_DATA_INDICATION\n");
+//#endif
+	}
+
+}
+
+/**
+ Protected method GalZbIf NLME_JOIN_indication
+
+ @param nwk_addr Short address of the device of interest.
+ @param ieee_addr IEEE address of the device of interest.
+ @param capability_info Capability information specifying the operation capability of the joining device.
+ @param secure_join Secure Join information specifying MAC association security level.
+ @return Void.
+ */
+
+void GalZbIf::NLME_JOIN_indication(ushort nwk_addr, uchar *ieee_addr,
+		uchar capability_info, uchar secure_join) {
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("GalZbIf::NLME_JOIN_indication");
+#endif
+
+	if (!listeners[ZB_NLME_JOIN_INDICATION].empty()) {
+		/*
+		 #ifdef DEBUG_ACTIVE_GALZB
+		 pLogger->debug("Map Listeners not empty");
+		 #endif
+		 */
+		std::map<int, std::list<void*> >::const_iterator currEventListeners;
+		std::list<void*> tempList;
+		std::list<void*>::iterator iter;
+
+		currEventListeners = listeners.find(ZB_NLME_JOIN_INDICATION);
+		tempList = currEventListeners->second;
+
+		for (iter = tempList.begin(); iter != tempList.end(); iter++) {
+			((ZB_NLME_JOIN_indication_Listener) (*iter))(nwk_addr, ieee_addr,
+					capability_info, secure_join);
+		}
+
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("Map Listeners empty");
+#endif
+	}
+
+	return;
+}
+
+/**
+ Protected method GalZbIf APSME_UPDATE_DEVICE_indication
+
+ @param src_ieee_addr IEEE address of the device originating the the update device command.
+ @param dev_ieee_addr IEEE address of the device whose status is being updated.
+ @param status Updated device status.
+ @param dev_nwk_addr Short address of the device whose status is being updated.
+ @return Void.
+ */
+
+void GalZbIf::APSME_UPDATE_DEVICE_indication(uchar *src_ieee_addr,
+		uchar *dev_ieee_addr, uchar status, ushort dev_nwk_addr) {
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("GalZbIf::APSME_UPDATE_DEVICE_indication");
+#endif
+
+	if (!listeners[ZB_APSME_UPDATE_DEVICE_INDICATION].empty()) {
+		/*
+		 #ifdef DEBUG_ACTIVE_GALZB
+		 pLogger->debug("Map Listeners not empty");
+		 #endif
+		 */
+		std::map<int, std::list<void*> >::const_iterator currEventListeners;
+		std::list<void*> tempList;
+		std::list<void*>::iterator iter;
+
+		currEventListeners = listeners.find(ZB_APSME_UPDATE_DEVICE_INDICATION);
+		tempList = currEventListeners->second;
+
+		for (iter = tempList.begin(); iter != tempList.end(); iter++) {
+			((ZB_APSME_UPDATE_DEVICE_indication_Listener) (*iter))(
+					src_ieee_addr, dev_ieee_addr, status, dev_nwk_addr);
+		}
+
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("APSME_UPDATE_DEVICE_indication - Map Listeners empty");
+#endif
+	}
+
+	return;
+}
+
+void GalZbIf::ZDO_MATCH_DESC_indication(ushort src_addr, ushort profile_id,
+		uchar nicl, ushort *icllist, uchar nocl, ushort *ocllist) {
+	//#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("GalZbIf::ZDO_MATCH_DESC_indication");
+	//#endif
+
+	if (!listeners[ZB_ZDO_MATCH_DESC_INDICATION].empty()) {
+		/*
+		 #ifdef DEBUG_ACTIVE_GALZB
+		 pLogger->debug("Map Listeners not empty");
+		 #endif
+		 */
+		std::map<int, std::list<void*> >::const_iterator currEventListeners;
+		std::list<void*> tempList;
+		std::list<void*>::iterator iter;
+
+		currEventListeners = listeners.find(ZB_ZDO_MATCH_DESC_INDICATION);
+		tempList = currEventListeners->second;
+
+		for (iter = tempList.begin(); iter != tempList.end(); iter++) {
+			((ZB_ZDO_MATCH_DESC_indication_Listener) (*iter))(src_addr,
+					profile_id, nicl, icllist, nocl, ocllist);
+		}
+
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("ZDO_MATCH_DESC_indication - Map Listeners empty");
+#endif
+	}
+
+	return;
+}
+
+void GalZbIf::GW_STATUS_CHANGED_event(int errorCode, uchar commandStatus) {
+	if (!listeners[GW_STATUS_CHANGED_EVENT].empty()) {
+		/*
+		 #ifdef DEBUG_ACTIVE_GALZB
+		 pLogger->debug("Map Listeners not empty");
+		 #endif
+		 */
+		std::map<int, std::list<void*> >::const_iterator currEventListeners;
+		std::list<void*> tempList;
+		std::list<void*>::iterator iter;
+
+		currEventListeners = listeners.find(GW_STATUS_CHANGED_EVENT);
+		tempList = currEventListeners->second;
+
+		for (iter = tempList.begin(); iter != tempList.end(); iter++) {
+			((GW_STATUS_CHANGED_event_Listener) (*iter))(this->getGWStatus(),
+					errorCode, commandStatus);
+		}
+
+	} else {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("GW_STATUS_CHANGED_event - Map Listeners empty");
+#endif
+	}
+
+}
+
+int GalZbIf::initTCKeyTable(void) {
+	if (this->erasePhase) {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("initTCKeyTable - erasePhase");
+#endif
+		return eraseTCKeyTable();
+	} else if (this->setPhase) {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->debug("initTCKeyTable - setPhase");
+#endif
+		return setTCKeyTable();
+	}
+	return -1;
+}
+
+int GalZbIf::eraseTCKeyTable(void) {
+	uchar entry[26];
+	int index = 0;
+	int c = 0;
+
+	entry[index++] = this->currentTCKeyTableEntryIndex;
+
+	for (c = 0; c < 8; c++) {
+		entry[index++] = 0x00;
+	}
+	entry[index++] = 0x00;
+	for (c = 0; c < 16; c++) {
+		entry[index++] = 0x00;
+	}
+	this->currentTCKeyTableEntryIndex++;
+	if (this->currentTCKeyTableEntryIndex == maxTCKeyTableSize) {
+		this->setPhase = true;
+		this->erasePhase = false;
+		this->currentTCKeyTableEntryIndex = 0;
+	}
+	APSME_SET_request(ZB_ATTR_KEY_TABLE_ENTRY, 26, entry);
+	return 0;
+}
+
+int GalZbIf::setTCKeyTable(void) {
+	uchar entry[26];
+
+	if (this->currentTCKeyTableEntryIndex == db.getTCKeyTableSize()) {
+		this->setPhase = false;
+		this->erasePhase = true;
+		this->currentTCKeyTableEntryIndex = 0;
+		return (-1);
+	}
+
+#ifdef DEBUG_ACTIVE_GALZB
+	pLogger->debug("setTCKeyTable - currentTCKeyTableEntryIndex = %d", this->currentTCKeyTableEntryIndex);
+#endif
+
+	int c = 0;
+	int index = 0;
+	tcKeyTableEntry* tableEntry;
+
+	tableEntry = db.getTCKeyTableEntry(this->currentTCKeyTableEntryIndex);
+
+	if (tableEntry == NULL) {
+#ifdef DEBUG_ACTIVE_GALZB
+		pLogger->fatal("setTCKeyTable - tableEntry == NULL");
+#endif
+		return (-1);
+	}
+
+	entry[index++] = tableEntry->keyTableEntryIndex;
+
+	for (c = 0; c < 8; c++) {
+		entry[index++] = tableEntry->ieeeAddress[7 - c];
+	}
+
+	entry[index++] = 0x01;
+
+	for (c = 0; c < 16; c++) {
+		entry[index++] = tableEntry->preconfiguredLinkKey[c];
+	}
+	this->currentTCKeyTableEntryIndex++;
+	APSME_SET_request(ZB_ATTR_KEY_TABLE_ENTRY, 26, entry);
+	return 0;
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/GalZbIf.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/GalZbIf.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/GalZbIf.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,388 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef _GALZBIF_H_
+#define _GALZBIF_H_
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#ifndef WIN32
+#include <arpa/inet.h>
+#include <pthread.h>
+#endif
+
+#include "zigbee.h"
+#include "winport.h"
+#include "ThreadPool.h"
+#include "TimerThread.h"
+
+#include <list>	
+#include "zigbee_ser.h"			// Included to get ZigBee codes
+#include "ZbNetDb.h"
+
+#include "CDebug.h"	
+
+#include "GWManagement.h"		//	It includes some constants relevant to GW management and used by both th GalZbIf and
+//	RPC layer (i.e. REST classes, in this implementation).
+
+/* Information base definitions: from Integration!!! */
+
+#define ZIB_STK_VERSION_STRING                  0xEF
+#define ZIB_CONFIG_NODE_DESCRIPTOR              0xF0
+#define ZIB_CONFIG_POWER_DESCRIPTOR             0xF1
+#define ZIB_CONFIG_SIMPLE_DESCRIPTOR            0xF2
+#define ZIB_CONFIG_NWK_MODE_AND_PARAMS          0xF3
+#define ZIB_CONFIG_NWK_SCAN_ATTEMPTS            0xF4
+#define ZIB_CONFIG_NWK_TIME_BTWN_SCANS          0xF5
+#define ZIB_CONFIG_COMPLEX_DESCRIPTOR           0xF6
+#define ZIB_CONFIG_USER_DESCRIPTOR              0xF7
+#define ZIB_CONFIG_MAX_BIND                     0xF8
+#define ZIB_CONFIG_MASTER_KEY                   0xF9
+#define ZIB_CONFIG_ENDDEV_BIND_TIMEOUT          0xFA
+#define ZIB_CONFIG_PERMIT_JOIN_DURATION         0xFB
+#define ZIB_CONFIG_NWK_SECURITY_LEVEL           0xFC
+#define ZIB_CONFIG_NWK_SECURE_ALL_FRAMES        0xFD
+#define ZIB_CONFIG_PANID                        0xFF
+
+#define PIB_IEEE_ADDRESS                        0x6F
+#define NIB_MAXCHILDREN                         0x84
+#define NIB_MAXROUTERS                          0x86
+#define NIB_MAXDEPTH                            0x85
+#define NIB_POLLINTERVAL			0x9C
+
+///	GAL error codes
+// TODO				Remove
+#define	GAL_SUCCESS				0	
+#define	GAL_E_ERROR				-1	// Generic error 
+#define	GAL_E_NOT_RUNNING			-2	// The GAL is not in GAL_SS_RUNNING state 
+#define	GAL_E_BUSY				-3	// The GAL is currently doing some other operations 
+
+#define AGO_NONE 0
+
+#define AGO_INQUIRY 			(1UL << 1)
+#define AGO_GET_ANNOUNCEMENTS		(1UL << 2)
+#define AGO_GET_NODE_DESC		(1UL << 3)
+#define AGO_GET_POWER_DESC		(1UL << 4)
+#define AGO_GET_SERVICE_DESC		(1UL << 5)
+#define AGO_GET_ACTIVE_EPS		(1UL << 6)
+#define AGO_ACT_EPS_DISCOVERY		(1UL << 7)
+#define AGO_SERVICE_DESC_DISCOVERY	(1UL << 8)
+#define AGO_PERMIT_JOIN	(1UL << 9)
+//
+#define AGO_GET_DEATH_NOTIFICATIONS	(1UL << 10)
+// new
+#define AGO_MGMT_BIND_REQUEST	(1UL << 11)
+#define AGO_BIND_REQUEST				(1UL << 12)
+#define AGO_UNBIND_REQUEST				(1UL << 13)
+
+//3
+#define MAX_ZDO_START_REQUEST_ATTEMPTS		1
+
+#define GET_BIT(a, bit_no) (((a) >> (bit_no)) & 0x01)		
+
+/**
+ * Class as defined by ZigBee API (Java-like APIs) -->CB
+ *
+ *
+ */
+class GalZbIf;
+
+/**
+ * This class initializes and interact with the ZigBee stack
+ */
+
+class GalZbIf: public CZbIf {
+
+public:
+	struct FeatureControl {
+		unsigned lockedFeatures;
+
+		FeatureControl();
+		bool lock(unsigned long features);
+		void unlock(unsigned long features);
+
+	};
+
+public:
+
+	///	Destructor:
+	~GalZbIf();
+
+	///	Pattern Singleton
+	static GalZbIf *Instance(void);
+
+	void init();
+
+	int securityLevel;
+	//bool isTCKeyTableDefined;
+	bool isFirstStart;
+	bool isEZSPstackRunning;
+	unsigned long ScanChannels;
+	/*
+	 ushort localShortAddress;
+	 uchar localShortAddressUc[2];
+	 uchar localIEEEAddress[8];
+	 */
+
+	///	Define function pointers types
+	typedef void * (*ZDO_IEEE_ADDR_confirm_Listener)(uchar status,
+			uchar *ieee_addr, ushort nwk_addr, uchar num_assoc_dev,
+			uchar start_index, ushort *nwk_addr_assoc_dev_list);
+
+	typedef void * (*ZB_MGMT_LQI_RESPONSE_Listener)(uchar srcAddrMode,
+			uchar* src_addr, uchar status, uchar NeighborTableEntries,
+			uchar StartIndex, uchar NeighborTableListCount,
+			ZB_NEIGHBOR_TABLE_LIST *NeighborTableList);
+
+	typedef void * (*ZDO_NWK_ADDR_confirm_Listener)(uchar status,
+			uchar *ieee_addr, ushort nwk_addr, uchar num_assoc_dev,
+			uchar start_index, ushort *nwk_addr_assoc_dev_list);
+
+	typedef void * (*ZDO_NODE_DESC_confirm_Listener)(uchar status,
+			ushort nwk_addr, ZB_NODE_DESC *node_descr);
+
+	typedef void * (*ZDO_POWER_DESC_confirm_Listener)(uchar status,
+			ushort nwk_addr, ZB_POWER_DESC *power_descr);
+
+	typedef void * (*ZDO_ACTIVE_EP_DESC_confirm_Listener)(uchar status,
+			ushort nwk_addr, uchar active_ep_count, uchar *active_ep_list);
+
+	typedef void * (*ZDO_SIMPLE_DESC_confirm_Listener)(uchar status,
+			ushort nwk_addr, ZB_SIMPLE_DESC *simple_desc);
+
+	typedef void * (*ZB_ZDO_DEVICE_ANNCE_indication_Listener)(ushort nwk_addr,
+			uchar *ieee_addr, uchar capability);
+
+	typedef void * (*APSDE_DATA_indication_Listener)(uchar dst_addr_mode,
+			uchar *dst_addr, uchar dst_ep, uchar src_addr_mode, uchar *src_addr,
+			uchar src_ep, ushort profile_id, ushort cluster_id, ushort asdu_len,
+			uchar *asdu, uchar was_broadcast, uchar sec_status);
+
+	typedef void * (*ZB_NLME_JOIN_indication_Listener)(ushort nwk_addr,
+			uchar *ieee_addr, uchar capability_info, uchar secure_join);
+
+	typedef void * (*ZB_ZDO_RESET_CONFIRM_Listener)(uchar status);
+
+	typedef void * (*ZB_MGMT_PERMIT_JOINING_response_Listener)(uchar status);
+
+	typedef void * (*ZB_ZDP_MGMT_BIND_Response_Listener)(uchar status,
+			ushort bindingTableEntries, ushort StartIndex,
+			ushort BindingTableListCount, ZB_BIND_STRUCT *BindingTableList);
+
+	typedef void * (*ZB_ZDP_BIND_response_Listener)(uchar status);
+
+	typedef void * (*ZB_ZDP_UNBIND_response_Listener)(uchar status);
+
+	typedef void * (*ZB_MGMT_LEAVE_response_Listener)(uchar status);
+
+	typedef void * (*ZB_APSME_UPDATE_DEVICE_indication_Listener)(
+			uchar *src_ieee_addr, uchar *dev_ieee_addr, uchar status,
+			ushort dev_nwk_addr);
+
+	typedef void * (*ZB_ZDO_MATCH_DESC_indication_Listener)(ushort src_addr,
+			ushort profile_id, uchar nicl, ushort *icllist, uchar nocl,
+			ushort *ocllist);
+
+	typedef void * (*GW_STATUS_CHANGED_event_Listener)(int gwStatus,
+			int errorCode, uchar commandStatus);
+
+	///	Configuration
+	int LoadConfig(const char *filename);
+	int SaveConfig(const char *filename);
+
+	///	Listeners - register and unregister (used by Agents) -> refer to std::map "listeners" defined in this file
+	int registerListener(int eventType, void *listener);
+	int unregisterListener(int eventType, void *listener);
+
+	ZbNetDb *getDb(void);
+
+	FeatureControl *getFeatureControl();
+
+	int getGalStatus(void);
+
+	int getGWStatus(void);
+
+	int setGWStatus(int gwStatus, int errorCode);
+
+	int setGWStatus(int gwStatus, int errorCode, uchar commandStatus);
+
+	/*
+	 ushort getLocalNwkAddress_us();
+	 uchar *getLocalNwkAddress_uc();
+	 uchar *getLocalIEEEAddress_uc();
+	 */
+
+	///	Start
+	int Start(void);
+
+	/// Connect and Disconnect lower layers
+	int ZbIfConnect_W(const char *device);
+
+	int ZbIfDisconnect_W(void);
+
+	// For test purpose
+	void APSDE_DATA_indication_Dummy(uchar dst_addr_mode, uchar *dst_addr,
+			uchar dst_ep, uchar src_addr_mode, uchar *src_addr, uchar src_ep,
+			ushort profile_id, ushort cluster_id, ushort asdu_len, uchar *asdu,
+			uchar was_broadcast, uchar sec_status);
+
+	void manageNodeTimeouts(uchar src_addr_mode, uchar *src_addr);
+
+protected:
+	GalZbIf();
+	GalZbIf(const GalZbIf&);
+	GalZbIf& operator=(const GalZbIf&);
+
+	void ZDO_RESET_confirm(uchar status, uchar restartGW //true=Restart, false=just init
+			);
+
+	void ZDO_START_confirm(uchar status, ushort nwk_addr);
+
+	void ZDO_IEEE_ADDR_confirm(uchar status, uchar *ieee_addr, ushort nwk_addr,
+			uchar num_assoc_dev, uchar start_index,
+			ushort *nwk_addr_assoc_dev_list);
+
+	void ZB_MGMT_LQI_response(uchar srcAddrMode, uchar* src_addr, uchar * asdu);
+
+	void ZDO_NWK_ADDR_confirm(uchar status, uchar *ieee_addr, ushort nwk_addr,
+			uchar num_assoc_dev, uchar start_index,
+			ushort *nwk_addr_assoc_dev_list);
+
+	int setSimpleDescriptor(void);
+
+	//Init TC Key Table
+	int initTCKeyTable(void);
+	int eraseTCKeyTable(void);
+	int setTCKeyTable(void);
+
+	void APSME_GET_confirm(uchar status, uchar attr, uchar length,
+			uchar * value);
+
+	void APSME_SET_confirm(uchar status, uchar attr);
+
+	void ZDO_END_DEVICE_BIND_confirm(uchar status);
+
+	void ZDP_MGMT_BIND_Response(uchar status, ushort bindingTableEntries,
+			ushort StartIndex, ushort BindingTableListCount,
+			ZB_BIND_STRUCT * BindingTableList);
+
+	void ZDP_BIND_response(uchar status);
+
+	void ZDP_UNBIND_response(uchar status);
+
+	void MGMT_PERMIT_JOINING_response(uchar status);
+
+	void MGMT_LEAVE_response(uchar status);
+
+	void MGMT_LEAVE_confirm(uchar *ieee_addr, uchar rejoin);
+
+	void ZDO_SIMPLE_DESC_confirm(uchar status, ushort nwk_addr,
+			ZB_SIMPLE_DESC *simple_desc);
+
+	void ZDO_POWER_DESC_confirm(uchar status, ushort nwk_addr,
+			ZB_POWER_DESC *power_descr);
+
+	void ZDO_NODE_DESC_confirm(uchar status, ushort nwk_addr,
+			ZB_NODE_DESC *node_descr);
+
+	void ZDO_ACTIVE_EP_DESC_confirm(uchar status, ushort nwk_addr,
+			uchar active_ep_count, uchar *active_ep_list);
+
+	virtual void NLME_SYNC_confirm(uchar status);
+
+	virtual void NLME_SYNC_indication(void);
+
+	void ZDO_DEVICE_ANNCE_indication(ushort nwk_addr, uchar *ieee_addr,
+			uchar capability);
+
+	void ZIGBEE_STACK_STATUS_indication(uchar status);
+
+	void APSDE_DATA_confirm(uchar dst_addr_mode, uchar *dst_addr, uchar dst_ep,
+			uchar src_ep, uchar status);
+
+	void APSDE_DATA_indication(uchar dst_addr_mode, uchar *dst_addr,
+			uchar dst_ep, uchar src_addr_mode, uchar *src_addr, uchar src_ep,
+			ushort profile_id, ushort cluster_id, ushort asdu_len, uchar *asdu,
+			uchar was_broadcast, uchar sec_status);
+
+	void NLME_JOIN_indication(ushort nwk_addr, uchar *ieee_addr,
+			uchar capability_info, uchar secure_join);
+
+	void APSME_UPDATE_DEVICE_indication(uchar *src_ieee_addr,
+			uchar *dev_ieee_addr, uchar status, ushort dev_nwk_addr);
+
+	void ZDO_MATCH_DESC_indication(ushort src_addr, ushort profile_id,
+			uchar nicl, ushort *icllist, uchar nocl, ushort *ocllist);
+
+	void GW_STATUS_CHANGED_event(int errorCode, uchar commandStatus);
+
+	///	Pointer to a Debug object -> logger
+	Debug *pLogger;
+
+	///	To enable/disable Debug (default value is 0)
+	bool debugEnabled;
+
+private:
+
+	/// Local attributes
+	static GalZbIf instance;
+
+	/** array used to store nodes by short address */
+	ZbNetDb db;
+
+	StartupAttributeInfo * currentSAS;
+
+	/** 
+	 Agent listeners. This map contains a list of pointers to static member functions of a generic Agent (e.g. DiscoveryAgent, ...).
+	 These static member functions are used as wrappers to callback to a non-static member of an arbitrary class.
+	 */
+	std::map<int, std::list<void*> > listeners;
+
+	/** count the number of outstanding SIMPLE_DESCR_requests */
+	int simple_desc_count; //TODO	Move to Management Agent
+	int count_expected_confirm; //TODO  Check - is it used?	NO
+
+	ushort profile_id;
+	ushort device_id;
+	int platform; //0=integration,1=zsdio
+	ushort startupControl;
+	ushort apscMaxWindowSize;
+	ushort apsInterframeDelay;
+	uchar preconfiguredTCLinkKey[16];
+	uchar networkKey[16];
+	int assignedChannelMask; //Just used to internally store the channel mask!
+	SimpleDescriptor *lastSDSet;
+
+	//TCKeyTable
+	int currentTCKeyTableEntryIndex;
+	int tcKT_setIndex;
+	int tcKT_eraseIndex;
+	bool erasePhase;
+	bool setPhase;
+
+	FeatureControl featureControl;
+
+	//TODO		--> not to be considered in this class -> move it
+	/** server socket port */
+	int server_port;
+
+	/// GW Status
+	int gwStatus;
+
+	int zdoStartAttempts;
+
+	pthread_mutex_t mux;
+
+	std::list<SimpleDescriptor> sdList;
+
+};
+
+#endif
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/Makefile.am
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/Makefile.am (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/Makefile.am Fri Oct 19 18:37:43 2012
@@ -1,0 +1,39 @@
+# Process with automake to obtain a configuration script
+
+AUTOMAKE_OPTIONS = foreign
+
+bin_PROGRAMS = gal
+
+gal_SOURCES = \
+	main.cpp \
+	ZbNetDb.cpp \
+	CLogStorage.cpp \
+	CDebug.cpp \
+	CMessage.cpp \
+	GalZbIf.cpp \
+	GWManagement.cpp \
+	Agents.cpp \
+	XMLProcessor.cpp \
+	CQueryParser.cpp \
+	CHTTPClient.cpp \
+	CHTTPServer.cpp \
+	CResource.cpp \
+	CRESTServer.cpp \
+	CRESTClient.cpp \
+	CRESTBroker.cpp \
+	CLocalNode.cpp \
+	ACL.cpp \
+	NodeMap.cpp \
+	ConfigurationRepository.cpp \
+	StaticACLLoader.cpp
+
+include_HEADERS = \
+	CDiscoveryAgent.cpp \
+	CServiceAgent.cpp \
+	CManagementAgent.cpp \
+	CTrustCenterAgent.cpp 
+
+distrib:
+	tar zcvf gal_$(VERSION)_$(HOSTARCH)_`date +'%Y%m%d%H%M%S'`.tar.gz -C $(PREFIX)/usr/$(EXTRA)/bin/ gal
+
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/Makefile.cross
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/Makefile.cross (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/Makefile.cross Fri Oct 19 18:37:43 2012
@@ -1,0 +1,49 @@
+include ../Makefile.rules
+
+#ifeq ($(strip $(TARGET_PLATFORM)),cygwin)
+#CURL_DIR=/usr
+#else
+CURL_DIR=$(PREFIX_TMP)
+#endif
+
+all:
+	$(MAKE) all
+
+clean:
+	rm -f *~
+	$(MAKE) clean
+
+distclean:
+	$(MAKE) distclean
+
+genmake:
+	aclocal
+	autoheader
+	automake -a
+	autoconf
+
+config:
+	./configure \
+	--prefix=$(PREFIX_TMP) \
+	--host=$(HOSTARCH) \
+	--build=$(BUILDARCH) \
+	--enable-zigbee-pro \
+	--enable-debug \
+	--with-debug-flags=RB:SB:DA:SA:GALZB:MESSAGE:XMLMSGCOMPOSER:XMLMSGPARSER:RESTSERVER:RESTCLIENT:HTTPCLIENT	
+#--with-debug-flags=RB:SB:DA:SA:GALZB	#:MESSAGE:XMLMSGCOMPOSER:XMLMSGPARSER:RESTSERVER:RESTCLIENT:HTTPCLIENT	
+
+install:
+	$(MAKE) $@
+	mkdir -p $(PREFIX)/usr/$(EXTRA)/bin
+	install gal $(PREFIX)/usr/$(EXTRA)/bin/gal
+	install start_gal.sh $(PREFIX)/usr/$(EXTRA)/bin/start_gal.sh
+	install -m 644 config.ini $(PREFIX)/usr/$(EXTRA)/bin
+	$(STRIP) $(PREFIX)/usr/$(EXTRA)/bin/gal
+
+uninstall:
+	rm -f $(PREFIX)/usr/$(EXTRA)/bin/gal
+	rm -f $(PREFIX)/usr/$(EXTRA)/etc/config.ini
+
+distrib:
+	$(MAKE) $@
+	

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/MakefileDebug.cross
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/MakefileDebug.cross (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/MakefileDebug.cross Fri Oct 19 18:37:43 2012
@@ -1,0 +1,45 @@
+include ../Makefile.rules
+
+all:
+	$(MAKE) all
+
+clean:
+	rm -f *~
+	$(MAKE) clean
+
+distclean:
+	$(MAKE) distclean
+
+genmake:
+	aclocal
+	autoheader
+	automake -a
+	autoconf
+
+
+config:
+	./configure \
+	--prefix=$(PREFIX_TMP) \
+	--host=$(HOSTARCH) \
+	--build=$(BUILDARCH) \
+	--enable-zigbee-pro \
+	--with-local-libs=.. \
+	--with-upnp-libs=$(PREFIX_TMP)/lib \
+	--with-curl-libs=$(PREFIX_TMP)/lib \
+	--with-upnp-cflags=-I$(PREFIX_TMP)/include/upnp \
+	--with-curl-cflags=-I$(PREFIX_TMP)/include/curl
+	--enable-debug --with-debug-flags=RB:SB:DA:MESSAGE:SA:RESTSERVER:XMLMSGCOMPOSER:GALZB:XMLMSGPARSER
+
+install:
+	$(MAKE) $@
+	mkdir -p $(PREFIX)/usr/$(EXTRA)/bin
+	install gal $(PREFIX)/usr/$(EXTRA)/bin/gal
+	install start_gal.sh $(PREFIX)/usr/$(EXTRA)/bin/start_gal.sh
+	install -m 644 config.ini $(PREFIX)/usr/$(EXTRA)/etc
+	$(STRIP) $(PREFIX)/usr/$(EXTRA)/bin/gal
+
+uninstall:
+	rm -f $(PREFIX)/usr/$(EXTRA)/bin/gal
+	rm -f $(PREFIX)/usr/$(EXTRA)/etc/config.ini
+
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/NodeMap.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/NodeMap.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/NodeMap.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,291 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "NodeMap.h"
+#include <iterator>
+#include <stdio.h>
+#include <sstream>
+
+using namespace std;
+
+#ifdef DEBUG_ACTIVE_NODEMAP
+Debug *NMIstaticDebug=NULL;
+#endif
+
+/// see included header file
+NodeMap::NodeMap() {
+#ifdef DEBUG_ACTIVE_NODEMAP
+	_pLogger = new Debug ( "DiscoveryAgent" );
+	_pLogger->setDebugLevel ( DEBUGGING );
+	_pLogger->setDebugMode ( DBG_ENABLED );
+	_pLogger->setDebugMsgFormat ( DBGMSGFORMAT_SIMPLE );
+	_pLogger->enableDebugOuput ( DBG_SCREEN );
+	//pLogger->enableDebugOuput ( DBG_LOGFILE );
+	NMIstaticDebug = _pLogger;
+#endif
+
+#ifdef DEBUG_ACTIVE_NODEMAP
+	_pLogger->debug ( "NodeMap: constructor." );
+#endif
+
+}
+
+/// see included header file
+NodeMap::~NodeMap() {
+
+#ifdef DEBUG_ACTIVE_NODEMAP
+	_pLogger->debug ( "NodeMap: distructor." );
+#endif
+
+	this->erase();
+}
+
+/// see included header file
+void NodeMap::erase() {
+#ifdef DEBUG_ACTIVE_NODEMAP
+	_pLogger->debug ( "NodeMap: erase." );
+#endif
+
+//Empty the node list
+	NodeMapItem *ptr = NULL;
+	while (!_accesslist.empty()) {
+		ptr = (_accesslist.front());
+		delete ptr;
+		_accesslist.pop_front();
+	}
+
+}
+
+/// see included header file
+bool NodeMap::addNode(NodeMapItem *addr) {
+#ifdef DEBUG_ACTIVE_NODEMAP
+	_pLogger->debug ( "NodeMap: Adding node [%s]",addr->toString().c_str() );
+#endif
+// if the list is full, I return false
+	if (this->size() >= NodeMap_MAX_ENTRIES) {
+#ifdef DEBUG_ACTIVE_NODEMAP
+		_pLogger->error ( "NodeMap: List is full cannot add node %s",addr->toString().c_str() );
+#endif
+		return false;
+	}
+// I create a local copy
+	NodeMapItem *ptr = new NodeMapItem(addr);
+	_accesslist.push_back(ptr);
+	return true;
+}
+
+/// see included header file
+bool NodeMap::removeNode(NodeMapItem *addr) {
+#ifdef DEBUG_ACTIVE_NODEMAP
+	_pLogger->debug ( "NodeMap: removing node %s",addr->toString().c_str() );
+#endif
+
+	if (this->isPresent(addr)) {
+//node is present, I remove it from the list and I free the memory
+		NodeMapItem *node = this->getNode(addr->getLongAddr());
+		this->_accesslist.remove(node);
+		delete node;
+		return true;
+	}
+// not present, What can I remove ?
+#ifdef DEBUG_ACTIVE_NODEMAP
+	_pLogger->debug ( "NodeMap: warning; removing node %s, but was not present",addr->toString().c_str() );
+#endif
+
+	return false;
+}
+
+/// see included header file
+bool NodeMap::isPresent(NodeMapItem *addr) {
+	return (this->getNode(addr->getLongAddr()) != NULL);
+}
+
+/// see included header file
+int NodeMap::size() {
+	return _accesslist.size();
+}
+
+/// see included header file
+bool NodeMap::isPresent(uchar ieeeaddr[IEEE_RAWADDRESS_SIZE]) {
+	return (this->getNode(ieeeaddr) != NULL);
+
+}
+
+/// see included header file
+NodeMapItem::NodeMapItem(uchar ieeeaddr[IEEE_RAWADDRESS_SIZE]) {
+
+//random values, with this constructor, anyway, these values are protected by the fact that the hasparent value is false ... (this constructor is used for ACL, so you don't actually have other parameters ...)
+	this->init(65535, ieeeaddr, 0, 0, false);
+}
+
+/// see included header file
+NodeMapItem::~NodeMapItem() {
+}
+
+/// see included header file
+uchar *NodeMapItem::getLongAddr() {
+	return _longaddr;
+}
+
+/// see included header file
+NodeMapItem *NodeMap::getNode(uchar ieeeaddr[IEEE_RAWADDRESS_SIZE]) {
+	NodeMapItem *ptr;
+
+	NodeMapItem other(ieeeaddr);
+
+	for (std::list<NodeMapItem *>::iterator list_iter = _accesslist.begin();
+			list_iter != _accesslist.end(); list_iter++) {
+		ptr = *list_iter;
+
+		if (ptr->compareLongAddr(&other)) {
+			return ptr;
+		}
+
+	}
+	return NULL;
+
+}
+
+/// see included header file
+void NodeMapItem::setLongAddr(uchar ieeeaddr[IEEE_RAWADDRESS_SIZE]) {
+	for (int i = 0; i < IEEE_RAWADDRESS_SIZE; i++) {
+		this->_longaddr[i] = ieeeaddr[i];
+	}
+}
+
+/// see included header file
+bool NodeMapItem::compareLongAddr(NodeMapItem *other) {
+	int i;
+	uchar *otheraddr = other->getLongAddr();
+
+	for (i = 0; i < IEEE_RAWADDRESS_SIZE; i++) {
+		if (this->_longaddr[i] != otheraddr[i]) {
+			return false;
+		}
+	}
+	return true;
+}
+
+/// see included header file
+string NodeMapItem::toString() {
+	char tmpstring[IEEE_RAWADDRESS_SIZE * 10];
+	ostringstream a;
+
+	snprintf(tmpstring, IEEE_RAWADDRESS_SIZE * 10, "%x-%x-%x-%x-%x-%x-%x-%x",
+			_longaddr[0], _longaddr[1], _longaddr[2], _longaddr[3],
+			_longaddr[4], _longaddr[5], _longaddr[6], _longaddr[7]);
+
+	a << "Node addr " << tmpstring << " nwkaddr " << _nwk_addr;
+
+	return a.str();
+}
+
+/// see included header file
+NodeMapItem::NodeMapItem(ushort nwk_addr, uchar *ieee_addr,
+		uchar capability_info, uchar secure_join, bool authorizedbywsnc) {
+
+	this->init(nwk_addr, ieee_addr, capability_info, secure_join,
+			authorizedbywsnc);
+}
+
+/// see included header file
+void NodeMapItem::init(ushort nwk_addr, uchar *ieee_addr, uchar capability_info,
+		uchar secure_join, bool authorizedbywsnc) {
+
+	this->setLongAddr(ieee_addr);
+	_nwk_addr = nwk_addr;
+	_capability_info = capability_info;
+	_secure_join = secure_join;
+
+	_authorizedbywsnc = authorizedbywsnc;
+
+}
+
+/// see included header file
+NodeMapItem::NodeMapItem(NodeMapItem *n) {
+	this->init(n->getNwkAddr(), n->getLongAddr(), n->getCapabilityInfo(),
+			n->getSecureJoin(), n->getAuthorizedByWSNC());
+}
+
+/// see included header file
+ushort NodeMapItem::getNwkAddr() {
+	return _nwk_addr;
+}
+
+/// see included header file
+uchar NodeMapItem::getCapabilityInfo() {
+	return _capability_info;
+}
+
+/// see included header file
+uchar NodeMapItem::getSecureJoin() {
+	return _secure_join;
+}
+
+/// see included header file
+bool NodeMapItem::getAuthorizedByWSNC() {
+	return _authorizedbywsnc;
+}
+
+void NodeMapItem::setParentAddr(uchar *parent_addr) {
+
+	if (parent_addr != NULL) {
+
+		for (int i = 0; i < IEEE_RAWADDRESS_SIZE; i++) {
+			this->_parentaddr[i] = parent_addr[i];
+		}
+	} else {
+
+//this code should be unreachable, but just in case, I set a "magic" address...
+		for (int i = 0; i < IEEE_RAWADDRESS_SIZE; i++) {
+			this->_parentaddr[i] = 0x00;
+		}
+	}
+
+}
+
+/// see included header file
+bool NodeMap::removeNode(uchar ieeeaddr[IEEE_RAWADDRESS_SIZE]) {
+
+	NodeMapItem *addr = this->getNode(ieeeaddr);
+
+#ifdef DEBUG_ACTIVE_NODEMAP
+	_pLogger->debug ( "NodeMap: removing node %s",addr->toString().c_str() );
+#endif
+
+	if (this->isPresent(addr)) {
+//node is present, I remove it from the list and I free the memory
+		NodeMapItem *node = this->getNode(addr->getLongAddr());
+		this->_accesslist.remove(node);
+		delete node;
+		return true;
+	}
+// not present, What can I remove ?
+#ifdef DEBUG_ACTIVE_NODEMAP
+	_pLogger->debug ( "NodeMap: warning; removing node %s, but was not present",addr->toString().c_str() );
+#endif
+
+	return false;
+}
+
+bool NodeMapItem::getHasParent() {
+	return _hasparent;
+}
+
+void NodeMapItem::setHasParent(bool value) {
+	this->_hasparent = value;
+}
+
+uchar *NodeMapItem::getParentAddr() {
+	return _parentaddr;
+}

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/NodeMap.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/NodeMap.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/NodeMap.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,211 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef NodeMap_H_INCLUDED_
+#define NodeMap_H_INCLUDED_
+
+#include <list>
+#include <string>
+
+#ifdef __GNUC__
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+#endif
+//debug flag, comment to remove from the code the debug messages.
+//#define DEBUG_ACTIVE_NODEMAP
+//#define DEBUG_ACTIVE_NODEMAP_VERBOSE
+
+#ifdef DEBUG_ACTIVE_NODEMAP
+#include "CDebug.h"
+#endif
+
+using namespace std;
+
+/**
+ @param IEEE_RAWADDRESS_SIZE - size of Raw IEEE address
+ */
+#define IEEE_RAWADDRESS_SIZE 8
+/**
+ Simple wrapper class for IEEE address, to be used with the NodeMapClass
+ */
+class NodeMapItem {
+public:
+
+	/**
+	 NodeMapItem TrustCenter constructor. The first parameters are the same as the ones received with a join indication. authorizedbywsnc is internal, and it is used to keep track of nodes authorized by wsn-c, but it is not received with the join indication.
+	 */
+	NodeMapItem(ushort nwk_addr, uchar *ieee_addr, uchar capability_info,
+			uchar secure_join, bool authorizedbywsnc);
+
+	/**
+	 Simple constructor for ACL
+	 @param ieeeaddr Raw IEEE address
+	 */
+	NodeMapItem(uchar ieeeaddr[IEEE_RAWADDRESS_SIZE]);
+
+/// Copy constructor
+
+	NodeMapItem(NodeMapItem *n);
+
+	/**
+	 Default distructor
+	 */
+	~NodeMapItem();
+
+	/**
+	 Set ieee address
+	 @param ieeeaddr Raw address
+	 */
+	void setLongAddr(uchar ieeeaddr[IEEE_RAWADDRESS_SIZE]);
+
+	/**
+	 @return Raw IEEE address
+	 */
+	uchar *getLongAddr();
+
+	/**
+	 @return Compare the IEEE address with another NodeMapItem
+	 */
+	bool compareLongAddr(NodeMapItem *other);
+
+	string toString();
+
+	ushort getNwkAddr();
+	uchar getCapabilityInfo();
+	uchar getSecureJoin();
+	bool getAuthorizedByWSNC();
+
+	void setTimerDescriptor(unsigned int *val) {
+		_timerdescriptor = val;
+	}
+	unsigned int *getTimerDescriptor() {
+		return _timerdescriptor;
+	}
+
+	void setParentAddr(uchar *parent_addr);
+	uchar *getParentAddr();
+
+	void setHasParent(bool value);
+	bool getHasParent();
+
+private:
+//parameters from join indication
+///Long IEEE address from join indication/other
+	uchar _longaddr[IEEE_RAWADDRESS_SIZE];
+
+///Long parent IEEE address from join indication/other
+	uchar _parentaddr[IEEE_RAWADDRESS_SIZE];
+
+///network address from join indication
+	ushort _nwk_addr;
+
+///capability_info from join indication
+	uchar _capability_info;
+
+///secure_join from join indication
+	uchar _secure_join;
+
+	bool _hasparent;
+//internal parameters
+
+///TRUE if the node has been authorized remotely
+	bool _authorizedbywsnc;
+
+// private methods
+///internal subconstructor
+	void init(ushort nwk_addr, uchar *ieee_addr, uchar capability_info,
+			uchar secure_join, bool authorizedbywsnc);
+
+	unsigned int *_timerdescriptor;
+
+};
+
+/**
+ @param NodeMap_MAX_ENTRIES Max allowed number of entries inside a NodeMap
+ */
+#define NodeMap_MAX_ENTRIES 1000
+
+/**
+ * NodeMap Class - Genereic Node Repository
+ *
+ * @author Riccardo Tomasi <tomasi at ismb.it>
+ */
+
+class NodeMap {
+
+public:
+	/**
+	 default constructor
+	 */
+	NodeMap();
+
+	/**
+	 default distructor
+	 */
+	virtual ~NodeMap();
+
+	/**
+	 Add a node to the NodeMap. The NodeMap creates a local copy of the added address, so the parameter must not be kept after the addition, and can be freed.
+	 @return false, if the maximum number of nodes is reached, and the add is not succesfull
+	 */
+	bool addNode(NodeMapItem *addr);
+
+	/**
+	 Remove a node from the NodeMap.
+	 @return false, if the node was not present.
+	 */
+	bool removeNode(NodeMapItem *addr);
+
+	/**
+	 Remove a node from the NodeMap.
+	 @return false, if the node was not present.
+	 */
+	bool removeNode(uchar ieeeaddr[IEEE_RAWADDRESS_SIZE]);
+
+	/**
+	 Check if a node is inside the NodeMap
+	 @param addr NodeMapItem to check
+	 @return true, if the node is actually present in the map
+	 */
+	bool isPresent(NodeMapItem *addr);
+
+	/**
+	 Check if a node is inside the NodeMap, using raw address
+	 @param ieeeaddr Raw IEEE addr
+	 @return true, if the node is actually present in the map
+	 */
+	bool isPresent(uchar ieeeaddr[IEEE_RAWADDRESS_SIZE]);
+
+	/**
+	 @return the number of nodes inside the NodeMap
+	 */
+	int size();
+
+	/**
+	 clear NodeMap
+	 */
+	void erase();
+
+	/**
+	 @return NodeMapItem with specified Raw address. If not present, returns NULL
+	 */
+	NodeMapItem *getNode(uchar ieeeaddr[IEEE_RAWADDRESS_SIZE]);
+
+private:
+	/**
+	 Internal list used to store addresses
+	 */
+	std::list<NodeMapItem *> _accesslist;
+
+#ifdef DEBUG_ACTIVE_NODEMAP
+	Debug *_pLogger;
+#endif
+};
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/RESTErrors.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/RESTErrors.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/RESTErrors.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,47 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef RESTERRORS_H
+#define RESTERRORS_H
+
+/**
+ REST Status codes. They are defined in the ZGD specs
+ */
+
+#define REC_SUCCESS					0x00
+#define REC_TIMEOUT					0x01
+#define REC_GENERAL_ERROR				0x02
+#define REC_PARAMETER_MISSING				0x03
+#define REC_PARAMETER_INVALID_VALUE			0x04
+#define REC_NETWORK_NOT_READY				0x05
+#define REC_EMPTY					0x06
+#define REC_NOT_ALLOWED					0x07
+#define REC_MEMORY_ERROR				0x08
+#define REC_APS_FAILURE					0x09
+#define REC_NETWORK_FAILURE					0x0a
+
+enum RESTError {
+
+	NO_ERROR,
+	METHOD_NOT_ALLOWED,
+	WRONG_REQUEST,
+	FEATURE_NOT_SUPPORTED,
+	GENERIC_REST_ERROR,
+	BAD_PARAMETER,
+	PARAMETER_MISSING,
+	URILISTENER_ALREADY_REGISTERED,
+	URILISTENER_NOT_REGISTERED,
+	URILISTENER_LIST_MAX_SIZE_EXCEEDED,
+	TIMEOUT,
+	NO_MESSAGE_YET,
+	ZB_NWK_FAILURE,
+};
+
+#endif
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/StaticACLLoader.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/StaticACLLoader.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/StaticACLLoader.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,305 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "StaticACLLoader.h"
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#include "CDebug.h"
+
+#ifdef DEBUG_ACTIVE_STATICACLLOADER
+Debug *getStaticAclLoaderLogger();
+Debug *_StaticAclLoaderLogger = NULL;
+#endif
+
+///See included header file
+uchar *StaticACLLoader::parseBytes(string stringa, unsigned size) {
+
+#ifdef DEBUG_ACTIVE_STATICACLLOADER_VERBOSE
+	Debug *dbg = getStaticAclLoaderLogger();
+	dbg->debug ( "parse of string [%s] requested, size is %d",stringa.c_str(),size );
+#endif
+//the argument must have exactly 2 characters for each bye
+	if (stringa.length() != 2 * size) {
+#ifdef DEBUG_ACTIVE_STATICACLLOADER_VERBOSE
+		Debug *dbg = getStaticAclLoaderLogger();
+		dbg->debug ( "parse of string [%s] requested, size is %d failed for wrong size",stringa.c_str(),size );
+#endif
+		return NULL;
+	}
+
+//check the number for invalid characters
+
+	const char *cstring = stringa.c_str();
+	for (unsigned i = 0; i < stringa.length(); i++) {
+		if (!StaticACLLoader::isvalidchar(cstring[i])) {
+#ifdef DEBUG_ACTIVE_STATICACLLOADER_VERBOSE
+			Debug *dbg = getStaticAclLoaderLogger();
+			dbg->debug ( "parse of string [%s], size is %d failed on invalid character %c (index is %d)",stringa.c_str(),size,cstring[i],i );
+#endif
+			return NULL;
+		}
+	}
+//String parsing
+	uchar *ret = new uchar[size];
+	int len = stringa.length();
+	for (int i = 0; i < len; i += 2) {
+
+#ifdef DEBUG_ACTIVE_STATICACLLOADER_VERBOSE
+		Debug *dbg = getStaticAclLoaderLogger();
+		dbg->debug ( "cycle %d",i );
+#endif
+
+		string nextbyte = stringa.substr(i, 2);
+
+#ifdef DEBUG_ACTIVE_STATICACLLOADER_VERBOSE
+		dbg->debug ( "Parsing byte %s",nextbyte.c_str() );
+#endif
+
+		unsigned int singlebyte;
+
+		sscanf(nextbyte.c_str(), "%x", &singlebyte);
+//parse single byte
+
+		ret[i / 2] = singlebyte;
+	}
+
+	return ret;
+}
+
+///See included header file
+NodeMapItem *StaticACLLoader::parseIEEAddr(string line) {
+
+	uchar *addr = StaticACLLoader::parseBytes(line, IEEE_RAWADDRESS_SIZE);
+
+	/*	uchar addr[IEEE_RAWADDRESS_SIZE];
+	 unsigned int tmpaddr[IEEE_RAWADDRESS_SIZE];
+	 const char *stringa = line.c_str();
+
+	 #ifdef DEBUG_ACTIVE_STATICACLLOADER_VERBOSE
+	 Debug *dbg = getStaticAclLoaderLogger();
+	 dbg->mytodo();
+	 #endif
+
+	 sscanf ( stringa,"%2x%2x%2x%2x%2x%2x%2x%2x",&tmpaddr[0],&tmpaddr[1],&tmpaddr[2],&tmpaddr[3],&tmpaddr[4],&tmpaddr[5],&tmpaddr[6],&tmpaddr[7] );
+
+	 for ( int i=0;i<IEEE_RAWADDRESS_SIZE;i++ )
+	 {
+	 addr[i] = tmpaddr[i];
+	 }
+
+	 #ifdef DEBUG_ACTIVE_STATICACLLOADER_VERBOSE
+	 // 	Debug *dbg = getStaticAclLoaderLogger();
+	 dbg->debug ( "StaticACLLoader parsed: %2x-%2x-%2x-%2x-%2x-%2x-%2x-%2x",addr[0],addr[1],addr[2],addr[3],addr[4],addr[5],addr[6],addr[7] );
+	 #endif*/
+	NodeMapItem *it = new NodeMapItem(addr);
+// delete addr;
+	return it;
+}
+
+///See included header file
+bool StaticACLLoader::actual_load(const char *filename, ACL *acl) {
+
+	string line;
+	int nlines = 0;
+
+#ifdef DEBUG_ACTIVE_STATICACLLOADER_VERBOSE
+	Debug *dbg = getStaticAclLoaderLogger();
+	dbg->debug ( " StaticACLLoader actual loading " );
+#endif
+
+	ifstream myfile(filename);
+	if (myfile.is_open()) {
+		while (!myfile.eof()) {
+			getline(myfile, line);
+
+			if (StaticACLLoader::iscommentline(line)) {
+#ifdef DEBUG_ACTIVE_STATICACLLOADER_VERBOSE
+				dbg->debug ( " StaticACLLoader removed comment line %s ",line.c_str() );
+#endif
+
+				continue;
+			}
+
+			if (StaticACLLoader::iserrorline(line)) {
+#ifdef DEBUG_ACTIVE_STATICACLLOADER_VERBOSE
+				Debug *dbg = getStaticAclLoaderLogger();
+				dbg->error ( " StaticACLLoader error in line [%s]",line.c_str() );
+#endif
+
+				myfile.close();
+				return -1;
+			}
+
+			nlines++;
+#ifdef DEBUG_ACTIVE_STATICACLLOADER_VERBOSE
+			Debug *dbg = getStaticAclLoaderLogger();
+			dbg->debug ( " StaticACLLoader read valid line [%s]",line.c_str() );
+#endif
+			NodeMapItem *addr;
+			addr = StaticACLLoader::parseIEEAddr(line);
+			acl->addNode(addr);
+			delete addr;
+
+		}
+		myfile.close();
+		return nlines;
+	} else {
+		return -1;
+	}
+
+}
+///See included header file
+bool StaticACLLoader::load(const char *filename, ACL *acl) {
+
+	if (-1 == StaticACLLoader::validate(filename)) {
+		return false;
+	}
+
+	acl->erase();
+
+	if (-1 == StaticACLLoader::actual_load(filename, acl)) {
+		return false;
+	}
+
+	return true;
+}
+///See included header file
+int StaticACLLoader::validate(const char *filename) {
+	string line;
+	int nlines = 0;
+
+	ifstream myfile(filename);
+	if (myfile.is_open()) {
+		while (!myfile.eof()) {
+			getline(myfile, line);
+
+#ifdef DEBUG_ACTIVE_STATICACLLOADER_VERBOSE
+			Debug *dbg = getStaticAclLoaderLogger();
+			dbg->error ( " going to validate line [%s]",line.c_str() );
+#endif
+
+			if (StaticACLLoader::iscommentline(line)) {
+				continue;
+			}
+
+			if (StaticACLLoader::iserrorline(line)) {
+#ifdef DEBUG_ACTIVE_STATICACLLOADER_VERBOSE
+				Debug *dbg = getStaticAclLoaderLogger();
+				dbg->error ( " validation error for ACL file %s, line %d line [%s]",filename,nlines,line.c_str() );
+#endif
+
+				myfile.close();
+				return -1;
+			}
+
+			nlines++;
+		}
+		myfile.close();
+		return nlines;
+	} else {
+		return -1;
+	}
+
+}
+
+///See included header file
+bool StaticACLLoader::iscommentline(string line) {
+	const char *c = line.c_str();
+
+	if (line.length() == 0) {
+		return true;
+	}
+
+	if (c[0] == COMMENTTERMINATOR || c[0] == '\n') {
+		return true;
+	}
+
+	return false;
+}
+
+///See included header file
+bool StaticACLLoader::iserrorline(string line) {
+
+	if (line.length() != (2 * IEEE_RAWADDRESS_SIZE)) {
+		return true;
+	}
+
+	const char *stringa = line.c_str();
+
+	for (unsigned int i = 0; i < line.length(); i++) {
+		if (!StaticACLLoader::isvalidchar(stringa[i])) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+///See included header file
+bool StaticACLLoader::isvalidchar(const char c) {
+
+	switch (c) {
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+	case 'a':
+	case 'b':
+	case 'c':
+	case 'd':
+	case 'e':
+	case 'f':
+		return true;
+		break;
+
+	default:
+		return false;
+	}
+	return false;
+}
+
+#ifdef DEBUG_ACTIVE_STATICACLLOADER
+///See included header file
+Debug *getStaticAclLoaderLogger() {
+
+	if (_StaticAclLoaderLogger == NULL) {
+		_StaticAclLoaderLogger = new Debug("StaticACLLoader");
+		_StaticAclLoaderLogger->setDebugLevel(DEBUGGING);
+		_StaticAclLoaderLogger->setDebugMode(DBG_ENABLED);
+		_StaticAclLoaderLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+		_StaticAclLoaderLogger->enableDebugOuput(DBG_SCREEN);
+		//pLogger->enableDebugOuput ( DBG_LOGFILE );
+	}
+
+	return _StaticAclLoaderLogger;
+}
+
+#endif
+
+/*Debug *StaticACLLoader::getDebug(){
+
+
+
+
+
+ }
+ */
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/StaticACLLoader.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/StaticACLLoader.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/StaticACLLoader.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,80 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef STATICACLLOADER_H_INCLUDED_
+#define STATICACLLOADER_H_INCLUDED_
+
+#include "ACL.h"
+#include "CDebug.h"
+
+#define DEBUG_ACTIVE_STATICACLLOADER
+//  #define DEBUG_ACTIVE_STATICACLLOADER_VERBOSE
+
+using namespace std;
+
+/**
+ Defines the Comment character in ACL files
+ */
+#define COMMENTTERMINATOR '#'
+/**
+ This class, which includes only static methods, is used to load ACL lists from file
+ */
+class StaticACLLoader {
+public:
+	/**
+	 Loads access control list from file filename to ACL.
+	 @param filename
+	 @param  acl
+	 */
+	static bool load(const char *filename, ACL *acl);
+
+	/**
+	 Parse string for a certain number of bytes, in hex format.
+	 (for instance "0102030aab",5 -> [01] [02]) [03 [0a] [ab]
+	 @return NULL in case of error
+	 */
+	static uchar *parseBytes(string stringa, unsigned size);
+
+private:
+//unusable, abstract class
+	StaticACLLoader();
+	/**
+	 internal function. Performs the actual loading from file.
+	 */
+	static bool actual_load(const char *filename, ACL *acl);
+
+	/**
+	 internal function. Check if the ACL file is formally valid
+	 */
+	static int validate(const char *filename);
+
+	/**
+	 internal function. check if line is a comment
+	 */
+	static bool iscommentline(string line);
+
+	/**
+	 internal function. check if the line contains a valid address
+	 */
+	static bool iserrorline(string line);
+
+	/**
+	 internal function. check if the character is valid for address
+	 */
+	static bool isvalidchar(const char c);
+
+	/**
+	 internal function. Parse IEEE address from string.
+	 */
+	static NodeMapItem *parseIEEAddr(string line);
+
+};
+
+#endif
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/XMLProcessor.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/XMLProcessor.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/XMLProcessor.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,3197 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include "XMLProcessor.h"
+
+#define BLANKS " \t\n\r"
+#define HEX "0123456789abcdefABCDEF"
+
+#define XML_HEADING "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+#define REST_NS_URI  "http://www.zigbee.org/GWGRESTSchema"
+#define GAL_NS_URI   "http://www.zigbee.org/GWGSchema"
+#define XML_NS 	     "xmlns:"
+
+//**************************************************************************
+//*************  XMLMsgParser  *********************************************
+//**************************************************************************
+
+XMLMsgParser XMLMsgParser::instance;
+
+/**
+ Constructor
+ XMLMsgParser constructor. It is a protected method (pattern Singleton)
+
+ @param void Void.
+ @return Void.
+ */
+
+XMLMsgParser::XMLMsgParser() {
+	// We load the configuration from the ConfigurationManager
+	ConfigurationRepository *_conf = ConfigurationRepository::instance();
+	this->debugEnabled = _conf->getint("main:debugEnabled", false);
+	pLogger = new Debug("XMLMsgParser");
+	//pLogger->setDebugMode(this->debugEnabled);
+	//pLogger->setDebugMode(DBG_ENABLED);
+	pLogger->setDebugMode(DBG_DISABLED);
+	pLogger->setDebugLevel(DEBUGGING);
+	//pLogger->setDebugLevel(TEST);
+	pLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+	pLogger->enableDebugOuput(DBG_SCREEN);
+	//pLogger->enableDebugOuput(DBG_LOGFILE);
+
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+	pLogger->debug("Constructor");
+#endif
+
+	this->init();
+}
+
+/**
+ Destructor
+ XMLMsgParser destructor.
+
+ @param void Void.
+ @return Void.
+ */
+
+XMLMsgParser::~XMLMsgParser() {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+	pLogger->debug("XMLMsgParser Destructor");
+#endif
+
+	delete pLogger;
+}
+
+/**
+ Public method XMLMsgParser *Instance(void)
+ (pattern Singleton)
+
+ @param void Void.
+ @return Instance of XMLMsgParser class.
+ */
+
+XMLMsgParser *XMLMsgParser::Instance(void) {
+	return &instance;
+}
+
+/**
+ Public method XMLMsgParser init
+ XMLMsgParser initialization: macrofunction context is initialized.
+
+
+ @param void Void.
+ @return Void.
+ */
+
+void XMLMsgParser::init() {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+	pLogger->debug("XMLMsgParser init");
+#endif
+
+	//Init deviceType enumeration type
+	deviceType["Current"] = 0x00; //Current device type configuration
+	deviceType["Coordinator"] = 0x01; //ZigBee coordinator
+	deviceType["Router"] = 0x02; //ZigBee Router
+	deviceType["EndDevice"] = 0x03; //ZigBee End Device
+
+	ls_Level["MACLevel"] = MACLevel;
+	ls_Level["NWKLevel"] = NWKLevel;
+	ls_Level["APSLevel"] = APSLevel;
+	ls_Level["INTRPLevel"] = INTRPLevel;
+
+	ds_DecodeLevel["DecodeMAC"] = DecodeMAC;
+	ds_DecodeLevel["DecodeNWK"] = DecodeNWK;
+	ds_DecodeLevel["DecodeInterPAN"] = DecodeAPS;
+	ds_DecodeLevel["DecodeAPS"] = DecodeAPS;
+	ds_DecodeLevel["DecodeZCL"] = DecodeZCL;
+	ds_DecodeLevel["DecodeZDP"] = DecodeZDP;
+
+}
+
+TiXmlElement *XMLMsgParser::getNode(TiXmlElement *node, const char *prefix,
+		const char *label, TiXmlElement *prev) {
+	std::string clabel;
+
+	if (label != NULL) {
+		if (prefix != NULL)
+			clabel = clabel + prefix + ":" + label;
+		else
+			clabel = label;
+
+		if (prev == NULL)
+			node = node->FirstChildElement(clabel);
+		else
+			node = prev->NextSiblingElement(clabel);
+	}
+
+	return node;
+}
+
+const char *XMLMsgParser::getPrefix(TiXmlElement *root, const char *uri) {
+	TiXmlAttribute *attr;
+	const char *p;
+
+	for (attr = root->FirstAttribute(); attr != NULL; attr = attr->Next())
+		if (!strncmp(attr->Name(), XML_NS, strlen(XML_NS))
+				&& !strcmp(attr->Value(), uri))
+			break;
+
+	if (attr == NULL)
+		return NULL;
+
+	p = attr->Name();
+	p += strlen(XML_NS);
+
+	return *p ? p : NULL;
+}
+
+TiXmlElement *XMLMsgParser::getRoot(TiXmlDocument &doc, std::string &xmlMsg,
+		std::string &label, const char *&galPrefix, const char *&restPrefix) {
+	std::stringstream myistream(xmlMsg);
+	TiXmlElement *node;
+	size_t pos;
+
+	myistream >> doc;
+	node = doc.RootElement();
+	if (node == NULL)
+		return NULL;
+
+	label = node->ValueStr();
+	pLogger->debug("getRoot - Value of label: %s\r\n", label.c_str());
+	pos = label.find(":");
+	if (pos != string::npos) {
+		label = label.substr(pos + 1);
+		galPrefix = getPrefix(node, GAL_NS_URI);
+		restPrefix = getPrefix(node, REST_NS_URI);
+	} else {
+		galPrefix = NULL;
+		restPrefix = NULL;
+	}
+	pLogger->debug("getRoot - galPrefix %s, restPrefix %s\r\n", galPrefix, restPrefix);
+	return node;
+}
+
+int XMLMsgParser::parseAddress(TiXmlElement *node, const char *prefix,
+		const char *label, uchar &mode, unsigned char address[8],
+		const char *galPrefix) {
+	TiXmlElement *child;
+	const char *text;
+	unsigned long a10;
+	char *endp;
+	int length;
+	std::string pfx;
+
+	node = getNode(node, prefix, label);
+	if (node == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseAddress - %s element not found",
+				label);
+#endif
+		return 1;
+	}
+
+	child = node->FirstChildElement();
+	if (child == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseAddress - No address info is empty");
+#endif
+		return 1;
+	}
+
+	text = child->GetText();
+	if (text == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseAddress - %s/%s is empty",
+				node->ValueStr().c_str(),
+				child->ValueStr().c_str());
+#endif
+	}
+
+	memset(address, 0, sizeof(address));
+
+	if (galPrefix != NULL) {
+		pfx += galPrefix;
+		pfx += ":";
+	}
+
+	if (child->ValueStr().find(pfx + "IeeeAddress") != string::npos) {
+		text += strspn(text, BLANKS);
+		length = 0;
+		while (isdigit(text[length]))
+			length++;
+		if (length <= 0 || text[length + strspn(text + length, BLANKS)]) {
+//#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+			pLogger->debug("parseAddress - bad IEEE address "
+					" '%s'", text);
+//#endif
+			return 1;
+		}
+
+		unsigned long long value;
+		sscanf(text, "%llu", &value);
+		pLogger->info("IEEE Address : %llx",value);
+
+		char ieeeAddr[17];
+		sprintf(ieeeAddr, "%.16llx", value);
+
+		//pLogger->info("IEEE Address (string) : %s",ieeeAddr);
+		int address2[8];
+
+		sscanf(ieeeAddr, "%2x%2x%2x%2x%2x%2x%2x%2x", &address2[0], &address2[1],
+				&address2[2], &address2[3], &address2[4], &address2[5],
+				&address2[6], &address2[7]);
+		int z = 7;
+		for (int c = 0; c < 8; c++) {
+			address[c] = (unsigned char) (address2[z] & 0xFF);
+			z--;
+		}
+		pLogger->info("IEEE Address reversed - %0.2x%0.2x%0.2x%0.2x%0.2x%0.2x%0.2x%0.2x",address[0],address[1],address[2],address[3],address[4],address[5],address[6],address[7]);
+		mode = 3;
+	} else if (child->ValueStr().find(pfx + "NetworkAddress") != string::npos) {
+		text += strspn(text, BLANKS);
+		a10 = strtoul(text, &endp, 10);
+		endp += strspn(endp, BLANKS);
+		if (*endp || endp == text) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+			pLogger->debug("parseAddress - bad nwk address "
+					" '%s'", text);
+#endif
+		}
+		mode = 2;
+		address[0] = a10 & 0xff;
+		address[1] = (a10 >> 8) & 0xff;
+
+	} else if ((child->ValueStr().find(pfx + "AliasAddress")) != string::npos) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseAddress - alias addresses not supported");
+#endif
+		return 1;
+	} else {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseAddress - %s address type is unknown", child->ValueStr().c_str());
+#endif
+		return 1;
+	}
+
+	return 0;
+}
+
+int XMLMsgParser::parseDeviceElement(TiXmlElement *node, const char *prefix,
+		const char *label, uchar &endPoint, unsigned char address[8],
+		const char *galPrefix) {
+	TiXmlElement *child;
+	const char *text;
+	int length;
+	long l;
+	std::string pfx;
+	//const char endPointLabel[13] = "gal:Endpoint";
+
+	node = getNode(node, prefix, label);
+	if (node == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseDeviceElement - %s element not found", label);
+#endif
+		return 1;
+	}
+
+	child = node->FirstChildElement();
+
+	if (child == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseDeviceElement - No Device info (empty)");
+#endif
+		return 1;
+	}
+
+	text = child->GetText();
+	if (text == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseDeviceElement - %s/%s is empty",
+				node->ValueStr().c_str(),
+				child->ValueStr().c_str());
+#endif
+	}
+
+	memset(address, 0, sizeof(address));
+
+	if (galPrefix != NULL) {
+		pfx += galPrefix;
+		pfx += ":";
+	}
+
+	if (child->ValueStr().find(pfx + "Address") != string::npos) {
+		text += strspn(text, BLANKS);
+		length = 0;
+		while (isdigit(text[length]))
+			length++;
+		if (length <= 0 || text[length + strspn(text + length, BLANKS)]) {
+			pLogger->debug("parseDeviceElement - bad IEEE address "
+					" '%s'", text);
+			return 1;
+		}
+
+		unsigned long long value;
+		sscanf(text, "%llu", &value);
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->info("IEEE Address : %llx",value);
+#endif
+		char ieeeAddr[17];
+		sprintf(ieeeAddr, "%.16llx", value);
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->info("IEEE Address (string) : %s",ieeeAddr);
+#endif
+		int address2[8];
+		sscanf(ieeeAddr, "%2x%2x%2x%2x%2x%2x%2x%2x", &address2[0], &address2[1],
+				&address2[2], &address2[3], &address2[4], &address2[5],
+				&address2[6], &address2[7]);
+		int z = 7;
+		for (int c = 0; c < 8; c++) {
+			address[c] = (unsigned char) (address2[z] & 0xFF);
+			z--;
+		}
+		pLogger->info("IEEE Address - %0.2x%0.2x%0.2x%0.2x%0.2x%0.2x%0.2x%0.2x",address[0],address[1],address[2],address[3],address[4],address[5],address[6],address[7]);
+		//mode = 3;
+	} else {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseDeviceElement - %s address type is unknown", child->ValueStr().c_str());
+#endif
+		return 1;
+	}
+
+	// Get the endpoint
+	if (parseLong(node, galPrefix, "Endpoint", l, 10, 0, 255)) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseDeviceElement - Endpoint not found!");
+#endif
+		return 1;
+	}
+	endPoint = (uchar) l;
+	return 0;
+}
+
+/**
+ Public method XMLMsgParser parseTxOptions.
+ Parses a 'TxOptions' type element, returning the ZigBee bitfield.
+
+ The node parameter is the 'Address' tag
+ In the former case, 'label' should be null; in the latter, it should
+ be the tag of the child tag to parse.
+
+ @param node the node to start from
+ @param label if not null, the name of the child tag to parse
+ @param value the bitfield
+ @param address where to the address (either as a short or long address)
+ @return an integer: 0 if it has done everything, 1 otherwise .
+ */
+int XMLMsgParser::parseTxOptions(TiXmlElement *node, const char *prefix,
+		const char *label, uchar &value, const char *galPrefix) {
+	bool b;
+
+	node = getNode(node, prefix, label);
+	if (node == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseTxOptions - %s element not found",
+				label);
+#endif
+		return 1;
+	}
+
+	value = 0;
+	if (parseBoolean(node, galPrefix, "SecurityEnabled", b))
+		return 1;
+	if (b)
+		value |= 1;
+
+	if (parseBoolean(node, galPrefix, "UseNetworkKey", b))
+		return 1;
+	if (b)
+		value |= 2;
+
+	if (parseBoolean(node, galPrefix, "Acknowledged", b))
+		return 1;
+	if (b)
+		value |= 4;
+
+	if (parseBoolean(node, galPrefix, "PermitFragmentation", b))
+		return 1;
+	if (b)
+		value |= 8;
+
+	return 0;
+}
+
+int XMLMsgParser::parseBoolean(TiXmlElement *node, const char *prefix,
+		const char *label, bool &value) {
+	const char *text;
+
+	node = getNode(node, prefix, label);
+	if (node == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseBoolean - %s element not found",
+				label);
+#endif
+		return 1;
+	}
+
+	text = node->GetText();
+	if (text == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseBoolean - %s is empty",
+				node->ValueStr().c_str());
+#endif
+		return 1;
+	}
+
+	text += strspn(text, BLANKS);
+	if (!strncasecmp(text, "true", 4))
+		value = TRUE;
+	else if (!strncasecmp(text, "false", 5))
+		value = FALSE;
+	else {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseBoolean - %s is invalid: '%s'",
+				node->ValueStr().c_str(), text);
+#endif
+		return 1;
+	}
+
+	return 0;
+}
+
+int XMLMsgParser::parseLong(TiXmlElement *node, const char *prefix,
+		const char *label, long &l, int base, long min, long max) {
+	const char *text;
+	char *endp;
+
+	node = getNode(node, prefix, label);
+	if (node == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseLong - %s element not found",
+				label);
+#endif
+		return 1;
+	}
+
+	text = node->GetText();
+	if (text == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseLong - %s is empty",
+				node->ValueStr().c_str());
+#endif
+		return 1;
+	}
+
+	text += strspn(text, BLANKS);
+	l = strtol(text, &endp, base);
+	if (endp == text || *endp) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseLong - %s is invalid: '%s'",
+				node->ValueStr().c_str(), text);
+#endif
+		return 1;
+	}
+
+	if (l < min || l > max) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseLong - %s - %l is not within %l and %l",
+				node->ValueStr().c_str(), l, min, max);
+#endif
+		return 1;
+	}
+
+	return 0;
+}
+
+int XMLMsgParser::parseHex(TiXmlElement *node, const char *prefix,
+		const char *label, unsigned char *&p, long &length) {
+	const char *text;
+	int i, j, digit;
+	int len;
+
+	node = getNode(node, prefix, label);
+	if (node == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseHex - %s element not found",
+				label);
+#endif
+		return 1;
+	}
+
+	text = node->GetText();
+	if (text == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseHex - %s is empty",
+				node->ValueStr().c_str());
+#endif
+		return 1;
+	}
+
+	text += strspn(text, BLANKS);
+	len = strspn(text, HEX);
+	if (!len || text[len + strspn(text + len, BLANKS)]) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseHex - %s is an invalid hex string",
+				node->ValueStr().c_str());
+#endif
+		return 1;
+	}
+
+	if (len & 1) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseHex - %s - odd number of digits",
+				node->ValueStr().c_str());
+#endif
+		return 1;
+	}
+
+	p = new unsigned char[len / 2];
+	if (p == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseHex - %s - Out of memory",
+				node->ValueStr().c_str());
+#endif
+		return 1;
+	}
+	memset(p, 0, len / 2);
+
+	i = j = 0;
+	while (i < len) {
+		digit = isdigit(text[i]) ? text[i] - '0' : tolower(text[i]) - 'a' + 10;
+		i++;
+		p[j] |= digit << 4;
+
+		digit = isdigit(text[i]) ? text[i] - '0' : tolower(text[i]) - 'a' + 10;
+		i++;
+		p[j] |= digit;
+		j++;
+	}
+
+	length = j;
+
+	return 0;
+}
+
+int XMLMsgParser::parseEnumeration(TiXmlElement *node, const char *prefix,
+		const char *label, StrIntMap *restriction, int &value) {
+	const char *text;
+
+	node = getNode(node, prefix, label);
+	if (node == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseEnumeration - %s element not found",
+				label);
+#endif
+		return 1;
+	}
+
+	text = node->GetText();
+	if (text == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("parseEnumeration - %s is empty",
+				node->ValueStr().c_str());
+#endif
+		return 1;
+	}
+
+	std::map<string, int>::iterator it;
+	it = restriction->find(text);
+	if (it != restriction->end()) {
+		value = it->second;
+		pLogger->info("parseEnumeration - value = %d ",value);
+	} else {
+		pLogger->info("parseEnumeration - value present but not valid");
+		return 2;
+	}
+	return 0;
+}
+
+/**
+ Public method XMLMsgParser getZCLCommandToWSN
+ This method analyzes a XML message (xmlMsg) in order to fill the message will be send to ZigBee network.
+
+ @param msg pointer to an instance of class Message.
+ @param xmlMsg XML message to be analyzed.
+ @return an integer: 0 if it has done everything, 1 otherwise .
+ */
+
+int XMLMsgParser::getZCLCommandToWSN(Message *msg, std::string *xmlMsg) {
+	/*
+	 <tns:ZCLCommand>
+	 <gal:DestinationAddressMode>1</gal:DestinationAddressMode>
+	 <gal:DestinationAddress>
+	 <gal:NetworkAddress>1</gal:NetworkAddress>
+	 <gal:IEEEAddress>3781220503714125</gal:IEEEAddress>
+	 </gal:DestinationAddress>
+	 <gal:DestinationEndpoint>1</gal:DestinationEndpoint>
+	 <gal:SourceEndpoint>1</gal:SourceEndpoint>
+	 <gal:ProfileID>1</gal:ProfileID>
+	 <gal:ClusterID>2</gal:ClusterID>
+	 <gal:ZCLHeader>010203</gal:ZCLHeader>
+	 <gal:ZCLPayload>0405060708090a0b0c0d0e0f</gal:ZCLPayload>
+	 <gal:TxOptions>
+	 <gal:SecurityEnabled>true</gal:SecurityEnabled>
+	 <gal:UseNetworkKey>true</gal:UseNetworkKey>
+	 <gal:Acknowledged>true</gal:Acknowledged>
+	 <gal:PermitFragmentation>true</gal:PermitFragmentation>
+	 </gal:TxOptions>
+	 <gal:Radius>3</gal:Radius>
+	 </tns:ZCLCommand>
+	 */
+
+	TiXmlDocument doc;
+	TiXmlElement *node;
+	uchar address[8];
+	uchar swappedAddr[8];
+	uchar* zclHeader;
+	uchar* zclPayload;
+	std::string root;
+	const char *galPrefix, *restPrefix;
+	uchar c;
+	long l, i;
+
+	node = getRoot(doc, *xmlMsg, root, galPrefix, restPrefix);
+	if (node == NULL || root.compare("ZCLCommand") != 0) {
+		//#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getZCLCommandToWSN - ZCLCommand element not found");
+		//#endif
+		return 1;
+	}
+
+	/*	Ignore it and use the value extracted by parseAddress, "c"
+	 if (parseLong (node, galPrefix, "DestinationAddressMode", l, 10, 0, 255)){
+	 //#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+	 pLogger->debug("getZCLCommandToWSN - WARNING: DestinationAddressMode element not present");
+	 //#endif
+	 } else
+	 msg->setDstAddrMode(l);
+	 */
+	if (parseAddress(node, galPrefix, "DestinationAddress", c, address,
+			galPrefix)) {
+		//#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getZCLCommandToWSN - WARNING: DestinationAddress element not present");
+		//#endif
+	} else {
+		msg->setDstAddrMode(c);
+		if (c == ZB_AM_DIRECT) {
+			swappedAddr[0] = address[1];
+			swappedAddr[1] = address[0];
+			msg->setDstAddr(swappedAddr);
+		} else {
+			swappedAddr[0] = address[7];
+			swappedAddr[1] = address[6];
+			swappedAddr[2] = address[5];
+			swappedAddr[3] = address[4];
+			swappedAddr[4] = address[3];
+			swappedAddr[5] = address[2];
+			swappedAddr[6] = address[1];
+			swappedAddr[7] = address[0];
+			msg->setDstAddr(swappedAddr);
+		}
+	}
+
+	if (parseLong(node, galPrefix, "DestinationEndpoint", l, 10, 0, 255)) {
+		//#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getZCLCommandToWSN - WARNING: DestinationEndpoint element not present");
+		//#endif
+	} else
+		msg->setDstEp((uchar) l);
+
+	if (parseLong(node, galPrefix, "ProfileID", l, 10, 0, 65535)) {
+		//#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getZCLCommandToWSN - WARNING: ProfileID element not present");
+		//#endif
+	} else
+		msg->setProfileId(l);
+
+	if (parseLong(node, galPrefix, "ClusterID", l, 10, 0, 65535)) {
+		pLogger->debug("getZCLCommandToWSN - ERROR: ClusterID element not present");
+		return 1;
+	}
+	msg->setClusterId(l);
+
+	if (parseLong(node, galPrefix, "SourceEndpoint", l, 10, 0, 255)) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getZCLCommandToWSN - WARNING: SourceEndpoint element not present");
+#endif
+	} else
+		msg->setSrcEp((uchar) l);
+
+	if (parseTxOptions(node, galPrefix, "TxOptions", c, galPrefix)) {
+		pLogger->debug("getZCLCommandToWSN - ERROR: TxOptions element not present");
+		return 1;
+	}
+	msg->setTxSettings(c);
+
+	if (parseLong(node, galPrefix, "Radius", l, 10, 0, 255)) {
+		pLogger->debug("getZCLCommandToWSN - ERROR: Radius element not present");
+		return 1;
+	}
+	msg->setMaxHopsNumber(l);
+
+	if (parseHex(node, galPrefix, "ZCLPayload", zclPayload, i)) {
+		pLogger->debug("getZCLCommandToWSN - ERROR: ZCLPayload element not present");
+		return 1;
+	}
+
+	if (parseHex(node, galPrefix, "ZCLHeader", zclHeader, l)) {
+		pLogger->debug("getZCLCommandToWSN - ERROR: ZCLHeader element not present");
+		return 1;
+	}
+
+	msg->concatenateZCLHeaderAndPayload(zclHeader, l, zclPayload, i);
+
+	delete[] zclHeader;
+	delete[] zclPayload;
+
+	return 0;
+}
+
+/**
+ Public method XMLMsgParser getZDPCommandToWSN
+ This method analyzes a XML message (xmlMsg) in order to fill the message will be send to ZigBee network.
+
+ @param msg pointer to an instance of class Message.
+ @param xmlMsg XML message to be analyzed.
+ @return an integer: 0 if it has done everything, 1 otherwise .
+ */
+
+int XMLMsgParser::getZDPCommandToWSN(Message *msg, std::string *xmlMsg) {
+	/*
+	 <complexType name="ZDPCommand">
+	 <sequence>
+	 <element name="Destination" type="tns:Address"
+	 minOccurs="1" maxOccurs="1" />
+	 <element name="TxOptions" type="tns:TxOptions" minOccurs="0"
+	 maxOccurs="1" />
+	 <element name="Radius" type="unsignedByte" minOccurs="0"
+	 maxOccurs="1" />
+	 <element name="ClusterID" type="tns:ClusterIdentifier"
+	 minOccurs="1" maxOccurs="1" />
+	 <element name="CommandID" type="hexBinary" minOccurs="1"
+	 maxOccurs="1" />
+	 <element name="DestinationAddrMode" type="unsignedInt"
+	 minOccurs="1"  maxOccurs="1"/>
+	 </sequence>
+	 </complexType>
+	 */
+
+	TiXmlDocument doc;
+	TiXmlElement *node;
+	uchar address[8];
+	uchar swappedAddr[8];
+	std::string root;
+	const char *galPrefix, *restPrefix;
+	uchar traSeqNum[2] = { 0x00, 0x01 };
+	uchar* command;
+	uchar c;
+	long l;
+
+	node = getRoot(doc, *xmlMsg, root, galPrefix, restPrefix);
+	if (node == NULL || root.compare("ZDPCommand") != 0) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getZDPCommandToWSN - ZDPCommand element not found");
+#endif
+		return 1;
+	}
+
+	if (parseAddress(node, galPrefix, "Destination", c, address, galPrefix)) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getZDPCommandToWSN - WARNING: Destination element not present");
+#endif
+	} else {
+		msg->setDstAddrMode(c);
+		if (c == ZB_AM_DIRECT) {
+			swappedAddr[0] = address[1];
+			swappedAddr[1] = address[0];
+			msg->setDstAddr(swappedAddr);
+		} else {
+			swappedAddr[0] = address[7];
+			swappedAddr[1] = address[6];
+			swappedAddr[2] = address[5];
+			swappedAddr[3] = address[4];
+			swappedAddr[4] = address[3];
+			swappedAddr[5] = address[2];
+			swappedAddr[6] = address[1];
+			swappedAddr[7] = address[0];
+			msg->setDstAddr(swappedAddr);
+		}
+	}
+
+	if (parseTxOptions(node, galPrefix, "TxOptions", c, galPrefix)) {
+		pLogger->debug("getZDPCommandToWSN - ERROR: TxOptions element not present");
+	} else
+		msg->setTxSettings(c);
+
+	if (parseLong(node, galPrefix, "Radius", l, 10, 0, 255)) {
+		pLogger->debug("getZDPCommandToWSN - WARNING: Radius element not present");
+	} else
+		msg->setMaxHopsNumber(l);
+
+	if (parseLong(node, galPrefix, "ClusterID", l, 10, 0, 65535)) {
+		pLogger->debug("getZDPCommandToWSN - ERROR: ClusterID element not present");
+		return 1;
+	}
+	msg->setClusterId(l);
+
+	if (parseHex(node, galPrefix, "Command", command, l)) {
+		pLogger->debug("getZDPCommandToWSN - ERROR: Command element not present");
+		return 1;
+	}
+	//Note: ZCLHeader in this case acts for "traSeqNum"...
+	msg->concatenateZCLHeaderAndPayload(traSeqNum, 2, command, l); //The ASDU shall be the ZDP command frame (ZigBee spec from page 99...)
+
+	delete[] command;
+
+	// Finally, set all the default values..
+	msg->setSrcEp(0x00);
+	msg->setDstEp(0x00);
+	msg->setProfileId(0x0000);
+	return 0;
+}
+
+/**
+ Public method XMLMsgParser getAPSMessageToWSN
+ This method analyzes a XML message (xmlMsg) in order to fill the message will be send to ZigBee network.
+
+
+ @param msg pointer to an instance of class Message.
+ @param xmlMsg XML message to be analyzed.
+ @return an integer: 0 if it has done everything, 1 otherwise .
+ */
+
+int XMLMsgParser::getAPSMessageToWSN(Message *msg, std::string *xmlMsg) {
+
+	/*
+
+	 <tns:APSMessage>
+	 <gal:DestinationAddress>
+	 <gal:NetworkAddress>12348</gal:NetworkAddress>
+	 <gal:IEEEAddress>3781220503714125</gal:IEEEAddress>
+	 </gal:DestinationAddress>
+	 <gal:DestinationEndpoint>1</gal:DestinationEndpoint>
+	 <gal:SourceEndpoint>1</gal:SourceEndpoint>
+	 <gal:ProfileID>1</gal:ProfileID>
+	 <gal:ClusterID>2</gal:ClusterID>
+	 <gal:Data>0102030405060708090a0b0c0d0e0f</gal:Data>
+	 <gal:TxOptions>
+	 <gal:SecurityEnabled>true</gal:SecurityEnabled>
+	 <gal:UseNetworkKey>true</gal:UseNetworkKey>
+	 <gal:Acknowledged>true</gal:Acknowledged>
+	 <gal:PermitFragmentation>true</gal:PermitFragmentation>
+	 </gal:TxOptions>
+	 <gal:Radius>3</gal:Radius>
+	 </tns:APSMessage>
+
+	 */
+	TiXmlDocument doc;
+	TiXmlElement *node;
+	uchar address[8];
+	uchar swappedAddr[8];
+	uchar* payload;
+	std::string root;
+	const char *galPrefix, *restPrefix;
+	uchar c;
+	long l;
+
+	node = getRoot(doc, *xmlMsg, root, galPrefix, restPrefix);
+	if (node == NULL || root.compare("APSMessage") != 0) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getMessageToWSN - APSMessage element not found");
+#endif
+		return 1;
+	}
+
+	if (parseLong(node, galPrefix, "DestinationEndpoint", l, 10, 0, 255))
+		return 1;
+	msg->setDstEp((uchar) l);
+
+	if (parseLong(node, galPrefix, "SourceEndpoint", l, 10, 0, 255))
+		return 1;
+	msg->setSrcEp((uchar) l);
+
+	if (parseLong(node, galPrefix, "ProfileID", l, 10, 0, 65535)) {
+//#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getMessageToWSN - WARNING: ProfileID element not present");
+//#endif
+	} else {
+		msg->setProfileId(l);
+	}
+
+	if (parseLong(node, galPrefix, "ClusterID", l, 10, 0, 65535))
+		return 1;
+	msg->setClusterId(l);
+
+	if (parseTxOptions(node, galPrefix, "TxOptions", c, galPrefix))
+		return 1;
+	msg->setTxSettings(c);
+
+	if (parseLong(node, galPrefix, "Radius", l, 10, 0, 255))
+		return 1;
+	msg->setMaxHopsNumber(l);
+
+	if (parseHex(node, galPrefix, "Data", payload, l))
+		return 1;
+	msg->setPayload(payload, l);
+
+	delete[] payload;
+
+	if (parseAddress(node, galPrefix, "DestinationAddress", c, address,
+			galPrefix)) {
+		return 1;
+	}
+	msg->setDstAddrMode(c);
+	if (c == ZB_AM_DIRECT) {
+		swappedAddr[0] = address[1];
+		swappedAddr[1] = address[0];
+		msg->setDstAddr(swappedAddr);
+	} else {
+		swappedAddr[0] = address[7];
+		swappedAddr[1] = address[6];
+		swappedAddr[2] = address[5];
+		swappedAddr[3] = address[4];
+		swappedAddr[4] = address[3];
+		swappedAddr[5] = address[2];
+		swappedAddr[6] = address[1];
+		swappedAddr[7] = address[0];
+		msg->setDstAddr(swappedAddr);
+	}
+	return 0;
+}
+
+int XMLMsgParser::getBindindCommand(ZB_BIND_STRUCT *bindParams,
+		std::string *xmlMsg) {
+	/*
+	 <tns:Binding>
+	 <gal:SourceIEEEAddress>3781220503714125</gal:SourceIEEEAddress>
+	 <gal:SourceEndpoint>1</gal:SourceEndpoint>
+	 <gal:ClusterID>2</gal:ClusterID>
+	 <gal:GroupDestination>1234</gal:GroupDestination>
+	 <gal:DeviceDestination>
+	 <gal:Address>3781220503714125</gal:Address>
+	 <gal:Endpoint>1</gal:Endpoint>
+	 </gal:DeviceDestination>
+	 </tns:Binding>
+	 */
+
+	TiXmlDocument doc;
+	TiXmlElement *node, *child;
+	uchar address[8];
+	uchar swappedAddr[8];
+	//uchar* payload;
+	std::string root;
+	const char *galPrefix, *restPrefix;
+	//const char sourceLabel[19] = "SourceIEEEAddress";
+	uchar c;
+	long l;
+	const char *text;
+	//unsigned long a10;
+	int length;
+	std::string pfx;
+
+	node = getRoot(doc, *xmlMsg, root, galPrefix, restPrefix);
+	if (node == NULL || root.compare("Binding") != 0) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getBindindCommand - Binding element not found");
+#endif
+		return 1;
+	}
+	// Get the SourceIEEEAddress
+	child = node->FirstChildElement();
+	if (child == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getBindindCommand - No SourceIEEEAddress (empty)");
+#endif
+		return 1;
+	}
+	text = child->GetText();
+	if (text == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getBindindCommand - %s/%s is empty", node->ValueStr().c_str(),child->ValueStr().c_str());
+#endif
+	}
+	memset(address, 0, sizeof(address));
+	if (galPrefix != NULL) {
+		pfx += galPrefix;
+		pfx += ":";
+	}
+	if (child->ValueStr().find(pfx + "SourceIEEEAddress") != string::npos) {
+		text += strspn(text, BLANKS);
+		length = 0;
+		while (isdigit(text[length]))
+			length++;
+		if (length <= 0 || text[length + strspn(text + length, BLANKS)]) {
+			pLogger->debug("getBindindCommand - bad IEEE address '%s'", text);
+			return 1;
+		}
+		unsigned long long value;
+		sscanf(text, "%llu", &value);
+		pLogger->info("IEEE Address : %llx",value);
+		char ieeeAddr[17];
+		sprintf(ieeeAddr, "%.16llx", value);
+		pLogger->info("IEEE Address (string) : %s",ieeeAddr);
+		int address2[8];
+		sscanf(ieeeAddr, "%2x%2x%2x%2x%2x%2x%2x%2x", &address2[0], &address2[1],
+				&address2[2], &address2[3], &address2[4], &address2[5],
+				&address2[6], &address2[7]);
+
+		/*
+		 int z = 7;
+		 for (int c=0; c<8; c++)
+		 {
+		 bindParams->src_addr[c] = (unsigned char) (address2[z] & 0xFF);
+		 z--;
+		 }
+		 */
+		for (int c = 0; c < 8; c++) {
+			bindParams->src_addr[c] = (unsigned char) (address2[c] & 0xFF);
+		}
+		pLogger->info("IEEE Address - %0.2x%0.2x%0.2x%0.2x%0.2x%0.2x%0.2x%0.2x",bindParams->src_addr[0],
+				bindParams->src_addr[1],bindParams->src_addr[2],bindParams->src_addr[3],bindParams->src_addr[4],
+				bindParams->src_addr[5],bindParams->src_addr[6],bindParams->src_addr[7]);
+	} else {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getBindindCommand - %s address type is unknown", child->ValueStr().c_str());
+#endif
+		return 1;
+	}
+	// Get the SourceEndpoint
+	if (parseLong(node, galPrefix, "SourceEndpoint", l, 10, 0, 255)) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getBindindCommand - SourceEndpoint not found!");
+#endif
+		return 1;
+	}
+	bindParams->src_ep = (uchar) l;
+	// Get the ClusterID
+	if (parseLong(node, galPrefix, "ClusterID", l, 10, 0, 65535)) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getBindindCommand - ClusterID not found!");
+#endif
+		return 1;
+	}
+	bindParams->cluster_id = l;
+	// Get the GroupDestination
+	if (parseLong(node, galPrefix, "GroupDestination", l, 10, 0, 255)) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getBindindCommand - Optional element GroupDestination not found");
+#endif
+	}
+	//Group destination ignored (not need for this command)
+	//bindParams->groupDestination = (uchar) l;
+	// Get the DeviceDestination element
+	if (parseDeviceElement(node, galPrefix, "DeviceDestination", c, address,
+			galPrefix)) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getBindindCommand - DeviceDestination parsing error");
+#endif
+		return 1;
+	}
+	// Store the Endpoint (destEndPoint)
+	bindParams->dst_ep = c;
+	// Store the IEEEAddress (DestionationAddress)
+	swappedAddr[0] = address[7];
+	swappedAddr[1] = address[6];
+	swappedAddr[2] = address[5];
+	swappedAddr[3] = address[4];
+	swappedAddr[4] = address[3];
+	swappedAddr[5] = address[2];
+	swappedAddr[6] = address[1];
+	swappedAddr[7] = address[0];
+	memcpy(bindParams->dst_addr, swappedAddr, 8);
+	//memcpy(bindParams->dst_addr, address, 8);
+	return 0;
+}
+
+int XMLMsgParser::getSimpleDescriptor(SimpleDescriptor *sd,
+		std::string *xmlMsg) {
+	TiXmlDocument doc;
+	TiXmlElement *node, *p;
+	const char *galPrefix, *restPrefix;
+	std::string root, label;
+	long l;
+
+	node = getRoot(doc, *xmlMsg, root, galPrefix, restPrefix);
+	if (node == NULL || root.compare("SimpleDescriptor") != 0) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getSimpleDescriptor - SimpleDescriptor element not found");
+#endif
+		return 1;
+	}
+
+	if (parseLong(node, galPrefix, "EndPoint", l, 10, 0, 65535)) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("WARNING: SimpleDescriptor element does not contain an EndPoint value");
+#endif
+		// Set endPoint value equals to zero since this is a not allow value (it is reserved for ZDO messages)
+		sd->end_point = 0;
+	} else
+		sd->end_point = l;
+	if (parseLong(node, galPrefix, "ApplicationProfileIdentifier", l, 10, 0,
+			65535)) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("WARNING: SimpleDescriptor element does not contain an ApplicationProfileIdentifier value");
+#endif
+	} else
+		sd->profile_id = l;
+
+	if (parseLong(node, galPrefix, "ApplicationDeviceIdentifier", l, 10, 0,
+			65535)) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("WARNING: SimpleDescriptor element does not contain an ApplicationDeviceIdentifier value");
+#endif
+	} else
+		sd->device_id = l;
+
+	if (parseLong(node, galPrefix, "ApplicationDeviceVersion", l, 10, 0, 15)) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("WARNING: SimpleDescriptor element does not contain an ApplicationDeviceVersion value");
+#endif
+	} else
+		sd->device_ver = l;
+
+	p = NULL;
+	while (1) {
+		p = getNode(node, galPrefix, "ApplicationInputCluster", p);
+		if (p == NULL)
+			break;
+
+		if (parseLong(p, NULL, NULL, l, 10, 0, 65535))
+			return 1;
+
+		sd->input_cluster.push_back(l);
+	}
+
+	p = NULL;
+	while (1) {
+		p = getNode(node, galPrefix, "ApplicationOutputCluster", p);
+		if (p == NULL)
+			break;
+
+		if (parseLong(p, NULL, NULL, l, 10, 0, 65535))
+			return 1;
+
+		sd->output_cluster.push_back(l);
+	}
+
+	//TODO: Those two parameters are not standard, check what they accomplish
+	sd->complex_desc_available = 0;
+	sd->user_desc_available = 0;
+
+	return 0;
+}
+
+int XMLMsgParser::getJoiningInfoValues(int *PermitDuration,
+		bool *TCSignificance, std::string *xmlMsg) {
+	TiXmlDocument doc;
+	TiXmlElement *node;
+	const char *galPrefix, *restPrefix;
+	std::string root, label;
+	long l;
+
+	node = getRoot(doc, *xmlMsg, root, galPrefix, restPrefix);
+	if (node == NULL || root.compare("JoiningInfo") != 0) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getJoiningInfoValues - JoiningInfo element not found");
+#endif
+		return 1;
+	}
+
+	if (parseLong(node, galPrefix, "PermitDuration", l, 10, 0, 65535)) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("ERROR: PermitDuration value not present");
+#endif
+		return 1;
+	} else
+		*PermitDuration = l;
+
+	if (parseBoolean(node, galPrefix, "TCSignificance", *TCSignificance))
+		return 1;
+
+	return 0;
+}
+
+int XMLMsgParser::getCallback(Callback *cb, std::string *xmlMsg) {
+	/* EXAMPLE
+
+	 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+	 <Callback xmlns:ns2="http://www.zigbee.org/GWGRESTSchema" xmlns:ns3="http://www.zigbee.org/GWGSchema">
+	 <ns3:Filter>
+	 <ns3:LevelSpecification>		--uno!
+	 <ns3:Level>APSLevel</ns3:Level>	-- uno o pi�!
+	 </ns3:LevelSpecification>
+	 <ns3:AddressSpecification>	-- zero o pi�!
+	 <ns3:NWKSourceAddress>
+	 <ns3:NetworkAddress>3412</ns3:NetworkAddress>	-- zero o uno
+	 </ns3:NWKSourceAddress>
+	 <ns3:APSSourceEndpoint>
+	 <ns3:Endpoint>01</ns3:Endpoint>	-- zero o uno
+	 </ns3:APSSourceEndpoint>
+	 <ns3:APSDestinationEndpoint>
+	 <ns3:Endpoint>01</ns3:Endpoint>	-- zero o uno
+	 </ns3:APSDestinationEndpoint>
+	 </ns3:AddressSpecification>
+	 <ns3:MessageSpecification>			-- zero o pi�!
+	 <ns3:APSClusterIdentifier>
+	 <ns3:ClusterIdentifier>3412</ns3:ClusterIdentifier>	-- zero o uno!
+	 </ns3:APSClusterIdentifier>
+	 <ns3:APSClusterGroup>
+	 <ns3:ClusterGroup>3412</ns3:ClusterGroup>	-- zero o uno!
+	 </ns3:APSClusterGroup>
+	 </ns3:MessageSpecification>
+	 </ns3:Filter>
+	 <ns3:Buffer>0000000000000</ns3:Buffer>
+	 <ns3:Action>
+	 <ns3:DecodeSpecification>	-- uno!
+	 <ns3:DecodeLevel>DecodeMAC</ns3:DecodeLevel>	-- uno o pi�!
+	 </ns3:DecodeSpecification>
+	 <ns3:callbackDestination>00000000</ns3:callbackDestination>	-- uno!
+	 <ns3:ForwardingSpecification>	-- uno!
+	 <ns3:ForwardScheme>1234</ns3:ForwardScheme>
+	 </ns3:ForwardingSpecification>
+	 </ns3:Action>
+	 </Callback>
+
+	 * */
+
+	TiXmlDocument doc;
+	TiXmlElement *node, *tmp, *sub1, *sub2;
+	const char *galPrefix, *restPrefix;
+	std::string root, label;
+	long l;
+	uchar c;
+	uchar address[8];
+
+	Filter filter;
+	LevelSpecification ls;
+	AddressSpecification as;
+	MessageSpecification ms;
+
+	Action action;
+
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+	pLogger->debug("getCallback");
+#endif
+
+	// Get the root element
+	node = getRoot(doc, *xmlMsg, root, galPrefix, restPrefix);
+
+	if (node == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->warn("getCallback - ERROR: Callback element not found");
+#endif
+		return 2;
+	}
+
+	if (root.compare("Callback") != 0) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getCallback - ERROR: Callback element not found");
+#endif
+		return 1;
+	}
+
+	// Get the "Filter" sub-element ************ FILTER ************
+	sub1 = getNode(node, galPrefix, "Filter");
+	if (sub1 == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getCallback - WARNING: Filter element not present");
+#endif
+
+		filter.isDefined = false;
+		// Continue, since Filter element is optional
+
+	} else {
+		// Filter defined
+		filter.isDefined = true;
+
+		// Extract the  the "LevelSpecification" sub-element
+		sub2 = getNode(sub1, galPrefix, "LevelSpecification", NULL);
+		if (sub2 == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+			pLogger->debug("getCallback - ERROR: LevelSpecification element not found!");
+#endif
+			// Return Error Code 1: "LevelSpecification" sub-element must be present!
+			return 1;
+		} else {
+
+			// Get all the Level values
+			tmp = NULL;
+			while (1) {
+
+				tmp = getNode(sub2, galPrefix, "Level", tmp);
+				if (tmp == NULL)
+					break;
+				ls.level += std::string(tmp->GetText());
+			}
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+			pLogger->debug("getCallback - ls.level found: %s",ls.level.c_str());
+#endif
+			filter.levelSpec = ls;
+		}
+
+		// Extract the  the "AddressSpecification" sub-element
+		sub2 = getNode(sub2, galPrefix, "AddressSpecification", sub2);
+
+		if (sub2 == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+			pLogger->debug("getCallback - WARNING: AddressSpecification element not present!");
+#endif
+			as.isDefined = false;
+			as.isNWKSourceAddressDefined = false;
+			as.isAPSSourceEndpointDefined = false;
+			as.isAPSDestinationEndpointDefined = false;
+
+			// AddressSpecification is optional, leave empty!
+		} else {
+
+			as.isDefined = true;
+
+			// Get all the values
+			// Extract the  the "AddressSpecification" sub-element
+			if (parseAddress(sub2, galPrefix, "NWKSourceAddress", c, address,
+					galPrefix)) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+				pLogger->debug("getCallback - WARNING: NWKSourceAddress element not present!");
+#endif
+				as.isNWKSourceAddressDefined = false;
+			} else {
+				//TODO ..... TO BE CHECKED!
+				memcpy(&(as.NWKSourceAddress), address, sizeof(short));
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+				pLogger->debug("getCallback - address found: %04x",as.NWKSourceAddress);
+#endif
+
+				as.isNWKSourceAddressDefined = true;
+			}
+
+			tmp = getNode(sub2, galPrefix, "APSSourceEndpoint", NULL);
+			if (tmp == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+				pLogger->debug("getCallback - WARNING: APSSourceEndpoint element not present!");
+#endif
+				as.isAPSSourceEndpointDefined = false;
+				// APSSourceEndpoint is optional, leave empty!
+			} else {
+				if (parseLong(tmp, NULL, NULL, l, 10, 0, 65535))
+					return 1;
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+				pLogger->debug("getCallback - APSSourceEndpoint found: %li\r\n",l);
+#endif
+
+				as.APSSourceEndpoint = l;
+				as.isAPSSourceEndpointDefined = true;
+			}
+
+			tmp = getNode(sub2, galPrefix, "APSDestinationEndpoint", NULL);
+			if (tmp == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+				pLogger->debug("getCallback - WARNING: APSDestinationEndpoint element not present!");
+#endif
+				as.isAPSDestinationEndpointDefined = false;
+				// It cannot be present, so leave empty!
+			} else {
+				if (parseLong(tmp, NULL, NULL, l, 10, 0, 65535))
+					return 1;
+				as.APSDestinationEndpoint = l;
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+				pLogger->debug("getCallback - APSDestinationEndpoint found: %li\r\n",as.APSDestinationEndpoint);
+#endif
+				as.isAPSDestinationEndpointDefined = true;
+			}
+		}
+		filter.addressSpec = as;
+
+		// Extract the  the "MessageSpecification" sub-element
+		if (sub2 == NULL)
+			sub2 = getNode(sub1, galPrefix, "MessageSpecification");
+		else
+			sub2 = getNode(sub2, galPrefix, "MessageSpecification", sub2);
+		if (sub2 == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+			pLogger->debug("getCallback - WARNING: MessageSpecification element not present!");
+#endif
+			ms.isDefined = false;
+			ms.isAPSClusterIdentifierDefined = false;
+			ms.isAPSClusterGroupDefined = false;
+			// MessageSpecification is optional, leave empty!
+		} else {
+
+			ms.isDefined = true;
+
+			// Get all the values
+			tmp = getNode(sub2, galPrefix, "APSClusterIdentifier", NULL);
+			if (tmp == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+				pLogger->debug("getCallback - WARNING: APSClusterIdentifier element not present!");
+#endif
+				ms.isAPSClusterIdentifierDefined = false;
+				// It cannot be present, so leave empty!
+			} else {
+				ms.isAPSClusterIdentifierDefined = true;
+				ms.APSClusterIdentifier = std::string(tmp->GetText());
+
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+				pLogger->debug("getCallback - APSClusterIdentifier found: %s\r\n",ms.APSClusterIdentifier.c_str());
+#endif
+			}
+			if (tmp == NULL)
+				tmp = getNode(sub2, galPrefix, "APSClusterGroup", tmp);
+			else
+				tmp = getNode(tmp, galPrefix, "APSClusterGroup", tmp);
+			if (tmp == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+				pLogger->debug("getCallback - WARNING: APSClusterGroup element not present!");
+#endif
+
+				ms.isAPSClusterGroupDefined = false;
+				// Continue, since APSClusterGroup element is optional
+			} else {
+
+				ms.APSClusterGroup = std::string(tmp->GetText());
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+				pLogger->debug("getCallback - APSClusterGroup found: %s\r\n",ms.APSClusterGroup.c_str());
+#endif
+				ms.isAPSClusterGroupDefined = true;
+			}
+		}
+		filter.messageSpec = ms;
+	}
+	cb->filter = filter;
+	// Get the "Buffer" sub-element ************ BUFFER ************
+	if (sub1 == NULL)
+		sub1 = getNode(node, galPrefix, "Buffer");
+	else
+		sub1 = getNode(sub1, galPrefix, "Buffer", sub1);
+	if (sub1 == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getCallback - WARNING: Buffer element not present");
+#endif
+		// Continue, since Buffer can be not present!
+	} else {
+		// Extract the  the "Buffer" sub-element
+		cb->buffer = std::string(sub1->GetText());
+
+	}
+
+	// Get the "Action" sub-element ************ ACTION ************
+	if (sub1 == NULL)
+		sub1 = getNode(node, galPrefix, "Action");
+	else
+		sub1 = getNode(sub1, galPrefix, "Action", sub1);
+	if (sub1 == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getCallback - WARNING: Action element not present");
+#endif
+		action.isDefined = false;
+
+		// Continue, since Action element is optional
+	} else {
+		// Parse the  the "Action" sub-element
+
+		action.isDefined = true;
+
+		// Init structures
+		memset(action.decodeSpecification.decodeLevel, 0, 6);
+
+		// Get DecodeSpecification element ****
+		sub2 = getNode(sub1, galPrefix, "DecodeSpecification");
+		if (sub2 == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+			pLogger->debug("getCallback - ERROR: DecodeSpecification element not found!");
+#endif
+			// Return Error Code 1: DecodeSpecification element must be present!
+			return 1;
+		} else {
+			// Get the DecodeLevel values
+			int val, parseEnumValue;
+			int numElemFound = 0;
+
+			tmp = NULL;
+			while (true) {
+				tmp = getNode(sub2, galPrefix, "DecodeLevel", tmp);
+				if (tmp == NULL) {
+					if (numElemFound == 0)
+						// Return Error Code 1: at least one DecodeLevel must be present!
+						return 1;
+					else
+						break;
+				}
+
+				parseEnumValue = parseEnumeration(tmp, NULL, NULL,
+						&ds_DecodeLevel, val);
+				if (parseEnumValue == 1) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+					pLogger->error("getCallback - DecodeLevel not present (unreachable status");
+#endif
+				} else if (parseEnumValue == 2) {
+					pLogger->warn("getCallback - Warning: DecodeLevel has not a valid value");
+					// Return Error Code 1: Invalid value
+					return 1;
+				} else {
+					action.decodeSpecification.decodeLevel[val] = true;
+					numElemFound++;
+				}
+			}
+		}
+
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		for (int i = 0; i < 6; i++)
+		pLogger->debug("getCallback - DecodeSpecification - DecodeLevel[%d] = %d", i, action.decodeSpecification.decodeLevel[i]);
+#endif
+
+		// get the ForwardingSpecification  ****
+		if (sub2 == NULL)
+			sub2 = getNode(sub1, galPrefix, "ForwardingSpecification");
+		else
+			sub2 = getNode(sub2, galPrefix, "ForwardingSpecification", sub2);
+		if (sub2 == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+			pLogger->info("getCallback - ERROR: ForwardingSpecification element not found!");
+#endif
+			// Return Error Code 1: ForwardingSpecification element must be present!
+			return 1;
+		} else {
+			action.forwardingSpecification = std::string(sub2->GetText());
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+			pLogger->debug("getCallback - forwardingSpec element %s\r\n",action.forwardingSpecification.c_str());
+#endif
+		}
+	}
+
+	cb->action = action;
+
+	return 0;
+}
+
+int XMLMsgParser::getValueAttribute(std::string *value, std::string *xmlMsg) {
+	//Value element: sent with Get and UpdateCallbackTimeout!
+	TiXmlDocument doc;
+	TiXmlElement *node;
+	const char *galPrefix, *restPrefix;
+	std::string root, label;
+	//long l;
+
+	node = getRoot(doc, *xmlMsg, root, galPrefix, restPrefix);
+	if (node == NULL) {
+		pLogger->debug("getValueAttribute - No XMLMessage sent!");
+		return 1;
+	}
+	//value = &std::string(node->GetText());
+	(*value) = std::string(node->GetText());
+	//.copy(*value,255,0);
+	pLogger->info("getValueAttribute - Value extracted: %s", (*value).c_str());
+
+	return 0;
+}
+
+int XMLMsgParser::getStartupAttributeInfo(StartupAttributeInfo *sai,
+		std::string *xmlMsg) {
+	TiXmlDocument doc;
+	TiXmlElement *node;
+	const char *galPrefix, *restPrefix;
+	std::string root, label;
+	long l;
+	int val;
+
+	node = getRoot(doc, *xmlMsg, root, galPrefix, restPrefix);
+	if (node == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getStartupAttributeInfo - Element not found");
+#endif
+		return 1;
+	}
+
+	if (parseLong(node, galPrefix, "StartupAttributeSetIndex", l, 10, 0, 65535))
+		return 2; //This is a mandatory element...
+
+	sai->startupAttributeSetIndex = l;
+	pLogger->info("getStartupAttributeInfo - StartupAttributeSetIndex %d", sai->startupAttributeSetIndex);
+
+	// DeviceType ---
+	int parseEnumReturnValue;
+	parseEnumReturnValue = parseEnumeration(node, galPrefix, "DeviceType",
+			&deviceType, val);
+	if (parseEnumReturnValue == 1) {
+		sai->isDeviceTypeDefined = false;
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getStartupAttributeInfo - DeviceType not present");
+#endif
+	} else if (parseEnumReturnValue == 2) {
+		pLogger->warn("StartupControl - Warning: DeviceType %0X is not a valid value!", sai->StartupControl);
+		return 3; //Invalid value!
+	} else {
+		sai->deviceType = val;
+		sai->isDeviceTypeDefined = true;
+		pLogger->debug("getStartupAttributeInfo - DeviceType = %d - isDeviceTypeDefined = %x",
+				sai->deviceType, sai->isDeviceTypeDefined);
+	}
+
+	// StartupControl ---
+	if (parseLong(node, galPrefix, "StartupControl", l, 10, 0, 65535)) {
+		sai->isStartupControlDefined = false;
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getStartupAttributeInfo - StartupControl not present");
+#endif
+	} else {
+		sai->StartupControl = l; //StartupControl is a ushort!
+		if (sai->StartupControl > 0x03)
+			return 3; //Invalid value!
+		else {
+			sai->isStartupControlDefined = true;
+			pLogger->info("StartupControl - value %0X - isStartupControlDefined = %x",
+					sai->StartupControl, sai->isStartupControlDefined);
+		}
+	}
+	// ChannelMask ---
+	if (parseLong(node, galPrefix, "ChannelMask", l, 10, 0, 65535)) {
+		sai->isChannelMaskDefined = false;
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getStartupAttributeInfo - ChannelMask not present");
+#endif
+	} else {
+		sai->channelMask = l;
+		sai->isChannelMaskDefined = true;
+		pLogger->info("StartupControl - value %0X", sai->channelMask);
+	}
+	return 0;
+}
+
+int XMLMsgParser::getValue(unsigned long &l, std::string *xmlMsg) {
+	std::string s;
+	const char *text;
+	char *endp;
+
+	if (getValue(s, xmlMsg))
+		return 1;
+
+	text = s.c_str();
+	text += strspn(text, BLANKS);
+	l += strtoul(text, &endp, 0);
+	endp += strspn(endp, BLANKS);
+	if (endp == text || *endp) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getValue - Bad long: %s", text);
+#endif
+		return 1;
+	}
+
+	return 0;
+
+}
+
+int XMLMsgParser::getValue(std::string &s, std::string *xmlMsg) {
+	const char *galPrefix, *restPrefix;
+	TiXmlDocument doc;
+	TiXmlElement *node;
+	std::string root;
+
+	node = getRoot(doc, *xmlMsg, root, galPrefix, restPrefix);
+	if (node == NULL || root.compare("Value") != 0) {
+#ifdef DEBUG_ACTIVE_XMLMSGPARSER
+		pLogger->debug("getValue - Value element not found");
+#endif
+		return 1;
+	}
+
+	s = node->GetText();
+
+	return 0;
+}
+
+//**************************************************************************
+//*************  XMLMsgComposer  *******************************************
+//**************************************************************************
+
+XMLMsgComposer *XMLMsgComposer::pInstance = NULL;
+
+/**
+ Constructor
+ XMLMsgComposer constructor. It is a protected method (pattern Singleton)
+
+ @param void Void.
+ @return Void.
+ */
+
+XMLMsgComposer::XMLMsgComposer() {
+
+	pLogger = new Debug("XMLMsgComposer");
+	ConfigurationRepository *_conf = ConfigurationRepository::instance();
+	// We load the configuration from the ConfigurationManager
+	this->debugEnabled = _conf->getint("main:debugEnabled", false);
+
+	pLogger->setDebugMode(this->debugEnabled);
+	//pLogger->setDebugMode(DBG_ENABLED);
+	//pLogger->setDebugMode(DBG_DISABLED);
+	pLogger->setDebugLevel(DEBUGGING);
+	//pLogger->setDebugLevel(TEST);
+	pLogger->setDebugMsgFormat(DBGMSGFORMAT_SIMPLE);
+	pLogger->enableDebugOuput(DBG_SCREEN);
+	//pLogger->enableDebugOuput(DBG_LOGFILE);
+
+	enableNamespaces(false);
+
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("Constructor");
+#endif
+}
+
+/**
+ Destructor
+ XMLMsgComposer destructor.
+
+ @param void Void.
+ @return Void.
+ */
+
+XMLMsgComposer::~XMLMsgComposer() {
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	printf("XMLMsgComposer Destructor\n");
+#endif
+	delete pLogger;
+}
+
+/**
+ Public method XMLMsgComposer *Instance(void)
+ (pattern Singleton)
+
+ @param void Void.
+ @return Instance of XMLMsgComposer class.
+ */
+
+XMLMsgComposer *XMLMsgComposer::Instance(void) {
+	if (pInstance == NULL) {
+		pInstance = new XMLMsgComposer;
+	}
+	return pInstance;
+}
+
+/**
+ Public method XMLMsgComposer init
+ XMLMsgComposer initialization: macrofunction context is initialized.
+
+
+ @param void Void.
+ @return Void.
+ */
+
+void XMLMsgComposer::init() {
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("init");
+#endif
+}
+
+/**
+ Public method XMLMsgComposer enableNamespaces
+ Enables or disables generation of namespaces in generated XML
+ messages. By default, they are disabled
+
+ @param flag true to enable, false to disable
+ @return Void.
+ */
+
+void XMLMsgComposer::enableNamespaces(bool flag) {
+	if (flag) {
+		galPrefix = "gal";
+		restPrefix = "tns";
+		//galPrefix = "ns2";
+		//restPrefix = "ns3";
+	} else {
+		galPrefix = NULL;
+		restPrefix = NULL;
+	}
+}
+
+int XMLMsgComposer::hexStringToInt(const char* hexString) {
+	int value;
+
+	sscanf(hexString, "%x", &value);
+	return value;
+}
+
+unsigned long long XMLMsgComposer::ieeeAddrToULongLong(uchar* array) {
+	unsigned long long value = 0;
+
+	for (int i = 0; i < 8; i++) {
+		//pLogger->debug("array[%d] = %d",i,array[i]);
+		value = (value << 8) + (unsigned long long) array[i];
+		//pLogger->debug("counter - i = %d, value = %llu - hex version = %x",i,value, value);
+	}
+	return value;
+}
+
+/**
+ Public method XMLMsgComposer createVersionMsg
+ This method allows creating a XML message whose root element is "Version".
+
+ @return String containing the XML message created.
+ */
+
+std::string XMLMsgComposer::createVersionMsg(void) {
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("createVersionMsg");
+#endif
+
+	std::stringstream response, s;
+
+	dumpLong(s, galPrefix, "VersionIdentifier", 1);
+	dumpLong(s, galPrefix, "FeatureSetIdentifier", 0);
+	dumpString(s, galPrefix, "RPCProtocol", "REST");
+	dumpString(s, galPrefix, "ManufacturerVersion", VERSION);
+
+	dumpString(response, restPrefix, "Version", s);
+
+	return response.str();
+}
+
+/**
+ Public method XMLMsgComposer createGetAttributeMsg
+ This method allows creating a XML message whose get a specific attribute
+
+ @return String containing the XML message created containing the attribute requested.
+ */
+
+std::string XMLMsgComposer::createGetAttributeMsg(std::string value) {
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("createGetAttributeMsg");
+#endif
+
+	std::stringstream response;
+
+	dumpString(response, restPrefix, "Value", value.c_str());
+
+	return response.str();
+}
+
+/**
+ Public method XMLMsgComposer setAttributeMsg
+ This method allows creating a XML message whose get a default response after setting an attribute
+
+ @return String containing the XML message in response of a Set procedure.
+ */
+std::string XMLMsgComposer::setAttributeMsg(void) {
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("setAttributeMsg");
+#endif
+
+	std::stringstream response;
+
+	//dumpLong (response, galPrefix, "Status", 0);
+
+	return response.str();
+}
+
+/**
+ Public method XMLMsgComposer createGenericResponseMsg
+ This method allows creating a generic XML message useful when no specific XML response is request.
+
+ @return String containing the XML message created.
+ */
+
+std::string XMLMsgComposer::createGenericResponseMsg(void) {
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("createGenericResponseMsg");
+#endif
+
+	std::stringstream response;
+	return response.str();
+}
+
+/**
+ Public method XMLMsgComposer createWSNNodesMsg
+ This method allows creating a XML message whose root element is "WSNNodes" (it contains only one "WSNNode" element).
+ The resulting XML message is used by Inquiry notification callback.
+
+ @param result Inquiry function result (at the moment, it is not used).
+ @param node Pointer to a Node object.
+ @return String containing the XML message created.
+ */
+
+std::string XMLMsgComposer::createWSNNodeMsg(int result, Node *node) {
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("createWSNNodeMsg");
+#endif
+
+	std::stringstream response;
+	dumpNode(response, restPrefix, "WSNNode", node);
+	return response.str();
+}
+
+/**
+ Public method XMLMsgComposer createWSNNodesListMsg
+ This method allows creating a XML message whose root element is "WSNNodes" (it can contain more than one "WSNNode" element).
+ The resulting XML message is used when retrieving the list of discovered WSN nodes.
+
+ @param result Inquiry function result (at the moment, it is not used).
+ @param buffer Pointer to the buffer containing Inquiry macrofunction (refer to Discovery Agent) results.
+ @return String containing the XML message created.
+ */
+
+std::string XMLMsgComposer::createWSNNodesListMsg(int result, ZbNetDb *buffer) {
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("createWSNNodesListMsg");
+#endif
+
+	std::map<ushort, Node *> nodes;
+	std::map<ushort, Node *>::const_iterator iter;
+	std::stringstream response, inner;
+
+	nodes = buffer->getNodeDict();
+	for (iter = nodes.begin(); iter != nodes.end(); iter++)
+		if ((iter->second)->getIsActive() == true) {
+			dumpNode(inner, galPrefix, "WSNNode", iter->second);
+		}
+	dumpString(response, restPrefix, "WSNNodes", inner);
+
+	return response.str();
+}
+
+std::string XMLMsgComposer::createAliasesMsg(int result, ZbNetDb *buffer) {
+	int count = 0;
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("createAliasesMsg");
+#endif
+
+	std::map<ushort, Node *> nodes;
+	std::map<ushort, Node *>::const_iterator iter;
+	std::stringstream response, inner;
+
+	nodes = buffer->getNodeDict();
+	for (iter = nodes.begin(); iter != nodes.end(); iter++) {
+		if (((iter->second)->getIsActive() == true) || (result == -1)) {
+			dumpAddress(inner, galPrefix, "Alias", 3, iter->second);
+			count++;
+		}
+	}
+	dumpLong(inner, galPrefix, "NumberOfAlias", count);
+	dumpString(response, restPrefix, "Aliases", inner);
+	return response.str();
+}
+
+/**
+ Public method XMLMsgComposer createNodeDescMsg
+ This method allows creating a XML message whose root element is "Descriptors" and contains one element "NodeDescriptor"
+ The method buildNodeDescTag is used.
+
+ @param result Function result (at the moment, it is not used).
+ @param node_desc Node Descriptor.
+ @return String containing the XML message created.
+ */
+
+std::string XMLMsgComposer::createNodeDescMsg(int result,
+		NodeDescriptor &node_desc) {
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("createNodeDescMsg");
+#endif
+
+	std::stringstream response, s;
+
+	dumpLogicalType(s, galPrefix, "LogicalType", node_desc.logicaltype);
+	dumpFreqBand(s, galPrefix, "FrequencyBand", node_desc.frequencyband);
+	dumpMACCapability(s, galPrefix, "MACCapabilityFlag", node_desc.mac_cap);
+	dumpLong(s, galPrefix, "ManufacturerCode", node_desc.manufacturecode);
+	dumpLong(s, galPrefix, "MaximumBufferSize", node_desc.maximumbuffersize);
+	dumpServerMask(s, galPrefix, "ServerMask", node_desc.server_mask);
+
+	dumpString(response, restPrefix, "NodeDescriptor", s);
+
+	return response.str();
+}
+
+std::string XMLMsgComposer::createGetNodeBindingMsg(int result,
+		short bindingTableEntries, short startIndex,
+		short bindingTableListCount, ZB_BIND_STRUCT *bindingtableList) {
+
+	int i = 0;
+	std::stringstream bindings, binding, s, devDest, ieee;
+
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("createGetNodeBindingMsg");
+#endif
+
+	for (i = 0; i < bindingTableListCount; i++) {
+		unsigned long long value = ieeeAddrToULongLong(
+				bindingtableList[i].src_addr);
+		ieee.str("");
+		s.str("");
+		devDest.str("");
+		ieee << value;
+		dumpString(s, galPrefix, "SourceIEEEAddress", ieee.str().c_str());
+		dumpLong(s, galPrefix, "SourceEndpoint", bindingtableList[i].src_ep);
+		dumpLong(s, galPrefix, "ClusterID", bindingtableList[i].cluster_id);
+		value = ieeeAddrToULongLong(bindingtableList[i].dst_addr);
+		ieee.str("");
+		ieee << value;
+		//Device Destination
+		dumpString(devDest, galPrefix, "Address", ieee.str().c_str());
+		dumpLong(devDest, galPrefix, "Endpoint", bindingtableList[i].dst_ep);
+		dumpString(s, galPrefix, "DeviceDestination", devDest);
+		//Binding
+		dumpString(binding, galPrefix, "Binding", s);
+	}
+	//Bindings
+	dumpString(bindings, restPrefix, "Bindings", binding);
+	return bindings.str();
+}
+
+std::string XMLMsgComposer::createLQIInformationMsg(ZbNetDb *buffer) {
+	int size, i;
+	Node * currentNode;
+	LQIInformationEntry * nodeLQIentries;
+	std::stringstream response, output;
+
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("createLQIInformationMsg");
+#endif
+
+	currentNode = buffer->getFirstNode();
+	while (currentNode != NULL) {
+		nodeLQIentries = currentNode->getLQIInformationTable(&size); //Note: Some entries could be NULL!
+		if (currentNode->getIsActive() == true && nodeLQIentries != NULL) {
+			std::stringstream lqi, neighbor;
+			std::stringstream ieee;
+			unsigned long long value = ieeeAddrToULongLong(
+					currentNode->get_ieee_addr());
+			ieee.str("");
+			ieee << value;
+			dumpString(lqi, galPrefix, "NodeAddress", ieee.str().c_str());
+			if (size == 0)
+				dumpString(lqi, galPrefix, "NeighborList", "");
+			else {
+				for (i = 0; i < size; i++) {
+					std::stringstream s;
+					value = ieeeAddrToULongLong(nodeLQIentries[i].ieeeAddress);
+					ieee.str("");
+					ieee << value;
+					dumpLong(s, galPrefix, "ShortAddress",
+							nodeLQIentries[i].shortAddress);
+					dumpString(s, galPrefix, "IeeeAddress", ieee.str().c_str());
+					dumpLong(s, galPrefix, "DeviceTypeRxOnWhenIdleRelationship",
+							nodeLQIentries[i].devTypeRxOnRelation);
+					dumpLong(s, galPrefix, "Depth", nodeLQIentries[i].depth);
+					dumpLong(s, galPrefix, "LQI", nodeLQIentries[i].lqi);
+					dumpString(neighbor, galPrefix, "Neighbor", s);
+				}
+				dumpString(lqi, galPrefix, "NeighborList", neighbor);
+			}
+			dumpString(output, restPrefix, "LQINode", lqi);
+		}
+		currentNode = buffer->getNextNode(currentNode);
+	}
+	dumpString(response, restPrefix, "LQIInformation", output);
+	return response.str();
+}
+
+/**
+ Public method XMLMsgComposer createPowerDescMsg
+ This method allows creating a XML message whose root element is "Descriptors" and contains one element "PowerDescriptor"
+ The method buildPowerDescTag is used.
+
+ @param result Function result (at the moment, it is not used).
+ @param nwk_addr Node Network Address.
+ @param ieee_addr Node IEEE Address.
+ @param power_desc Power Descriptor
+ @return String containing the XML message created.
+ */
+
+std::string XMLMsgComposer::createPowerDescMsg(int result, ushort nwk_addr,
+		uchar *ieee_addr, PowerDescriptor &power_desc) {
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("createPowerDescMsg");
+#endif
+
+	std::stringstream response, s;
+
+	dumpPowerMode(s, galPrefix, "CurrentPowerMode",
+			power_desc.currentpowermode);
+
+	dumpPowerSources(s, galPrefix, "AvailablePowerSources",
+			power_desc.avaiablepowersource);
+
+	dumpPowerSources(s, galPrefix, "CurrentPowerSources",
+			power_desc.currentpowersource);
+
+	dumpPowerSourceLevel(response, restPrefix, "PowerSourceLevel",
+			power_desc.currentpowersourcelevel);
+
+	dumpString(response, restPrefix, "PowerDescriptor", s);
+
+	return response.str();
+}
+
+/**
+ Public method XMLMsgComposer createAllNodesAllDescMsg
+ This method allows creating a XML message whose root element is "Descriptors" and contains the results of a superDiscovery macrofunction
+ (refer to Discovery Agent).
+
+ @param result Inquiry function result (at the moment, it is not used).
+ @param buffer Pointer to the buffer containing Inquiry macrofunction (refer to Discovery Agent) results.
+ @return String containing the XML message created.
+ */
+
+std::string XMLMsgComposer::createAllNodesServiceDescMsg(int result,
+		ZbNetDb *buffer) {
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("createAllNodesAllDescMsg");
+#endif
+
+	std::map<ushort, Node *> nodes;
+	std::map<ushort, Node *>::const_iterator iter;
+	std::stringstream response, inner;
+
+	nodes = buffer->getNodeDict();
+	for (iter = nodes.begin(); iter != nodes.end(); iter++) {
+		if ((iter->second)->getIsActive() == true)
+			dumpNodeServices(inner, galPrefix, "NodeServices", iter->second);
+	}
+	dumpString(response, restPrefix, "NodeServicesList", inner);
+
+	return response.str();
+}
+
+/**
+ Public method XMLMsgComposer createActiveEndPointMsg
+ This method allows creating a XML message whose root element is "Services" and contains the list of all active endpoints related to a
+ specific ZigBee node (refer to Service Agent)
+
+ @param result Function result (at the moment, it is not used).
+ @param node Pointer to a Node object.
+ @return String containing the XML message created.
+ */
+
+std::string XMLMsgComposer::createActiveEndPointMsg(int result, Node *node) {
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("createActiveEndPointMsg");
+#endif
+
+	std::stringstream response;
+
+	dumpNodeServices(response, restPrefix, "NodeServices", node);
+
+	return response.str();
+}
+
+std::string XMLMsgComposer::createActiveEndPointLocalNodeMsg(int numEndPoints,
+		int * endPoints) {
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("createActiveEndPointLocalNodeMsg");
+#endif
+	std::stringstream response;
+	std::stringstream inner, inner2, eps;
+	std::stringstream nwk;
+
+	nwk.str("");
+	nwk << "0";
+	dumpString(inner2, galPrefix, "NetworkAddress", nwk.str().c_str());
+	dumpString(inner, galPrefix, "Address", inner2);
+
+	for (int i = 0; i < numEndPoints; i++) {
+		eps.str("");
+		dumpLong(eps, galPrefix, "EndPoint", endPoints[i], 10); //10=decimal base
+		dumpString(inner, galPrefix, "ActiveEndpoints", eps);
+	}
+	dumpString(response, restPrefix, "NodeServices", inner);
+	return response.str();
+}
+
+/**
+ Public method XMLMsgComposer createServiceDescriptorMsg
+ This method allows creating a XML message whose root element is "Services" and contains the service descriptor related to a specific
+ endpoint of a ZigBee node (refer to Service Agent)
+
+ @param result Function result (at the moment, it is not used).
+ @param node Pointer to a Node object.
+ @param endpoint Endpoint identifier of interest.
+ @return String containing the XML message created.
+ */
+
+std::string XMLMsgComposer::createServiceDescriptorMsg(int result, Node *node,
+		int endpoint) {
+	SimpleDescriptor *sd;
+	std::list<int> clusterList;
+	std::list<int>::iterator i;
+	std::stringstream response, s, inner;
+
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("createServiceDescriptorMsg");
+#endif
+
+	//dumpAddress(s, galPrefix, "Address", 3, node -> get_ieee_addr());
+	// New dumpAddress
+	dumpAddress(s, galPrefix, "Address", 3, node);
+
+	dumpLong(s, galPrefix, "EndPoint", endpoint);
+
+	sd = node->getSimpleDescr(endpoint);
+	if (sd != NULL) {
+		dumpLong(inner, galPrefix, "EndPoint", endpoint);
+		dumpLong(inner, galPrefix, "ApplicationProfileIdentifier",
+				sd->profile_id);
+		dumpLong(inner, galPrefix, "ApplicationDeviceIdentifier",
+				sd->device_id);
+		dumpLong(inner, galPrefix, "ApplicationDeviceVersion", sd->device_ver);
+
+		clusterList = sd->input_cluster;
+		for (i = clusterList.begin(); i != clusterList.end(); i++)
+			dumpLong(inner, galPrefix, "ApplicationInputCluster", *i);
+
+		clusterList = sd->output_cluster;
+		for (i = clusterList.begin(); i != clusterList.end(); i++)
+			dumpLong(inner, galPrefix, "ApplicationOutputCluster", *i);
+	}
+	dumpString(s, galPrefix, "SimpleDescriptor", inner);
+
+	dumpString(response, restPrefix, "ServiceDescriptor", s);
+
+	return response.str();
+}
+
+/**
+ Public method XMLMsgComposer createLocalNodeEnbdpointMsg
+ This method allows creating a XML message whose root element is "Endpoint" and contains the endpoint assigned to a service descriptor (refer to Service Agent)
+
+ @param result Function result (at the moment, it is not used).
+ @param serviceDesc Pointer to a data structure containing the service descriptor of interest.
+ @return String containing the XML message created.
+ */
+
+std::string XMLMsgComposer::createLocalNodeEndpointMsg(int result,
+		SimpleDescriptor *serviceDesc) {
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("createLocalNodeEndpointMsg");
+#endif
+
+	std::stringstream response;
+
+	// Root element is EndPoint
+	dumpLong(response, restPrefix, "Endpoint", serviceDesc->end_point);
+
+	return response.str();
+}
+
+std::string XMLMsgComposer::createCallbackIdentifierMsg(std::string &s) {
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("createCallbackIdentifierMsg");
+#endif
+
+	std::stringstream callbackIdentifier;
+	std::stringstream response;
+
+	int value = hexStringToInt(s.c_str());
+	callbackIdentifier << value;
+
+	// Root element is EndPoint
+	dumpString(response, restPrefix, "CallbackIdentifier",
+			callbackIdentifier.str().c_str());
+
+	return response.str();
+}
+
+/**
+ Public method XMLMsgComposer createErrorMsg
+ This method allows creating a XML message whose root element is "Info". In particular, it relates to a XML message describing
+ the error has just occured.
+
+ @param swElement It specifies the software element (e.g. REST, DISCOVERY AGENT, ...) in which the error has occured.
+ @param errorCode Error code
+ @param errorDesc Error description text.
+ @param text Additional information.
+ @return String containing the XML message created.
+ */
+
+std::string XMLMsgComposer::createErrorMsg(int errorCode, const char *errorDesc,
+		const char *nwkStatus, const char *requestIdentifier) {
+
+	//TODO - WARNING - CONSIDER THIS ---
+	/*
+	 if (errorCode == 10 || errorCode == 11) {
+	 pLogger->debug("\n createErrorMsg\n");
+	 return createRestInfoMsg(0, errorDesc, NULL, requestIdentifier, NULL,"********************");
+	 }
+	 */
+	return createRestInfoMsg(errorCode, errorDesc, NULL, requestIdentifier,
+			NULL, nwkStatus);
+}
+
+/**
+ Public method XMLMsgComposer createSuccessMsg
+ This method allows creating a XML message whose root element is "Info".
+
+ @param detail the XML document that should be put into the Detail enumeration. If NULL, it will be ignored.
+ @param errorCode Error code
+ @return String containing the XML message created.
+ */
+
+std::string XMLMsgComposer::createSuccessMsg(const char *detail,
+		const char *nwkStatus, const char *requestIdentifier) {
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("createSuccessMsg");
+#endif
+
+	return createRestInfoMsg(0, NULL, detail, requestIdentifier, NULL,
+			nwkStatus);
+}
+
+std::string XMLMsgComposer::createGwStatusChangedMsg(
+//	const char * swElement,
+		//	const char * text
+		GwDescriptor *gwDescriptor) {
+	char tmp_str[BUFFER_SIZE];
+
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("createGwStatusChangedMsg");
+#endif
+	// Root element Info
+	std::string response = "<GWDescriptor>";
+
+	/*	if (swElement != NULL)
+	 {
+	 response += swElement;
+	 response += " ";
+	 }
+	 if (text != NULL)
+	 response += text;
+	 */
+
+	// Element WSNId
+	response += "<WSNId>";
+	response += gwDescriptor->getWSNId();
+	response += "</WSNId>";
+
+	// Element GWState
+	response += "<GWState>";
+	sprintf(tmp_str, "%02X", gwDescriptor->getGwState());
+	tmp_str[strlen(tmp_str)] = '\0';
+	response += tmp_str;
+	response += "</GWState>";
+
+	// Element GWStateDescription
+	response += "<GWStateDescription>";
+	response += gwDescriptor->getGwStateDescription();
+	response += "</GWStateDescription>";
+
+	// Element ErrorCode
+	response += "<ErrorCode>";
+	sprintf(tmp_str, "%02X", gwDescriptor->getErrorCode());
+	tmp_str[strlen(tmp_str)] = '\0';
+	response += tmp_str;
+	response += "</ErrorCode>";
+
+	// Element ErrorCodeDescription
+	response += "<ErrorCodeDescription>";
+	response += gwDescriptor->getErrorCodeDescription();
+	response += "</ErrorCodeDescription>";
+
+	// Element TimeStamp
+	response += "<TimeStamp>";
+	response += gwDescriptor->getTimeStamp();
+	response += "</TimeStamp>";
+
+	// Element FirmwareVersion
+	response += "<FirmwareVersion>";
+	response += gwDescriptor->getFirmwareVersion();
+	response += "</FirmwareVersion>";
+
+	response += "<NWKDescriptors>";
+	response += "</NWKDescriptors>";
+
+	response += "</GWDescriptor>";
+	return response;
+}
+
+//TODO Not used??
+std::string XMLMsgComposer::createCallbackIdentiferMsg(
+		std::list<std::string> ids) {
+	std::stringstream response, s;
+	std::list<std::string>::iterator i;
+
+	for (i = ids.begin(); i != ids.end(); i++) {
+		dumpString(response, restPrefix, "CallbackIdentifier", i->c_str());
+
+	}
+	return response.str();
+}
+
+std::string XMLMsgComposer::createCallbacksMsg(std::list<std::string> ids) {
+	std::stringstream response, s, callbackIdentifier;
+	std::list<std::string>::iterator i;
+
+	for (i = ids.begin(); i != ids.end(); i++) {
+		// CallbackIdentifier has to be expressed in Dec format
+		int value = hexStringToInt(i->c_str());
+		callbackIdentifier.str("");
+		callbackIdentifier << value;
+
+		dumpString(s, galPrefix, "CallbackIdentifier",
+				callbackIdentifier.str().c_str());
+	}
+	dumpString(response, restPrefix, "Callbacks", s);
+	return response.str();
+}
+
+//TODO Use XMLMsgComposer methods to compose the message (also considering prefix)
+std::string XMLMsgComposer::createWsncWSNConnEventMsg(int endpointId,
+		const char *uriListener, const char *wsnConnStatus) {
+	char tmp_str[BUFFER_SIZE];
+
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("createWsncWSNConnCreatedMsg");
+#endif
+	//TODO Check this modification related to createWsncWSNConnEventMsg
+	//std::string response("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+	std::string response("");
+
+	// Root element
+	response += "<WsncWSNConnectionEvent>";
+
+	response += "<Endpoint>";
+	sprintf(tmp_str, "%3d", endpointId);
+	tmp_str[strlen(tmp_str)] = '\0';
+	response += tmp_str;
+	response += "</Endpoint>";
+
+	response += "<URIListener>";
+	response += uriListener;
+	response += "</URIListener>";
+
+	response += "<WSNConnectionStatus>";
+	response += wsnConnStatus;
+	response += "</WSNConnectionStatus>";
+
+	response += "</WsncWSNConnectionEvent>";
+	return response;
+}
+
+std::string XMLMsgComposer::createRestInfoMsg(int errorCode,
+		const char *errorDesc, const char *detail,
+		const char *requestIdentifier, const char *eventCallbackIdentifier,
+		const char *nwkStatus) {
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("createRestInfoMsg");
+#endif
+	std::stringstream response, s;
+
+	dumpLong(s, restPrefix, "Code", errorCode);
+	if (errorDesc != NULL)
+		dumpString(s, restPrefix, "Message", errorDesc);
+	dumpString(response, restPrefix, "Status", s);
+
+	if (detail != NULL)
+		dumpString(response, restPrefix, "Detail", detail);
+
+	if (requestIdentifier != NULL)
+		dumpString(response, restPrefix, "RequestIdentifier",
+				requestIdentifier);
+
+	if (eventCallbackIdentifier != NULL) {
+		std::stringstream evtCbId;
+		int value = hexStringToInt(eventCallbackIdentifier);
+		evtCbId << value;
+		dumpString(response, restPrefix, "EventCallbackIdentifier",
+				evtCbId.str().c_str());
+	}
+
+	if (nwkStatus != NULL)
+		dumpString(response, restPrefix, "NWKStatus", nwkStatus);
+
+	return createDocElement(restPrefix, "Info", response.str().c_str());
+}
+
+std::string XMLMsgComposer::createDocElement(const char *prefix,
+		const char *label, const char *text) {
+	std::string response;
+
+	response = XML_HEADING;
+
+	if (prefix != NULL) {
+		response = response + "<" + prefix + ":" + label + " ";
+		response = response + "xmlns:" + galPrefix + "=" + "\"" + GAL_NS_URI
+				+ "\" ";
+		response = response + "xmlns:" + restPrefix + "=" + "\"" + REST_NS_URI
+				+ "\">\n";
+		response += text;
+		response = response + "\n</" + prefix + ":" + label + ">";
+	} else {
+		response = response + "<" + label + ">\n";
+		response += text;
+		response = response + "\n</" + label + ">";
+	}
+
+	return response;
+}
+
+/**
+ Public method XMLMsgComposer createResourceInfoMsg
+ This method allows creating a XML message whose root element is "Info". In particular, it relates to a XML message listing
+ the next step URIs concerning a specific resource URI. It is used by RESTBroker method restResourceInfo_Rsp.
+
+ @param relRootUri The invoked resource URI.
+ @param resource Pointer to a specific Resource object containing all the related information (e.g. all the URIs,...).
+ @return String containing the XML message created.
+ */
+
+std::string XMLMsgComposer::createResourceInfoMsg(Resource *resource)
+
+{
+	std::list<Resource *>::iterator i;
+	std::stringstream res;
+
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("createResourceInfoMsg");
+#endif
+
+	for (i = resource->children.begin(); i != resource->children.end(); i++)
+		res << "<Resource><ResourceId>" << (*i)->rd.path
+				<< "</ResourceId></Resource>\n";
+
+	return res.str();
+}
+
+/**
+ Public method XMLMsgComposer createZCLMessage This method allows
+ creating a XML message whose root element is "ZCLMessage". In
+ particular, it relates to a XML message describing the results
+ of sending a ZCLCommand message.
+
+ @param confirmStatus the Status parameter of the APSDE_DATA.confirm
+ @param txTime the TxTime parameter of the APSDE_DATA.confirm
+ @param msg A Message structure containing some useful information to be included in the response message
+ */
+std::string XMLMsgComposer::createZCLMessage(uchar confirmStatus,
+		unsigned txTime, Message *msg) {
+	std::stringstream response, s;
+	int i;
+	ushort l;
+	uchar *data;
+
+	//TODO: We're including a txTime in a RxTime response, so probably the whole message is intended
+	// to be the message received and not the message just sent! :-(
+	dumpLong(s, galPrefix, "RxTime", txTime);
+	dumpLong(s, galPrefix, "DestinationEndpoint", msg->getDstEp());
+	msg->getSrcAddr(&i);
+
+	if (i == 0) {
+		//sourceAddress not specified...
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+		pLogger->debug("############## SourceAddress not specified!! ###################\n");
+#endif
+		dumpLong(s, galPrefix, "SourceAddress", 0x0000);
+	} else {
+		data = (uchar *) malloc(((int) i) * sizeof(uchar));
+		memcpy(data, msg->getSrcAddr(NULL), i);
+		dumpHex(s, galPrefix, "SourceAddress", data, i);
+		delete[] data;
+	}
+	dumpLong(s, galPrefix, "SourceEndpoint", msg->getSrcEp());
+	dumpLong(s, galPrefix, "ProfileID", msg->getProfileId());
+	dumpLong(s, galPrefix, "ClusterID", msg->getClusterId());
+
+	msg->getPayload(&l);
+	free(data);
+	data = (uchar *) malloc(((int) l) * sizeof(uchar));
+	memcpy(data, msg->getPayload(NULL), l);
+	dumpHex(s, galPrefix, "ZCLPayload", &data[6], l - 6);
+	dumpLong(s, galPrefix, "APSStatus", confirmStatus);
+	if (i == 0) {
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+		pLogger->debug("############## SourceAddressMode not specified!! ###################\n");
+#endif
+		dumpLong(s, galPrefix, "SourceAddressMode", 2);
+	} else
+		dumpLong(s, galPrefix, "SourceAddressMode", msg->getSrcAddrMode());
+	dumpHex(s, galPrefix, "ZCLHeader", data, 6);
+	free(data);
+	dumpString(response, galPrefix, "ZCLMessage", s);
+	return response.str();
+}
+
+/**
+ Public method XMLMsgComposer createZDPMessage This method allows
+ creating a XML message whose root element is "ZDPMessage". In
+ particular, it relates to a XML message describing the results
+ of sending a ZDPCommand message.
+
+ @param confirmStatus the Status parameter of the APSDE_DATA.confirm
+ @param txTime the TxTime parameter of the APSDE_DATA.confirm
+ @param msg A Message structure containing some useful information to be included in the response message
+ */
+std::string XMLMsgComposer::createZDPMessage(uchar confirmStatus,
+		unsigned txTime, Message * msg) {
+	std::stringstream response, s;
+	int i;
+	ushort l;
+
+	dumpHex(s, galPrefix, "SourceAddress", msg->getSrcAddr(&i), i);
+	dumpLong(s, galPrefix, "SourceAddressMode", 0x02);
+	//SecurityStatus
+	//LinkQuality
+	dumpLong(s, galPrefix, "RxTime", txTime);
+	dumpLong(s, galPrefix, "ClusterID", msg->getClusterId());
+	dumpHex(s, galPrefix, "Command", msg->getPayload(&l), l);
+
+	dumpString(response, galPrefix, "ZDPMessage", s);
+
+	return response.str();
+}
+
+/**
+ Public method XMLMsgComposer createAPSResultMsg This method allows
+ creating a XML message whose root element is "APSMesasgeResult". In
+ particular, it relates to a XML message describing the results
+ of sending an APS message.
+
+ @param confirmStatus the Status parameter of the APSDE_DATA.confirm
+ @return txTime the TxTime parameter of the APSDE_DATA.confirm
+ */
+std::string XMLMsgComposer::createAPSResultMsg(uchar confirmStatus,
+		unsigned txTime) {
+	std::stringstream response, s;
+
+	dumpLong(s, galPrefix, "ConfirmStatus", confirmStatus);
+	dumpLong(s, galPrefix, "TxTime", txTime);
+
+	dumpString(response, restPrefix, "APSMessageResult", s);
+
+	return response.str();
+}
+
+/**
+ Public method XMLMsgComposer createRXMessageMsg
+ This method allows creating a XML message whose root element
+ is "APSMessageEvent". In particular, it relates to a XML message describing
+ the received ZigBee application message.
+
+ @param msg Pointer to Message Object.
+ @return String containing the XML message created.
+ */
+
+std::string XMLMsgComposer::createRXMessageMsg(Message *msg) {
+	uchar *payload;
+	uchar *srcAddr;
+	int srcAddrLength, srcAddrMode;
+	uchar srcEp;
+	uchar *dstAddr;
+	int dstAddrLength, dstAddrMode;
+	uchar dstEp;
+	ushort profileId;
+	ushort clusterId;
+	ushort payloadLength;
+
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("createRXMessageMsg");
+#endif
+
+	std::stringstream response, s;
+	if (msg == NULL) {
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+		pLogger->debug("WARNING: Message Empty!\n");
+#endif
+		return "";
+	}
+	dstAddr = msg->getDstAddr(&dstAddrLength);
+	dstAddrMode = msg->getDstAddrMode();
+	dstEp = msg->getDstEp();
+	srcAddr = msg->getSrcAddr(&srcAddrLength);
+	srcAddrMode = msg->getSrcAddrMode();
+	srcEp = msg->getSrcEp();
+
+	profileId = msg->getProfileId();
+	clusterId = msg->getClusterId();
+
+	payload = msg->getPayload(&payloadLength);
+
+	dumpLong(s, galPrefix, "DestinationAddressMode", dstAddrMode);
+	dumpAddress(s, galPrefix, "DestinationAddress", dstAddrMode, dstAddr);
+	dumpLong(s, galPrefix, "DestinationEndpoint", dstEp);
+
+	dumpLong(s, galPrefix, "SourceAddressMode", srcAddrMode);
+	dumpAddress(s, galPrefix, "SourceAddress", srcAddrMode, srcAddr);
+	dumpLong(s, galPrefix, "SourceEndpoint", srcEp);
+
+	dumpLong(s, galPrefix, "ProfileID", profileId);
+	dumpLong(s, galPrefix, "ClusterID", clusterId);
+	dumpHex(s, galPrefix, "Data", payload, payloadLength);
+	dumpLong(s, galPrefix, "APSStatus", ZB_ZDO_SUCCESS);
+
+	//dumpLong(s, galPrefix, "SecurityStatus", 0xaf);
+	dumpString(s, galPrefix, "SecurityStatus", "SecuredNwkKey");
+
+	dumpLong(s, galPrefix, "LinkQuality", 0xff);
+	//pLogger->debug("13");
+	dumpLong(s, galPrefix, "RxTime", time(NULL));
+
+	dumpString(response, restPrefix, "APSMessageEvent", s);
+
+	return response.str();
+}
+
+//#ifdef WSN_C_PROTOCOL_BACKWARD_COMPATIBILITY
+std::string XMLMsgComposer::createRXMessageMsg_BC(Message *msg) {
+	char tmp_str[BUFFER_SIZE];
+	uchar *payload;
+	uchar *srcAddr;
+	int srcAddrLength;
+	uchar srcEp;
+	uchar *dstAddr;
+	int dstAddrLength;
+	uchar dstEp;
+	ushort profileId;
+	ushort clusterId;
+	ushort payloadLength;
+
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("createRXMessageMsg");
+#endif
+
+	std::string response("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+
+	// Root element Message
+	response += "<Message>";
+
+	// Element RXMessage
+	response += "<RXMessage>";
+
+	srcAddr = msg->getSrcAddr(&srcAddrLength);
+	srcEp = msg->getSrcEp();
+	// Element SourceURL
+	response += "<SourceURL>";
+	response += "zigbee://";
+
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("srcAddrLength = %d",srcAddrLength);
+#endif
+	// We need to invert the way how it created the sourceAddress (with Freescale there were some problems)
+	for (int i = 0; i < srcAddrLength; i++) {
+		//for (int i = srcAddrLength-1; i >= 0; i--) {
+		sprintf(tmp_str, "%02X", (int) (srcAddr[i]));
+		tmp_str[strlen(tmp_str)] = '\0';
+		response += tmp_str;
+	}
+	response += ":";
+	sprintf(tmp_str, "%02X", (int) srcEp);
+	tmp_str[strlen(tmp_str)] = '\0';
+	response += tmp_str;
+	response += "</SourceURL>";
+
+	dstAddr = msg->getDstAddr(&dstAddrLength);
+	dstEp = msg->getDstEp();
+	// Element DestinationURL
+	response += "<DestinationURL>";
+	response += "zigbee://";
+
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("dstAddrLength = %d",dstAddrLength);
+#endif
+	for (int i = dstAddrLength - 1; i >= 0; i--) {
+		sprintf(tmp_str, "%02X", (int) (dstAddr[i]));
+		tmp_str[strlen(tmp_str)] = '\0';
+		response += tmp_str;
+	}
+
+	response += ":";
+	sprintf(tmp_str, "%02X", (int) dstEp);
+	tmp_str[strlen(tmp_str)] = '\0';
+	response += tmp_str;
+	response += "</DestinationURL>";
+
+	profileId = msg->getProfileId();
+	// Element ProfileId
+	response += "<ProfileId>";
+	sprintf(tmp_str, "%02X", (int) profileId);
+	tmp_str[strlen(tmp_str)] = '\0';
+	response += tmp_str;
+	response += "</ProfileId>";
+
+	clusterId = msg->getClusterId();
+	// Element ClusterId
+	response += "<ClusterId>";
+	sprintf(tmp_str, "%02X", (int) clusterId);
+	tmp_str[strlen(tmp_str)] = '\0';
+	response += tmp_str;
+	response += "</ClusterId>";
+
+	// Element MsgId
+	response += "<MsgId>";
+	sprintf(tmp_str, "%d", (int) (msg->getMsgId()));
+	tmp_str[strlen(tmp_str)] = '\0';
+	response += tmp_str;
+	response += "</MsgId>";
+
+	payload = msg->getPayload(&payloadLength);
+	// Element Payload
+
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("payloadLength = %d\n",payloadLength);
+#endif
+
+	response += "<Payload>";
+	for (int i = 0; i < (int) payloadLength; i++) {
+		sprintf(tmp_str, "%02X", (int) (payload[i]));
+		tmp_str[strlen(tmp_str)] = '\0';
+		response += tmp_str;
+	}
+	response += "</Payload>";
+
+	response += "</RXMessage>";
+	response += "</Message>";
+
+	return response;
+}
+//#endif
+
+std::string XMLMsgComposer::createPolledAPSMessage(std::string &s) {
+	std::stringstream response, inner;
+
+	dumpString(inner, galPrefix, "AppliedDecodeSpecification", "DecodeMAC");
+	inner << s;
+
+	dumpString(response, restPrefix, "PolledMessage", inner);
+
+	return response.str();
+}
+
+//	Private methods
+/**
+ Private method XMLMsgComposer dumpString
+ Build a generic XML tag containing a string.
+
+ @param s the destination buffer
+ @param label the tag name
+ @param text the text to put inside of it
+ */
+void XMLMsgComposer::dumpString(std::stringstream &s, const char *prefix,
+		const char *label, const char *text, const char *attrPrefix,
+		std::map<const char *, std::string> *attrs) {
+	std::map<const char *, std::string>::iterator i;
+
+	s << "<";
+	if (prefix != NULL)
+		s << prefix << ":";
+	s << label;
+
+	if (attrs != NULL) {
+		for (i = attrs->begin(); i != attrs->end(); i++) {
+			cout << (*i).first << endl;
+			cout << (*i).second << endl;
+			s << " ";
+//WARNING//
+//			if (prefix != NULL)
+//				s << prefix << ":";
+//WARNING//
+			s << (*i).first << "=\"" << (*i).second << "\"";
+		}
+	}
+	s << ">" << text << "</";
+	if (prefix != NULL)
+		s << prefix << ":";
+	s << label << ">";
+}
+
+void XMLMsgComposer::dumpString(std::stringstream &s, const char *prefix,
+		const char *label, std::stringstream &inner) {
+	dumpString(s, prefix, label, inner.str().c_str());
+}
+
+/**
+ Private method XMLMsgComposer dumpAddress
+ Build a generic XML tag containing a network (short) address.
+
+ @param s the destination buffer
+ @param label the tag name
+ @param mode the address mode
+ @param address the (little endian) address to put inside of it
+ */
+void XMLMsgComposer::dumpAddress(std::stringstream &s, const char *prefix,
+		const char *label, uchar mode, unsigned char address[8]) {
+	std::stringstream inner;
+
+	//TODO - To be modified -> use dumpLong!!!!
+
+	switch (mode) {
+	case 2: {
+		std::stringstream nwk;
+		nwk.str("");
+		nwk << ((address[0] << 8) + address[1]);
+		dumpString(inner, galPrefix, "NetworkAddress", nwk.str().c_str());
+	}
+		break;
+
+	case 3: {
+		std::stringstream ieee;
+		unsigned long long value = ieeeAddrToULongLong(address);
+		ieee.str("");
+		ieee << value;
+		dumpString(inner, galPrefix, "IeeeAddress", ieee.str().c_str());
+	}
+		break;
+	}
+
+	dumpString(s, prefix, label, inner);
+}
+
+void XMLMsgComposer::dumpAddress(std::stringstream &s, const char *prefix,
+		const char *label, uchar mask, Node *node) {
+	std::stringstream inner;
+
+	if (mask & 0x01) {
+		std::stringstream nwk;
+		nwk.str("");
+		nwk << node->get_nwk_addr();
+		dumpString(inner, galPrefix, "NetworkAddress", nwk.str().c_str());
+	}
+
+	if (mask & 0x02) {
+		std::stringstream ieee;
+		unsigned long long value = ieeeAddrToULongLong(node->get_ieee_addr());
+		ieee.str("");
+		ieee << value;
+		dumpString(inner, galPrefix, "IeeeAddress", ieee.str().c_str());
+	}
+
+	dumpString(s, prefix, label, inner);
+}
+
+/**
+ Private method XMLMsgComposer dumpLong
+ Build a generic XML tag containing a long int.
+
+ @param s the destination buffer
+ @param label the tag name
+ @param l the long to put inside of it
+ */
+void XMLMsgComposer::dumpLong(std::stringstream &s, const char *prefix,
+		const char *label, long l, int base) {
+	std::stringstream val;
+
+	if (base == 16)
+		val << hex;
+
+	val << l;
+
+	dumpString(s, prefix, label, val);
+}
+
+void XMLMsgComposer::dumpBoolean(std::stringstream &s, const char *prefix,
+		const char *label, bool flag) {
+	dumpString(s, prefix, label, flag ? "true" : "false");
+}
+
+/**
+ Private method XMLMsgComposer dumpHex
+ Build a generic XML tag containing a hex string.
+
+ @param s the destination buffer
+ @param label the tag name
+ @param p a pointer to binary data
+ @param len the binary data length
+ */
+void XMLMsgComposer::dumpHex(std::stringstream &s, const char *prefix,
+		const char *label, unsigned char *p, int len) {
+	std::stringstream val;
+	int i;
+
+	val << hex;
+	for (i = 0; i < len; i++) {
+		val.width(2);
+		val.fill('0');
+		val << (unsigned int) p[i];
+	}
+
+	dumpString(s, prefix, label, val);
+}
+
+void XMLMsgComposer::dumpNode(std::stringstream &s, const char *prefix,
+		const char *label, Node *node) {
+	std::map<const char *, std::string> attrs;
+	std::stringstream inner, ieee, nwk;
+
+	//if (node -> getParentNode() != NULL)
+	//	dumpAddress(inner, galPrefix, "ParentAddress", 3, node -> getParentNode());
+	dumpAddress(inner, galPrefix, "Address", 3, node);
+	dumpString(s, prefix, label, inner);
+}
+
+void XMLMsgComposer::dumpLogicalType(std::stringstream &s, const char *prefix,
+		const char *label, enum enum_logicaltype ltype) {
+	const char *type;
+
+	switch (ltype) {
+	case COORDINATOR:
+		type = "Coordinator";
+		break;
+
+	case ROUTER:
+		type = "Router";
+		break;
+
+	case ENDDEVICE:
+		type = "EndDevice";
+		break;
+
+	default:
+		return;
+	}
+
+	dumpString(s, prefix, label, type);
+}
+
+void XMLMsgComposer::dumpFreqBand(std::stringstream &s, const char *prefix,
+		const char *label, enum enum_frequencyband fband) {
+	const char *band;
+
+	switch (fband) {
+	case F868_868D6:
+		band = "868MHz";
+		break;
+
+	case F902_928:
+		band = "900MHz";
+		break;
+
+	case F2400_2483D5:
+		band = "2400MHz";
+		break;
+
+	default:
+		return;
+	}
+
+	dumpString(s, prefix, label, band);
+}
+
+void XMLMsgComposer::dumpMACCapability(std::stringstream &s, const char *prefix,
+		const char *label, int mcaps) {
+	std::stringstream inner;
+
+	dumpBoolean(inner, galPrefix, "AlternatePanCoordinator", mcaps & 1);
+	dumpBoolean(inner, galPrefix, "DeviceIsFFD", mcaps & 2);
+	dumpBoolean(inner, galPrefix, "MainsPowered", mcaps & 4);
+	dumpBoolean(inner, galPrefix, "ReceiverOnWhenIdle", mcaps & 8);
+	dumpBoolean(inner, galPrefix, "SecuritySupported", mcaps & 64);
+	dumpBoolean(inner, galPrefix, "AllocateAddress", mcaps & 128);
+
+	dumpString(s, prefix, label, inner);
+}
+
+void XMLMsgComposer::dumpServerMask(std::stringstream &s, const char *prefix,
+		const char *label, int mask) {
+	std::stringstream inner;
+
+	dumpBoolean(inner, galPrefix, "PrimaryTrustCenter", mask & 1);
+	dumpBoolean(inner, galPrefix, "BackupTrustCenter", mask & 2);
+	dumpBoolean(inner, galPrefix, "PrimaryBindingTableCache", mask & 4);
+	dumpBoolean(inner, galPrefix, "BackupBindingTableCache", mask & 8);
+	dumpBoolean(inner, galPrefix, "PrimaryDiscoveryCache", mask & 16);
+	dumpBoolean(inner, galPrefix, "BackupDiscoveryCache", mask & 32);
+	dumpBoolean(inner, galPrefix, "NetworkManager", mask & 64);
+
+	dumpString(s, prefix, label, inner);
+}
+
+void XMLMsgComposer::dumpPowerMode(std::stringstream &s, const char *prefix,
+		const char *label, enum enum_currentpowermode mode) {
+	const char *tag;
+
+	switch (mode) {
+	case SYNCHRONIZED_WITH_RECEIVERONWHENIDLE:
+		tag = "Synchronized";
+		break;
+
+	case PERIODICALLYON:
+		tag = "Periodic";
+		break;
+
+	case WHENSTIMULATED:
+		tag = "Stimulated";
+		break;
+
+	case UNKNOWN_POWERMODE:
+	default:
+		return;
+	}
+
+	dumpString(s, prefix, label, tag);
+}
+
+void XMLMsgComposer::dumpPowerSources(std::stringstream &s, const char *prefix,
+		const char *label, bool psource[3]) {
+	std::stringstream inner;
+
+	dumpBoolean(inner, galPrefix, "ConstrantMains", psource[MAINPOWER]);
+	dumpBoolean(inner, galPrefix, "RechargeableBattery", psource[RECHARGEABLE]);
+	dumpBoolean(inner, galPrefix, "DisposableBattery", psource[DISPOSABLE]);
+
+	dumpString(s, prefix, label, inner);
+}
+
+void XMLMsgComposer::dumpPowerSourceLevel(std::stringstream &s,
+		const char *prefix, const char *label,
+		enum enum_currentpowersourcelevel l) {
+	const char *tag;
+
+	switch (l) {
+	case CRITICAL:
+		tag = "Critical";
+		break;
+
+	case P33:
+		tag = "33Percent";
+		break;
+
+	case P66:
+		tag = "66Percent";
+		break;
+
+	case P100:
+		tag = "100Percent";
+		break;
+
+	case UNKNOWN_PSLEVEL:
+	default:
+		return;
+	}
+
+	dumpString(s, prefix, label, tag);
+}
+
+void XMLMsgComposer::dumpNodeServices(std::stringstream &response,
+		const char *prefix, const char *label, Node *node) {
+	std::stringstream inner, eps;
+	std::list<int> endpoints;
+	std::list<int>::iterator it;
+	int numEndPoints = 0;
+
+#ifdef DEBUG_ACTIVE_XMLMSGCOMPOSER
+	pLogger->debug("dumpNodeServices");
+#endif
+
+	endpoints = node->getEndPointList();
+
+	dumpAddress(inner, galPrefix, "Address", 3, node);
+
+	for (it = endpoints.begin(); it != endpoints.end(); it++) {
+		eps.str("");
+		dumpLong(eps, galPrefix, "EndPoint", *it, 10);
+		dumpString(inner, galPrefix, "ActiveEndpoints", eps);
+		numEndPoints++;
+	}
+	if (numEndPoints == 0) {
+		// No endPoint discovered so far, but the "ActiveEndpoints" is mandatory!
+		dumpString(inner, galPrefix, "ActiveEndpoints/", NULL);
+	}
+
+	dumpString(response, prefix, "NodeServices", inner);
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/XMLProcessor.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/XMLProcessor.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/XMLProcessor.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,343 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef XMLPROCESSOR_H
+#define XMLPROCESSOR_H
+
+// Enabling printing information
+//#define DEBUG_ACTIVE_XMLMSGCOMPOSER
+//#define DEBUG_ACTIVE_XMLMSGPARSER
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "ThreadPool.h"
+#include "TimerThread.h"
+
+#include "GalZbIf.h"
+#include "CMessage.h"
+#include "ZbNetDb.h"
+
+#include "GWManagement.h"		// used for GW_DESCRIPTOR
+#include "CDebug.h"
+
+#include "CResource.h"
+#include "NodeMap.h"
+
+#include "ConfigurationRepository.h"
+
+#include "tinyxml.h"
+
+#include <string>
+
+#ifdef WIN32
+#define snprintf	_snprintf
+#endif
+
+#define BUFFER_SIZE			500
+
+class XMLMsgParser {
+
+public:
+	// Constructors
+
+	// Destructor
+	~XMLMsgParser();
+
+	// Functions: modifiers (set), selectors (get)
+
+	// Pattern Singleton
+	static XMLMsgParser *Instance(void);
+
+	void init();
+
+	int getZCLCommandToWSN(Message *msg, std::string *xmlMsg);
+
+	int getZDPCommandToWSN(Message *msg, std::string *xmlMsg);
+
+	int getAPSMessageToWSN(Message *msg, std::string *xmlMsg);
+
+	int getBindindCommand(ZB_BIND_STRUCT *bindParams, std::string *xmlMsg);
+
+	int getSimpleDescriptor(SimpleDescriptor *sd, std::string *xmlMsg);
+
+	int getJoiningInfoValues(int *PermitDuration, bool *TCSignificance,
+			std::string *xmlMsg);
+
+	int getCallback(Callback *sd, std::string *xmlMsg);
+
+	int getValueAttribute(std::string *value, std::string *xmlMsg);
+
+	int getStartupAttributeInfo(StartupAttributeInfo *sai, std::string *xmlMsg);
+
+	int getValue(unsigned long &l, std::string *xmlMsg);
+
+	int getValue(std::string &s, std::string *xmlMsg);
+
+	// iterators:
+	// Attributes visible by scope of instantiation and use
+
+	///	Constructor (pattern Singleton)
+	XMLMsgParser();
+
+	TiXmlElement *getRoot(TiXmlDocument &doc, std::string &xmlMsg,
+			std::string &label, const char *&galPrefix,
+			const char *&restPrefix);
+
+	int parseLong(TiXmlElement *node, const char *prefix, const char *label,
+			long &l, int base, long min, long max);
+
+protected:
+
+	TiXmlElement *getNode(TiXmlElement *node, const char *prefix,
+			const char *label, TiXmlElement *prev = NULL);
+	const char *getPrefix(TiXmlElement *root, const char *uri);
+
+	// Attributes visible to descendents
+
+	///	Pointer to a Debug object -> logger
+	Debug *pLogger;
+
+	///	To enable/disable Debug (default value is 0)
+	bool debugEnabled;
+
+private:
+
+	typedef std::map<string, int> StrIntMap;
+
+	// Local methods
+	int parseAddress(TiXmlElement *node, const char *prefix, const char *label,
+			uchar &mode, unsigned char address[8], const char *galPrefix);
+
+	int parseDeviceElement(TiXmlElement *node, const char *prefix,
+			const char *label, uchar &endPoint, unsigned char address[8],
+			const char *galPrefix);
+
+	int parseTxOptions(TiXmlElement *node, const char *prefix,
+			const char *label, uchar &value, const char *galPrefix);
+
+	int parseBoolean(TiXmlElement *node, const char *prefix, const char *label,
+			bool &value);
+
+	int parseHex(TiXmlElement *node, const char *prefix, const char *label,
+			unsigned char *&p, long &len);
+
+	int parseEnumeration(TiXmlElement *node, const char *prefix,
+			const char *label, StrIntMap *restriction, int &value);
+
+	// Local attributes
+
+	// Pattern Singleton
+	static XMLMsgParser instance;
+
+	// String - Int map related to DeviceType (StartupAttributeInfo parameter)
+	StrIntMap deviceType;
+	// String - Int map related to DecodeLevel in DecodeSpecification (a parameter used
+	// to define the filter considered in CreatCallback procedure)
+	StrIntMap ds_DecodeLevel;
+
+	StrIntMap ls_Level;
+};
+
+//**************************************************************************
+//**************************************************************************
+
+class XMLMsgComposer {
+
+public:
+	// Constructors
+
+	// Destructor
+	~XMLMsgComposer();
+
+	// Functions: modifiers (set), selectors (get)
+
+	// Pattern Singleton
+	static XMLMsgComposer *Instance(void);
+
+	void init();
+
+	void enableNamespaces(bool flag);
+
+	///	Version
+	std::string createVersionMsg(void);
+
+	/// Get procedure
+	std::string createGetAttributeMsg(std::string value);
+
+	/// Set procedure
+	std::string setAttributeMsg(void);
+
+	/// GenericResponse
+	std::string createGenericResponseMsg(void);
+
+	///	WSNNodes
+	std::string createWSNNodeMsg(int result, Node *node);
+
+	std::string createWSNNodesListMsg(int result, ZbNetDb *buffer);
+
+	std::string createAliasesMsg(int result, ZbNetDb *buffer);
+
+	///	Node Descriptor
+	std::string createNodeDescMsg(int result, NodeDescriptor &node_desc);
+
+	std::string createGetNodeBindingMsg(int result, short bindingTableEntries,
+			short startIndex, short bindingTableListCount,
+			ZB_BIND_STRUCT *bindingtableList);
+
+	std::string createLQIInformationMsg(ZbNetDb *buffer);
+
+	///	Power Descriptor
+	std::string createPowerDescMsg(int result, ushort nwk_addr,
+			uchar *ieee_addr, PowerDescriptor &power_desc);
+
+	std::string createAllNodesServiceDescMsg(int result, ZbNetDb *buffer);
+
+	///	Services
+	std::string createActiveEndPointMsg(int result, Node *node);
+
+	std::string createActiveEndPointLocalNodeMsg(int numEndPoints,
+			int * endPoints);
+
+	std::string createServiceDescriptorMsg(int result, Node *node,
+			int endpoint);
+
+	std::string createLocalNodeEndpointMsg(int result,
+			SimpleDescriptor *serviceDesc);
+
+	std::string createCallbackIdentifierMsg(std::string &s);
+
+	std::string createZCLMessage(uchar confirmStatus, unsigned txTime,
+			Message *msg);
+
+	std::string createZDPMessage(uchar confirmStatus, unsigned txTime,
+			Message * msg);
+
+	///	ZigBee message send status
+	std::string createAPSResultMsg(uchar confirmStatus, unsigned txTime);
+
+	///	ZigBee message received
+	std::string createRXMessageMsg(Message *msg);
+
+//#ifdef WSN_C_PROTOCOL_BACKWARD_COMPATIBILITY
+	std::string createRXMessageMsg_BC(Message *msg);
+//#endif
+
+	std::string createPolledAPSMessage(std::string &s);
+
+	///	GW Status Changed Event
+	std::string createGwStatusChangedMsg(GwDescriptor *gwDescriptor);
+
+	std::string createCallbackIdentiferMsg(std::list<std::string> ids);
+
+	std::string createCallbacksMsg(std::list<std::string> ids);
+
+	///	WSNConnection created by WSN-C - Event
+	std::string createWsncWSNConnEventMsg(int endpointId,
+			const char *uriListener, const char *wsnConnStatus);
+
+	///	Error message
+	std::string createErrorMsg(int errorCode, const char *errorDesc,
+			const char *nwkStatus, const char *requestIdentifier);
+
+	///	Success message
+	std::string createSuccessMsg(const char *text, const char *nwkStatus,
+			const char *requestIdentifier);
+
+	///	Resource Info message
+	std::string createResourceInfoMsg(Resource *resource);
+
+	// iterators:
+	// Attributes visible by scope of instantiation and use
+
+	std::string createRestInfoMsg(int errorCode, const char *errorDesc,
+			const char *detail, const char *requestIdentifier,
+			const char *eventCallbackIdentifier, const char *nwkStatus);
+
+protected:
+
+	///	Constructor (pattern Singleton)
+	XMLMsgComposer();
+
+	// Attributes visible to descendents
+
+	/// Pointer to a Debug object -> logger
+	Debug *pLogger;
+
+	///	To enable/disable Debug (default value is 0)
+	bool debugEnabled;
+
+private:
+	// Local methods
+	void dumpString(std::stringstream &s, const char *prefix, const char *label,
+			const char *text, const char *attrPrefix = NULL,
+			std::map<const char *, std::string> *attrs = NULL);
+
+	void dumpString(std::stringstream &s, const char *prefix, const char *label,
+			std::stringstream &inner);
+
+	void dumpAddress(std::stringstream &s, const char *prefix,
+			const char *label, uchar mode, unsigned char *address);
+
+	void dumpAddress(std::stringstream &s, const char *prefix,
+			const char *label, uchar mask, Node *node);
+
+	void dumpLong(std::stringstream &s, const char *prefix, const char *label,
+			long l, int base = 10);
+
+	void dumpBoolean(std::stringstream &s, const char *prefix,
+			const char *label, bool flag);
+
+	void dumpHex(std::stringstream &s, const char *prefix, const char *label,
+			unsigned char *p, int len);
+
+	void dumpNode(std::stringstream &s, const char *prefix, const char *label,
+			Node *node);
+
+	void dumpLogicalType(std::stringstream &s, const char *prefix,
+			const char *label, enum enum_logicaltype ltype);
+
+	void dumpFreqBand(std::stringstream &s, const char *prefix,
+			const char *label, enum enum_frequencyband fband);
+
+	void dumpMACCapability(std::stringstream &s, const char *prefix,
+			const char *label, int mcaps);
+
+	void dumpServerMask(std::stringstream &s, const char *prefix,
+			const char *label, int mask);
+
+	void dumpPowerMode(std::stringstream &s, const char *prefix,
+			const char *label, enum enum_currentpowermode mode);
+
+	void dumpPowerSources(std::stringstream &s, const char *prefix,
+			const char *label, bool psource[3]);
+
+	void dumpPowerSourceLevel(std::stringstream &s, const char *prefix,
+			const char *label, enum enum_currentpowersourcelevel level);
+
+	void dumpNodeServices(std::stringstream &response, const char *prefix,
+			const char *label, Node *node);
+
+	std::string createDocElement(const char *prefix, const char *label,
+			const char *text);
+
+	int hexStringToInt(const char* hexString);
+	unsigned long long ieeeAddrToULongLong(uchar* array);
+
+	// Local attributes
+
+	// Pattern Singleton
+	static XMLMsgComposer *pInstance;
+
+	const char *galPrefix, *restPrefix;
+
+};
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ZbNetDb.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ZbNetDb.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ZbNetDb.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,1295 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef WIN32
+#include "stdafx.h"
+#else
+#include "winport.h"
+#endif
+
+#include <sys/time.h>
+#include <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include "ZbNetDb.h"
+
+//**************************************************************************
+//*************  Node  *****************************************************
+//**************************************************************************
+
+/**
+ * Constructor
+ * Node constructor. It receives as parameter the network address of the device of interest.
+ *
+ * @param nwk_addr Network address of the device.
+ * @return Void.
+ */
+
+Node::Node(ushort nwk_addr) {
+	this->nwk_addr = nwk_addr;
+	// Init node and power descriptor
+	this->node_desc.filled = false;
+	this->power_desc.filled = false;
+	this->isActive = false;
+	this->nodeTimer = 0xFFFFFFFF; // This value indicates that timeout has not been set yet!
+	this->numOfPingsDone = 0;
+	this->forcePingTimer = 0x00000000;
+	// Initialize the IEEE Address
+	this->ieee_addr[0] = 0x00;
+	this->ieee_addr[1] = 0x00;
+	this->ieee_addr[2] = 0x00;
+	this->ieee_addr[3] = 0x00;
+	this->ieee_addr[4] = 0x00;
+	this->ieee_addr[5] = 0x00;
+	this->ieee_addr[6] = 0x00;
+	this->ieee_addr[7] = 0x00;
+	// The LQIInformationTable is empty when a new node is created
+	this->currentLQIInformationTableSize = 0;
+	// Initialize the neighbor table
+	this->neighbor.clear();
+}
+
+/**
+ * Destructor
+ * Node destructor.
+ *
+ * @param void Void.
+ * @return Void.
+ */
+
+Node::~Node() {
+
+	// Clear neighbor list
+	neighbor.clear();
+
+	//NEW
+	// Delete all the simple descriptors
+	std::map<int, SimpleDescriptor *>::iterator it;
+	for (it = simpleDesc.begin(); it != simpleDesc.end(); ++it) {
+		delete (it->second);
+	}
+}
+
+/**
+ * Public method Node set_ieee_addr
+ * This method allows setting IEEE address for a specific Node
+ *
+ * @param ieee_addr IEEE address.
+ * @return Void.
+ */
+
+void Node::set_ieee_addr(uchar *ieee_addr) {
+	if (ieee_addr != NULL)
+		memcpy(this->ieee_addr, ieee_addr, IEEE_ADDR_LEN);
+}
+
+/**
+ * Public method Node set_ieee_addr
+ * This method allows setting short address for a specific Node
+ *
+ * @param nwk_addr short address.
+ * @return Void.
+ */
+
+void Node::set_nwk_addr(ushort nwk_addr) {
+	this->nwk_addr = nwk_addr;
+}
+
+/**
+ * Public method Node get_ieee_addr
+ *
+ * @param void Void.
+ * @return IEEE (i.e. full) address of a specif Node.
+ */
+
+uchar *Node::get_ieee_addr() {
+	return ieee_addr;
+}
+
+/**
+ * Public method Node get_nwk_addr
+ *
+ * @param void Void.
+ * @return Network (i.e. short) address of a specif Node.
+ */
+
+ushort Node::get_nwk_addr() {
+	return nwk_addr;
+}
+
+LQIInformationEntry * Node::getLQIInformationTable(int * size) {
+	*size = currentLQIInformationTableSize;
+	return LQIInformationTable;
+}
+
+/**
+ * This function updates the neighbor LQI information for this specific Node
+ *  */
+void Node::updateLQIInformation(ushort shortAddr, uchar * ieeeAddr,
+		uchar devTypeRxOnRelation, uchar depth, uchar lqi) {
+	int index = -1;
+	int i = 0;
+
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+	printf("updateLQIInformation\n");
+#endif
+
+	//Find the eventual entry
+	while (i < currentLQIInformationTableSize) {
+		if (LQIInformationTable[i].shortAddress == shortAddr) {
+			//Node found
+			index = i;
+			break;
+		}
+		i++;
+	}
+	if (index == -1) {
+		//Not found, a new entry neds to be created
+		if (currentLQIInformationTableSize >= maxLQIInformationTableSize) {
+			printf("updateLQIInformation - Maximum limit reached (%d)",
+					currentLQIInformationTableSize);
+			return;
+		}
+		index = currentLQIInformationTableSize;
+		currentLQIInformationTableSize++;
+		LQIInformationTable[index].shortAddress = shortAddr;
+		memcpy(LQIInformationTable[index].ieeeAddress, ieeeAddr, 8);
+		LQIInformationTable[index].devTypeRxOnRelation = devTypeRxOnRelation;
+		LQIInformationTable[index].depth = depth;
+		LQIInformationTable[index].lqi = lqi;
+	} else {
+		//Update the current entry
+		LQIInformationTable[index].shortAddress = shortAddr;
+		memcpy(LQIInformationTable[index].ieeeAddress, ieeeAddr, 8);
+		LQIInformationTable[index].devTypeRxOnRelation = devTypeRxOnRelation;
+		LQIInformationTable[index].depth = depth;
+		LQIInformationTable[index].lqi = lqi;
+	}
+}
+
+/**
+ * This function is responsible to clean all neighbors now not present anymore in the Node's neighbors table
+ */
+void Node::removeOldLQIInformation(ZB_NEIGHBOR_TABLE_LIST * neighbors,
+		int neighborsCount) {
+	int i, j;
+	bool nodeFound[maxLQIInformationTableSize];
+
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+	printf("removeOldLQIInformation\n");
+#endif
+
+	if (neighborsCount == 0) {
+		// Careful: here we're automatically removing all the entries!
+		currentLQIInformationTableSize = 0;
+		return;
+	}
+	//Find which nodes needs to be removed
+	for (i = 0; i < currentLQIInformationTableSize; i++) {
+		for (j = 0; j < neighborsCount; j++) {
+			if (LQIInformationTable[i].shortAddress
+					== neighbors[j].NetworkAddress) {
+				nodeFound[i] = true;
+				break;
+			}
+		}
+		if (j == neighborsCount)
+			nodeFound[i] = false;
+	}
+	// All the entries in 'nodeFound' array with boolean 'false' needs to be removed!
+	for (i = 0; i < currentLQIInformationTableSize; i++) {
+		if (nodeFound[i] == false) {
+			//Node to be removed: take the last one entry and move it to this current position
+			LQIInformationTable[i] =
+					LQIInformationTable[currentLQIInformationTableSize - 1];
+			nodeFound[i] = nodeFound[currentLQIInformationTableSize - 1]; //idem for the nodeFound array entry
+			// The total entries now are updated (since the is one less item in total)
+			currentLQIInformationTableSize--;
+			// Keeping scanning from this entry (don't skip this just-moved entry)
+			i--;
+		}
+	}
+	// This is just a control check
+	if (currentLQIInformationTableSize != neighborsCount)
+		printf("removeOldLQIInformation - Algorithm error!\n");
+}
+
+/**
+ * Public method Node dump
+ * This method prints the short address related to the node of interest.
+ *
+ * @param void Void.
+ * @return Void.
+ */
+
+void Node::dump(void) {
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+	printf("Node %04X \n", nwk_addr);
+#endif
+}
+
+/**
+ * Public method Node getEndPointList
+ * This method allows retrieving the EndPoints list related to node of interest.
+ *
+ * @param void Void.
+ * @return EndPoints list related to node of interest.
+ */
+
+std::list<int> Node::getEndPointList() {
+
+	return this->endpoints;
+
+}
+
+/**
+ * Public method Node getSimpleDescr
+ * This method allows retrieving the simple (i.e. service) descriptor related to a specific endpoint.
+ *
+ * @param endpoint Endpoint of interest.
+ * @return Simple descriptor data structure.
+ */
+
+SimpleDescriptor* Node::getSimpleDescr(int endpoint) {
+	std::map<int, SimpleDescriptor *>::iterator it;
+
+	it = simpleDesc.find(endpoint);
+	if (it == simpleDesc.end()) {
+		// No entries found!
+		return NULL;
+	}
+	return it->second;
+}
+
+void Node::setIsActive(bool b) {
+	this->isActive = b;
+}
+
+bool Node::getIsActive(void) {
+	return this->isActive;
+}
+
+void Node::setKANodeTimer(long timeout) {
+	this->nodeTimer = timeout;
+}
+
+long Node::getKANodeTimer(void) {
+	return this->nodeTimer;
+}
+
+void Node::setnumOfPingsDone(int value) {
+	this->numOfPingsDone = value;
+}
+
+int Node::getnumOfPingsDone(void) {
+	return this->numOfPingsDone;
+}
+
+void Node::setForcePingTimer(long timeout) {
+	this->forcePingTimer = timeout;
+}
+
+long Node::getForcePingTimer(void) {
+	return this->forcePingTimer;
+}
+
+//**************************************************************************
+//*************  ZbNetDb  **************************************************
+//**************************************************************************
+
+/**
+ * Constructor
+ * ZbNetDb constructor.
+ *
+ * @param void Void.
+ * @return Void.
+ */
+
+ZbNetDb::ZbNetDb() :
+		root(NULL), locked(false) {
+}
+
+ZbNetDb::~ZbNetDb() {
+	clearAll();
+	// Remove all the translationEntry entries
+	removeAllTCKeyTableEntry();
+	// Remove the StartupAttributeInfo
+	removeAllStartupAttributeInfo();
+}
+
+/**
+ * Public method ZbNetDb clearAll
+ * This method is used to clear the information contained in ZbNetDb object.
+ *
+ * @param void Void.
+ * @return Status.
+ */
+
+int ZbNetDb::clearAll(void) {
+
+	if (root != NULL || node_dict.size() != 0) {
+
+		// Delete all the objects contained in node dictionary
+		std::map<ushort, Node *>::iterator iter;
+		Node * tmpNode;
+
+		for (iter = node_dict.begin(); iter != node_dict.end(); ++iter) {
+			tmpNode = iter->second;
+			delete (tmpNode);
+		}
+
+		node_dict.clear();
+
+		root = NULL;
+	}
+	return 0;
+}
+
+int ZbNetDb::clearAllButRoot() {
+
+	if (root == NULL) {
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+		printf("ZbNetDb::clearAllButRoot - ERROR: no root node set!");
+#endif
+		return -1;
+	} else if (node_dict.size() == 0) {
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+		printf("ZbNetDb::clearAllButRoot - WARNING: node_dict already empty.");
+#endif
+		return -2;
+	}
+	// Delete all the objects contained in node dictionary apart from nwkAddr
+	std::map<ushort, Node *>::iterator iter;
+	Node * tmpNode;
+
+	for (iter = node_dict.begin(); iter != node_dict.end();) {
+		if (root->nwk_addr != iter->first) {
+			tmpNode = iter->second;
+			delete (tmpNode);
+			node_dict.erase(iter++);
+		} else {
+			//The root now became this unique remaining node!
+			root = iter->second;
+			++iter;
+		}
+	}
+	return 0;
+}
+
+/**
+ * Public method ZbNetDb setRoot
+ *
+ * @param node Pointer to a Node object.
+ * @return Status.
+ */
+
+int ZbNetDb::setRoot(Node *node) {
+	assert(node != NULL);
+
+	if (root != NULL) {
+		//clearAll();
+		return -1;
+	}
+	root = node;
+	// Add the node to the dictionary
+	node_dict[node->get_nwk_addr()] = node;
+	//Root node never sleep!
+	root->node_desc.receiveronwhenidle = true;
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+	printf("\nZbNetDb::setRoot - Root node set!\n\n");
+#endif
+	return 0;
+}
+
+/**
+ * Public method ZbNetDb addEndPoint
+ *
+ * @param node Pointer to the Node object of interest.
+ * @param epNumber EndPoint identifier to be added.
+ * @return Status.
+ */
+
+int ZbNetDb::addEndPoint(Node *node, int epNumber) {
+
+	assert(node != NULL);
+	node->endpoints.push_back(epNumber);
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+	printf("ZbNetDb::addEndPoint - #endpoint= %d", epNumber);
+#endif
+	return 0;
+}
+
+/**
+ * Public method ZbNetDb addEndPoint
+ *
+ * @param node Pointer to the Node object of interest.
+ * @return Status.
+ */
+
+int ZbNetDb::clearEndPointList(Node *node) {
+
+	assert(node != NULL);
+	node->endpoints.clear();
+	return 0;
+}
+
+/**
+ * Public method ZbNetDb getEndPointList
+ *
+ * @param node Pointer to the Node object of interest.
+ * @return EndPoint list.
+ */
+
+std::list<int> ZbNetDb::getEndPointList(Node *node) {
+	assert(node != NULL);
+	return node->endpoints;
+}
+
+/**
+ * Public method ZbNetDb initSimpleDescr
+ *
+ * @param node Pointer to the Node object of interest.
+ * @return Status.
+ */
+
+int ZbNetDb::createDefaultSimpleDescr(int endPoint, SimpleDescriptor * sd) {
+
+	// Configure a Common Data Sink Cluster as SimpleDescriptor
+	sd->end_point = endPoint;
+	sd->profile_id = 0xa1e0;
+	sd->device_id = 0x0001;
+	sd->device_ver = 0;
+	//sd.complex_desc_available;
+	//sd.user_desc_available;
+	//sd->input_cluster_count = 1;
+	sd->input_cluster.push_back(0x0300); //0x0300 is the common data sink cluster
+	//sd->output_cluster_count = 1;
+	sd->output_cluster.push_back(0x0300);
+
+	return 0;
+}
+
+/**
+ * Public method ZbNetDb addSimpleDescr
+ *
+ * @param node Pointer to the Node object of interest.
+ * @param sd Pointer to the simple descriptor data structure to be added in simple descriptor map related to the node of interest.
+ * @return Status.
+ */
+
+int ZbNetDb::addSimpleDescr(Node *node, SimpleDescriptor *sd) {
+
+	assert(node != NULL);
+	assert(sd != NULL);
+
+	// Add this new simple descriptor to the node
+	node->simpleDesc[sd->end_point] = sd;
+
+	return 0;
+}
+
+/**
+ * Public method ZbNetDb clearSimpleDescrList
+ *
+ * @param node Pointer to the Node object of interest.
+ * @return Status.
+ */
+
+int ZbNetDb::clearSimpleDescrList(Node *node) {
+	assert(node != NULL);
+
+	std::map<int, SimpleDescriptor *>::iterator it;
+	for (it = node->simpleDesc.begin(); it != node->simpleDesc.end(); ++it) {
+
+		delete (it->second);
+	}
+
+	node->simpleDesc.clear();
+
+	return 0;
+}
+
+/**
+ * Public method ZbNetDb clearSimpleDescr
+ *
+ * @param node Pointer to the Node object of interest.
+ * @param endpoint Endpoint whose simple descriptor has to be erased.
+ * @return Status.
+ */
+
+int ZbNetDb::clearSimpleDescr(Node *node, int endpoint) {
+	assert(node != NULL);
+
+	std::map<int, SimpleDescriptor *>::iterator it;
+	it = node->simpleDesc.find(endpoint);
+	if (it != node->simpleDesc.end()) {
+		delete (it->second);
+		node->simpleDesc.erase(endpoint);
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+		printf("ZbNetDb::clearSimpleDescr - element removed!");
+#endif
+		return 0;
+	}
+
+	// No entries found
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+	printf("ZbNetDb::clearSimpleDescr - no match found!");
+#endif
+	return -1;
+}
+
+/**
+ * Public method ZbNetDb getSimpleDescr
+ *
+ * @param node Pointer to the Node object of interest.
+ * @param endpoint Endpoint whose simple descriptor is considered.
+ * @return Status.
+ */
+
+SimpleDescriptor* ZbNetDb::getSimpleDescr(Node *node, int endpoint) {
+	assert(node != NULL);
+
+	return node->simpleDesc[endpoint];
+}
+
+/**
+ * Public method ZbNetDb addNeighbor
+ *
+ * @param node Pointer to the Node object of interest.
+ * @param neighbor Pointer to the neighbor Node object.
+ * @return Status.
+ */
+
+int ZbNetDb::addNeighbor(Node *node, Node *neighbor) {
+	assert(node != NULL);
+	assert(neighbor != NULL);
+	// Delete the eventual neighbor's information if it was already present
+	//list<Node *>::iterator p;
+	//p = find(node->neighbor.begin( ), node->neighbor.end( ), neighbor);
+	//p = node->neighbor.erase(p);
+	//Combine erase and remove to remove a found element
+	//node->neighbor.erase(remove(node->neighbor.begin( ), node->neighbor.end( ), neighbor),node->neighbor.end( ));
+	node->neighbor.remove(neighbor);
+	// Add neighbor
+	node->neighbor.push_back(neighbor);
+	// Add/update the node to the dictionary
+	node_dict[neighbor->get_nwk_addr()] = neighbor;
+	return 0;
+}
+
+int ZbNetDb::removeNeighbor(Node *node, Node *neighbor) {
+	if (node == NULL || neighbor == NULL)
+		return 1;
+	// Delete the eventual neighbor's information present in the current node
+	node->neighbor.remove(neighbor);
+	return 0;
+}
+
+/**
+ * Public method ZbNetDb findNodeByNwkAddr
+ * Returns the Node object related to the passed Zigbee Network Address
+ *
+ * @param nwk_addr Network address of the node the caller is interested in.
+ * @return Node or NULL, if nwk_addr doesn't correspond to any node already stored in the DB.
+ */
+
+Node *ZbNetDb::findNodeByNwkAddr(ushort nwk_addr) {
+	std::map<ushort, Node *>::iterator it;
+	it = node_dict.find(nwk_addr);
+	if (it == node_dict.end()) {
+		// No entries found!
+		return NULL;
+	}
+	return it->second;
+}
+
+/**
+ * Public method ZbNetDb findNodeByIEEEAddr
+ * Returns the Node object related to the passed Zigbee IEEE Address
+ *
+ * @param ieee_addr IEEE address of the node the caller is interested in (big endian format).
+ * @return Node or NULL, if ieee_addr doesn't correspond to any node already stored in the DB.
+ */
+Node *ZbNetDb::findNodeByIEEEAddr(uchar *ieee_addr) {
+	std::map<ushort, Node *>::iterator iter;
+	Node * tmpNode;
+	bool found = false;
+
+	if (this->node_dict.empty())
+		return NULL;
+
+	for (iter = node_dict.begin(); iter != node_dict.end(); ++iter) {
+		tmpNode = iter->second;
+		/*
+		 printf("Element in DB: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, element passed: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x!\n",
+		 tmpNode->get_ieee_addr()[0],tmpNode->get_ieee_addr()[1],tmpNode->get_ieee_addr()[2],tmpNode->get_ieee_addr()[3],tmpNode->get_ieee_addr()[4],tmpNode->get_ieee_addr()[5],tmpNode->get_ieee_addr()[6],tmpNode->get_ieee_addr()[7],
+		 ieee_addr[0],ieee_addr[1],ieee_addr[2],ieee_addr[3],ieee_addr[4],ieee_addr[5],ieee_addr[6],ieee_addr[7]);
+		 */
+		if (memcmp(tmpNode->get_ieee_addr(), ieee_addr, 8) == 0) {
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+			printf("ZbNetDb::findNodeByIEEEAddr - element found\n");
+#endif
+			found = true;
+			break;
+		}
+	}
+	if (found)
+		return tmpNode;
+	/* Patch 23-12-2011*/
+	//Try the reverse!
+	uchar ieee_addr_rev[8];
+	ieee_addr_rev[0] = ieee_addr[7];
+	ieee_addr_rev[1] = ieee_addr[6];
+	ieee_addr_rev[2] = ieee_addr[5];
+	ieee_addr_rev[3] = ieee_addr[4];
+	ieee_addr_rev[4] = ieee_addr[3];
+	ieee_addr_rev[5] = ieee_addr[2];
+	ieee_addr_rev[6] = ieee_addr[1];
+	ieee_addr_rev[7] = ieee_addr[0];
+	//Let's start
+	for (iter = node_dict.begin(); iter != node_dict.end(); ++iter) {
+		tmpNode = iter->second;
+		if (memcmp(tmpNode->get_ieee_addr(), ieee_addr_rev, 8) == 0) {
+			printf(
+					"ZbNetDb::findNodeByIEEEAddr - ERROR: element requested: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, element found: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x!\n",
+					ieee_addr[0], ieee_addr[1], ieee_addr[2], ieee_addr[3],
+					ieee_addr[4], ieee_addr[5], ieee_addr[6], ieee_addr[7],
+					ieee_addr_rev[0], ieee_addr_rev[1], ieee_addr_rev[2],
+					ieee_addr_rev[3], ieee_addr_rev[4], ieee_addr_rev[5],
+					ieee_addr_rev[6], ieee_addr_rev[7]);
+			found = true;
+			break;
+		}
+	}
+	if (found)
+		return tmpNode;
+	/* END PATCH*/
+	return NULL;
+}
+
+/**
+ * Public method ZbNetDb translateAddress
+ * Returns the network address related to the passed Zigbee IEEE Address
+ *
+ * @param ieee_addr IEEE address of the node the caller is interested in (big endian format).
+ * @return network address or NULL
+ */
+ushort ZbNetDb::translateAddress(uchar * ieeeAddr) {
+	std::string ieeeAddrString((const char *) ieeeAddr, 8);
+	if (translate_ieee_dict.find(ieeeAddrString) != translate_ieee_dict.end())
+		return translate_ieee_dict[ieeeAddrString];
+	else
+		return 0xFFFF; //question
+}
+
+/**
+ * Public method ZbNetDb translateAddress
+ * Returns the Zigbee IEEE Address related to the passed network address
+ *
+ * @param nwkAddr network address of the node the caller is interested in.
+ * @return ieee address or NULL
+ */
+uchar * ZbNetDb::translateAddress(ushort nwkAddr) {
+	uchar * ieeeAddrUchar = NULL;
+	if (translate_nwk_dict.find(nwkAddr) == translate_nwk_dict.end())
+		ieeeAddrUchar = (uchar *) translate_nwk_dict[nwkAddr].c_str(); //question
+	return ieeeAddrUchar;
+}
+
+/**
+ * Public method ZbNetDb translateAddress
+ * Returns the Zigbee IEEE Address related to the passed network address
+ *
+ * @param nwkAddr network address of the node the caller is interested in.
+ * @return ieee address or NULL
+ */
+void ZbNetDb::addTranslationEntry(ushort nwkAddr, uchar * ieeeAddr) {
+	std::string ieeeAddrString((const char *) ieeeAddr, 8);
+
+	translate_ieee_dict[ieeeAddrString] = nwkAddr;
+	translate_nwk_dict[nwkAddr] = ieeeAddrString;
+}
+
+/**
+ * Public method ZbNetDb removeTranslationEntry
+ * Returns the network address related to the passed Zigbee IEEE Address
+ *
+ * @param ieee_addr IEEE address of the node the caller is interested in (big endian format).
+ * @return void
+ */
+void ZbNetDb::removeTranslationEntry(uchar * ieeeAddr) {
+	std::map<std::string, ushort>::iterator iter1;
+	std::map<ushort, std::string>::iterator iter2;
+
+	std::string ieeeAddrString((const char *) ieeeAddr, 8);
+	ushort nwkAddr = translate_ieee_dict[ieeeAddrString];
+
+	iter1 = translate_ieee_dict.find(ieeeAddrString);
+	if (iter1 != translate_ieee_dict.end())
+		translate_ieee_dict.erase(iter1);
+
+	iter2 = translate_nwk_dict.find(nwkAddr);
+	if (iter2 != translate_nwk_dict.end())
+		translate_nwk_dict.erase(iter2);
+}
+
+/**
+ * Public method ZbNetDb removeTranslationEntry
+ * Returns the Zigbee IEEE Address related to the passed network address
+ *
+ * @param nwkAddr network address of the node the caller is interested in.
+ * @return void
+ */
+void ZbNetDb::removeTranslationEntry(ushort nwkAddr) {
+	std::map<std::string, ushort>::iterator iter1;
+	std::map<ushort, std::string>::iterator iter2;
+
+	std::string ieeeAddrString = translate_nwk_dict[nwkAddr];
+	iter1 = translate_ieee_dict.find(ieeeAddrString);
+	if (iter1 != translate_ieee_dict.end())
+		translate_ieee_dict.erase(iter1);
+
+	iter2 = translate_nwk_dict.find(nwkAddr);
+	if (iter2 != translate_nwk_dict.end())
+		translate_nwk_dict.erase(iter2);
+}
+
+/**
+ * Public method ZbNetDb getFirstNode
+ * Returns the first Node object in the node dictionary.
+ * This method is used to visit the node dictionary.
+ *
+ * @param void Void.
+ * @return The first Node contained in the node dictionary.
+ */
+
+Node *ZbNetDb::getFirstNode() {
+	std::map<ushort, Node *>::iterator it;
+
+	it = node_dict.begin();
+	if (it == node_dict.end()) {
+		/// No entries found!
+		return NULL;
+	}
+	return it->second;
+}
+
+/**
+ * Public method ZbNetDb getNextNode
+ * Returns the Node object (in the node dictionary) subsequent to the one passed as parameter.
+ * This method is used to visit the node dictionary.
+ *
+ * @param currNode Pointer to the current Node.
+ * @return The pointer to the Node object next to current Node of interest.
+ */
+
+Node *ZbNetDb::getNextNode(Node *currNode) {
+	std::map<ushort, Node *>::iterator it;
+	ushort nwk_addr;
+
+	if (currNode == NULL)
+		return NULL; //Another option here it could be to return the first item...
+	nwk_addr = currNode->get_nwk_addr();
+	it = node_dict.find(nwk_addr);
+	if (it == node_dict.end()) {
+		// No entries found!
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+		printf("\nNo entries found!\n");
+#endif
+		return NULL;
+	}
+	++it;
+	if (it == node_dict.end()) {
+		// End of the node dictionary
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+		printf("\nEnd of the node dictionary\n");
+#endif
+		return NULL;
+	}
+	return it->second;
+}
+
+int ZbNetDb::getDBNodesSize() {
+	return node_dict.size();
+}
+
+/**
+ * Public method ZbNetDb removeNodeByNwkAddr
+ * It removes (from node dictionary) the Node object related to the specified ZigBee network address. Moreover, the node has to be removed from neighbor lists
+ *
+ * @param nwk_addr Network address of the node to be removed.
+ * @return 0 if the node has been correctly removed; if no entries in the node dictionary match the passed network address, -1 is returned.
+ */
+
+int ZbNetDb::removeNodeByNwkAddr(ushort nwk_addr) {
+	std::map<ushort, Node *>::iterator it;
+	Node * currentNode;
+
+	//Ignore the root local node
+	if (root != NULL && nwk_addr == root->nwk_addr) {
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+		printf("removeNodeByNwkAddr - Not possible to remove root address!\n");
+#endif
+		return -1;
+	}
+	// Remove all the entries where the node to remove could be present!
+	currentNode = getFirstNode();
+	while (currentNode != NULL) {
+		removeNeighbor(currentNode, findNodeByNwkAddr(nwk_addr));
+		currentNode = getNextNode(currentNode);
+	}
+	// Find the node
+	it = node_dict.find(nwk_addr);
+	if (it == node_dict.end()) {
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+		printf("removeNodeByNwkAddr -Node to delete not found!\n");
+#endif
+	} else {
+		currentNode = it->second;
+		// Remove (from node dictionary) the pointer to the Node object considered.
+		node_dict.erase(nwk_addr);
+		// Delete the Node object to be removed.
+		delete (currentNode);
+	}
+	return 0;
+}
+
+/**
+ * Public method ZbNetDb getNodesCount
+ * If node is NULL, this method returns the number of nodes in the dictionary.
+ *
+ * @param node Pointer to a Node object.
+ * @return The number of Nodes in the dictionary.
+ */
+
+int ZbNetDb::getNodesCount(const Node *node) const {
+	if (node != NULL) {
+		// Never used at the moment!
+		return -1;
+	} else {
+		return node_dict.size();
+	}
+}
+
+/**
+ * Public method ZbNetDb getNodeDict
+ * This method return the node dictionary map.
+ *
+ * @param void Void.
+ * @return Node dictionary map.
+ */
+
+std::map<ushort, Node *> ZbNetDb::getNodeDict() {
+
+	return (node_dict);
+}
+
+/**
+ * Public method ZbNetDb getNodeDict
+ * 
+ *
+ * @param nwk_addr New network address
+ * @param ieee_addr Related IEEE address
+ * @param capability Flags
+ * @return Old network address or null.
+ */
+
+Node * ZbNetDb::nodeAnnounce(ushort annced_nwk_addr, uchar *annced_ieee_addr,
+		uchar capability) {
+	struct timeval tv;
+
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+	printf("nodeAnnounce - device 0x%04x - %02X%02X%02X%02X%02X%02X%02X%02X\n",
+			annced_nwk_addr, annced_ieee_addr[0], annced_ieee_addr[1], annced_ieee_addr[2],
+			annced_ieee_addr[3], annced_ieee_addr[4], annced_ieee_addr[5], annced_ieee_addr[6], annced_ieee_addr[7]);
+#endif
+
+	//update translate dictionaries    
+	if (translateAddress(annced_ieee_addr) != 0xFFFF) {
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+		printf ("nodeAnnounce - entry found\n");
+#endif
+		//entry present
+		removeTranslationEntry(annced_ieee_addr);
+	}
+
+	addTranslationEntry(annced_nwk_addr, annced_ieee_addr);
+
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+	printf("addTranslationEntry - end\n");
+#endif
+
+	//update node dictionary
+	Node * node = this->findNodeByIEEEAddr(annced_ieee_addr); //search in node_dict
+	if (node == NULL) {
+		//node not present in node_dict
+		Node * died_node = this->findNodeByNwkAddr(annced_nwk_addr);
+		if (died_node != NULL) {
+			//if it's present a Node for annced_nwk_addr, then this means that
+			//the router have assigned a short address previously allocated to another node
+			//and needs to erase and delete
+			node_dict.erase(annced_nwk_addr);
+			delete (died_node);
+		}
+		//create new node and set ieee address
+		node = new Node(annced_nwk_addr);
+		node->set_ieee_addr(annced_ieee_addr);
+		((capability & 0x08) == 0x08) ? node->node_desc.receiveronwhenidle =
+												true :
+										node->node_desc.receiveronwhenidle =
+												false;
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+		printf("nodeAnnounce - capability %02x, receiveOnWhenIdleValue=0x%02x\n",capability,node->node_desc.receiveronwhenidle);
+#endif
+		//add to node_dict
+		node_dict[annced_nwk_addr] = node;
+	} else {
+		//found in node_dict
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+		printf("nodeAnnounce - Node present in node_dict\n");
+#endif     
+		//IEEE Address is fine, just update the ShortAddress (and its capability)
+		ushort old_nwk_addr = node->get_nwk_addr(); //get old network address
+		if (annced_nwk_addr != old_nwk_addr) {
+			//node present in node_dict & short address has changed
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+			printf("nodeAnnounce - Node's short address has changed");
+#endif
+			//set new network address on the same node
+			node->set_nwk_addr(annced_nwk_addr);
+			// Set the capability
+			((capability & 0x08) == 0x08) ? node->node_desc.receiveronwhenidle =
+													true :
+											node->node_desc.receiveronwhenidle =
+													false;
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+			printf("nodeAnnounce - capability received %02x, receiveOnWhenIdleValue=0x%02x\n",capability,node->node_desc.receiveronwhenidle);
+#endif
+			//erase old entry and add node to entry releted to new network address
+			node_dict.erase(old_nwk_addr);
+			//add to node_dict
+			node_dict[annced_nwk_addr] = node;
+		}
+	}
+	//update the timestamps!
+	gettimeofday(&tv, NULL);
+	node->setKANodeTimer(tv.tv_sec);
+	node->setForcePingTimer(0x00000000); //If the node has just been announced there is no reason to force a ping soon again!
+	return node;
+}
+
+void ZbNetDb::updateLQIDetails(Node * node, ZB_NEIGHBOR_TABLE_LIST * neighbors,
+		int neighborsCount) {
+	int i;
+
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+	printf("updateLQIDetails\n");
+#endif
+
+	if (node == NULL)
+		// Not possible
+		return;
+	for (i = 0; i < neighborsCount; i++) {
+		node->updateLQIInformation(neighbors[i].NetworkAddress,
+				neighbors[i].ExtendedAddress, neighbors[i].devTypeRxOnRelation,
+				neighbors[i].Depth, neighbors[i].LQI);
+	}
+	// This line has been removed and moved in CDiscoveryAgent (in the forcePingAlgorithm) - 28/08/12
+	//node->removeOldLQIInformation(neighbors, neighborsCount);
+}
+
+SimpleDescriptor* ZbNetDb::getFirstServicesSD() {
+	std::map<int, SimpleDescriptor *>::iterator it;
+
+	it = this->servicesSDTable.begin();
+	if (it == this->servicesSDTable.end()) {
+		/// No entries found!
+		return NULL;
+	}
+	return it->second;
+}
+
+SimpleDescriptor* ZbNetDb::getNextServicesSD(SimpleDescriptor *sd) {
+
+	std::map<int, SimpleDescriptor *>::iterator it;
+	int endpoint;
+
+	endpoint = sd->end_point;
+	it = this->servicesSDTable.find(endpoint);
+	if (it == this->servicesSDTable.end()) {
+		// No entries found!
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+		printf("\nNo entries found!\n");
+#endif
+		return NULL;
+	}
+	++it;
+	if (it == this->servicesSDTable.end()) {
+		// End of the node dictionary
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+		printf("\nEnd of the this->servicesSDTable\n");
+#endif
+		return NULL;
+	}
+	return it->second;
+
+}
+
+int ZbNetDb::setServicesSD(SimpleDescriptor *sd) {
+	if (sd != NULL) {
+		this->servicesSDTable[sd->end_point] = sd;
+		return 0;
+	} else {
+		printf("\nsetServicesSD -SimpleDescriptor sd == NULL\n");
+		return -1;
+	}
+}
+
+int ZbNetDb::removeServicesSD(SimpleDescriptor *sd) {
+	if (sd != NULL) {
+		std::map<int, SimpleDescriptor *>::iterator i;
+
+		i = this->servicesSDTable.find(sd->end_point);
+		if (i != servicesSDTable.end())
+			servicesSDTable.erase(i);
+
+		return 0;
+	} else {
+		printf("\nremoveServicesSD - SimpleDescriptor sd == NULL\n");
+		return -1;
+	}
+}
+
+int ZbNetDb::getStartModeSetting(void) {
+	return startupMode;
+}
+
+void ZbNetDb::setStartModeSetting(int value) {
+	startupMode = value;
+}
+
+StartupAttributeInfo* ZbNetDb::getStartupAttributeInfo(
+		int startupAttributeSetIndex) {
+	std::map<int, StartupAttributeInfo *>::iterator it;
+
+	it = startupAttributeSet.find(startupAttributeSetIndex);
+	if (it == startupAttributeSet.end()) {
+		// No entries found!
+		return NULL;
+	}
+	return it->second;
+}
+
+int ZbNetDb::setStartupAttributeInfo(int type, StartupAttributeInfo *sai) {
+	std::map<int, StartupAttributeInfo *>::iterator it;
+	StartupAttributeInfo *saiEntry;
+	bool isNewEntryRequired = false;
+
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+	printf("setStartAttributeInfo - check whether an entry already exists for startAttributeSetIndex =%d",startupAttributeSetIndex);
+#endif
+
+	it = this->startupAttributeSet.find(sai->startupAttributeSetIndex);
+	if (it == startupAttributeSet.end()) {
+		// No entries found -> create a new StartupAttributeInfo
+		isNewEntryRequired = true;
+		saiEntry = new StartupAttributeInfo();
+
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+		printf("setStartAttributeInfo - no entries found for startAttributeSetIndex = %d -> create a new one",startupAttributeSetIndex);
+#endif
+	} else {
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+		printf("setStartAttributeInfo - an entry already exists for startAttributeSetIndex =%d -> overwrite it",startupAttributeSetIndex);
+#endif
+		saiEntry = it->second;
+	}
+
+	this->setCurrentStartupAttributeSetIndex(sai->startupAttributeSetIndex);
+
+	// DeviceType setting
+	if (sai->isDeviceTypeDefined) {
+		if (sai->deviceType == 0) {
+			// Use current Device Type configuration or the default one
+			if (isNewEntryRequired) {
+				saiEntry->deviceType = startupAttributeSet[0]->deviceType;
+			}
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+			zb_print("setStartAttributeInfo - Device Type stored = %d\n",saiEntry->deviceType);
+#endif
+		} else {
+			// Set Device Type value
+			saiEntry->deviceType = sai->deviceType;
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+			zb_print("setStartAttributeInfo - Device Type = %d\n",saiEntry->deviceType);
+#endif
+		}
+	} else {
+		// Use default Device Type configuration
+		saiEntry->deviceType = startupAttributeSet[0]->deviceType;
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+		zb_print("setStartAttributeInfo - default Device Type = %d\n",saiEntry->deviceType);
+#endif
+	}
+
+	// StartupControl setting
+	if (sai->isStartupControlDefined) {
+		saiEntry->StartupControl = sai->StartupControl;
+	} else {
+		// Use default StartupControl configuration
+		saiEntry->StartupControl = startupAttributeSet[0]->StartupControl;
+	}
+
+	if (type == 0) {
+		// Default configuration is being loaded
+
+		// Channel Mask
+		saiEntry->channelMask = sai->channelMask;
+		// PAN Id
+		saiEntry->PANId = sai->PANId;
+		// ExtendedPANId
+		memcpy(saiEntry->extendedPANId, sai->extendedPANId, 8);
+		// _securityLevel
+		saiEntry->_securityLevel = sai->_securityLevel;
+		// NetworkKey
+		memcpy(saiEntry->networkKey, sai->networkKey, 16);
+		// preconfiguredLinkKey
+		memcpy(saiEntry->preconfiguredLinkKey, sai->preconfiguredLinkKey, 16);
+		//saiEntry->_isTCKeyTableDefined = sai->_isTCKeyTableDefined;
+
+	} else {
+		// A configuration different from the default one is being considered.
+		// However, the following parameters cannot be set through the REST interface.
+		// As a consequence, the values are taken from the default configuration.
+		// Channel Mask
+		saiEntry->channelMask = startupAttributeSet[0]->channelMask;
+		// PAN Id
+		saiEntry->PANId = startupAttributeSet[0]->PANId;
+		// ExtendedPANId
+		uchar extendedPANId_tmp[8];
+		memcpy(extendedPANId_tmp, startupAttributeSet[0]->extendedPANId, 8);
+		memcpy(saiEntry->extendedPANId, extendedPANId_tmp, 8);
+		// _securityLevel
+		saiEntry->_securityLevel = startupAttributeSet[0]->_securityLevel;
+		// NetworkKey
+		uchar networkKey_tmp[16];
+		memcpy(networkKey_tmp, startupAttributeSet[0]->networkKey, 16);
+		memcpy(saiEntry->networkKey, networkKey_tmp, 16);
+		// preconfiguredLinkKey
+		uchar preconfiguredLinkKey_tmp[16];
+		memcpy(preconfiguredLinkKey_tmp,
+				startupAttributeSet[0]->preconfiguredLinkKey, 16);
+		memcpy(saiEntry->preconfiguredLinkKey, preconfiguredLinkKey_tmp, 16);
+	}
+
+	startupAttributeSet[sai->startupAttributeSetIndex] = saiEntry;
+
+	return 0;
+}
+
+void ZbNetDb::removeAllStartupAttributeInfo() {
+	int size, i;
+	//std::map <int, StartupAttributeInfo *>::iterator it;
+
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+	printf("removeAllStartupAttributeInfo\n");
+#endif
+
+	size = startupAttributeSet.size();
+	//printf("Removing startupAttributeSet, size %d, index %d\n",size,getCurrentStartupAttributeSetIndex());
+	for (i = 0; i < size; i++) {
+		delete (startupAttributeSet[i]);
+		//printf("Removing index %d\n",i);
+	}
+	this->startupAttributeSet.clear();
+}
+
+int ZbNetDb::getCurrentStartupAttributeSetIndex() {
+	return currentstartAttributeSetIndex;
+}
+
+int ZbNetDb::setCurrentStartupAttributeSetIndex(int value) {
+	currentstartAttributeSetIndex = value;
+	return 0;
+}
+
+int ZbNetDb::setTCKeyTableEntry(tcKeyTableEntry *entry) {
+	std::map<int, tcKeyTableEntry *>::iterator it;
+	tcKeyTableEntry * keytableEntry;
+
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+	printf("setTCKeyTableEntry - check whether an entry already exists for keyTableEntryIndex =%d", entry->keyTableEntryIndex);
+#endif
+
+	it = this->TCKeyTable.find(entry->keyTableEntryIndex);
+	if (it == TCKeyTable.end()) {
+		// No entries found -> create a new keytableEntry
+		keytableEntry = new tcKeyTableEntry();
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+		printf("setTCKeyTableEntry - no entries found for keyTableEntryIndex = %d -> create a new one", entry->keyTableEntryIndex);
+#endif
+	} else {
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+		printf("setTCKeyTableEntry - an entry already exists for keyTableEntryIndex =%d -> update it", entry->keyTableEntryIndex);
+#endif
+		keytableEntry = it->second;
+	}
+	keytableEntry->keyTableEntryIndex = entry->keyTableEntryIndex;
+	// IEEE address
+	memcpy(keytableEntry->ieeeAddress, entry->ieeeAddress, 8);
+	// preconfiguredLinkKey
+	memcpy(keytableEntry->preconfiguredLinkKey, entry->preconfiguredLinkKey,
+			16);
+	TCKeyTable[keytableEntry->keyTableEntryIndex] = keytableEntry;
+	return 0;
+}
+
+void ZbNetDb::removeAllTCKeyTableEntry() {
+	int size, i;
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+	printf("removeAllTCKeyTableEntry\n");
+#endif
+	size = TCKeyTable.size();
+	for (i = 0; i < size; i++)
+		TCKeyTable.erase(i);
+	this->TCKeyTable.clear();
+}
+
+tcKeyTableEntry* ZbNetDb::getTCKeyTableEntry(int tcKeyTableEntryIndex) {
+	std::map<int, tcKeyTableEntry *>::iterator it;
+
+	it = TCKeyTable.find(tcKeyTableEntryIndex);
+	if (it == TCKeyTable.end()) {
+		// No entries found!
+		return NULL;
+	}
+	return it->second;
+}
+
+int ZbNetDb::setTCKeyTableSize(int size) {
+	this->TCKeyTableSize = size;
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+	printf("setTCKeyTableSize - table size = %d", this->TCKeyTableSize);
+#endif
+	return 0;
+}
+
+int ZbNetDb::getTCKeyTableSize() {
+#ifdef DEBUG_ACTIVE_ZBNET_DB
+	printf("getTCKeyTableSize - table size = %d", this->TCKeyTableSize);
+#endif
+	return this->TCKeyTableSize;
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ZbNetDb.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ZbNetDb.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/ZbNetDb.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,379 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#pragma once
+
+#ifndef _ZB_NET_DB_
+#define _ZB_NET_DB_
+
+#if 0
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#endif
+#include <list>
+#include <map>
+#include <string>
+#include <string.h>
+
+#include "zigbee.h"
+
+enum enum_logicaltype {
+	COORDINATOR, ROUTER, ENDDEVICE, UNKNOWN_LOGICALTYPE
+};
+enum enum_frequencyband {
+	UNKNOWN_VALUE = 0, F868_868D6 = 1, F902_928 = 4, F2400_2483D5 = 8
+};
+enum enum_currentpowermode {
+	SYNCHRONIZED_WITH_RECEIVERONWHENIDLE = 0,
+	PERIODICALLYON = 1,
+	WHENSTIMULATED = 2,
+	UNKNOWN_POWERMODE = 10
+};
+enum enum_powersource {
+	MAINPOWER, RECHARGEABLE, DISPOSABLE
+};
+enum enum_currentpowersourcelevel {
+	CRITICAL = 0, P33 = 4, P66 = 8, P100 = 12, UNKNOWN_PSLEVEL = 20
+};
+
+struct NodeDescriptor {
+	enum_logicaltype logicaltype;
+	uchar APSflags; //3 bit (NOT SUPPORTED)
+	enum_frequencyband frequencyband;
+
+	uchar mac_cap; // MAC capability	
+
+	//start of sub-field of MAC capabilty flags field
+	bool alternatePANcoordinator; //true if this node is capable of becoming a PAN coordinator, false otherwise
+	bool devicetype; //true if FFD, false if RFD
+	bool powersource; //true if main power, false otherwise
+	bool receiveronwhenidle; //true if the device does not disable its receiver on idle period, false otherwise
+	bool securytycapability; //true if the device is capable of sending and receiving frames secured, false otherwise
+	//end of sub-field of MAC capabilty flags field
+	ushort manufacturecode; //16 bits
+	uchar maximumbuffersize; //8 bits
+	ushort maximumtransfersize; //16 bits (NOT SUPPORTED)
+	ushort server_mask;
+	bool filled;
+};
+
+struct PowerDescriptor {
+	enum_currentpowermode currentpowermode;
+	bool avaiablepowersource[3]; //use enum_powersource for indexing
+	bool currentpowersource[3]; //use enum_powersource for indexing
+	enum_currentpowersourcelevel currentpowersourcelevel;
+	bool filled;
+};
+
+struct SimpleDescriptor {
+	int end_point;
+	int profile_id;
+	int device_id;
+	int device_ver;
+
+	bool complex_desc_available;
+	bool user_desc_available;
+
+	std::list<int> input_cluster;
+	std::list<int> output_cluster;
+};
+
+enum enum_LevelSpecification {
+	MACLevel, NWKLevel, APSLevel, INTRPLevel
+};
+struct LevelSpecification {
+	std::string level;
+};
+
+struct AddressSpecification {
+	bool isDefined;
+	bool isNWKSourceAddressDefined;
+	ushort NWKSourceAddress;
+	bool isAPSSourceEndpointDefined;
+	int APSSourceEndpoint;
+	bool isAPSDestinationEndpointDefined;
+	int APSDestinationEndpoint;
+};
+
+struct MessageSpecification {
+	bool isDefined;
+
+	bool isAPSClusterIdentifierDefined;
+	std::string APSClusterIdentifier;
+
+	bool isAPSClusterGroupDefined;
+	std::string APSClusterGroup;
+};
+
+struct Filter {
+	bool isDefined;
+	LevelSpecification levelSpec;
+	AddressSpecification addressSpec;
+	MessageSpecification messageSpec;
+};
+
+enum enum_DecodeLevel {
+	DecodeMAC, DecodeNWK, DecodeInterPAN, DecodeAPS, DecodeZCL, DecodeZDP
+};
+struct DecodeSpecification {
+	bool decodeLevel[6];
+};
+
+struct Action {
+	bool isDefined;
+	DecodeSpecification decodeSpecification;
+	std::string forwardingSpecification;
+};
+
+struct Callback {
+	int internalId; //Used for Callback Management within the ZigBee Gateway
+	Filter filter;
+	std::string buffer;
+	Action action;
+};
+
+struct StartupAttributeInfo {
+	int startupAttributeSetIndex;
+
+	int deviceType;
+	bool isDeviceTypeDefined;
+
+	int protocolVersion;
+	ushort stackProfile;
+
+	unsigned long channelMask;
+	bool isChannelMaskDefined;
+
+	uchar extendedPANId[8];
+	ushort PANId;
+	ushort ShortAddress;
+	ushort TrustCenterAddress;
+	uchar *TrustCenterMasterKey;
+	uchar networkKey[16];
+	bool UseInsecureJoin;
+	uchar preconfiguredLinkKey[16];
+	int NetworkKeySeqNum;
+	int NetworkKeyType;
+	ushort NetworkManagerAddress;
+
+	ushort StartupControl;
+	bool isStartupControlDefined;
+
+	int ScanAttempts;
+	unsigned TimeBetweenScans;
+	unsigned RejoinInterval;
+	unsigned MaxRejoinInterval;
+	unsigned IndirectPollRate;
+	unsigned ParentRetryThreshold;
+	bool ConcentratorFlag;
+	int ConcentratorRadius;
+	unsigned ConcentratorDiscoveryTime;
+
+	int _securityLevel;
+};
+
+struct tcKeyTableEntry {
+	int keyTableEntryIndex;
+	uchar ieeeAddress[8];
+	uchar preconfiguredLinkKey[16];
+};
+
+struct LQIInformationEntry {
+	ushort shortAddress;
+	uchar ieeeAddress[8];
+	uchar devTypeRxOnRelation;
+	uchar depth;
+	uchar lqi;
+};
+
+#define maxLQIInformationTableSize 15
+
+enum enum_ZigBeeNetworkStatus {
+	HOLDING = 0x00,
+	INITIALIZING = 0x01,
+	DISCOVERING = 0x02,
+	JOINING = 0x03,
+	REJOINING = 0x04,
+	FORMING = 0x05,
+	AUTHENTICATING = 0x06,
+	FORMED = 0x07,
+	JOINED = 0x08,
+	ORPHANED = 0x09,
+	UNAUTHENTICATED = 0x0a
+};
+
+/**
+ * Implements the Database storing retrieved information
+ */
+
+class ZbNetDb;
+
+class Node {
+	friend class ZbNetDb;
+
+public:
+	NodeDescriptor node_desc;
+	PowerDescriptor power_desc;
+	int currentLQIInformationTableSize;
+
+	Node(ushort nwk_addr);
+	~Node();
+
+	void set_ieee_addr(uchar *ieee_addr);
+	void set_nwk_addr(ushort nwk_addr);
+	uchar *get_ieee_addr(void);
+	ushort get_nwk_addr(void);
+
+	LQIInformationEntry * getLQIInformationTable(int * size);
+	void updateLQIInformation(ushort shortAddr, uchar * ieeeAddress,
+			uchar devTypeRxOnRelation, uchar depth, uchar lqi);
+	void removeOldLQIInformation(ZB_NEIGHBOR_TABLE_LIST * neighbors,
+			int neighborsCount);
+
+	void dump(void);
+
+	std::list<int> getEndPointList();
+	SimpleDescriptor* getSimpleDescr(int endpoint);
+
+	void setIsActive(bool b);
+	bool getIsActive(void);
+	void setKANodeTimer(long timeout);
+	long getKANodeTimer(void);
+	void setnumOfPingsDone(int value);
+	int getnumOfPingsDone(void);
+	void setForcePingTimer(long timeout);
+	long getForcePingTimer(void);
+
+private:
+	uchar ieee_addr[8];
+	ushort nwk_addr;
+
+	std::list<Node *> neighbor;
+
+	std::list<int> endpoints;
+	std::map<int, SimpleDescriptor *> simpleDesc;
+
+	bool isActive; // Indicates whether the node is dead or not
+	long nodeTimer; // Contains a time since the last time a node received a message
+	int numOfPingsDone; // Reports how many times the node has been polled!
+	long forcePingTimer; // A timer need to counter when it is time to force a ping!
+
+	// LQIInformationTable
+	LQIInformationEntry LQIInformationTable[maxLQIInformationTableSize];
+};
+
+class ZbNetDb {
+
+private:
+	bool locked;
+
+	// Three possible scenario to startup the network (see config.ini)
+	int startupMode;
+
+	std::map<ushort, Node *> node_dict;
+
+	std::map<std::string, ushort> translate_ieee_dict;
+	std::map<ushort, std::string> translate_nwk_dict;
+
+	// StartupAttributeSet
+	std::map<int, StartupAttributeInfo *> startupAttributeSet;
+	int currentstartAttributeSetIndex;
+
+	// TrustCenter Key Table
+	std::map<int, tcKeyTableEntry *> TCKeyTable;
+	int TCKeyTableSize;
+
+	// Table containing the Simple Descriptors defining the services allocated
+	// in the local node (i.e. the ZigBee Gateway Device)
+	std::map<int, SimpleDescriptor *> servicesSDTable;
+
+public:
+	///	Root Node
+	Node *root;
+
+	///	Constructor
+	ZbNetDb();
+	~ZbNetDb();
+
+	int lockDb(void);
+	int unlockDb(void);
+
+	int clearAll(void);
+	int clearAllButRoot();
+	int setRoot(Node *node);
+
+	int addEndPoint(Node *node, int epNumber);
+	int clearEndPointList(Node *node);
+	std::list<int> getEndPointList(Node *node);
+
+	int addSimpleDescr(Node *node, SimpleDescriptor *sd);
+	int clearSimpleDescrList(Node *node);
+	int clearSimpleDescr(Node *node, int endpoint);
+	SimpleDescriptor* getSimpleDescr(Node *node, int endpoint);
+
+	int createDefaultSimpleDescr(int endPoint, SimpleDescriptor * sd);
+
+	int addNeighbor(Node *node, Node *child);
+	int removeNeighbor(Node *node, Node *neighbor);
+	int getNodesCount(const Node *node = NULL) const;
+
+	Node *findNodeByNwkAddr(ushort nwk_addr);
+	Node *findNodeByIEEEAddr(uchar *ieee_addr);
+	int removeNodeByNwkAddr(ushort nwk_addr);
+	uchar * translateAddress(ushort nwkAddr);
+	ushort translateAddress(uchar * ieeeAddr);
+	void addTranslationEntry(ushort nwkAddr, uchar * ieeeAddr);
+	void removeTranslationEntry(ushort nwkAddr);
+	void removeTranslationEntry(uchar * ieeeAddr);
+
+	Node *getFirstNode();
+	Node *getNextNode(Node *currNode);
+	int getDBNodesSize();
+	std::map<ushort, Node *> getNodeDict();
+
+	Node * nodeAnnounce(ushort nwk_addr, uchar *ieee_addr, uchar capability);
+
+	void updateLQIDetails(Node * node, ZB_NEIGHBOR_TABLE_LIST * neighbors,
+			int neighborsCount);
+
+	SimpleDescriptor *getFirstServicesSD();
+	SimpleDescriptor *getNextServicesSD(SimpleDescriptor *sd);
+	int setServicesSD(SimpleDescriptor *sd);
+
+	int removeServicesSD(SimpleDescriptor *sd);
+
+	int getStartModeSetting(void);
+	void setStartModeSetting(int value);
+
+	StartupAttributeInfo* getStartupAttributeInfo(int startupAttributeSetIndex);
+
+	// Public methods used to get and set the StartupAttributeSet
+	int setStartupAttributeInfo(int type, StartupAttributeInfo *sai);
+
+	void removeAllStartupAttributeInfo(void);
+
+	int getCurrentStartupAttributeSetIndex();
+
+	int setTCKeyTableEntry(tcKeyTableEntry *entry);
+
+	void removeAllTCKeyTableEntry();
+
+	tcKeyTableEntry* getTCKeyTableEntry(int tcKeyTableEntryIndex);
+
+	int setTCKeyTableSize(int size);
+	int getTCKeyTableSize();
+
+protected:
+
+	int setCurrentStartupAttributeSetIndex(int value);
+
+};
+
+#endif 

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/acl.txt
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/acl.txt (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/acl.txt Fri Oct 19 18:37:43 2012
@@ -1,0 +1,23 @@
+#Sample acl file for automatic test
+
+# comment
+1212121212121212
+1313131313131313
+1414141414141414
+1515151515151515
+# comment
+1616161616161616
+1717171717171717
+1818181818181818
+# comment
+1919191919191919
+ab13451263782796
+# 67080100004b1200
+
+
+
+#le linee vuote sono valide ..
+
+1a1a1a1a1a1a1a1a
+# comment
+# comment

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/config-trial.ini
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/config-trial.ini (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/config-trial.ini Fri Oct 19 18:37:43 2012
@@ -1,0 +1,148 @@
+[main]
+# Hardware platform desired: integration (0), zsdio/EZSP/freescale/MicroSD (1)
+Platform = 1
+
+# Autostart the ZigBee network: 0 to disable (it will wait for a StartGatewayDevice command), 1 to enabled
+autostart = 0
+
+# [Freescale only] Three possible scenario to startup the network:
+#0 - StartupSetMode=0x18 (CommissioningMode) AND StartupControlMode=0x00 (Association) --> To be used the first time, when the network is created
+#1 - StartupSetMode=0x00 (use NVM) AND StartupControlMode=0x04 (SilentStart) --> To be used at running time
+#2 - StartupSetMode=0x18 (CommissioningMode) AND StartupControlMode=0x04 (SilentStart) --> To be used for TC Replacement
+startupMode = 0
+
+# Enable a local registration to device announcement events (1 to enable, 0 to disable)
+localRegToDAnnce = 1
+
+# Specify how long to wait (in seconds) before to start polling each node to verify if they're still alive ('0' to disable)
+keepAliveThreshold = 90
+
+# Once keepAliveThreshold is reached, GAL tries to ping the node for 'keepAliveNumberOfAttempt' before considering it dead
+keepAliveNumberOfAttempt = 3
+
+# Specify in seconds a timeout before to force the gateway to send a ping (MGMT_LQI_Req) to the nodes (0 to disable)
+forcePingTimeout = 200
+
+# Automatic discovery unknown nodes before sending or after receiving a message (1 to enable, 0 to disable)
+autoDiscoveryUnknownNodes = 1
+
+# [Optional] "Callback URI listener" address. It represent the "GW Status Changed event" default URI Listener
+#gwStatusChanged_DefaultURIListener = http://10.192.33.20.:8080/gal/startup
+
+# APS level parameters (required for fragmentation services)
+apscMaxWindowSize = 1
+apsInterframeDelay = 100
+
+# To enable debug messages select "1"  (0 to disable)
+debugEnabled = 0
+
+
+[Debug]
+# Printing levels for class debugging - 0 (DEBUGGING), 1 (TEST), 3 (PRODUCTION)
+# HTTPServer class
+HTTPServerDL = 0 
+# HTTPSessionContext class
+HTTPSessionContextDL = 3
+# RESTClient class
+RESTClientDL = 0 
+# RESTBroker class
+RESTBrokerDL = 0
+# DiscoveryAgent class
+DiscoveryAgentDL = 0
+# ManagementAgent class
+ManagementAgentDL = 0
+# LocalNode class
+LocalNodeDL = 0
+
+
+[DefaultStartupAttributeSet]
+# Device Type (0 =Current device type; 1=Coordinator; 2=Router; 3=End Device)
+DeviceType = 1
+
+# Default Channel Mask [valid range: 11 - 26, or '0' for all channels]
+ChannelMask = 0
+
+# ZigBee Network PANId ('0xFFFF' = generate random value)
+PANId = 0xFFFF
+
+# Extended PAN Id (big-endian order) - Note: Set all zeros for Freescale dongle
+ExtendedPANId = 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+
+# StartupControl (0=Association; 1=Orphan Rejoin; 2=Network Rejoin; 3=Find and Rejoin; 4=Silent Start)
+StartUpControl = 0
+
+# SecurityLevel (0=Disabled, 5=Enabled)
+SecurityLevel = 5
+
+# [Freescale only] MAC Address mode: 0=use manufacture address (stored within the dongle), 1= generate random address
+freescaleMACAddressValue = 0
+
+# Default Network Key - Note: Set all zeros for Freescale dongle
+networkKey = 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+
+# Default Trust Center Link Key - 'ZigBeeAlliance09'
+preconfiguredLinkKey = 0x5a 0x69 0x67 0x42 0x65 0x65 0x41 0x6c 0x6c 0x69 0x61 0x6e 0x63 0x65 0x30 0x39
+
+# Default End Point
+DefaultEndPoint = 0x01
+
+[TCKeyTable]
+#TCKeyTableSize - Zero to disable the TrustCenterLinkKeytable - Note: maximum number of entries is 12 for Ember, 9 for Freescale
+TCKeyTableSize = 0
+
+#Entry n. 00
+IEEEAddress00 = 0x00 0x0d 0x6f 0x00 0x00 0x09 0x99 0x1f
+#TCLinkKey00 = 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07
+TCLinkKey00 = 0x5a 0x69 0x67 0x42 0x65 0x65 0x41 0x6c 0x6c 0x69 0x61 0x6e 0x63 0x65 0x30 0x39
+
+#Entry n. 01
+IEEEAddress01 = 0x00 0x0d 0x6f 0x00 0x00 0x09 0x93 0xa1
+TCLinkKey01 = 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x08
+
+#Entry n. 02
+IEEEAddress02 = 0x00 0x0d 0x6f 0x00 0x00 0x18 0x57 0x46
+TCLinkKey02 = 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x09
+
+
+[TC]
+# Insert the Trust Center IEEE Address
+IEEE_ADDRESS = "17161514131201ff"
+# Decide if the local ACL Conf shall be used (INSERT true) or if the WSN-C access is required (INSERT false)
+JOINREQUESTPROCESSING = false
+# Decide if process locally the leave notifications without warning the WSN-C (SELECT true). Otherwise insert false.
+LEAVENOTIFICATIONPROCESSING = true
+# File name containing the Access Control List
+ACLFILENAME = acl.txt
+# The network master key, 16-bytes long
+NETWORKKEY = "11000000000000000000000000000011"
+# The Security Timeout period (expressed in milliseconds)
+APPSECURITYTIMEOUTPERIOD = 9999
+
+
+[RESTBroker]
+# Decide if the Network Root URI can be obtained by appending the net/default' suffix (SELECT 1), or by appending the net/<ExtendedPANId>' suffix (SELECT 0)
+UseDefaultNWKRootURI = 1
+
+# Gateway Descriptor Asynchonous notification period (expressed in seconds), respectively before and after a WSN-C is attached. Note: This is like an "Hello" message to the WSN-C platform address
+HelloMsgNotifyPeriod = 10 
+HelloMsg_WSNCAttached_NotifyPeriod = 1800
+
+[RESTServer]
+# Port server where to receive REST commands
+serverPorts = "9000"
+
+# RESTServer parameters
+ssl = 0
+sslCertFile = "shttpd.pem"
+httpDigestAuth = 0
+httpDigestAuthPwdFile = "pwdfile"
+
+
+[RESTClient]
+# libcurl HTTP option application timeout (in seconds) - Note: for remote connection between GW and IPHA insert a value higher than 1
+httpOptTimeout = 3
+
+
+[PerfomanceTest]
+# Select the txPeriod used during the Performance tests
+txPeriod = 100000

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/config.ini
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/config.ini (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/config.ini Fri Oct 19 18:37:43 2012
@@ -1,0 +1,160 @@
+[main]
+# Hardware platform desired: integration (0), zsdio/EZSP/freescale/MicroSD (1)
+Platform = 1
+
+# Autostart the ZigBee network: 0 to disable (it will wait for a StartGatewayDevice command), 1 to enabled
+autostart = 1
+
+# [Freescale only] Three possible scenario to startup the network:
+#0 - StartupSetMode=0x18 (CommissioningMode) AND StartupControlMode=0x00 (Association) --> To be used the first time, when the network is created
+#1 - StartupSetMode=0x00 (use NVM) AND StartupControlMode=0x04 (SilentStart) --> To be used at running time
+#2 - StartupSetMode=0x18 (CommissioningMode) AND StartupControlMode=0x04 (SilentStart) --> To be used for TC Replacement
+startupMode = 1
+
+# Enable a local registration to device announcement events (1 to enable, 0 to disable)
+localRegToDAnnce = 1
+
+# Specify how long to wait (in seconds) before to start polling each node to verify if they're still alive ('0' to disable)
+keepAliveThreshold = 80
+
+# Once keepAliveThreshold is reached, GAL tries to ping the node for 'keepAliveNumberOfAttempt' before considering it dead
+keepAliveNumberOfAttempt = 3
+
+# Specify in seconds a timeout before to force the gateway to send a ping (MGMT_LQI_Req) to the nodes (0 to disable)
+forcePingTimeout = 200
+
+# Automatic discovery unknown nodes before sending or after receiving a message (1 to enable, 0 to disable)
+autoDiscoveryUnknownNodes = 1
+
+# [Optional] "Callback URI listener" address. It represent the "GW Status Changed event" default URI Listener
+#gwStatusChanged_DefaultURIListener = http://10.192.33.20.:8080/gal/startup
+
+# APS level parameters (required for fragmentation services)
+apscMaxWindowSize = 1
+apsInterframeDelay = 100
+
+# To enable debug messages select "1"  (0 to disable)
+debugEnabled = 1
+
+
+[Debug]
+# Printing levels for class debugging - 0 (DEBUGGING), 1 (TEST), 3 (PRODUCTION)
+# HTTPServer class
+HTTPServerDL = 0
+# HTTPSessionContext class
+HTTPSessionContextDL = 0
+# RESTClient class
+RESTClientDL = 0
+# RESTBroker class
+RESTBrokerDL = 0
+# DiscoveryAgent class
+DiscoveryAgentDL = 0
+# ManagementAgent class
+ManagementAgentDL = 0
+# LocalNode class
+LocalNodeDL = 0
+
+
+[DefaultStartupAttributeSet]
+# Device Type (0 =Current device type; 1=Coordinator; 2=Router; 3=End Device)
+DeviceType = 1
+
+# Default Channel Mask [valid range: 11 - 26, OR '0' for all channels]
+ChannelMask = 22
+
+# ZigBee Network PANId ('0xFFFF' = generate random value)
+PANId = 0xFFFF
+
+# Extended PAN Id (big-endian order) - Note: Set all zeros for Freescale dongle
+ExtendedPANId = 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+#ExtendedPANId = 0x00 0x01 0x02 0x03 0x04 0x05 0x04 0x03			//ExtendedPanId used for Energy at Home trial
+#ExtendedPANId = 0x00 0x00 0x00 0x10 0x77 0xC2 0x50 0x00		//ExtendedPanId used for commissioning mode
+#ExtendedPANId = 0x00 0x00 0x72 0x6F 0x73 0x6E 0x65 0x73		//ExtendedPanId used for some ZigBee Telecom Services tests
+
+# StartupControl (0=Association; 1=Orphan Rejoin; 2=Network Rejoin; 3=Find and Rejoin; 4=Silent Start)
+StartUpControl = 0 
+
+# SecurityLevel (0=Disabled, 5=Enabled)
+SecurityLevel = 5
+
+# [Freescale only] MAC Address mode: 0=use manufacture address (stored within the dongle), 1= generate random address
+freescaleMACAddressValue = 0
+
+# Default Network Key - Note: Set all zeros for Freescale dongle
+networkKey = 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+#networkKey = 0x01 0x02 0x03 0x42 0x65 0x65 0x41 0x6c 0x6c 0x69 0x61 0x6e 0x63 0x03 0x02 0x01
+
+# Default Trust Center Link Key - 'ZigBeeAlliance09'
+preconfiguredLinkKey = 0x5a 0x69 0x67 0x42 0x65 0x65 0x41 0x6c 0x6c 0x69 0x61 0x6e 0x63 0x65 0x30 0x39
+
+# Default End Point
+DefaultEndPoint = 0x01
+
+
+[TCKeyTable]
+#TCKeyTableSize - Zero to disable the TrustCenterLinkKeytable - Note: maximum number of entries is 12 for Ember, 9 for Freescale
+TCKeyTableSize = 0
+
+#Entry n. 00
+IEEEAddress00 = 0x00 0x0d 0x6f 0x00 0x00 0x09 0x99 0x1f
+#TCLinkKey00 = 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07
+TCLinkKey00 = 0x5a 0x69 0x67 0x42 0x65 0x65 0x41 0x6c 0x6c 0x69 0x61 0x6e 0x63 0x65 0x30 0x39
+
+#Entry n. 01
+IEEEAddress01 = 0x00 0x0d 0x6f 0x00 0x00 0x09 0x93 0xa1
+TCLinkKey01 = 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x08
+
+#Entry n. 02
+IEEEAddress02 = 0x00 0x0d 0x6f 0x00 0x00 0x18 0x57 0x46
+TCLinkKey02 = 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x09
+
+#Entry n. 03
+#Entry n. 04
+#Entry n. 05
+#Entry n. 06
+#Entry n. 07
+#Entry n. 08
+
+
+[TC]
+# Insert the Trust Center IEEE Address
+IEEE_ADDRESS = "17161514131201ff"
+# Decide if the local ACL Conf shall be used (INSERT true) or if the WSN-C access is required (INSERT false)
+JOINREQUESTPROCESSING = false
+# Decide if process locally the leave notifications without warning the WSN-C (SELECT true). Otherwise insert false.
+LEAVENOTIFICATIONPROCESSING = true
+# File name containing the Access Control List
+ACLFILENAME = acl.txt
+# The network master key, 16-bytes long
+NETWORKKEY = "11000000000000000000000000000011"
+# The Security Timeout period (expressed in milliseconds)
+APPSECURITYTIMEOUTPERIOD = 9999
+
+
+[RESTBroker]
+# Decide if the Network Root URI can be obtained by appending the net/default' suffix (SELECT 1), or by appending the net/<ExtendedPANId>' suffix (SELECT 0)
+UseDefaultNWKRootURI = 1
+
+# Gateway Descriptor Asynchonous notification period (expressed in seconds), respectively before and after a WSN-C is attached. Note: This is like an "Hello" message to the WSN-C platform address
+HelloMsgNotifyPeriod = 10 
+HelloMsg_WSNCAttached_NotifyPeriod = 1800
+
+[RESTServer]
+# Port server where to receive REST commands
+serverPorts = "9000"
+
+# RESTServer parameters
+ssl = 0
+sslCertFile = "shttpd.pem"
+httpDigestAuth = 0
+httpDigestAuthPwdFile = "pwdfile"
+
+
+[RESTClient]
+# libcurl HTTP option application timeout (in seconds) - Note: for remote connection between GW and IPHA insert a value higher than 1. Set to zero to completely disable caching
+httpOptTimeout = 10
+
+
+[PerfomanceTest]
+# Select the txPeriod used during the Performance tests
+txPeriod = 100000

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/configure.ac
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/configure.ac (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/configure.ac Fri Oct 19 18:37:43 2012
@@ -1,0 +1,153 @@
+dnl Process with autoconf to obtain a configuration script
+
+m4_define(linuxgal_version, 5.3.11)
+
+AC_INIT([Linux GAL], linuxgal_version)
+AM_INIT_AUTOMAKE(linuxgal, linuxgal_version)
+
+AC_PROG_CXX
+AC_PROG_INSTALL
+
+# Start with a known set of compiler optimizations
+CXXFLAGS="-Wall"
+
+AC_ARG_ENABLE(debug,
+	    [  --enable-debug		enable debugging],
+	    DEBUG="${enableval}", DEBUG="no")
+
+if test "x$DEBUG" = "xyes"
+then
+	    CXXFLAGS="-g -O0 ${CXXFLAGS}"
+else
+	    CXXFLAGS="-Os ${CXXFLAGS}"
+fi
+
+
+AC_ARG_WITH(debug-flags, 
+	    [  --with-debug-flags=f1:f2..  debug features to enable],
+	    DEBUG_FEATURES="${withval}",
+	    DEBUG_FEATURES="")
+
+AC_ARG_ENABLE(2006,
+	    [  --enable-2006		enable zigbee 2006],
+	    ZB_2006="${withval}",
+	    ZB_2006="yes")
+
+# Select ZigBee vs. ZigBee PRO
+AC_ARG_ENABLE(zigbee-pro,
+	    [  --enable-zigbee-pro	choose zigbee pro],
+	    ZB_STACK="zigbee", ZB_STACK="zigbee")
+
+# Now we have to look around for all the headers and libs
+AC_ARG_WITH(local-libs, 
+	    [  --with-local-libs=dir    default 3rd party lib (def: ..)],
+	    LOCAL_LIBS="${withval}", LOCAL_LIBS="${prefix}")
+
+AC_ARG_WITH(zblib-cflags, 
+	    [  --with-zblib-cflags=dir   ZigBee interface cflags],
+	    ZBLIB_CFLAGS="${withval}", 
+	    ZBLIB_CFLAGS="-I${LOCAL_LIBS}/include")
+
+AC_ARG_WITH(zblib-libs, 
+	    [  --with-zblib-libs=dir     ZigBee library file directory],
+	    ZBLIB_LIB="${withval}", 
+	    ZBLIB_LIB="${LOCAL_LIBS}/lib")
+
+AC_ARG_WITH(upnp-cflags, 
+	    [  --with-upnp-cflags=dir   upnp cflags],
+	    UPNP_CFLAGS="${withval}", 
+	    UPNP_CFLAGS="-I${LOCAL_LIBS}/include/upnp")
+
+AC_ARG_WITH(upnp-libs, 
+	    [  --with-upnp-libs=dir     upnp library file directory],
+	    UPNP_LIB="${withval}", 
+	    UPNP_LIB="${LOCAL_LIBS}/lib")
+
+AC_ARG_WITH(shttpd-cflags, 
+	    [  --with-shttpd-cflags=dir   SHTTPD cflags],
+	    SHTTPD_CFLAGS="${withval}", 
+	    SHTTPD_CFLAGS="-I${LOCAL_LIBS}/include")
+
+AC_ARG_WITH(shttpd-libs, 
+	    [  --with-shttpd-libs=dir     SHTTPD library file directory],
+	    SHTTPD_LIB="${withval}", 
+	    SHTTPD_LIB="${LOCAL_LIBS}/lib")
+
+AC_ARG_WITH(curl-cflags, 
+	    [  --with-curl-cflags=dir     CURL cflags],
+	    CURL_CFLAGS="${withval}", 
+	    CURL_CFLAGS="-I${LOCAL_LIBS}/include")
+
+AC_ARG_WITH(curl-libs, 
+	    [  --with-curl-libs=dir       CURL library file directory],
+	    CURL_LIB="${withval}", 
+	    CURL_LIB="${LOCAL_LIBS}/lib")
+
+AC_ARG_WITH(tinyxml-cflags, 
+	    [  --with-tinyxml-cflags=dir  TinyXML cflags],
+	    TINYXML_CFLAGS="${withval}", 
+	    TINYXML_CFLAGS="-I${LOCAL_LIBS}/include")
+
+AC_ARG_WITH(tinyxml-libs, 
+	    [  --with-tinyxml-libs=dir    TinyXML library file directory],
+	    UPNP_LIB="${withval}", 
+	    TINYXML_LIB="${LOCAL_LIBS}/lib")
+
+AC_ARG_WITH(iniparser-cflags, 
+	    [  --with-iniparser-cflags=dir  iniparser cflags],
+	    INIPARSER_CFLAGS="${withval}", 
+	    INIPARSER_CFLAGS="-I${LOCAL_LIBS}/include")
+
+AC_ARG_WITH(iniparser-libs, 
+	    [  --with-iniparser-libs=dir    iniparser library file directory],
+	    UPNP_LIB="${withval}", 
+	    INIPARSER_LIB="${LOCAL_LIBS}/lib")
+
+if test "x$ZB_2006" = "xyes"
+then
+	    AC_DEFINE(ZIGBEE_2006, 1, Define to support Zigbee 2006)
+fi
+
+old_ifs="$IFS"
+IFS=":$IFS"
+for i in $DEBUG_FEATURES
+do
+	CPPFLAGS="-D DEBUG_ACTIVE_$i $CPPFLAGS"
+done
+IFS="$old_ifs"
+	    
+CPPFLAGS="${UPNP_CFLAGS} ${SHTTPD_CFLAGS} ${CURL_CFLAGS} ${CPPFLAGS}"
+CPPFLAGS="${TINYXML_CFLAGS} ${INIPARSER_CFLAGS} ${ZBLIB_CFLAGS} ${CPPFLAGS}"
+
+AC_LANG_PUSH(C++)
+AC_CHECK_HEADERS(zigbee.h, [], [AC_MSG_ERROR([ZigBee interface not found])])
+AC_CHECK_HEADERS(ThreadPool.h, [], [AC_MSG_ERROR([threadutils library from upnp package not found])])
+AC_CHECK_HEADERS(shttpd.h, [], [AC_MSG_ERROR([SHTTPD library not found])])
+AC_CHECK_HEADERS(curl/curl.h, [], [AC_MSG_ERROR([CURL library not found])])
+AC_CHECK_HEADERS(tinyxml.h, [], [AC_MSG_ERROR([TinyXML library not found])])
+AC_CHECK_HEADERS(iniparser.h, [], [AC_MSG_ERROR([iniparser lib not found])])
+
+LDFLAGS="-L${UPNP_LIB} -L${SHTTPD_LIB} -L${CURL_LIB} ${LDFLAGS}"
+LDFLAGS="-L${TINYXML_LIB} -L${INIPARSER_LIB} -L${ZBLIB_LIB} ${LDFLAGS}"
+AC_CHECK_LIB(dl,dlopen)
+AC_CHECK_LIB(threadutil, TimerThreadInit,,
+	     [AC_MSG_ERROR([upnp headers found, however can't find libs])])
+AC_CHECK_LIB(shttpd, shttpd_init,,
+	     [AC_MSG_ERROR([SHTTPD headers found, however can't find libs])],
+	     [-ldl -lpthread])
+AC_CHECK_LIB(curl, curl_global_init,,
+	     [AC_MSG_ERROR([CURL headers found, however can't find libs])])
+# Is there a better way to test a C++ library?
+AC_CHECK_LIB(tinyxml, printf,,
+	     [AC_MSG_ERROR([TinyXML hdrs found, however can't find libs])])
+AC_CHECK_LIB(iniparser, iniparser_load,,
+	     [AC_MSG_ERROR([IniParser hdrs found, however can't find libs])])
+AC_CHECK_LIB(zigbee, ZBIFConnect,,
+	     [AC_MSG_ERROR([zigbee headers found, however can't find libs])])
+
+AC_LANG_POP
+
+AC_CONFIG_HEADER(config.h)
+AC_CONFIG_FILES([] [Makefile])
+
+AC_OUTPUT()

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/cscope.files
==============================================================================
    (empty)

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/doxy.conf
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/doxy.conf (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/doxy.conf Fri Oct 19 18:37:43 2012
@@ -1,0 +1,1098 @@
+# Doxyfile 1.3.5
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = "ZigBee interface"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = 
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = doc
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, 
+# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en 
+# (Japanese with English messages), Korean, Norwegian, Polish, Portuguese, 
+# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# This tag can be used to specify the encoding used in the generated output. 
+# The encoding is not always determined by the language that is chosen, 
+# but also whether or not the output is meant for Windows or non-Windows users. 
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES 
+# forces the Windows encoding (this is the default for the Windows binary), 
+# whereas setting the tag to NO uses a Unix-style encoding (the default for 
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING   = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is used 
+# as the annotated text. Otherwise, the brief description is used as-is. If left 
+# blank, the following values are used ("$name" is automatically replaced with the 
+# name of the entity): "The $name class" "The $name widget" "The $name file" 
+# "is" "provides" "specifies" "contains" "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = 
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited 
+# members of a class in the documentation of that class as if those members were 
+# ordinary class members. Constructors, destructors and assignment operators of 
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. It is allowed to use relative paths in the argument list.
+
+STRIP_FROM_PATH        = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like the Qt-style comments (thus requiring an 
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member 
+# documentation.
+
+DETAILS_AT_TOP         = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 4 
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources 
+# only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources 
+# only. Doxygen will then generate output that is more tailored for Java. 
+# For instance, namespaces will be presented as packages, qualified scopes 
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = YES
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = NO
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  =
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp 
+# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc
+
+FILE_PATTERNS          = 
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories 
+# that are symbolic links (a Unix filesystem feature) are excluded from the input.
+
+EXCLUDE_SYMLINKS       = YES 
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories.
+
+EXCLUDE_PATTERNS       = */CVS/*
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = 
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.
+
+INPUT_FILTER           = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = YES 
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default) 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = YES
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .6
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = NO
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse the 
+# parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or 
+# super classes. Setting the tag to NO turns the diagrams off. Note that this 
+# option is superseded by the HAVE_DOT option below. This is only a fallback. It is 
+# recommended to install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
+# generate a call dependency graph for every global function or class method. 
+# Note that enabling this option will significantly increase the time of a run. 
+# So in most cases it will be better to enable call graphs for selected 
+# functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_WIDTH    = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT   = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes that 
+# lay further from the root node will be omitted. Note that setting this option to 
+# 1 or 2 may greatly reduce the computation time needed for large code bases. Also 
+# note that a graph may be further truncated if the graph's image dimensions are 
+# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). 
+# If 0 is used for the depth value (the default), the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/main.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/main.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/main.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,205 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <signal.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include "winport.h"
+#endif
+
+#include <getopt.h>
+
+#include "GalZbIf.h"
+#include "CDiscoveryAgent.h"		
+#include "CServiceAgent.h"
+#include "CTrustCenterAgent.h"				
+#include "CLocalNode.h"
+
+#include "CMessage.h"
+#include "CQueryParser.h"
+
+#include "CRESTBroker.h"
+#include "ConfigurationRepository.h"
+
+#ifdef PERFORMANCE_TEST_ACTIVE
+#include "CDummyZigBeeDataSource.h"
+#endif
+
+#include "GWManagement.h"
+
+#define PROGRAM_NAME	"gal"
+
+static const char cmdlineOptions[] = "s:c:n:adhvV";
+
+bool verbose = false;
+const char *config_filename = "config.ini";
+const char *device_url = "zigbee:///dev/ttyUSB0?dongle=ezsp"; /* default */
+const char *WSN_Id = "";
+
+static const char help[] =
+		"Usage: " PROGRAM_NAME " [options...] <device url>\n"
+		"Options:\n"
+		"  -h               Show this information\n"
+		"  -c <filename>    Main configuration filename (default: \"config.ini\"\n"
+		"  -a               If present, create the network on startup (ignore config.ini setting)\n"
+		"  -m               If present, use the NVM setting (ignore config.ini setting)\n"
+		"  -d               Specify the device url\n"
+		"  -n <WSN name>    WSN name (i.e. VDT ethernet MAC address) \n"
+		"  -v               Be verbose.\n"
+		"  -V               Show the program version and quit.\n"
+		"\n";
+
+static void showHelp();
+static void showVersion();
+
+static LocalNode<RESTBroker> *pLocalNode = NULL;
+
+#ifdef PERFORMANCE_TEST_ACTIVE
+static DummyZigBeeDataSource *pDummyZigBeeDataSource = NULL;
+#endif
+
+static ConfigurationRepository *confrep = NULL;
+
+using namespace std;
+
+static RESTBroker *pRESTBroker = NULL;
+
+// To close everything before terminating
+static void handler(int signo);
+static void terminate_process(void);
+
+void handler(int signo) {
+	terminate_process();
+}
+
+int main(int argc, char *argv[]) {
+	int ret;
+	int c;
+	bool autostart = false;
+	bool startupModeUseNVMsetting = false;
+
+	struct sigaction act;
+
+	sigemptyset(&act.sa_mask);
+	act.sa_handler = handler; /* pointer to action */
+	act.sa_flags = 0;
+
+	ret = sigaction(SIGINT, &act, NULL);
+	if (ret < 0) {
+		fprintf(stderr, "ERROR: returned by sigaction\n");
+		return -1;
+	}
+
+	ret = sigaction(SIGTERM, &act, NULL);
+	if (ret < 0) {
+		fprintf(stderr, "ERROR: returned by sigaction\n");
+		return -1;
+	}
+
+	opterr = true;
+	while ((c = getopt(argc, argv, cmdlineOptions)) != -1) {
+
+		switch (c) {
+
+		case 'h':
+			showHelp();
+			break;
+
+		case 'c':
+			config_filename = optarg;
+			break;
+
+		case 'a':
+			autostart = true;
+			break;
+
+		case 'm':
+			startupModeUseNVMsetting = true;
+			break;
+
+		case 'd':
+			device_url = optarg;
+			break;
+
+		case 'n':
+			WSN_Id = optarg;
+			break;
+
+		case 'v':
+			verbose = true;
+			break;
+
+		case 'V':
+			showVersion();
+			break;
+
+		default:
+			showHelp();
+			break;
+		}
+	}
+
+	if (optind != argc)
+		device_url = argv[optind++];
+
+	// Load the GAL configuration
+	confrep = ConfigurationRepository::instance(config_filename);
+	if (!confrep->load()) {
+		printf("ERROR: Loading configuration file %s\n", config_filename);
+		exit(3);
+	}
+	printf("ZigBee Network Device - Gateway (version %s)\n",
+			ZIGBEE_GW_FIRMWARE_VERSION);
+
+	pLocalNode = LocalNode<RESTBroker>::getLocalNode();
+
+	pLocalNode->init(device_url);
+	pLocalNode->setWSNId(WSN_Id);
+
+#ifdef PERFORMANCE_TEST_ACTIVE
+	pDummyZigBeeDataSource = DummyZigBeeDataSource::getInstance();
+	pDummyZigBeeDataSource->init();
+#endif
+
+	pRESTBroker = new RESTBroker();
+	pRESTBroker->init(autostart, startupModeUseNVMsetting);
+	pRESTBroker->start();
+	// In case something goes wrong...
+	Sleep(1000);
+	terminate_process();
+	return 0;
+}
+
+void terminate_process(void) {
+	pLocalNode->stop();
+	if (pRESTBroker != NULL) {
+		delete (pRESTBroker);
+		pRESTBroker = NULL;
+	}
+	exit(4);
+}
+
+static void showHelp() {
+	printf("%s", help);
+	exit(5);
+}
+
+static void showVersion() {
+	printf("%s version %s\n", PROGRAM_NAME, ZIGBEE_GW_FIRMWARE_VERSION);
+	printf("GAL for ZigBee networks\n");
+	exit(6);
+}

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/mainconf.txt
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/mainconf.txt (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/mainconf.txt Fri Oct 19 18:37:43 2012
@@ -1,0 +1,27 @@
+#GAL MAIN CONFIGURATION FILE
+
+#TC Agent state if active = true, or not active = false
+#TC_AGENT=true
+TC_AGENT=false
+
+#trustcenter parameters
+TC_IEEE_ADDRESS=17161514131201ff
+
+#TC_JOINREQUESTPROCESSING: if true, local ACL Conf is used, else WSN-C access is required
+TC_JOINREQUESTPROCESSING=false
+#TC_JOINREQUESTPROCESSING=true
+
+#TC_LEAVENOTIFICATIONPROCESSING: if true, process locally leave notifications, not warning the WSN-C
+TC_LEAVENOTIFICATIONPROCESSING=false
+
+#TC_ACLFILENAME: file name containing the Access Control List
+TC_ACLFILENAME=acl.txt
+
+#TC_NETWORKKEY : The network master key, 16-bytes long
+#TC_NETWORKKEY=000102030405060708090a0b0c0d0e0f
+TC_NETWORKKEY=11000000000000000000000000000011
+#TC_NETWORKKEY=00000000000000000000000000000000
+
+#TC_APPSECURITYTIMEOUTPERIOD : Security Timeout period, in milliseconds
+#TC_APPSECURITYTIMEOUTPERIOD=1000
+TC_APPSECURITYTIMEOUTPERIOD=9999

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/pwdfile
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/pwdfile (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/pwdfile Fri Oct 19 18:37:43 2012
@@ -1,0 +1,1 @@
+telecom:mydomain.com:efe74d828da9b894a394109f382a4d5e 

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/run.sh
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/run.sh (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/run.sh Fri Oct 19 18:37:43 2012
@@ -1,0 +1,1 @@
+./gal -s off -c config.ini -n 0102030405060708 hdlc://130.192.86.163:3000,3001 

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/shttpd.conf
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/shttpd.conf (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/shttpd.conf Fri Oct 19 18:37:43 2012
@@ -1,0 +1,1 @@
+list_directories 0 

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/shttpd.pem
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/shttpd.pem (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/shttpd.pem Fri Oct 19 18:37:43 2012
@@ -1,0 +1,52 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAu8g/qfjqUf3ksZi45PPrmG4/cAQpHOI3UtDwWR/Vao85p2wv
+CbXocxOmyHVbQv//WI3kBj3Zwcwhatda3qI6edJwvmNyVldOGS9YGDhvyxyV4Yvw
+Mjyvytceo5jdnP5psk1+y+sTr1kEq3obWEEWlvrczeQuUd8NBg/FJA6oC1wqW5K1
+YxBFW950KzNWQjJn0o0A9tLZRCo7EKwsdj3NySILynlY5VrwfMgjZYzGWRprhzza
+dOnEIz0Ns1HSnY2xRJwshd6hb+MDHdLvwFcaSmHQ8IGnJJ8DhDbhWweQuI6wR+c0
+RjbOfgdzJCCiVFss+fn5ENaOZUnBgNbsoy+tvwIDAQABAoIBACxkUZCYFKTfdaH6
+bbNKaqa1YW/Uu/dlDxkX5cnb+bLgOwv2SkRsaZBS0/nNrI5xQGcp2/8RvhnPbRL5
+6DR7e4FzG04W6l+48fCIPbY0GVGV52TTlSv7Jr+4DTk1mSZVCp2pLlF8uEGatLzo
+9+/sKy/0DCDsUXrvVP/a2IsGn/lXH3lIpBll1gM8M8TEd1OknHzfICoYkwAi6HSg
+Sj7OKnF4MOm22SUL5gMREjvEDMH+02WzzejNcHGFmZa3iX274LPWsq9DHGZBSCsP
+oY91Sk4JKtn41iH+wS4F8wNEJWnZxU1XOIIzpabHh9VPri4Iw2Vi7gDATZamz+7y
+6r2HjCkCgYEA7X58Jw4VQIIv5OhS7cLMeWRQJIJ9Zwsr1mA6Xx5lLhLH5i8qTs8M
+WLRm97L8cRjeXv0xQAe/DKSbVd6C6KeBaIfa5wh0wQfDYTGR51IjQy+OFBcmy8kV
+Qu1hOxIh+5a8zlYr/mVibAFlX5m+f5/+Y3Cb7vtjdGYHzagUIdxbVmUCgYEAymod
+dN5TYV1fEIaaWLt6neL7uXyiCAv8JyFJ0TEKwJmsWG9PdG9JLBUhWgQNsFhADscY
+vvM3jTHlO03kHDiuePU1nzayLEKvthNziQg4q0diKAkH1zJH0f4BeDJn06hNZNeh
+xEFKsjCJ+Y0zTLIZgznqodd7KNHLa0y512jrz1MCgYBDrplJNA1AbhmiHceMdMh7
+C+h/DyUX2aorlQ7tjqb9I2MOqYBgJ0d4fCkgDEU/Ifw1i+ieO9bpjnuqVBhwn1QU
+6yqqTtGfNUwsBclz6AeenQ3bkeF/kBXcFfRwtjEzFvlFwG8XN+N9rkQqo5ETpBAG
+XNBDoibsxCsTJARgxgDNtQKBgAI1VCrxPgGi7iWVAlwTd4v/bPWiGXZzAwY+Q7rn
+iRF+27V/SWOgzzCO7nU39BpHbDN9EpUKvEFrGPAjsmhoaebh7frVsu3usFIRNkJ5
+d3zO45BCQPalEsmEtuljy2Qwwt9lxtsIR1NYWjkBxFyC2OpomFm5qxtP5qM+DA0A
+lQoHAoGALUT7oZ+Dyjc0OM4nf9f2aOmS535S0Y77Yn9jHUNlNw+sxX6irupwBUlJ
+9PLtUmWDxlx42PAbZ5tDIlpxKEY8W+KkL4LmOpMwuzzKD05JERlJIncbczG7nJWD
+gWCaIm8pGZXQ6IOMhoVHzIyM1fw8JMMuP3gUZq0pJmeYq1HVhjA=
+-----END RSA PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIIEQjCCAyqgAwIBAgIJAMleC121T3mqMA0GCSqGSIb3DQEBBQUAMHMxCzAJBgNV
+BAYTAklFMQ8wDQYDVQQIEwZEdWJsaW4xDzANBgNVBAcTBkR1YmxpbjEhMB8GA1UE
+ChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMR8wHQYDVQQDExZzaHR0cGQuc291
+cmNlZm9yZ2UubmV0MB4XDTA4MTEyNTE2MDIxMloXDTM3MDEyNzA5MzM1NlowczEL
+MAkGA1UEBhMCSUUxDzANBgNVBAgTBkR1YmxpbjEPMA0GA1UEBxMGRHVibGluMSEw
+HwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxHzAdBgNVBAMTFnNodHRw
+ZC5zb3VyY2Vmb3JnZS5uZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQC7yD+p+OpR/eSxmLjk8+uYbj9wBCkc4jdS0PBZH9VqjzmnbC8JtehzE6bIdVtC
+//9YjeQGPdnBzCFq11reojp50nC+Y3JWV04ZL1gYOG/LHJXhi/AyPK/K1x6jmN2c
+/mmyTX7L6xOvWQSrehtYQRaW+tzN5C5R3w0GD8UkDqgLXCpbkrVjEEVb3nQrM1ZC
+MmfSjQD20tlEKjsQrCx2Pc3JIgvKeVjlWvB8yCNljMZZGmuHPNp06cQjPQ2zUdKd
+jbFEnCyF3qFv4wMd0u/AVxpKYdDwgacknwOENuFbB5C4jrBH5zRGNs5+B3MkIKJU
+Wyz5+fkQ1o5lScGA1uyjL62/AgMBAAGjgdgwgdUwHQYDVR0OBBYEFESv7NXSXUbW
+u0gSWEea8t9JdA9pMIGlBgNVHSMEgZ0wgZqAFESv7NXSXUbWu0gSWEea8t9JdA9p
+oXekdTBzMQswCQYDVQQGEwJJRTEPMA0GA1UECBMGRHVibGluMQ8wDQYDVQQHEwZE
+dWJsaW4xITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEfMB0GA1UE
+AxMWc2h0dHBkLnNvdXJjZWZvcmdlLm5ldIIJAMleC121T3mqMAwGA1UdEwQFMAMB
+Af8wDQYJKoZIhvcNAQEFBQADggEBAIXzl7iruGGICH8XXIbsi4OfF+DBVlvY/xPj
+La3qaFaYz3NE7NqN67Z2fTOSmMsj9rknFslabXOFeTW9Y0yK7WLZ0eTt6vjpN63L
+7VuJqKrv7AQgYKuf86TMC+IZOV1G/rLKrFxDZFygoSsZbKU2VVgyZqPxoTrCo8qq
+uFa0l05toAbpYqg6a9wLPoggEEwU7RdqhavAHl2AgQWjyaVKQG2+J652P3/Aw/Rh
+s+KFKy1MFDdtmgqIlQuS2bZ/x1nY2+irOtVQ6uSGuxPru9a7qhE2/Jpoc/JrclyP
+iNOJ3HwypOfIyOSH+K4QDqbVhOQRfEV8cnryElDRyY2kKW70XlA=
+-----END CERTIFICATE-----

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/start_gal.sh
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/start_gal.sh (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/start_gal.sh Fri Oct 19 18:37:43 2012
@@ -1,0 +1,5 @@
+#!/bin/sh
+export LD_LIBRARY_PATH=$SOURCES_ROOT/targets/$PROFILE/fs/$EXTRA_PATH/lib
+./gal -c config.ini 'zigbee:///dev/ttyUSB0?dongle=freescale&speed=115200'
+
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/start_gal_valgrind.sh
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/start_gal_valgrind.sh (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/start_gal_valgrind.sh Fri Oct 19 18:37:43 2012
@@ -1,0 +1,5 @@
+#!/bin/sh
+export LD_LIBRARY_PATH=$SOURCES_ROOT/targets/$PROFILE/fs/$EXTRA_PATH/lib
+valgrind --leak-check=full ./gal -c config.ini 'zigbee:///dev/ttyUSB0?dongle=freescale&speed=115200' > aaa.log
+
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/winport.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/winport.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/linuxgal/winport.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,88 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "winport.h"
+#include "ThreadPool.h"
+#include "TimerThread.h"
+
+#define MAX_THREADS		10
+#define MIN_THREADS		10	
+#define JOBS_PER_THREAD		10
+#define THREAD_IDLE_TIME 5000
+#define MAX_JOBS_TOTAL 10
+
+void timer_cb(void *input);
+void free_timeout(void *event);
+
+ThreadPool threadPool;
+ThreadPoolJob job1;
+
+int InitTimers(void) {
+	ThreadPoolAttr attr;
+
+	TPAttrInit(&attr);
+	TPAttrSetMaxThreads(&attr, MAX_THREADS);
+	TPAttrSetMinThreads(&attr, MIN_THREADS);
+	TPAttrSetJobsPerThread(&attr, JOBS_PER_THREAD);
+	TPAttrSetIdleTime(&attr, THREAD_IDLE_TIME);
+
+#ifdef NEW_VERSION
+	TPAttrSetMaxJobsTotal(&attr, MAX_JOBS_TOTAL);
+#endif
+
+	if (ThreadPoolInit(&threadPool, &attr) != 0) {
+		return -1;
+	}
+
+	return 0;
+}
+
+unsigned int *SetTimer(int timer_id, int time, void *callback) {
+	int eventId;
+	int res;
+
+	TimerThread *timer;
+	ThreadPoolJob *job;
+
+	job = (ThreadPoolJob *) malloc(sizeof(ThreadPoolJob));
+
+	job = &job1;
+
+	TPJobInit(job, (start_routine) timer_cb, (void *) timer_id);
+	TPJobSetFreeFunction(job, (free_routine) free_timeout);
+	TPJobSetPriority(job, MED_PRIORITY);
+
+	timer = (TimerThread *) malloc(sizeof(TimerThread));
+
+	res = TimerThreadInit(timer, &threadPool);
+	if (res != 0) {
+		return -1;
+	}
+
+	res = TimerThreadSchedule(timer, time, REL_SEC, job, SHORT_TERM, &eventId);
+
+	if (res != 0) {
+		return -1;
+	}
+
+	return (unsigned int *) timer;
+}
+
+int KillTimer(unsigned int *timer) {
+	return 0;
+}
+
+void timer_cb(void *input) {
+	printf("Scattato %d !!!\n", (int) input);
+}
+
+void free_timeout(void *event) {
+}

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/readme.rtf
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/readme.rtf (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/readme.rtf Fri Oct 19 18:37:43 2012
@@ -1,0 +1,415 @@
+{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch0\stshfloch37\stshfhich37\stshfbi37\deflang1040\deflangfe1040\themelang1040\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f2\fbidi \fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;}
+{\f3\fbidi \froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;}{\f10\fbidi \fnil\fcharset2\fprq2{\*\panose 05000000000000000000}Wingdings;}{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}
+{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
+{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}
+{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
+{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}
+{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f39\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
+{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
+{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f59\fbidi \fmodern\fcharset238\fprq1 Courier New CE;}{\f60\fbidi \fmodern\fcharset204\fprq1 Courier New Cyr;}
+{\f62\fbidi \fmodern\fcharset161\fprq1 Courier New Greek;}{\f63\fbidi \fmodern\fcharset162\fprq1 Courier New Tur;}{\f64\fbidi \fmodern\fcharset177\fprq1 Courier New (Hebrew);}{\f65\fbidi \fmodern\fcharset178\fprq1 Courier New (Arabic);}
+{\f66\fbidi \fmodern\fcharset186\fprq1 Courier New Baltic;}{\f67\fbidi \fmodern\fcharset163\fprq1 Courier New (Vietnamese);}{\f379\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}{\f380\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;}
+{\f382\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f383\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f386\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}{\f387\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);}
+{\f409\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f410\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f412\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f413\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}
+{\f416\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f417\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
+{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
+{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
+{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
+{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
+{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
+{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;}
+{\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\fhimajor\f31536\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
+{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
+{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
+{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
+{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
+{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
+{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
+{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
+{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}
+{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}
+{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
+{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
+{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
+{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;
+\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp \f37 }{\*\defpap 
+\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\qj \fi-431\li431\ri0\sb480\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin431\itap0 \rtlch\fcs1 \af0\afs22\alang1025 
+\ltrch\fcs0 \f37\fs22\lang1040\langfe1033\cgrid\langnp1040\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*
+\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv 
+\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af37\afs20\alang1025 \ltrch\fcs0 \f37\fs20\lang1040\langfe1040\cgrid\langnp1040\langfenp1040 \snext11 \ssemihidden \sunhideused Normal Table;}{\*\cs15 
+\additive \rtlch\fcs1 \af0 \ltrch\fcs0 \ul\cf2 \sbasedon10 \sunhideused \styrsid9008840 Hyperlink;}}{\*\listtable{\list\listtemplateid-611808454\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat2\levelspace0
+\levelindent0{\leveltext\leveltemplateid-748882420\'01-;}{\levelnumbers;}\loch\af0\hich\af0\dbch\af0\fbias0 \fi-360\li720\lin720 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0
+{\leveltext\leveltemplateid68157443\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid68157445
+\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li2160\lin2160 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid68157441\'01\u-3913 ?;}{\levelnumbers;}
+\f3\fbias0 \fi-360\li2880\lin2880 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid68157443\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li3600\lin3600 }
+{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid68157445\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li4320\lin4320 }{\listlevel\levelnfc23\levelnfcn23
+\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid68157441\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0
+\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid68157443\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0
+\levelindent0{\leveltext\leveltemplateid68157445\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li6480\lin6480 }{\listname ;}\listid679162211}}{\*\listoverridetable{\listoverride\listid679162211\listoverridecount0\ls1}}{\*\rsidtbl \rsid1663242
+\rsid3671221\rsid6184790\rsid6431663\rsid9008840\rsid12272503\rsid12541765\rsid13772960\rsid14426498}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\author 11618205}
+{\operator 11618205}{\creatim\yr2011\mo11\dy15\hr16\min21}{\revtim\yr2011\mo11\dy18\hr11\min24}{\version4}{\edmins93}{\nofpages5}{\nofwords1701}{\nofchars9699}{\*\company Telecom Italia S.p.A.}{\nofcharsws11378}{\vern49247}}{\*\xmlnstbl {\xmlns1 http://sc
+hemas.microsoft.com/office/word/2003/wordml}}\paperw11906\paperh16838\margl720\margr720\margt720\margb720\gutter0\ltrsect 
+\deftab708\widowctrl\ftnbj\aenddoc\hyphhotz283\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0
+\showxmlerrors1\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin720\dgvorigin720\dghshow1\dgvshow1
+\jexpand\viewkind1\viewscale96\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct
+\asianbrkrule\rsidroot9008840\newtblstyruls\nogrowautofit\utinl \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sectrsid9008840\sftnbj {\*\pnseclvl1
+\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5
+\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang 
+{\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\qc \li0\ri0\sb100\sa100\sbauto1\saauto1\sl20\slmult0
+\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid9008840\indmirror\contextualspace \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \f37\fs22\lang1040\langfe1033\cgrid\langnp1040\langfenp1033 {\rtlch\fcs1 \af0\afs24 
+\ltrch\fcs0 \b\f0\fs32\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid12272503 GAL (Gateway Abstraction Layer)
+\par 
+\par }\pard \ltrpar\ql \li0\ri0\sb100\sa100\sbauto1\saauto1\sl20\slmult0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid9008840\indmirror\contextualspace {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 This document tries to help a new user to get familiar to the GAL and its usage.}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid14426498 
+ For any information please contact Andrea Ranalli (}{\field{\*\fldinst {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid14426498  HYPERLINK "mailto:andrea.ranalli at telecomitalia.it" }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\lang1033\langfe1033\langnp1033\insrsid12272503 {\*\datafield 
+00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b660000006d00610069006c0074006f003a0061006e0064007200650061002e00720061006e0061006c006c0069004000740065006c00650063006f006d006900740061006c00690061002e00690074000000795881f4
+3b1d7f48af2c825dc485276300000000a5ab000000}}}{\fldrslt {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \cs15\f0\fs24\ul\cf2\lang1033\langfe1033\langnp1033\insrsid14426498\charrsid13772960 andrea.ranalli at telecomitalia.it}}}\sectd \ltrsect
+\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sectrsid9008840\sftnbj {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid14426498 ) or Nicola Portinaro (}{\field{\*\fldinst {\rtlch\fcs1 
+\af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid14426498  HYPERLINK "mailto:nicola.portinaro at telecomitalia.it" }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid12272503 {\*\datafield 
+00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b6a0000006d00610069006c0074006f003a006e00690063006f006c0061002e0070006f007200740069006e00610072006f004000740065006c00650063006f006d006900740061006c00690061002e00690074000000
+795881f43b1d7f48af2c825dc485276300000000a5ab000000}}}{\fldrslt {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \cs15\f0\fs24\ul\cf2\lang1033\langfe1033\langnp1033\insrsid14426498\charrsid13772960 nicola.portinaro at telecomitalia.it}}}\sectd \ltrsect
+\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sectrsid9008840\sftnbj {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid14426498 ).}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid14426498\charrsid9008840 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \b\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid12272503 ------------------------------------------------------------------------
+\par Configure setting:
+\par ------------------------------------------------------------------------
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid12272503 This tutorial describes how to configure the environment in order to use the GAL with cygwin:
+\par 
+\par - First step: download the latest version of cygwin (http://www.cygwin.com) and include all the following
+\par packages (based on Cygwin DLL 1.7.7-1):
+\par 
+\par automake wrapper (4-10) and 1.11.1-1
+\par autoconf wrapper (10-1) and 2.68-1
+\par gcc-g++ 3.4.4-999
+\par openssl-devel 0.8.8r-1
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 libcurl-dlevel 7.19.6-1
+\par [all their dependencies]
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 Note: \'93libcurl-dlevel 7.19.6-1\'94  could be avoid if we can configure the local folder 'curl' (generally used for linux}{\rtlch\fcs1 
+\af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840  O.S.}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 )
+\par 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840 -}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 
+ Download the latest release of GAl from the repository at}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840  }{\field{\*\fldinst {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840  HYPERLINK "}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 http://atlantis.tilab.com/svn/gal/trunk}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840 " }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid12272503 {\*\datafield 
+00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b6800000068007400740070003a002f002f00610074006c0061006e007400690073002e00740069006c00610062002e0063006f006d002f00730076006e002f00670061006c002f007400720075006e006b0000007958
+81f43b1d7f48af2c825dc485276300000000a5ab000000}}}{\fldrslt {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \cs15\f0\fs24\ul\cf2\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid13772960 http://atlantis.tilab.com/svn/gal/trunk}}}\sectd \ltrsect
+\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sectrsid9008840\sftnbj {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840  and c}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 opy the whole folder into your home folder (or wherever you like), then open a cygwin shell and go into it.
+\par 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \b\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid12272503 ------------------------------------------------------------------------
+\par Automatic installation
+\par ------------------------------------------------------------------------
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid12272503 
+\par Type the following commands (starting from the gal root directory)
+\par . setup.bash
+\par gal_cygwin\tab //or gal_something, depending on your O.S.
+\par cd linuxgal
+\par make -f Makefile.cross genmake
+\par cd ..
+\par make clean all
+\par 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\ul\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid12272503 Useful commands:
+\par }\pard \ltrpar\ql \fi-4245\li4245\ri0\sb100\sa100\sbauto1\saauto1\sl20\slmult0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin4245\itap0\pararsid9008840\indmirror\contextualspace {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840 make distclean\tab \tab }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 
+//To clean everything and to force execution of configure scripts when 'make all' is issued again
+\par }\pard \ltrpar\ql \li0\ri0\sb100\sa100\sbauto1\saauto1\sl20\slmult0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid9008840\indmirror\contextualspace {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 ldd gal.exe\tab \tab \tab }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840 \tab \tab }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 //To figure out which dll are needed to let the gal work properly
+\par gal\tab \tab \tab \tab }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840 \tab \tab }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 
+//This is a macro call that brings you to the trunk folder!
+\par }\pard \ltrpar\ql \fi-4245\li4245\ri0\sb100\sa100\sbauto1\saauto1\sl20\slmult0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin4245\itap0\pararsid9008840\indmirror\contextualspace {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 make -f Makefile.cross all install\tab }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840 \tab }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 //To compile after modifies made only in "linuxgal" or "zigBee" go to the folder and run...
+\par }\pard \ltrpar\ql \li0\ri0\sb100\sa100\sbauto1\saauto1\sl20\slmult0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid9008840\indmirror\contextualspace {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 make -f Makefile.cross clean all install }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840 \tab }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 //To compile instead the single package!
+\par 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\ul\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid12272503 Note}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid12272503 :
+\par - In zigbee/Makefile.cross set the EMBER_STACK_PROFILE according to the ZigBee or ZigBeePRO stack that you would like to use.
+\par - To enable/disable the debug, in linuxgal/Makefile.cross add/remove the following line in the "config" section:
+\par \tab }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 --enable-debug \\\tab \tab --with-debug-flags=RB:SB:DA:MESSAGE:SA:RESTSERVER:XMLMSGCOMPOSER:GALZB:XMLMSGPARSER
+\par 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid12272503 Note: If some error occur
+s in "make config" or "make all", this is probably due to the fact that the curl library are not found yet by the GAL (since they're not compiled yet). To fix this problem, launch again "make config" and "make all" and it should work (or alternatively run
+ "make -f Makefile.cross all install" in linuxgal)
+\par The output generated by the previous commands is the gal file, present in linuxgal for debugging, and another gal present in [...]/fs/usr/ti/bin, that has been stripped and that shall be used as executable 
+file for a trial. The macro called 'galfs' brings you where the files has been installed:
+\par bin -> exe gal
+\par lib -> librerie
+\par etc -> config.ini
+\par 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \b\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid12272503 ------------------------------------------------------------------------
+\par Manual installation
+\par ------------------------------------------------------------------------
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid12272503 
+\par If this is your first time that you download and use the GAL, you need to compile the "initparser",
+\par "shttpd" and "tinyxml" folders:
+\par \tab - go to "initparser" and run "make clean" and "make"
+\par \tab - go to "\\http\\shttpd\\src" and run "make" (for cygwin type "SSL_VER=0.9.8 make cygwin")
+\par \tab - go to "tinyxml\\src" and run "make clean" and "make"
+\par 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 Maybe a tipical problem that you could encounter is related to the libupnp libraries. }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid12272503 In the "extras" folder
+\par there is a file, libupnp-1.4.6.tar, that must be installed before to continue.
+\par 
+\par Once those steps are accomplished, you're ready to compile the GAL, focusing on the two main 
+\par folder, "linuxgal" and "zigbee".
+\par \tab - linuxgal contains all the main files responsible to compile and execute the gal
+\par \tab - zigbee contains all the file needed to setup the ZigBee or ZigBeePRO stack
+\par 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 A list of the command that shall be execute is reported below, as well with some comments:
+\par #!/bin/bash
+\par echo "***}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840 CHOOSE THE EMBER STACK PROFILE, 1=ZigBee or 2=ZigBeePRO }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 ***"
+\par export EMBER_STACK_PROFILE=1
+\par cd zigbee/
+\par make clean
+\par make
+\par cd ..
+\par echo "***ZIGBEE STACK PROFILE $EMBER_STACK_PROFILE DONE ***"}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 echo "***COMPILING THE GAL, PLEASE WAIT ***"
+\par cd linuxgal
+\par make clean
+\par echo "***MAKE CLEAN DONE, EXECUTING aclocal and autoheader ***"
+\par aclocal
+\par autoheader
+\par echo "***aclocal and autoheader DONE, EXECUTING automake and autoconf ***"
+\par automake -a
+\par autoconf
+\par echo "***automake and autoconf DONE, EXECUTING configure}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840  (the first one is for linux, the second one is used for windows)}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840  ***"
+\par #./configure --enable-zigbee-pro --with-local-libs=.. --with-upnp-cflags=-I/usr/local/include/upnp --with-upnp-libs=/usr/local/lib
+\par ./configure --enable-zigbee-pro --with-local-libs=.. --with-upnp-cflags=-I/usr/local/include/upnp --with-upnp-libs=/usr/local/lib --enable-debug --with-debug-flags=RB:SB:DA:MESSAGE:SA:RESTSERVER:XMLMSGCOMPOSER:GALZB:XMLMSGPARSER}{\rtlch\fcs1 \af0\afs24 
+\ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 echo "***configure DONE, EXECUTING make ***"
+\par make
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840 #}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 mv gal ..}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 mv gal}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840 .exe}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840  ..
+\par cd ..
+\par echo "***PROCESS TERMINATED, gal.exe CREATED ***"}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid9008840 
+\par The main error that a user could encounter here is the wrong path for the upnp library so it must be
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid12272503 checked first if this library is installed and where.
+\par 
+\par Under the linux O.S., for example, another valid path that could be used is:
+\par ./configure --enable-zigbee-pro --with-local-libs=.. --with-upnp-cflags=-I/usr/include/upnp --with-upnp-libs=/usr/lib
+\par This one will fix issues relater to the wrong position of the upnp library (the user must check first where
+\par it was installed). Also, some problem could be related to the curl library (to be installed as well) and
+\par in that case a useful path could be:
+\par ./configure --enable-zigbee-pro --with-local-libs=../libs --with-upnp-cflags=-I/usr/include/upnp --with-curl-cflags=-I/usr/include/curl --with-curl-libs=/usr/lib  --enable-debug
+\par Also, if not present the file libcurl.so under /usr/lib, please create it using a soft link (ln -s libcurl.so.4 libcurl.so)
+\par 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \b\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid12272503 ------------------------------------------------------------------------
+\par How to run GAL:
+\par ------------------------------------------------------------------------
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid12272503 The easiest way to run a GAL is by tipying the following path:
+\par gal.exe -s on -c config.ini 'zigbee:///dev/com9?dongle=ezsp'
+\par where:
+\par \tab - gal.exe (galPRO.exe) is the result of the previous step (the compiling phase)
+\par \tab - config.ini is the file containing precious information regarding the configuration of
+\par \tab   the ZigBee network (like channel, panId, extendedPanID, security, etc...)
+\par \tab - 'zigbee:///dev/com9?dongle=ezsp' specify at which port your Telegesis dondle is installed
+\par \tab   and that you're using a Ember firmware (called EZSP: Ember ZigBee Serial Protocol)
+\par 
+\par Note: Under linux the Teleesis dongle could be found using the path 'zigbee:///dev/ttyUSB0?dongle=ezsp'
+\par 
+\par To run the GAL using the MicroSD type instead:
+\par ./gal -c config.ini "zigbee:///dev/com8?dongle=microSD&speed=115200"
+\par 
+\par 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \b\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid12272503 ------------------------------------------------------------------------
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \b\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid14426498 How to compile and run the GAL under a Linux O.S.}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \b\f0\fs24\lang1033\langfe1033\langnp1033\insrsid12272503 
+ for ARM:}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \b\f0\fs24\lang1033\langfe1033\langnp1033\insrsid9008840\charrsid14426498 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \b\f0\fs24\insrsid9008840\charrsid14426498 ------------------------------------------------------------------------
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid9008840\charrsid9008840 
+\par Questo breve tutorial spiega i passi da seguire per migrare l'attuale versione del GAL mantenuta sul repository (e configurata per lavorare con Cygwin sotto windows) sotto un sistema operativo Linux.
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid9008840 
+\par }\pard \ltrpar\ql \li0\ri0\sb100\sa100\sbauto1\saauto1\sl20\slmult0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12272503\indmirror\contextualspace {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\insrsid12272503\charrsid12272503 Steps:
+\par - fare il checkout del GAL dentro una nuova cartella (assicurandosi che il PC sia dentro GRIFFON):
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid12272503\charrsid6431663 svn co http://atlantis.tilab.com/svn/gal/trunk
+\par 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503\charrsid12272503 - scaricare ed installare }{\field{\*\fldinst {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503  HYPERLINK "https://}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\insrsid12272503\charrsid12272503 sourcery.mentor.com/sgpp/lite/arm/portal/subscription3057}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503 " }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid6431663 {\*\datafield 
+00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b9c000000680074007400700073003a002f002f0073006f007500720063006500720079002e006d0065006e0074006f0072002e0063006f006d002f0073006700700070002f006c006900740065002f00610072006d00
+2f0070006f007200740061006c002f0073007500620073006300720069007000740069006f006e0033003000350037000000795881f43b1d7f48af2c825dc485276300000000a5ab0000}}}{\fldrslt {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \cs15\f0\fs24\ul\cf2\insrsid12272503\charrsid6184790 
+https://sourcery.mentor.com/sgpp/lite/arm/portal/subscription3057}}}\sectd \ltrsect\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sectrsid9008840\sftnbj {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503  }{
+\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503\charrsid12272503 il file arm-2011.03-41-arm-none-linux-gnueabi.bin}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503 
+ qualora si intende fare una cross compilazione del GAL su macchine ARM. }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503\charrsid12272503 L'interfaccia grafica guider}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503 \'e0}{
+\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503\charrsid12272503 \~ l'installazion}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503 e verso una cartella che servir\'e0}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\insrsid12272503\charrsid12272503 \~ per il punto successivo (il CROSS_PATH)
+\par 
+\par - aggiornare il file Makefile.rules presente dentro la root. Le parti che ci interessano aggiornare sono i CROSS_PATH relativi a "gal_intel" (a) e "gal_freescale" (b):
+\par   }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid12272503\charrsid6431663 a) export CROSS_PATH\tab \tab = \tab /usr/bin/
+\par   }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid12272503\charrsid12272503 b) export CROSS_PATH\tab \tab =\tab /[}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid12272503 \'85]}{
+\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid12272503\charrsid12272503  /CodeSourcery/Sourcery_G++_Lite/bin/arm-none-linux-gnueabi-
+\par 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503\charrsid12272503 - nel caso di una compilazione per arm, assicurarsi che il file in /linuxgal/Makefile.cross non abbia nella sezione config alcun parametro per "--with-debug-flags="}{
+\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503 . Questo per ottimizzare la dimensione del file di output generato}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503\charrsid12272503 
+\par 
+\par - eseguire i seguenti comandi:
+\par   }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid12272503\charrsid6431663 . setup.bash
+\par   gal_freescale (oppure gal_intel)
+\par   cd linuxgal
+\par   make -f Makefile.cross genmake
+\par   }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503\charrsid12272503 cd..
+\par   make all
+\par 
+\par - Se non vi sono stati problemi, l'output del gal, oltre che in linuxgal, si trover}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503 \'e0}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503\charrsid12272503 \~ su trunk/targets/fr}{
+\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503 eescale/fs/usr/ti/bin (questo \'e8}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503\charrsid12272503  l'unico file da copiare sulla piattaforma arm)
+\par 
+\par - Per l'esecuzione in locale del GAL, bisogna anche andare a indicare dove si trovano le librerie upnp, e per far questo vi sono due opzioni:
+\par   a) si usa il comando export LD_LIBRARY_PATH=[...]/trunk/targets/freescale/fs/usr/ti/lib  (usare il comando "pwd" per individuare il path esatto)
+\par   b) tutto il contenuto di [...]/trunk/targets/freescale/fs/usr/ti/lib  va copiato in /usr/lib
+\par 
+\par - Infine, per poter eseguire il GAL il comando da inviare (abilitando valgrind) }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503 \'e8 il seguente}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503\charrsid12272503  (more info @ }
+{\field{\*\fldinst {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503  HYPERLINK "}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503\charrsid12272503 http://people.gnome.org/~newren/tutorials/developing-with-gnome/html/ch03s03.html}{
+\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503 " }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid6431663 {\*\datafield 
+00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90bbc00000068007400740070003a002f002f00700065006f0070006c0065002e0067006e006f006d0065002e006f00720067002f007e006e0065007700720065006e002f007400750074006f007200690061006c007300
+2f0064006500760065006c006f00700069006e0067002d0077006900740068002d0067006e006f006d0065002f00680074006d006c002f0063006800300033007300300033002e00680074006d006c000000795881f43b1d7f48af2c825dc485276300000000a5ab0000}}}{\fldrslt {\rtlch\fcs1 \af0\afs24 
+\ltrch\fcs0 \cs15\f0\fs24\ul\cf2\insrsid12272503\charrsid6184790 http://people.gnome.org/~newren/tutorials/developing-with-gnome/html/ch03s03.html}}}\sectd \ltrsect
+\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sectrsid9008840\sftnbj {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503  }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503\charrsid12272503 )
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid6431663 v}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid12272503\charrsid6431663 algrind}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\lang1033\langfe1033\langnp1033\insrsid6431663  -v}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid12272503\charrsid6431663  --tool=memcheck --leak-check=yes --show-reachable=yes --num-cal}{\rtlch\fcs1 
+\af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid6431663\charrsid6431663 lers=20 --track-fds=yes --log-file}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\lang1033\langfe1033\langnp1033\insrsid12272503\charrsid6431663 
+=valgrindOutput.txt ./gal -c config.ini 'zigbee:///dev/ttyUSB0?dongle=freescale&speed=115200'
+\par 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503\charrsid12272503 Not}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503 e}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503\charrsid12272503 :}{\rtlch\fcs1 \af0\afs24 
+\ltrch\fcs0 \f0\fs24\insrsid12272503 
+\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1040\langfe1033\langfenp1033\insrsid12272503\charrsid12272503 \hich\af0\dbch\af0\loch\f0 -\tab}}\pard \ltrpar\ql \fi-360\li720\ri0\sb100\sa100\sbauto1\saauto1\sl20\slmult0
+\widctlpar\wrapdefault\aspalpha\aspnum\faauto\ls1\adjustright\rin0\lin720\itap0\pararsid12272503\indmirror\contextualspace {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503\charrsid12272503 il }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\insrsid12272503 file valgrindOutput.txt deve gi\'e0\~}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503\charrsid12272503 esistere altrimenti non funziona
+\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1040\langfe1033\langfenp1033\insrsid12272503 \hich\af0\dbch\af0\loch\f0 -\tab}}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503 per}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\insrsid9008840\charrsid9008840  rendere i vari file di configurazione presenti nella root folder del gal (tipo "configureEnvironment") eseguibili tramite il comando
+\par }\pard \ltrpar\ql \fi360\li0\ri0\sb100\sa100\sbauto1\saauto1\sl20\slmult0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12272503\indmirror\contextualspace {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\insrsid9008840\charrsid9008840 chmod 777 "nomefile" (o comunque come si preferisce/conosce)
+\par }\pard \ltrpar\ql \li0\ri0\sb100\sa100\sbauto1\saauto1\sl20\slmult0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid9008840\indmirror\contextualspace {\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\insrsid9008840\charrsid9008840 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503 Alcuni problemi noti: 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid9008840\charrsid9008840 - libupnp3 o curl non installate in precedenza sul S.O. \endash 
+ In tal caso procedere alla loro installazione usando anche il normale gestore di pacchetti messo a disposizione da Ubuntu o altri (per le libupnp3 ver. 1.6.6-3 assicurarsi che esista la cartella /usr/include/upnp, mentre per curl assicurarsi che esista u
+n libcurl.so presente in /usr/lib, e se non c\rquote \'e8 fare un link simbolico ad uno dei libcurl.so.X presenti). Hint: ln \endash s libcurl.so.4 libcurl.so
+\par - il ./configure potrebbe non trovare alcune librerie dunque sostituire questa stringa nel configure del linuxgal:
+\par ./configure --enable-zigbee-pro --with-local-libs=.. --with-upnp-cflags=-I/usr/include/upnp --with-upnp-libs=/usr/lib --enable-debug --with-debug-flags=RB:SB:DA:MESSAGE:SA:RESTSERVER:XMLMSGCOMPOSER:GALZB:XMLMSGPARSER
+\par Di fatto questa stringa rispetto all\rquote originale elimina la cartella \'93local\'94 (opzionalmente aggiungere anche \endash with-curl-libs=/usr/lib, ma non \'e8 necessario )
+\par - Nel caso il make si blocchi sul file depcomp, prendere il file presente sulla root e sostituirlo a quello attualmente presente in linuxgal
+\par 
+\par Per eseguire il gal lanciare:
+\par ./gal -c config.ini 'zigbee:///dev/ttyUSB0?dongle=}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid12272503 freescale}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid9008840\charrsid9008840 '}{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 
+\f0\fs24\insrsid9008840 
+\par }{\rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \f0\fs24\insrsid14426498\charrsid9008840 
+\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a
+9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad
+5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6
+b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0
+0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6
+a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f
+c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512
+0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462
+a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865
+6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b
+4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b
+4757e8d3f729e245eb2b260a0238fd010000ffff0300504b03041400060008000000210030dd4329a8060000a41b0000160000007468656d652f7468656d652f
+7468656d65312e786d6cec594f6fdb3614bf0fd87720746f6327761a07758ad8b19b2d4d1bc46e871e698996d850a240d2497d1bdae38001c3ba618715d86d87
+615b8116d8a5fb34d93a6c1dd0afb0475292c5585e9236d88aad3e2412f9e3fbff1e1fa9abd7eec70c1d1221294fda5efd72cd4324f1794093b0eddd1ef62fad
+79482a9c0498f184b4bd2991deb58df7dfbb8ad755446282607d22d771db8b944ad79796a40fc3585ee62949606ecc458c15bc8a702910f808e8c66c69b9565b
+5d8a314d3c94e018c8de1a8fa94fd05093f43672e23d06af89927ac06762a049136785c10607758d9053d965021d62d6f6804fc08f86e4bef210c352c144dbab
+999fb7b4717509af678b985ab0b6b4ae6f7ed9ba6c4170b06c788a705430adf71bad2b5b057d03606a1ed7ebf5babd7a41cf00b0ef83a6569632cd467faddec9
+699640f6719e76b7d6ac355c7c89feca9cccad4ea7d36c65b258a206641f1b73f8b5da6a6373d9c11b90c537e7f08dce66b7bbeae00dc8e257e7f0fd2badd586
+8b37a088d1e4600ead1ddaef67d40bc898b3ed4af81ac0d76a197c86826828a24bb318f3442d8ab518dfe3a20f000d6458d104a9694ac6d88728eee2782428d6
+0cf03ac1a5193be4cbb921cd0b495fd054b5bd0f530c1931a3f7eaf9f7af9e3f45c70f9e1d3ff8e9f8e1c3e3073f5a42ceaa6d9c84e5552fbffdeccfc71fa33f
+9e7ef3f2d117d57859c6fffac327bffcfc793510d26726ce8b2f9ffcf6ecc98baf3efdfdbb4715f04d814765f890c644a29be408edf3181433567125272371be
+15c308d3f28acd249438c19a4b05fd9e8a1cf4cd296699771c393ac4b5e01d01e5a30a787d72cf1178108989a2159c77a2d801ee72ce3a5c545a6147f32a9979
+3849c26ae66252c6ed637c58c5bb8b13c7bfbd490a75330f4b47f16e441c31f7184e140e494214d273fc80900aedee52ead87597fa824b3e56e82e451d4c2b4d
+32a423279a668bb6690c7e9956e90cfe766cb37b077538abd27a8b1cba48c80acc2a841f12e698f13a9e281c57911ce298950d7e03aba84ac8c154f8655c4f2a
+f074481847bd804859b5e696007d4b4edfc150b12addbecba6b18b148a1e54d1bc81392f23b7f84137c2715a851dd0242a633f900710a218ed715505dfe56e86
+e877f0034e16bafb0e258ebb4faf06b769e888340b103d331115bebc4eb813bf83291b63624a0d1475a756c734f9bbc2cd28546ecbe1e20a3794ca175f3fae90
+fb6d2dd99bb07b55e5ccf68942bd0877b23c77b908e8db5f9db7f024d9239010f35bd4bbe2fcae387bfff9e2bc289f2fbe24cfaa301468dd8bd846dbb4ddf1c2
+ae7b4c191ba8292337a469bc25ec3d411f06f53a73e224c5292c8de0516732307070a1c0660d125c7d44553488700a4d7bddd3444299910e254ab984c3a219ae
+a4adf1d0f82b7bd46cea4388ad1c12ab5d1ed8e1153d9c9f350a3246aad01c6873462b9ac05999ad5cc988826eafc3acae853a33b7ba11cd1445875ba1b236b1
+399483c90bd560b0b0263435085a21b0f22a9cf9356b38ec6046026d77eba3dc2dc60b17e92219e180643ed27acffba86e9c94c7ca9c225a0f1b0cfae0788ad5
+4adc5a9aec1b703b8b93caec1a0bd8e5de7b132fe5113cf312503b998e2c2927274bd051db6b35979b1ef271daf6c6704e86c73805af4bdd476216c26593af84
+0dfb5393d964f9cc9bad5c313709ea70f561ed3ea7b053075221d51696910d0d339585004b34272bff7213cc7a510a5454a3b349b1b206c1f0af490176745d4b
+c663e2abb2b34b23da76f6352ba57ca2881844c1111ab189d8c7e07e1daaa04f40255c77988aa05fe06e4e5bdb4cb9c5394bbaf28d98c1d971ccd20867e556a7
+689ec9166e0a522183792b8907ba55ca6e943bbf2a26e52f48957218ffcf54d1fb09dc3eac04da033e5c0d0b8c74a6b43d2e54c4a10aa511f5fb021a07533b20
+5ae07e17a621a8e082dafc17e450ffb739676998b48643a4daa7211214f623150942f6a02c99e83b85583ddbbb2c4996113211551257a656ec1139246ca86be0
+aadedb3d1441a89b6a929501833b197fee7b9641a3503739e57c732a59b1f7da1cf8a73b1f9bcca0945b874d4393dbbf10b1680f66bbaa5d6f96e77b6f59113d
+316bb31a795600b3d256d0cad2fe354538e7566b2bd69cc6cbcd5c38f0e2bcc63058344429dc2121fd07f63f2a7c66bf76e80d75c8f7a1b622f878a18941d840
+545fb28d07d205d20e8ea071b283369834296bdaac75d256cb37eb0bee740bbe278cad253b8bbfcf69eca23973d939b97891c6ce2cecd8da8e2d343578f6648a
+c2d0383fc818c798cf64e52f597c740f1cbd05df0c264c49134cf09d4a60e8a107260f20f92d47b374e32f000000ffff0300504b030414000600080000002100
+0dd1909fb60000001b010000270000007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f7
+8277086f6fd3ba109126dd88d0add40384e4350d363f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89
+d93b64b060828e6f37ed1567914b284d262452282e3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd500
+1996509affb3fd381a89672f1f165dfe514173d9850528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0f
+bfff0000001c0200001300000000000000000000000000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6
+a7e7c0000000360100000b00000000000000000000000000300100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a
+0000001c00000000000000000000000000190200007468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d00140006000800000021
+0030dd4329a8060000a41b00001600000000000000000000000000d60200007468656d652f7468656d652f7468656d65312e786d6c504b01022d001400060008
+00000021000dd1909fb60000001b0100002700000000000000000000000000b20900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000ad0a00000000}
+{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d
+617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169
+6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363
+656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e}
+{\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef1\lsdunhideuseddef1\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;
+\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4;
+\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;
+\lsdpriority39 \lsdlocked0 toc 1;\lsdpriority39 \lsdlocked0 toc 2;\lsdpriority39 \lsdlocked0 toc 3;\lsdpriority39 \lsdlocked0 toc 4;\lsdpriority39 \lsdlocked0 toc 5;\lsdpriority39 \lsdlocked0 toc 6;\lsdpriority39 \lsdlocked0 toc 7;
+\lsdpriority39 \lsdlocked0 toc 8;\lsdpriority39 \lsdlocked0 toc 9;\lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdpriority1 \lsdlocked0 Default Paragraph Font;
+\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority59 \lsdlocked0 Table Grid;\lsdunhideused0 \lsdlocked0 Placeholder Text;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 1;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdunhideused0 \lsdlocked0 Revision;
+\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 2;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 2;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 2;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 3;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 3;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 4;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 4;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 5;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 5;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 5;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 6;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 6;
+\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;
+\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis;
+\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;
+\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdpriority37 \lsdlocked0 Bibliography;\lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;}}{\*\datastore 010500000200000018000000
+4d73786d6c322e534158584d4c5265616465722e362e3000000000000000000000060000
+d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e5000000000000000000000000f031
+7446dca5cc01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000105000000000000}}

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/readme.txt
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/readme.txt (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/readme.txt Fri Oct 19 18:37:43 2012
@@ -1,0 +1,178 @@
+GAL (Gateway Abstraction Layer)
+
+This document tries to help a new user to get familiar to the GAL and its usage. For any information please contact Andrea Ranalli (andrea.ranalli at telecomitalia.it) or Nicola Portinaro (nicola.portinaro at telecomitalia.it).
+
+------------------------------------------------------------------------
+Configure setting:
+------------------------------------------------------------------------
+This tutorial describes how to configure the environment in order to use the GAL with cygwin:
+
+- First step: download the latest version of cygwin (http://www.cygwin.com) and include all the following
+packages (based on Cygwin DLL 1.7.7-1):
+
+automake wrapper (4-10) and 1.11.1-1
+autoconf wrapper (10-1) and 2.68-1
+gcc-g++ 3.4.4-999
+openssl-devel 0.8.8r-1
+libcurl-dlevel 7.19.6-1
+[all their dependencies]
+
+Note: “libcurl-dlevel 7.19.6-1”  could be avoid if we can configure the local folder 'curl' (generally used for linux O.S.)
+
+- Download the latest release of GAl from the repository at http://atlantis.tilab.com/svn/gal/trunk and copy the whole folder into your home folder (or wherever you like), then open a cygwin shell and go into it.
+
+------------------------------------------------------------------------
+Automatic installation
+------------------------------------------------------------------------
+
+Type the following commands (starting from the gal root directory)
+. setup.bash
+gal_cygwin	//or gal_something, depending on your O.S.
+cd linuxgal
+make -f Makefile.cross genmake
+cd ..
+make clean all
+
+Useful commands:
+make distclean		//To clean everything and to force execution of configure scripts when 'make all' is issued again
+ldd gal.exe					//To figure out which dll are needed to let the gal work properly
+gal						//This is a macro call that brings you to the trunk folder!
+make -f Makefile.cross all install		//To compile after modifies made only in "linuxgal" or "zigBee" go to the folder and run...
+make -f Makefile.cross clean all install 	//To compile instead the single package!
+
+Note:
+- In zigbee/Makefile.cross set the EMBER_STACK_PROFILE according to the ZigBee or ZigBeePRO stack that you would like to use.
+- To enable/disable the debug, in linuxgal/Makefile.cross add/remove the following line in the "config" section:
+	--enable-debug \		--with-debug-flags=RB:SB:DA:MESSAGE:SA:RESTSERVER:XMLMSGCOMPOSER:GALZB:XMLMSGPARSER
+
+Note: If some error occurs in "make config" or "make all", this is probably due to the fact that the curl library are not found yet by the GAL (since they're not compiled yet). To fix this problem, launch again "make config" and "make all" and it should work (or alternatively run "make -f Makefile.cross all install" in linuxgal)
+The output generated by the previous commands is the gal file, present in linuxgal for debugging, and another gal present in [...]/fs/usr/ti/bin, that has been stripped and that shall be used as executable file for a trial. The macro called 'galfs' brings you where the files has been installed:
+bin -> exe gal
+lib -> librerie
+etc -> config.ini
+
+------------------------------------------------------------------------
+Manual installation
+------------------------------------------------------------------------
+
+If this is your first time that you download and use the GAL, you need to compile the "initparser",
+"shttpd" and "tinyxml" folders:
+	- go to "initparser" and run "make clean" and "make"
+	- go to "\http\shttpd\src" and run "make" (for cygwin type "SSL_VER=0.9.8 make cygwin")
+	- go to "tinyxml\src" and run "make clean" and "make"
+
+Maybe a tipical problem that you could encounter is related to the libupnp libraries. In the "extras" folder
+there is a file, libupnp-1.4.6.tar, that must be installed before to continue.
+
+Once those steps are accomplished, you're ready to compile the GAL, focusing on the two main 
+folder, "linuxgal" and "zigbee".
+	- linuxgal contains all the main files responsible to compile and execute the gal
+	- zigbee contains all the file needed to setup the ZigBee or ZigBeePRO stack
+
+A list of the command that shall be execute is reported below, as well with some comments:
+#!/bin/bash
+echo "***CHOOSE THE EMBER STACK PROFILE, 1=ZigBee or 2=ZigBeePRO ***"
+export EMBER_STACK_PROFILE=1
+cd zigbee/
+make clean
+make
+cd ..
+echo "***ZIGBEE STACK PROFILE $EMBER_STACK_PROFILE DONE ***"
+echo "***COMPILING THE GAL, PLEASE WAIT ***"
+cd linuxgal
+make clean
+echo "***MAKE CLEAN DONE, EXECUTING aclocal and autoheader ***"
+aclocal
+autoheader
+echo "***aclocal and autoheader DONE, EXECUTING automake and autoconf ***"
+automake -a
+autoconf
+echo "***automake and autoconf DONE, EXECUTING configure (the first one is for linux, the second one is used for windows) ***"
+#./configure --enable-zigbee-pro --with-local-libs=.. --with-upnp-cflags=-I/usr/local/include/upnp --with-upnp-libs=/usr/local/lib
+./configure --enable-zigbee-pro --with-local-libs=.. --with-upnp-cflags=-I/usr/local/include/upnp --with-upnp-libs=/usr/local/lib --enable-debug --with-debug-flags=RB:SB:DA:MESSAGE:SA:RESTSERVER:XMLMSGCOMPOSER:GALZB:XMLMSGPARSER
+echo "***configure DONE, EXECUTING make ***"
+make
+#mv gal ..
+mv gal.exe ..
+cd ..
+echo "***PROCESS TERMINATED, gal.exe CREATED ***"
+
+The main error that a user could encounter here is the wrong path for the upnp library so it must be
+checked first if this library is installed and where.
+
+Under the linux O.S., for example, another valid path that could be used is:
+./configure --enable-zigbee-pro --with-local-libs=.. --with-upnp-cflags=-I/usr/include/upnp --with-upnp-libs=/usr/lib
+This one will fix issues relater to the wrong position of the upnp library (the user must check first where
+it was installed). Also, some problem could be related to the curl library (to be installed as well) and
+in that case a useful path could be:
+./configure --enable-zigbee-pro --with-local-libs=../libs --with-upnp-cflags=-I/usr/include/upnp --with-curl-cflags=-I/usr/include/curl --with-curl-libs=/usr/lib  --enable-debug
+Also, if not present the file libcurl.so under /usr/lib, please create it using a soft link (ln -s libcurl.so.4 libcurl.so)
+
+------------------------------------------------------------------------
+How to run GAL:
+------------------------------------------------------------------------
+The easiest way to run a GAL is by tipying the following path:
+gal.exe -s on -c config.ini 'zigbee:///dev/com9?dongle=ezsp'
+where:
+	- gal.exe (galPRO.exe) is the result of the previous step (the compiling phase)
+	- config.ini is the file containing precious information regarding the configuration of
+	  the ZigBee network (like channel, panId, extendedPanID, security, etc...)
+	- 'zigbee:///dev/com9?dongle=ezsp' specify at which port your Telegesis dondle is installed
+	  and that you're using a Ember firmware (called EZSP: Ember ZigBee Serial Protocol)
+
+Note: Under linux the Teleesis dongle could be found using the path 'zigbee:///dev/ttyUSB0?dongle=ezsp'
+
+To run the GAL using the MicroSD type instead:
+./gal -c config.ini "zigbee:///dev/com8?dongle=microSD&speed=115200"
+
+
+------------------------------------------------------------------------
+How to compile and run the GAL under a Linux O.S. for ARM:
+------------------------------------------------------------------------
+
+Questo breve tutorial spiega i passi da seguire per migrare l'attuale versione del GAL mantenuta sul repository (e configurata per lavorare con Cygwin sotto windows) sotto un sistema operativo Linux.
+
+Steps:
+- fare il checkout del GAL dentro una nuova cartella (assicurandosi che il PC sia dentro GRIFFON):
+svn co http://atlantis.tilab.com/svn/gal/trunk
+
+- scaricare ed installare https://sourcery.mentor.com/sgpp/lite/arm/portal/subscription3057 il file arm-2011.03-41-arm-none-linux-gnueabi.bin qualora si intende fare una cross compilazione del GAL su macchine ARM. L'interfaccia grafica guiderà  l'installazione verso una cartella che servirà  per il punto successivo (il CROSS_PATH)
+
+- aggiornare il file Makefile.rules presente dentro la root. Le parti che ci interessano aggiornare sono i CROSS_PATH relativi a "gal_intel" (a) e "gal_freescale" (b):
+  a) export CROSS_PATH		= 	/usr/bin/
+  b) export CROSS_PATH		=	/[
] /CodeSourcery/Sourcery_G++_Lite/bin/arm-none-linux-gnueabi-
+
+- nel caso di una compilazione per arm, assicurarsi che il file in /linuxgal/Makefile.cross non abbia nella sezione config alcun parametro per "--with-debug-flags=". Questo per ottimizzare la dimensione del file di output generato
+
+- eseguire i seguenti comandi:
+  . setup.bash
+  gal_freescale (oppure gal_intel)
+  cd linuxgal
+  make -f Makefile.cross genmake
+  cd..
+  make all
+
+- Se non vi sono stati problemi, l'output del gal, oltre che in linuxgal, si troverà  su trunk/targets/freescale/fs/usr/ti/bin (questo è l'unico file da copiare sulla piattaforma arm)
+
+- Per l'esecuzione in locale del GAL, bisogna anche andare a indicare dove si trovano le librerie upnp, e per far questo vi sono due opzioni:
+  a) si usa il comando export LD_LIBRARY_PATH=[...]/trunk/targets/freescale/fs/usr/ti/lib  (usare il comando "pwd" per individuare il path esatto)
+  b) tutto il contenuto di [...]/trunk/targets/freescale/fs/usr/ti/lib  va copiato in /usr/lib
+
+- Infine, per poter eseguire il GAL il comando da inviare (abilitando valgrind) è il seguente (more info @ http://people.gnome.org/~newren/tutorials/developing-with-gnome/html/ch03s03.html )
+valgrind -v --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes --log-file=valgrindOutput.txt ./gal -c config.ini 'zigbee:///dev/ttyUSB0?dongle=freescale&speed=115200'
+
+Note:
+-	il file valgrindOutput.txt deve già esistere altrimenti non funziona
+-	per rendere i vari file di configurazione presenti nella root folder del gal (tipo "configureEnvironment") eseguibili tramite il comando
+chmod 777 "nomefile" (o comunque come si preferisce/conosce)
+
+Alcuni problemi noti: 
+- libupnp3 o curl non installate in precedenza sul S.O. – In tal caso procedere alla loro installazione usando anche il normale gestore di pacchetti messo a disposizione da Ubuntu o altri (per le libupnp3 ver. 1.6.6-3 assicurarsi che esista la cartella /usr/include/upnp, mentre per curl assicurarsi che esista un libcurl.so presente in /usr/lib, e se non c’è fare un link simbolico ad uno dei libcurl.so.X presenti). Hint: ln –s libcurl.so.4 libcurl.so
+- il ./configure potrebbe non trovare alcune librerie dunque sostituire questa stringa nel configure del linuxgal:
+./configure --enable-zigbee-pro --with-local-libs=.. --with-upnp-cflags=-I/usr/include/upnp --with-upnp-libs=/usr/lib --enable-debug --with-debug-flags=RB:SB:DA:MESSAGE:SA:RESTSERVER:XMLMSGCOMPOSER:GALZB:XMLMSGPARSER
+Di fatto questa stringa rispetto all’originale elimina la cartella “local” (opzionalmente aggiungere anche –with-curl-libs=/usr/lib, ma non è necessario )
+- Nel caso il make si blocchi sul file depcomp, prendere il file presente sulla root e sostituirlo a quello attualmente presente in linuxgal
+
+Per eseguire il gal lanciare:
+./gal -c config.ini 'zigbee:///dev/ttyUSB0?dongle=freescale'
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/setup.bash
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/setup.bash (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/setup.bash Fri Oct 19 18:37:43 2012
@@ -1,0 +1,44 @@
+export SOURCES_ROOT=`pwd` 
+
+# CVS repository settings for Access Gateway project
+alias gal='cd $SOURCES_ROOT'
+alias galfs='cd ${SOURCES_ROOT}/targets/$PROFILE/fs'
+alias galbin='cd ${SOURCES_ROOT}/targets/$PROFILE/fs/usr/ti/bin'
+alias galti='cd ${SOURCES_ROOT}/software/telecomitalia'
+
+alias gal_intel='export TARGET_PLATFORM=linux; export PROFILE=intel; export EXTRA_PATH=usr/ti; echo "gal_intel" > ~/.lgvprc'
+alias gal_linux='export TARGET_PLATFORM=linux; export PROFILE=linux; export EXTRA_PATH=usr/ti; echo "gal_linux" > ~/.lgvprc'
+alias gal_sheeva='export TARGET_PLATFORM=sheeva; export PROFILE=sheeva; export EXTRA_PATH=usr/ti; echo "gal_sheeva" > ~/.lgvprc'
+alias gal_native='export TARGET_PLATFORM=linux; export PROFILE=em; export EXTRA_PATH=usr/ti;echo "gal_native" > ~/.lgvprc'
+alias gal_teldat='export TARGET_PLATFORM=teldat; export PROFILE=teldat; export EXTRA_PATH=usr/ti;echo "gal_teldat" > ~/.lgvprc'
+alias gal_freescale='export TARGET_PLATFORM=freescale; export PROFILE=freescale; export EXTRA_PATH=usr/ti;echo "gal_freescale" > ~/.lgvprc'
+alias gal_cygwin='export TARGET_PLATFORM=cygwin; export PROFILE=cygwin; export EXTRA_PATH=usr/ti;echo "gal_cygwin" > ~/.lgvprc'
+
+if [ -e  ~/.lgvprc ]; then
+	last_lgvp=$(cat ~/.lgvprc)
+	case $last_lgvp in
+		gal_intel)
+			gal_intel ;;
+
+		gal_linux)
+			gal_linux ;;
+
+		gal_sheeva)
+			gal_sheeva ;;
+
+		gal_cygwin)
+			gal_cygwin ;;
+
+		gal_teldat)
+			gal_teldat ;;
+
+		gal_freescale)
+			gal_frescale ;;
+		*)
+			echo default is gal_sheeva 
+			gal_sheeva ;;
+	esac
+else
+    gal_arm
+fi
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/setup.csh
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/setup.csh (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/setup.csh Fri Oct 19 18:37:43 2012
@@ -1,0 +1,41 @@
+setenv GAL_ROOT `pwd` 
+
+# CVS repository settings for Access Gateway project
+alias cvs_vdt 'setenv CVSROOT :pserver:forge.cselt.it:/vdt'
+alias gal 'cd $VDT_ROOT'
+alias galfs 'cd ${VDT_ROOT}/targets/$PROFILE/fs'
+alias galti 'cd ${VDT_ROOT}/software/telecomitalia'
+
+alias gal_intel 'setenv TARGET_PLATFORM linux; setenv PROFILE lgvptiem; setenv EXTRA_PATH usr/ti; setenv PYTHONPATH; echo "vdt_intel" > ~/.lgvprc'
+alias gal_arm 'setenv TARGET_PLATFORM lgvp; setenv PROFILE lgvpti; setenv EXTRA_PATH usr/ti;setenv PYTHONPATH $VDT_ROOT/targets/$PROFILE/fs/$EXTRA_PATH/lib/python; echo "vdt_arm" > ~/.lgvprc'
+
+alias vdt_arm1 'setenv TARGET_PLATFORM lgvp; setenv PROFILE lgvpti_wh; setenv EXTRA_PATH usr/ti;setenv PYTHONPATH $VDT_ROOT/targets/$PROFILE/fs/$EXTRA_PATH/lib/python; echo "vdt_arm1" > ~/.lgvprc'
+
+alias vdt_none 'setenv TARGET_PLATFORM linux; setenv PROFILE em; setenv EXTRA_PATH usr/ti;unsetenv PYTHONPATH:$VDT_ROOT/targets/$PROFILE/fs/$EXTRA_PATH/lgvp:$VDT_ROOT/targets/$PROFILE/fs/usr/local/lgvp; echo "vdt_intel" > ~/.lgvprc'
+
+alias vdt_ag_pirelli 'setenv TARGET_PLATFORM linux; setenv PROFILE ag; setenv EXTRA_PATH usr/ti;unsetenv PYTHONPATH:$VDT_ROOT/targets/$PROFILE/fs/$EXTRA_PATH/lgvp:$VDT_ROOT/targets/$PROFILE/fs/usr/local/lgvp; echo "vdt_ag_pirelli" > ~/.lgvprc'
+
+if ( -e  ~/.lgvprc ) then
+    set last_lgvp=`cat ~/.lgvprc`
+
+    switch ($last_lgvp)
+    case gal_intel:
+        gal_intel
+		breaksw
+
+    case gal_intel1:
+        gal_intel
+		breaksw
+
+    case gal_arm:
+        gal_arm
+		breaksw
+
+   	default: 
+        gal_arm
+		breaksw
+	endsw
+else
+    gal_arm
+endif
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/shttpd/Makefile.cross
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/shttpd/Makefile.cross (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/shttpd/Makefile.cross Fri Oct 19 18:37:43 2012
@@ -1,0 +1,48 @@
+include ../Makefile.rules
+
+INCPATH = -I$(PREFIX_TMP)/include
+LIBPATH = -L$(DEVPATH)/lib
+
+LIBS    = $(LIBPATH)
+
+SRC_DIR	= 	src
+INC_DIR	= 	include
+
+CFLAGS += $(INCPATH)
+
+export LIBS
+export CFLAGS
+
+TARGETS = $(SRC_DIR)/shttpd$(LIB) $(SRC_DIR)/shttpd.a
+
+all:
+	$(MAKE) -C src unix
+
+install: 
+	mkdir -p $(PREFIX_TMP)/sbin
+	mkdir -p $(PREFIX_TMP)/include
+	mkdir -p $(PREFIX_TMP)/lib
+	mkdir -p $(PREFIX)/usr/$(EXTRA)/lib
+	#install $(SRC_DIR)/shttpd$(EXE) $(PREFIX_TMP)/sbin
+	#install -m 644 $(SRC_DIR)/libshttpd.a $(PREFIX_TMP)/lib
+	#install -m 644 $(SRC_DIR)/libshttpd.so.1.0.1 $(PREFIX_TMP)/lib
+	install -m 644 $(SRC_DIR)/libshttpd.a $(PREFIX_TMP)/lib
+	#install -m 644 $(PREFIX_TMP)/lib/libshttpd.so.1.0.1 $(PREFIX)/usr/$(EXTRA)/lib
+	#ln -sfn libshttpd.so.1.0.1 $(PREFIX)/usr/$(EXTRA)/lib/libshttpd.so
+	#ln -sfn libshttpd.so.1.0.1 $(PREFIX)/usr/$(EXTRA)/lib/libshttpd.so.1
+	install -m 644 $(SRC_DIR)/shttpd.h $(PREFIX_TMP)/include/shttpd.h
+	#$(STRIP) $(PREFIX)/usr/$(EXTRA)/lib/libshttpd.so.1.0.1
+	#$(STRIP) $(PREFIX_TMP)/sbin/shttpd$(EXE)
+
+uninstall: 
+	rm -f $(PREFIX_TMP)/lib/libshttpd.a
+	rm -f $(PREFIX_TMP)/lib/libshttpd.so.1.0.1
+	rm -f $(PREFIX_TMP)/sbin/shttpd
+	rm -f $(PREFIX_TMP)/include/shttpd.h
+
+clean:
+	$(MAKE) -C $(SRC_DIR) $@
+	rm -f *~
+
+distclean: clean
+	

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/tinyxml/Makefile.cross
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/tinyxml/Makefile.cross (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/tinyxml/Makefile.cross Fri Oct 19 18:37:43 2012
@@ -1,0 +1,38 @@
+include ../Makefile.rules
+
+CXXFLAGS += -DTIXML_USE_STL 
+
+SRC_DIR = src
+INCLUDE_DIR = include
+
+#SRC = tinystr.cpp  tinyxml.cpp  tinyxmlerror.cpp  tinyxmlparser.cpp
+
+#TARGETS = $(SRC_DIR)libtinyxml.a
+
+all:
+	$(MAKE) -C src
+
+libtinyxml.a: $(SRC)/tinystr.o  tinyxml.o  tinyxmlerror.o  tinyxmlparser.o 
+	@echo AR $@
+	@$(AR) r $@ $?
+
+clean:
+	$(MAKE) -C src clean
+	rm -f *~
+
+distclean: clean
+	
+config:
+	echo Nothing to config
+
+install:
+	mkdir -p $(PREFIX_TMP)/lib
+	install -m 644 $(INCLUDE_DIR)/tinyxml.h $(PREFIX_TMP)/include
+	install -m 644 $(INCLUDE_DIR)/tinystr.h $(PREFIX_TMP)/include
+	install -m 644 $(SRC_DIR)/libtinyxml.a $(PREFIX_TMP)/lib
+
+uninstall:
+	rm -f $(PREFIX_TMP)/lib/libtinyxml.a
+	rm -f $(PREFIX_TMP)/include/tinyxml.h
+	rm -f $(PREFIX_TMP)/include/tinystr.h
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/Makefile
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/Makefile (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/Makefile Fri Oct 19 18:37:43 2012
@@ -1,0 +1,181 @@
+
+export BUILD_FOR_INET=y
+export BUILD_FOR_SERIAL=y
+
+# to enable Integration-specific ZigBee API
+export BUILD_FOR_INTEGRATION=
+
+# to enable build of the various stubs separately
+export BUILD_INTEGRATION_STUB=
+export BUILD_ZSDIO_STUB=
+
+export BUILD_EZSP=
+export BUILD_FREESCALE=y
+export BUILD_MICRO_SD=
+export BUILD_ZSDIO=
+
+# to chose to be compatible with ZigBee 2006, otherwise Zigbee 2004
+export BUILD_ZIGBEE_2006=y
+
+# set to 'y' if you use glib events instead of threads
+export BUILD_FOR_GLIB=
+
+# Put 'y' if you compile under cygwin
+export BUILD_CYGWIN=
+
+INCLUDE_DIR = include
+
+#export INCLUDE_ZIGBEE_SECURITY
+
+# If EMBER_STACK_PROFILE is not already defined, set EMBER_STACK_PROFILE = 2 (default value)
+export EMBER_STACK_PROFILE?=2
+
+export CFLAGS	+= \
+				-I../$(INCLUDE_DIR) \
+				-I$(PREFIX_TMP)/include \
+				-I/opt/dev/iwmmxt/include \
+				-I$(DEVPATH)/include/glib-2.0 \
+				-I$(DEVPATH)/lib/glib-2.0/include
+
+export CXXFLAGS	+= \
+				-I../$(INCLUDE_DIR) \
+				-I$(PREFIX_TMP)/include \
+				-I/opt/dev/iwmmxt/include \
+				-I$(DEVPATH)/include/glib-2.0 \
+				-I$(DEVPATH)/lib/glib-2.0/include
+
+
+export LDFLAGS	= \
+				-L/opt/dev/iwmmxt/lib \
+				-L$(PREFIX)/usr/$(EXTRA)/lib \
+				-L$(PREFIX)/usr/local/lib
+
+export VERSION=1.2
+
+#Decide here if enable or not the debug options
+export CFLAGS +=  -c -g #-DDEBUG -DDEBUG_ZIGBEE_API -DDEBUG_HDLC_DL
+export CXXFLAGS += -c -g #-DDEBUG -DDEBUG_ZIGBEE_API -DDEBUG_HDLC_D
+#export CFLAGS +=  -c -g -DDEBUG -DDEBUG_ZIGBEE_API -DDEBUG_HDLC_DL
+#export CXXFLAGS += -c -g -DDEBUG -DDEBUG_ZIGBEE_API -DDEBUG_HDLC_DL
+
+# To enable patch on Ember IEEE Address Request -> in fact, the relevant response does not include the list of child routers; only child ZED are taken into account
+# If enabled, this issues is avoided on the ZigBee node connected to the GAL.
+export CFLAGS += -D IEEE_ADDR_REQUEST_PATCH
+# To enable ZigBee APS fragmentation --> Add "-D ZIGBEE_APS_FRAG_ENABLED"
+# To enable filtering of local broadcast loopback messages --> Add "-D FILTER_LOCALBROADCAST_LOOPBACK_MSGS"
+export CFLAGS += -D ZIGBEE_APS_FRAG_ENABLED -D FILTER_LOCALBROADCAST_LOOPBACK_MSGS -DIEEE_ADDR_REQUEST_PATCH
+
+
+ifeq ($(strip $(BUILD_ZIGBEE_2006)),y)
+CFLAGS += -DZIGBEE_2006
+endif
+
+ifeq ($(strip $(BUILD_CYGWIN)),y)
+export EXE = .exe
+endif
+
+ifeq ($(strip $(BUILD_FOR_GLIB)),y)
+CFLAGS += -DINCLUDE_GLIB
+export LIBS += -lglib-2.0
+endif
+
+ifeq ($(strip $(BUILD_INTEGRATION)),y)
+export BUILD_INTEGRATION=y
+endif
+
+ifeq ($(strip $(BUILD_ZSDIO)),y)
+export BUILD_ZSDIO=y
+endif
+
+ifeq ($(strip $(BUILD_EZSP)),y)
+export BUILD_EZSP=y
+endif
+
+ifeq ($(strip $(BUILD_FREESCALE)),y)
+export BUILD_FREESCALE=y
+endif
+
+ifeq ($(strip $(BUILD_MICRO_SD)),y)
+export BUILD_MICRO_SD=y
+endif
+
+SUBDIRS	= src #examples
+INSTALL_TARGETS = 
+
+ifeq ($(strip $(BUILD_FOR_INET)),y)
+export BUILD_FOR_INET
+endif
+
+ifeq ($(strip $(BUILD_FOR_SERIAL)),y)
+export BUILD_FOR_SERIAL
+endif
+
+all:
+	@list='$(SUBDIRS)'; \
+	for subdir in $$list; do \
+		(cd $$subdir && $(MAKE) $@) \
+	done
+	@echo "*** ZIGBEE STACK PROFILE $(EMBER_STACK_PROFILE) ... Compiled ***"
+	
+
+clean:
+	@list='$(SUBDIRS)'; \
+	for subdir in $$list; do \
+		(cd $$subdir && $(MAKE) $@) \
+	done
+	rm -rf *~ include/*~
+
+distclean: clean
+
+config:
+	echo "Not necessary"
+
+install: $(INSTALL_TARGETS)
+	mkdir -p $(PREFIX_TMP)/lib
+	mkdir -p $(PREFIX_TMP)/include
+	install -m 644 src/libzigbee.a  $(PREFIX_TMP)/lib
+	install -m 644 src/libzigbee.so $(PREFIX_TMP)/lib
+	install -m 644 include/zigbee.h  $(PREFIX_TMP)/include
+	install -m 644 include/zigbee_ser.h  $(PREFIX_TMP)/include
+	install -m 644 include/winport.h  $(PREFIX_TMP)/include
+	install -m 644 include/zigbee_utils.h  $(PREFIX_TMP)/include
+
+install_zsdio_stub:
+	mkdir -p $(PREFIX)/usr/$(EXTRA)/bin
+	install stubs/zsdio/zsdio $(PREFIX)/usr/$(EXTRA)/bin
+
+install_integration_stub:
+	mkdir -p $(PREFIX)/usr/$(EXTRA)/bin
+	install stubs/integration/integration $(PREFIX)/usr/$(EXTRA)/bin
+
+
+uninstall:
+	rm -rf $(PREFIX)/usr/$(EXTRA)/lib/modules/drivers/sdio
+	rm -f $(PREFIX)/usr/$(EXTRA)/etc/sdiodriver
+	rm -f $(PREFIX)/usr/$(EXTRA)/bin/zsdio
+	rm -f $(PREFIX)/usr/$(EXTRA)/bin/integration
+
+docs:
+	mkdir -p doc && cd doc && doxygen doxy.conf
+
+showdoc:
+	$(BROWSER) doc/html/index.html
+
+distrib: clean
+	cd ..;tar zcvf zsdio-$(VERSION)-`date +%d-%b-%Y`.tar.gz `find zigbee -type f | grep -v CVS | grep -v tags | grep -v drivers`
+
+distrib_boella: all
+	cd ..;tar zcvf zigbee-bin-$(VERSION)-`date +%d-%b-%Y`.tar.gz \
+		zigbee/include/zigbee.h \
+		zigbee/include/zigbee_ser.h \
+		zigbee/include/zigbee_log.h \
+		zigbee/include/zb_conn.h \
+		zigbee/include/zigbee_utils.h \
+		zigbee/include/winport.h \
+		zigbee/src/libzigbee.a \
+		zigbee/RELEASE_NOTES \
+		zigbee/README
+
+tags:
+	ctags-exuberant --recurse .
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/Makefile.cross
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/Makefile.cross (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/Makefile.cross Fri Oct 19 18:37:43 2012
@@ -1,0 +1,166 @@
+include ../Makefile.rules
+
+#export BUILD_EZSP=Y
+export BUILD_FREESCALE=y
+
+# to chose to be compatible with ZigBee 2006, otherwise Zigbee 2004
+export BUILD_ZIGBEE_2006=y
+
+# set to 'y' if you use glib events instead of threads
+export BUILD_FOR_GLIB=
+
+# Put 'y' if you compile under cygwin
+export BUILD_CYGWIN=
+
+#export EMBER_STACK_PROFILE=1
+export EMBER_STACK_PROFILE=2
+
+# If EMBER_STACK_PROFILE is not already defined, set EMBER_STACK_PROFILE = 2 (default value)
+export EMBER_STACK_PROFILE?=2
+
+INCLUDE_DIR = include
+
+export CFLAGS	+= \
+				-I../$(INCLUDE_DIR) \
+				-I$(PREFIX_TMP)/include
+
+export CXXFLAGS	+= \
+				-I../$(INCLUDE_DIR) \
+				-I$(PREFIX_TMP)/include
+
+
+export LDFLAGS	= \
+				-L/opt/dev/iwmmxt/lib \
+				-L$(PREFIX)/usr/$(EXTRA)/lib \
+				-L$(PREFIX)/usr/local/lib
+
+export VERSION=1.2
+
+export CFLAGS += -c -fPIC -DDEBUG_ZIGBEE_API  -DDEBUG_HDLC_DL -DDEBUG_ZIGBEE
+export CXXFLAGS += -c -fPIC -DDEBUG_ZIGBEE_API  -DDEBUG_HDLC_DL -DDEBUG_ZIGBEE
+#export CFLAGS += -c -fPIC   -DDEBUG_HDLC_DL	#-DDEBUG_ZIGBEE_API
+#export CXXFLAGS += -c -fPIC -DDEBUG_HDLC_DL	#-DDEBUG_ZIGBEE_API
+
+# To enable patch on Ember IEEE Address Request -> in fact, the relevant 
+# response does not include the list of child routers; only child ZED 
+# are taken into account.
+# If enabled, this issues is avoided on the ZigBee node connected to the GAL.
+export CFLAGS += -D IEEE_ADDR_REQUEST_PATCH
+# To enable ZigBee APS fragmentation --> Add "-D ZIGBEE_APS_FRAG_ENABLED"
+# To enable filtering of local broadcast loopback messages --> Add "-D FILTER_LOCALBROADCAST_LOOPBACK_MSGS"
+export CFLAGS += -D ZIGBEE_APS_FRAG_ENABLED -D FILTER_LOCALBROADCAST_LOOPBACK_MSGS -DIEEE_ADDR_REQUEST_PATCH
+
+ifeq ($(strip $(BUILD_ZIGBEE_2006)),y)
+CFLAGS += -DZIGBEE_2006
+endif
+
+ifeq ($(strip $(BUILD_CYGWIN)),y)
+export EXE = .exe
+endif
+
+ifeq ($(strip $(BUILD_INTEGRATION)),y)
+export BUILD_INTEGRATION=y
+endif
+
+ifeq ($(strip $(BUILD_ZSDIO)),y)
+export BUILD_ZSDIO=y
+endif
+
+ifeq ($(strip $(BUILD_EZSP)),y)
+export BUILD_EZSP=y
+CFLAGS += -I$(PREFIX_TMP)/include/upnp
+CXXFLAGS += -I$(PREFIX_TMP)/include/upnp
+endif
+
+BUILD_FREESCALE=y
+BUILD_EZSP=y
+
+ifeq ($(strip $(BUILD_FREESCALE)),y)
+export BUILD_FREESCALE=y
+endif
+
+SUBDIRS	= src examples
+INSTALL_TARGETS = 
+
+ifeq ($(strip $(BUILD_FOR_INET)),y)
+export BUILD_FOR_INET
+endif
+
+ifeq ($(strip $(BUILD_FOR_SERIAL)),y)
+export BUILD_FOR_SERIAL
+endif
+
+all:
+	@list='$(SUBDIRS)'; \
+	for subdir in $$list; do \
+		(cd $$subdir && $(MAKE) $@) \
+	done
+
+clean:
+	@list='$(SUBDIRS)'; \
+	for subdir in $$list; do \
+		(cd $$subdir && $(MAKE) $@) \
+	done
+	rm -rf *~ include/*~
+
+distclean: clean
+
+config:
+	echo "Not necessary"
+
+install: $(INSTALL_TARGETS)
+	mkdir -p $(PREFIX)/usr/$(EXTRA)/lib/modules/drivers/sdio
+	mkdir -p $(PREFIX)/usr/$(EXTRA)/etc
+	mkdir -p $(PREFIX_TMP)/lib
+	mkdir -p $(PREFIX_TMP)/include
+	install -m 644 src/libzigbee.a  $(PREFIX_TMP)/lib
+	install -m 644 include/zigbee.h  $(PREFIX_TMP)/include
+	install -m 644 include/zigbee_ser.h  $(PREFIX_TMP)/include
+	install -m 644 include/winport.h  $(PREFIX_TMP)/include
+	install -m 644 include/zigbee_utils.h  $(PREFIX_TMP)/include
+
+install_drivers:
+	install -m 644 drivers/sdio/pxahcd.o  $(PREFIX)/usr/$(EXTRA)/lib/modules/drivers/sdio
+	install -m 644 drivers/sdio/sdbt.o  $(PREFIX)/usr/$(EXTRA)/lib/modules/drivers/sdio
+	install -m 644 drivers/sdio/sdcore.o  $(PREFIX)/usr/$(EXTRA)/lib/modules/drivers/sdio
+	install -m 644 drivers/sdio/sdmmc.o  $(PREFIX)/usr/$(EXTRA)/lib/modules/drivers/sdio
+	install -m 644 drivers/sdio/sduart.o  $(PREFIX)/usr/$(EXTRA)/lib/modules/drivers/sdio
+	install scripts/sdiodriver  $(PREFIX)/usr/$(EXTRA)/etc/
+
+install_zsdio_stub:
+	mkdir -p $(PREFIX)/usr/$(EXTRA)/bin
+	install stubs/zsdio/zsdio $(PREFIX)/usr/$(EXTRA)/bin
+
+install_integration_stub:
+	mkdir -p $(PREFIX)/usr/$(EXTRA)/bin
+	install stubs/integration/integration $(PREFIX)/usr/$(EXTRA)/bin
+
+uninstall:
+	rm -rf $(PREFIX)/usr/$(EXTRA)/lib/modules/drivers/sdio
+	rm -f $(PREFIX)/usr/$(EXTRA)/etc/sdiodriver
+	rm -f $(PREFIX)/usr/$(EXTRA)/bin/zsdio
+	rm -f $(PREFIX)/usr/$(EXTRA)/bin/integration
+
+docs:
+	mkdir -p doc && cd doc && doxygen doxy.conf
+
+showdoc:
+	$(BROWSER) doc/html/index.html
+
+distrib: clean
+	cd ..;tar zcvf zigbee-$(VERSION)-`date +%d-%b-%Y`.tar.gz `find zigbee -type f | grep -v CVS | grep -v tags | grep -v drivers`
+	cd ..;tar zcvf EZSP-$(VERSION)-`date +%d-%b-%Y`.tar.gz `find EZSP -type f | grep -v CVS | grep -v tags | grep -v drivers`
+
+distrib_boella: all
+	cd ..;tar zcvf zigbee-bin-$(VERSION)-`date +%d-%b-%Y`.tar.gz \
+		zsdio/include/zigbee.h \
+		zsdio/include/zigbee_ser.h \
+		zsdio/include/zigbee_utils.h \
+		zsdio/include/winport.h \
+		zsdio/src/libhdlc.a \
+		zsdio/src/libzigbee.a \
+		zsdio/RELEASE_NOTES
+
+tags:
+	ctags-exuberant --recurse .
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/README
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/README (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/README Fri Oct 19 18:37:43 2012
@@ -1,0 +1,28 @@
+This directory contains the ZigBee API abstraction layer (ZAL) implementation.
+This layer permits to any 'user' to interact with ZigBee stacks coming 
+from different versions using a common API.
+
+The ZAL will support:
+
+- ZigBee Dongle implementing the EZSP protocol on USB or Serial Port
+- ZigBee Integration Dongle on USB (Windowns machines)
+- ZigBee Integration Dongle on Serial Port (Linux machines)
+- ZSDIO Dongle on Linux
+
+
+Supported URI:
+
+zigbee://<hostname>:30000?dongle=zsdio
+zigbee://<device>?dongle=zsdio
+zigbee://<device>?dongle=ezsp+speed=115600
+zigbee://<device>?dongle=ezsp
+
+Where device is the device where the dongle is plugged on:
+
+/dev/ttyS0 
+/dev/ttyUSB0 
+...
+
+
+
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/doc/doxy.conf
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/doc/doxy.conf (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/doc/doxy.conf Fri Oct 19 18:37:43 2012
@@ -1,0 +1,1098 @@
+# Doxyfile 1.3.5
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = "ZigBee interface"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = 
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = doc
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, 
+# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en 
+# (Japanese with English messages), Korean, Norwegian, Polish, Portuguese, 
+# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# This tag can be used to specify the encoding used in the generated output. 
+# The encoding is not always determined by the language that is chosen, 
+# but also whether or not the output is meant for Windows or non-Windows users. 
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES 
+# forces the Windows encoding (this is the default for the Windows binary), 
+# whereas setting the tag to NO uses a Unix-style encoding (the default for 
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING   = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is used 
+# as the annotated text. Otherwise, the brief description is used as-is. If left 
+# blank, the following values are used ("$name" is automatically replaced with the 
+# name of the entity): "The $name class" "The $name widget" "The $name file" 
+# "is" "provides" "specifies" "contains" "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = 
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited 
+# members of a class in the documentation of that class as if those members were 
+# ordinary class members. Constructors, destructors and assignment operators of 
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. It is allowed to use relative paths in the argument list.
+
+STRIP_FROM_PATH        = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like the Qt-style comments (thus requiring an 
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member 
+# documentation.
+
+DETAILS_AT_TOP         = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 4 
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources 
+# only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources 
+# only. Doxygen will then generate output that is more tailored for Java. 
+# For instance, namespaces will be presented as packages, qualified scopes 
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = YES
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = NO
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  =
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp 
+# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc
+
+FILE_PATTERNS          = 
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories 
+# that are symbolic links (a Unix filesystem feature) are excluded from the input.
+
+EXCLUDE_SYMLINKS       = YES 
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories.
+
+EXCLUDE_PATTERNS       = */CVS/*
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = 
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.
+
+INPUT_FILTER           = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = YES 
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default) 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = YES
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .6
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = NO
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse the 
+# parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or 
+# super classes. Setting the tag to NO turns the diagrams off. Note that this 
+# option is superseded by the HAVE_DOT option below. This is only a fallback. It is 
+# recommended to install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
+# generate a call dependency graph for every global function or class method. 
+# Note that enabling this option will significantly increase the time of a run. 
+# So in most cases it will be better to enable call graphs for selected 
+# functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_WIDTH    = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT   = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes that 
+# lay further from the root node will be omitted. Note that setting this option to 
+# 1 or 2 may greatly reduce the computation time needed for large code bases. Also 
+# note that a graph may be further truncated if the graph's image dimensions are 
+# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). 
+# If 0 is used for the depth value (the default), the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/examples/Makefile
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/examples/Makefile (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/examples/Makefile Fri Oct 19 18:37:43 2012
@@ -1,0 +1,61 @@
+INCLUDE_DIR	= ../include/
+
+TARGETS 	= zbpcapsniffer$(EXE) zperf$(EXE) #moon$(EXE) lightswitch$(EXE) zperf$(EXE) #test_zsdio_1$(EXE) #temp_sensor_zb$(EXE) test_cpp_proxy$(EXE)
+CFLAGS		+= -Os -DDEVICE_SWITCH -DDEVICE_DISPLAY
+LDFLAGS		+= -L../src -lzigbee -L$(PREFIX_TMP)/lib $(LIBS) -lthreadutil
+
+ 
+all: $(TARGETS) 
+
+lightswitch.o: lightswitch.c 
+	$(CC) $(CFLAGS) $< 
+
+moon.o: moon.c 
+	$(CC) $(CFLAGS) $< 
+
+lightswitch$(EXE): lightswitch.o ../src/libzigbee.a
+	$(CC) -g -o $@ $^ $(LDFLAGS) -lpthread -lstdc++
+
+#moon$(EXE): moon.o ../src/libzigbee.a
+#	$(CC) -g -o $@ $^ $(LDFLAGS) -lpthread -lstdc++
+
+zperf.o: zperf.c 
+	$(CC) $(CFLAGS) $< 
+
+zbpcapsniffer.o: zbpcapsniffer.c 
+	$(CC) $(CFLAGS) $< 
+
+zbpcapsniffer$(EXE): zbpcapsniffer.o
+	$(CC) -g -o $@ $^ $(LDFLAGS) -lpthread -lstdc++
+
+zbpcap.o: zbpcap.c 
+	$(CC) $(CFLAGS) $< 
+
+libzbpcap.a: zbpcap.o
+	@echo AR $@ $?
+	@$(AR) r $@ $?
+	cp $@ /mnt/experiments/winpcap/wpcap/libpcap/rpcapd
+
+zperf$(EXE): zperf.o ../src/libzigbee.a
+	$(CC) -g -o $@ $^ $(LDFLAGS) -lpthread -lstdc++
+
+test_zsdio_1.o: test_zsdio_1.c
+	$(CC) $(CFLAGS) $< 
+
+test_zsdio_1$(EXE): test_zsdio_1.o ../src/libzigbee.a
+	$(CC) -g -o $@ $^ $(LDFLAGS) -lpthread -lstdc++
+
+temp_sensor_zb.o: temp_sensor_zb.c
+	$(CC) $(CFLAGS) $< 
+
+temp_sensor_zb$(EXE): temp_sensor_zb.o ../src/libzigbee.a
+	$(CC) -g -o $@ $^ $(LDFLAGS) -lpthread -lstdc++
+
+#test_cpp_proxy.o: test_cpp_proxy.cpp
+#	$(CXX) $(CFLAGS) $< 
+
+test_cpp_proxy$(EXE): test_cpp_proxy.o ../src/libzigbee.a
+	$(CC) -g -o $@ $^ $(LDFLAGS) -lpthread -lstdc++
+
+clean:
+	rm -rf *~ $(TARGETS) *.o *.so *.exe 

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/examples/lightswitch.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/examples/lightswitch.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/examples/lightswitch.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,708 @@
+/**
+ * Operation proceed in the following way:
+ *
+ * 1. Set PAN ID to the requested value
+ * 2. Configure the local node as a Coordinator or a Router
+ *    by calling the following primitives:
+ * 	  	ZIB_CONFIG_NODE_DESCRIPTOR
+ * 	  	ZIB_CONFIG_NWK_MODE_AND_PARAMS
+ * 	  	ZIB_CONFIG_SIMPLE_DESCRIPTOR
+ *
+ * 3.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <pthread.h>
+#include <string.h>
+#include <signal.h>
+
+#include "zigbee.h"
+
+#define zb_print_error printf
+
+/* Information base definitions: from Integration!!! */
+
+#define ZIB_STK_VERSION_STRING                  0xEF
+#define ZIB_CONFIG_NODE_DESCRIPTOR              0xF0
+#define ZIB_CONFIG_POWER_DESCRIPTOR             0xF1
+#define ZIB_CONFIG_SIMPLE_DESCRIPTOR            0xF2
+#define ZIB_CONFIG_NWK_MODE_AND_PARAMS          0xF3
+#define ZIB_CONFIG_NWK_SCAN_ATTEMPTS            0xF4
+#define ZIB_CONFIG_NWK_TIME_BTWN_SCANS          0xF5
+#define ZIB_CONFIG_COMPLEX_DESCRIPTOR           0xF6
+#define ZIB_CONFIG_USER_DESCRIPTOR              0xF7
+#define ZIB_CONFIG_MAX_BIND                     0xF8
+#define ZIB_CONFIG_MASTER_KEY                   0xF9
+#define ZIB_CONFIG_ENDDEV_BIND_TIMEOUT          0xFA
+#define ZIB_CONFIG_PERMIT_JOIN_DURATION         0xFB
+#define ZIB_CONFIG_NWK_SECURITY_LEVEL           0xFC
+#define ZIB_CONFIG_NWK_SECURE_ALL_FRAMES        0xFD
+#define ZIB_CONFIG_PANID                        0xFF
+
+#define PIB_IEEE_ADDRESS                        0x6F
+#define NIB_MAXCHILDREN                         0x84
+#define NIB_MAXROUTERS                          0x86
+#define NIB_MAXDEPTH                            0x85
+#define NIB_POLLINTERVAL						0x9C
+
+void *test_thread(void *arg);
+int test_zb(void);
+
+void my_Bind(void);
+void my_GetSimpleDescriptor(void);
+void my_DoSwitch(void);
+int set_switch_status(int set_on);
+
+uchar DevType = 0; // Coordinator
+static int switch_status = 0; /* off */
+
+pthread_mutex_t test_mutex;
+
+int step;
+uchar g_status;
+ushort g_nwk_addr = 0x0001;
+ushort g_profile_id = 0xC021;
+ushort g_device_id = 0x0001;
+uchar g_active_ep_count = 0x00;
+uchar g_active_ep = 0x00;
+ushort g_panid = 0x1AAA;
+
+ZB_SIMPLE_DESC g_simple_desc;
+ZB_NODE_DESC g_node_desc; /* node descriptor to be configured on the local node */
+
+void handler(int signo);
+void terminate(void);
+
+void handler(int signo) {
+	terminate();
+}
+
+void my_ZDO_NWK_ADDR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		uchar *ieee_addr, ushort nwk_addr, uchar num_assoc_dev,
+		uchar start_index, ushort *nwk_addr_assoc_dev_list);
+
+void my_ZDO_IEEE_ADDR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		uchar *ieee_addr, ushort nwk_addr, uchar num_assoc_dev,
+		uchar start_index, ushort *nwk_addr_assoc_dev_list);
+
+void my_ZDO_NODE_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, ZB_NODE_DESC *node_desc);
+
+void my_ZDO_POWER_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, ZB_POWER_DESC *power_desc);
+
+void my_ZDO_SIMPLE_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, ZB_SIMPLE_DESC *simple_desc);
+
+void my_ZDO_ACTIVE_EP_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, uchar active_ep_count, uchar *active_ep_list);
+
+void my_ZDO_MATCH_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, uchar match_len, uchar *match_list);
+
+void my_ZDO_MATCH_DESC_indication(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		ushort profile_id, uchar nicl, ushort *icllist, uchar nocl,
+		ushort *ocllist);
+
+void my_APSME_SET_confirm(ZBIF_HANDLE zbif_handle, uchar status, uchar attr);
+
+void my_ZDO_RESET_confirm(ZBIF_HANDLE zbif_handle, uchar status);
+
+void my_ZDO_START_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr);
+
+void my_APSME_GET_confirm(ZBIF_HANDLE zbif_handle, uchar status, uchar attr,
+		uchar attr_len, uchar *attr_value);
+
+void my_APSDE_DATA_confirm(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, uchar src_ep, uchar status);
+
+void my_APSDE_DATA_indication(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, uchar src_addr_mode, uchar *src_addr,
+		uchar src_ep, ushort profile_id, ushort cluster_id, uchar asdu_len,
+		uchar *asdu, uchar was_broadcast, uchar sec_status);
+
+void my_ZDO_DEVICE_ANNCE_indication(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar *ieee_addr, uchar capability);
+
+void my_ZDO_END_DEVICE_BIND_confirm(ZBIF_HANDLE zbif_handle, uchar status);
+
+void my_ZDO_ERROR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort cluster_id, uchar expected_len);
+
+static ZBIFCbs_t cbs = { .ZDO_RESET_confirm = my_ZDO_RESET_confirm,
+		.ZDO_START_confirm = my_ZDO_START_confirm, .ZDO_NWK_ADDR_confirm =
+				my_ZDO_NWK_ADDR_confirm, .ZDO_IEEE_ADDR_confirm =
+				my_ZDO_IEEE_ADDR_confirm, .ZDO_NODE_DESC_confirm =
+				my_ZDO_NODE_DESC_confirm, .ZDO_SIMPLE_DESC_confirm =
+				my_ZDO_SIMPLE_DESC_confirm, .ZDO_POWER_DESC_confirm =
+				my_ZDO_POWER_DESC_confirm, .ZDO_ACTIVE_EP_DESC_confirm =
+				my_ZDO_ACTIVE_EP_DESC_confirm, .ZDO_MATCH_DESC_confirm =
+				my_ZDO_MATCH_DESC_confirm, .ZDO_END_DEVICE_BIND_confirm =
+				my_ZDO_END_DEVICE_BIND_confirm, .ZDO_DEVICE_ANNCE_indication =
+				my_ZDO_DEVICE_ANNCE_indication, .APSME_SET_confirm =
+				my_APSME_SET_confirm, .APSME_GET_confirm = my_APSME_GET_confirm,
+		.APSDE_DATA_confirm = my_APSDE_DATA_confirm, .APSDE_DATA_indication =
+				my_APSDE_DATA_indication, .ZDO_ERROR_confirm =
+				my_ZDO_ERROR_confirm };
+
+ushort profile_id = 0x0104;
+#if defined(DEVICE_SWITCH)
+ushort device_id = 0x0001;
+#elif defined (DEVICE_LIGHT)
+ushort device_id = 0x0002;
+#else
+#error define DEVICE_SWITCH or DEVICE_LIGHT
+#endif
+
+static ZBIF_HANDLE zbif_handle = NULL;
+struct sigaction act, oact;
+
+int main(int argc, char *argv[]) {
+	int res;
+
+	ZB_Init_SIMPLE_DESC(&g_simple_desc);
+	ZB_Init_NODE_DESC(&g_node_desc);
+
+	g_node_desc.logical_type = ZB_COORDINATOR;
+	g_node_desc.complx_desc_avail = 0;
+	g_node_desc.user_desc_avail = 0;
+	g_node_desc.reserved = 0;
+	g_node_desc.aps_flags = 0;
+	g_node_desc.freq_band = 0;
+	g_node_desc.mac_cap = 0;
+	g_node_desc.manifact_code = 0;
+	g_node_desc.max_buf_size = 0x7A;
+	g_node_desc.max_transf_size = 0;
+
+#ifdef ZIGBEE_2006
+	g_node_desc.server_mask = 0;
+#endif
+
+	uchar *p = (uchar *) &g_node_desc;
+	int i;
+
+	sigemptyset(&act.sa_mask);
+	act.sa_handler = handler; /* pointer to action */
+	act.sa_flags = 0;
+
+	res = sigaction(SIGINT, &act, &oact);
+	if (res < 0) {
+		zb_print_error("ERROR: returned by sigaction\n");
+		return -1;
+	}
+
+	if (argc < 2) {
+		zb_print_error("Usage:\n\t%s <uri>\n", argv[0]);
+		exit(1);
+	}
+
+	zbif_handle = ZBIFConnect(argv[1], &cbs, NULL);
+	if (zbif_handle == NULL) {
+		zb_print_error("ERROR: connecting to the ZigBee device\n");
+		exit(1);
+	}
+
+	step = 1; /* ZSDIO */
+
+	pthread_mutex_init(&test_mutex, NULL);
+
+	while (1) {
+		pthread_mutex_lock(&test_mutex);
+		res = test_zb();
+		if (!res) {
+			break;
+		}
+	}
+
+	printf("FINITO!!!!\n");
+
+	while (1) {
+		sleep(1);
+	}
+
+	terminate();
+	exit(0);
+}
+
+void terminate(void) {
+	if (zbif_handle != NULL) {
+		ZBIFDisconnect(zbif_handle);
+	}
+	exit(0);
+}
+
+void my_ZDO_RESET_confirm(ZBIF_HANDLE zbif_handle, uchar status) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_APSME_GET_confirm(ZBIF_HANDLE zbif_handle, uchar status, uchar attr,
+		uchar attr_len, uchar *attr_value) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_NWK_ADDR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		uchar *ieee_addr, ushort nwk_addr, uchar num_assoc_dev,
+		uchar start_index, ushort *nwk_addr_assoc_dev_list) {
+	g_nwk_addr = nwk_addr;
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_IEEE_ADDR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		uchar *ieee_addr, ushort nwk_addr, uchar num_assoc_dev,
+		uchar start_index, ushort *nwk_addr_assoc_dev_list) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_NODE_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, ZB_NODE_DESC *node_desc) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_POWER_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, ZB_POWER_DESC *power_desc) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_SIMPLE_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, ZB_SIMPLE_DESC *simple_desc) {
+	g_profile_id = simple_desc->app_profile_id;
+	ZB_Copy_SIMPLE_DESC(&g_simple_desc, simple_desc);
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_ACTIVE_EP_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, uchar active_ep_count, uchar *active_ep_list) {
+	if (active_ep_count > 0) {
+		g_active_ep = active_ep_list[0];
+	}
+	g_active_ep_count = active_ep_count;
+
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_MATCH_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, uchar match_len, uchar *match_list) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_MATCH_DESC_indication(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		ushort profile_id, uchar nicl, ushort *icllist, uchar nocl,
+		ushort *ocllist) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_APSDE_DATA_indication(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, uchar src_addr_mode, uchar *src_addr,
+		uchar src_ep, ushort profile_id, ushort cluster_id, uchar asdu_len,
+		uchar *asdu, uchar was_broadcast, uchar sec_status) {
+	printf("my_APSDE_DATA_indication\n");
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_DEVICE_ANNCE_indication(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar *ieee_addr, uchar child_type) {
+	//ZDO_NWK_ADDR_request (zbif_handle, ieee_addr, ZDO_REQ_TYPE_SD_RES , 0);
+
+	//ZDO_ACTIVE_EP_DESC_request (zbif_handle, nwk_addr, nwk_addr);
+	ZDO_SIMPLE_DESC_request(zbif_handle, nwk_addr, nwk_addr, 0x01);
+}
+
+void my_APSME_SET_confirm(ZBIF_HANDLE zbif_handle, uchar status, uchar attr) {
+	if (status != ZB_ZDO_SUCCESS) {
+		zb_print_error("ERROR: set attribute 0x%02X\n", attr);
+	}
+
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_START_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr) {
+	if (status == ZB_ZDO_SUCCESS) {
+		printf("Device Started\n");
+		if (DevType == 2) {
+			// ZDO_NLME_SYNC_request(zbif_handle, 1 ); // Sync & Track
+		}
+
+	} else if (status == ZB_NWK_STARTUP_FAILURE) {
+		zb_print_error("ERROR: network startup failure!\n");
+		exit(1);
+	} else {
+		zb_print_error("ERROR: %d returned while starting network\n", status);
+	}
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_ERROR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort cluster_id, uchar expected_len) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_GetSimpleDescriptor(void) {
+}
+
+void my_Bind(void) {
+
+	/* ZSDIO ieee addr */
+	uchar src_ieee_addr[IEEE_ADDR_LEN] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+			0x06, 0x07 };
+	//uchar src_ieee_addr[IEEE_ADDR_LEN] = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00};
+
+#ifdef DEVICE_LIGHT
+	ushort cl1[1] = {1}; /* Input Cluster List */
+#endif
+	ushort ocl[2] = { 0x0000, 0x0001 }; /* Output Cluster List */
+	ushort icl[1] = { 0x0000 }; /* Input Cluster List */
+
+	printf("Starting bind in 20 secs\n");
+
+	sleep(10);
+
+	printf("Bind in progress ...\n");
+	/* send the bind request! */
+#ifdef DEVICE_SWITCH
+	ZDO_END_DEVICE_BIND_request (
+			zbif_handle,
+			0x0000, // LocalCoordinator
+			src_ieee_addr,
+			g_active_ep,// DEP
+			profile_id,
+#if 1 
+			1, // NumInClusters
+			icl,// InClusterList
+			2,// NumOutClusters
+			ocl// cluster
+#else
+			g_simple_desc.app_out_cluster_count,
+			g_simple_desc.app_out_cluster_list,
+			g_simple_desc.app_in_cluster_count,
+			g_simple_desc.app_in_cluster_list
+#endif
+	);
+#else
+	ZDO_END_DEVICE_BIND_request(zbif_handle, 0x0000, // LocalCoordinator
+			src_ieee_addr, g_active_ep, // DEP
+			profile_id, 0, // NumInClusters
+			NULL, // InClusterList
+			1, // NumOutClusters
+			cl1 // OutClusterList
+			);
+#endif
+}
+
+void my_ZDO_END_DEVICE_BIND_confirm(ZBIF_HANDLE zbif_handle, uchar status) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+int set_switch_status(int set_on) {
+
+	static uchar tsn = 0;
+
+	/* to turn on/off the switch */
+	uchar switch_cmd[7];
+
+	switch_cmd[0] = 0x21; // MSG transaction
+	switch_cmd[1] = tsn++; // TSN
+	switch_cmd[2] = 4; // length following
+	switch_cmd[3] = 1; // frame control
+	switch_cmd[4] = 0; // 'Move to level' command
+	switch_cmd[5] = 0; // up/down/stop/fade
+
+	if (set_on) {
+		/* so Switch it on */
+		switch_cmd[6] = 1; /* level */
+		printf("Sending light-on command\n");
+	} else {
+		/* so switch it off */
+		switch_cmd[6] = 0; /* level */
+		printf("Sending light-off command\n");
+	}
+
+	ushort cluster_id = 0x0001;
+
+	/* send the actual command */
+	APSDE_DATA_request(zbif_handle, ZB_AM_INDIRECT, /* dst_addr_mode 	*/
+	NULL, /* dst_addr			*/
+	0, /* dst_ep			*/
+	profile_id, cluster_id, 1, /* src_ep 			*/
+	sizeof(switch_cmd), /* asdu_len 		*/
+	switch_cmd, /* asdu				*/
+	0, /* tx_options		*/
+	0 /* radius			*/
+	);
+
+	/* returns the new switch status */
+	return set_on;
+}
+
+int send_data(int set_on) {
+
+	static uchar tsn = 0;
+
+	/* to turn on/off the switch */
+	uchar switch_cmd[7];
+
+	switch_cmd[0] = 0x21; // MSG transaction
+	switch_cmd[1] = tsn++; // TSN
+	switch_cmd[2] = 4; // length following
+	switch_cmd[3] = 1; // frame control
+	switch_cmd[4] = 0; // 'Move to level' command
+	switch_cmd[5] = 0; // up/down/stop/fade
+
+	if (set_on) {
+		/* so Switch it on */
+		switch_cmd[6] = 1; /* level */
+		printf("Sending light-on command\n");
+	} else {
+		/* so switch it off */
+		switch_cmd[6] = 0; /* level */
+		printf("Sending light-off command\n");
+	}
+
+	ushort cluster_id = 0x0001;
+	ushort dst_addr = 0x0001;
+
+	/* send the actual command */
+	APSDE_DATA_request(zbif_handle, ZB_AM_DIRECT, /* dst_addr_mode 	*/
+	(uchar *) &dst_addr, /* dst_addr			*/
+	1, /* dst_ep			*/
+	profile_id, cluster_id, 1, /* src_ep 			*/
+	sizeof(switch_cmd), /* asdu_len 		*/
+	switch_cmd, /* asdu				*/
+	0, /* tx_options		*/
+	0 /* radius			*/
+	);
+
+	/* returns the new switch status */
+	return set_on;
+}
+
+void my_APSDE_DATA_confirm(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, uchar src_ep, uchar status) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+int test_zb(void) {
+	printf("Performing step %d\n", step);
+
+	//uchar ieee_addr[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* Integration's node: no case */
+	//uchar ieee_addr[8] = { 0x00, 0x12, 0x4B, 0x00, 0x00, 0x04, 0x07, 0xB8 };  /* Roberta's node */
+	//uchar ieee_addr[8] = { 0x00, 0x12, 0x4B, 0x00, 0x00, 0x04, 0x07, 0xB8 }; /* Contapassi */
+	uchar ieee_addr[8] = { 0x00, 0x0D, 0xEB, 0x00, 0x00, 0x00, 0x10, 0xEA }; /* Integration's node: with case */
+	//uchar ieee_addr[8] = { 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x08, 0x2E }; /* ZSDIO: Garino */
+	//uchar ieee_addr[8] = { 0x66, 0x00, 0x02, 0x00, 0x00, 0x4B, 0x12, 0x00 }; /* EB Board: Roberta */
+
+	switch (step) {
+
+	case 1:
+		ZDO_RESET_request(zbif_handle, 0);
+		step++;
+		break;
+
+	case 2:
+		APSME_SET_request(zbif_handle, ZB_ATTR_CONFIG_NODE_DESCRIPTOR,
+				sizeof(g_node_desc), (uchar *) &g_node_desc);
+		step++;
+		break;
+
+	case 3: {
+		ushort panid = htozs(g_panid);
+		APSME_SET_request(zbif_handle, ZB_ATTR_CONFIG_PANID, 2,
+				(char *) &panid);
+#ifdef INTEGRATION
+		step++;
+#else
+		step = 8;
+#endif
+		break;
+	}
+
+#ifdef INTEGRATION
+
+		case 4: {
+			unsigned char nwk_mode_and_params[11];
+
+			int Channel = 11;
+
+			unsigned long ScanChannels = 1L << Channel;
+
+			nwk_mode_and_params[0] = (uchar) ScanChannels; // Scan Channels
+			nwk_mode_and_params[1] = (uchar) (ScanChannels >> 8);// Scan Channels
+			nwk_mode_and_params[2] = (uchar) (ScanChannels >> 16);// Scan Channels
+			nwk_mode_and_params[3] = (uchar) (ScanChannels >> 24);// Scan Channels
+			nwk_mode_and_params[4] = 5;// Scan Duration
+			nwk_mode_and_params[5] = 1;// Protocol Version
+			nwk_mode_and_params[6] = 1;// Stack Profile
+			nwk_mode_and_params[7] = 0x0F;// Beacon Order
+			nwk_mode_and_params[8] = 0x0F;// Superframe Order
+			nwk_mode_and_params[9] = 0;// Battery Life Extension
+			nwk_mode_and_params[10] = 0;// Security Level
+
+			printf("Setting the Mode Descriptor\n" );
+
+			APSME_SET_request(zbif_handle, ZIB_CONFIG_NWK_MODE_AND_PARAMS, sizeof(nwk_mode_and_params), nwk_mode_and_params);
+			step++;
+		}
+		break;
+
+		case 5: {
+			unsigned char buffer[20];
+
+			uchar *p = buffer;
+
+			/* 
+			 * configures EP #1
+			 */
+
+			*p++ = 1; // gives 1 for endpoint
+
+			*p++ = LSB_USHORT(profile_id);
+			*p++ = MSB_USHORT(profile_id);
+
+			*p++ = LSB_USHORT(device_id);
+			*p++ = MSB_USHORT(device_id);
+
+			*p++= 0;// version flags
+
+#ifdef DEVICE_SWITCH
+			*p++ = 0; /* switch input cluster count */
+			*p++ = 1; /* switch output cluster count */
+
+			PUT_USHORT(p, 1); /* cluster 1 is output */
+#else
+			*p++ = 2; /* light input cluster count */
+
+			PUT_USHORT(p, 0); /* cluster 0 is input */
+			PUT_USHORT(p, 1); /* cluster 1 is input */
+			*p++ = 1; /* light output cluster count */
+			PUT_USHORT(p, 0); /* cluster 0 is output */
+#endif
+
+			printf("Setting the Simple Descriptor\n" );
+
+			APSME_SET_request(zbif_handle, ZIB_CONFIG_SIMPLE_DESCRIPTOR, p - buffer, buffer);
+			step = 7;
+		}
+		break;
+#else
+	case 4:
+		step = 8;
+		break;
+#endif
+
+	case 7:
+		APSME_GET_request(zbif_handle, ZB_ATTR_CONFIG_NODE_DESCRIPTOR);
+		step++;
+		break;
+
+	case 8: {
+		uchar buf[4];
+		int i;
+		unsigned long channel_mask = 0x00000800;
+		channel_mask = htozl(channel_mask);
+
+		APSME_SET_request(zbif_handle, ZB_ATTR_CONFIG_CHANNEL_MASK, 4,
+				(uchar *) &channel_mask);
+		step = 11;
+		break;
+	}
+
+	case 9:
+		APSME_GET_request(zbif_handle, ZB_ATTR_CONFIG_PANID);
+		step++;
+		break;
+
+	case 10:
+		APSME_GET_request(zbif_handle, ZB_ATTR_CONFIG_CHANNEL_MASK);
+		step++;
+		break;
+
+	case 11:
+		ZDO_START_request(zbif_handle);
+		step = 22;
+		break;
+
+	case 12:
+		sleep(2);
+		ZDO_NWK_ADDR_request(zbif_handle, ieee_addr, ZDO_REQ_TYPE_SD_RES, 0);
+		step++;
+		break;
+
+	case 13:
+		ZDO_IEEE_ADDR_request(zbif_handle, g_nwk_addr, ZDO_REQ_TYPE_SD_RES, 0);
+		step++;
+		break;
+
+	case 14:
+		ZDO_NWK_ADDR_request(zbif_handle, ieee_addr, ZDO_REQ_TYPE_EX_RES, 0);
+		step++;
+		break;
+
+	case 15:
+		ZDO_IEEE_ADDR_request(zbif_handle, g_nwk_addr, ZDO_REQ_TYPE_EX_RES, 0);
+		step++;
+		break;
+
+	case 16:
+		ZDO_IEEE_ADDR_request(zbif_handle, g_nwk_addr, ZDO_REQ_TYPE_EX_RES, 0);
+		step = 22;
+		break;
+
+	case 17:
+		ZDO_NODE_DESC_request(zbif_handle, g_nwk_addr, g_nwk_addr);
+		step++;
+		break;
+
+	case 18:
+		ZDO_POWER_DESC_request(zbif_handle, g_nwk_addr, g_nwk_addr);
+		step++;
+		break;
+
+	case 19:
+		ZDO_ACTIVE_EP_DESC_request(zbif_handle, g_nwk_addr, g_nwk_addr);
+		step++;
+		break;
+
+	case 20:
+		if (g_active_ep_count > 0) {
+			ZDO_SIMPLE_DESC_request(zbif_handle, g_nwk_addr, g_nwk_addr,
+					g_active_ep);
+			step++;
+			break;
+		} else {
+			step++;
+		}
+
+	case 21: {
+		/* use clusters returned by a previously ZDO_SIMPLE_DESC_request */
+
+		ZDO_MATCH_DESC_request(zbif_handle, g_nwk_addr, g_nwk_addr,
+				g_profile_id, g_simple_desc.app_in_cluster_count,
+				g_simple_desc.app_in_cluster_list,
+				g_simple_desc.app_out_cluster_count,
+				g_simple_desc.app_out_cluster_list);
+		step = 22;
+	}
+
+	case 22:
+		my_Bind();
+		step++;
+		break;
+
+	case 23:
+		sleep(4);
+		switch_status = send_data(!switch_status);
+		step++;
+		break;
+
+	default:
+		printf("UNKNOWN: Test Step %d: exiting\n", step);
+		/* stop tests */
+		return 0;
+	}
+	return 1;
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/examples/moon.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/examples/moon.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/examples/moon.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,694 @@
+/**
+ * Operation proceed in the following way:
+ *
+ * 1. Set PAN ID to the requested value
+ * 2. Configure the local node as a Coordinator or a Router
+ *    by calling the following primitives:
+ * 	  	ZIB_CONFIG_NODE_DESCRIPTOR
+ * 	  	ZIB_CONFIG_NWK_MODE_AND_PARAMS
+ * 	  	ZIB_CONFIG_SIMPLE_DESCRIPTOR
+ *
+ * 3.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <pthread.h>
+#include <string.h>
+#include <signal.h>
+
+#include "zigbee.h"
+
+#define zb_print_error printf
+
+/* Information base definitions: from Integration!!! */
+
+#define ZIB_STK_VERSION_STRING                  0xEF
+#define ZIB_CONFIG_NODE_DESCRIPTOR              0xF0
+#define ZIB_CONFIG_POWER_DESCRIPTOR             0xF1
+#define ZIB_CONFIG_SIMPLE_DESCRIPTOR            0xF2
+#define ZIB_CONFIG_NWK_MODE_AND_PARAMS          0xF3
+#define ZIB_CONFIG_NWK_SCAN_ATTEMPTS            0xF4
+#define ZIB_CONFIG_NWK_TIME_BTWN_SCANS          0xF5
+#define ZIB_CONFIG_COMPLEX_DESCRIPTOR           0xF6
+#define ZIB_CONFIG_USER_DESCRIPTOR              0xF7
+#define ZIB_CONFIG_MAX_BIND                     0xF8
+#define ZIB_CONFIG_MASTER_KEY                   0xF9
+#define ZIB_CONFIG_ENDDEV_BIND_TIMEOUT          0xFA
+#define ZIB_CONFIG_PERMIT_JOIN_DURATION         0xFB
+#define ZIB_CONFIG_NWK_SECURITY_LEVEL           0xFC
+#define ZIB_CONFIG_NWK_SECURE_ALL_FRAMES        0xFD
+#define ZIB_CONFIG_PANID                        0xFF
+
+#define PIB_IEEE_ADDRESS                        0x6F
+#define NIB_MAXCHILDREN                         0x84
+#define NIB_MAXROUTERS                          0x86
+#define NIB_MAXDEPTH                            0x85
+#define NIB_POLLINTERVAL						0x9C
+
+void *test_thread(void *arg);
+int test_zb(void);
+
+void my_Bind(void);
+void my_GetSimpleDescriptor(void);
+void my_DoSwitch(void);
+int set_switch_status(int set_on);
+
+uchar DevType = 0; // Coordinator
+static int switch_status = 0; /* off */
+
+pthread_mutex_t test_mutex;
+
+int step;
+uchar g_status;
+ushort g_nwk_addr = 0x0001;
+ushort g_profile_id = 0xC021;
+ushort g_device_id = 0x0001;
+uchar g_active_ep_count = 0x00;
+uchar g_active_ep = 0x00;
+ushort g_panid = 0x1AAA;
+
+ZB_SIMPLE_DESC g_simple_desc;
+ZB_NODE_DESC g_node_desc; /* node descriptor to be configured on the local node */
+
+void handler(int signo);
+void terminate(void);
+
+void handler(int signo) {
+	terminate();
+}
+
+void my_ZDO_NWK_ADDR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		uchar *ieee_addr, ushort nwk_addr, uchar num_assoc_dev,
+		uchar start_index, ushort *nwk_addr_assoc_dev_list);
+
+void my_ZDO_IEEE_ADDR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		uchar *ieee_addr, ushort nwk_addr, uchar num_assoc_dev,
+		uchar start_index, ushort *nwk_addr_assoc_dev_list);
+
+void my_ZDO_NODE_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, ZB_NODE_DESC *node_desc);
+
+void my_ZDO_POWER_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, ZB_POWER_DESC *power_desc);
+
+void my_ZDO_SIMPLE_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, ZB_SIMPLE_DESC *simple_desc);
+
+void my_ZDO_ACTIVE_EP_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, uchar active_ep_count, uchar *active_ep_list);
+
+void my_ZDO_MATCH_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, uchar match_len, uchar *match_list);
+
+void my_ZDO_MATCH_DESC_indication(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		ushort profile_id, uchar nicl, ushort *icllist, uchar nocl,
+		ushort *ocllist);
+
+void my_APSME_SET_confirm(ZBIF_HANDLE zbif_handle, uchar status, uchar attr);
+
+void my_ZDO_RESET_confirm(ZBIF_HANDLE zbif_handle, uchar status);
+
+void my_ZDO_START_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr);
+
+void my_APSME_GET_confirm(ZBIF_HANDLE zbif_handle, uchar status, uchar attr,
+		uchar attr_len, uchar *attr_value);
+
+void my_APSDE_DATA_confirm(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, uchar src_ep, uchar status);
+
+void my_APSDE_DATA_indication(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, uchar src_addr_mode, uchar *src_addr,
+		uchar src_ep, ushort profile_id, ushort cluster_id, uchar asdu_len,
+		uchar *asdu, uchar was_broadcast, uchar sec_status);
+
+void my_ZDO_DEVICE_ANNCE_indication(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar *ieee_addr, uchar capability);
+
+void my_ZDO_END_DEVICE_BIND_confirm(ZBIF_HANDLE zbif_handle, uchar status);
+
+void my_ZDO_ERROR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort cluster_id, uchar expected_len);
+
+static ZBIFCbs_t cbs = { .ZDO_RESET_confirm = my_ZDO_RESET_confirm,
+		.ZDO_START_confirm = my_ZDO_START_confirm, .ZDO_NWK_ADDR_confirm =
+				my_ZDO_NWK_ADDR_confirm, .ZDO_IEEE_ADDR_confirm =
+				my_ZDO_IEEE_ADDR_confirm, .ZDO_NODE_DESC_confirm =
+				my_ZDO_NODE_DESC_confirm, .ZDO_SIMPLE_DESC_confirm =
+				my_ZDO_SIMPLE_DESC_confirm, .ZDO_POWER_DESC_confirm =
+				my_ZDO_POWER_DESC_confirm, .ZDO_ACTIVE_EP_DESC_confirm =
+				my_ZDO_ACTIVE_EP_DESC_confirm, .ZDO_MATCH_DESC_confirm =
+				my_ZDO_MATCH_DESC_confirm, .ZDO_END_DEVICE_BIND_confirm =
+				my_ZDO_END_DEVICE_BIND_confirm, .ZDO_DEVICE_ANNCE_indication =
+				my_ZDO_DEVICE_ANNCE_indication, .APSME_SET_confirm =
+				my_APSME_SET_confirm, .APSME_GET_confirm = my_APSME_GET_confirm,
+		.APSDE_DATA_confirm = my_APSDE_DATA_confirm, .APSDE_DATA_indication =
+				my_APSDE_DATA_indication, .ZDO_ERROR_confirm =
+				my_ZDO_ERROR_confirm };
+
+ushort profile_id = 0x0104;
+#if defined(DEVICE_SWITCH)
+ushort device_id = 0x0001;
+#elif defined (DEVICE_LIGHT)
+ushort device_id = 0x0002;
+#else
+#error define DEVICE_SWITCH or DEVICE_LIGHT
+#endif
+
+static ZBIF_HANDLE zbif_handle = NULL;
+struct sigaction act, oact;
+
+int main(int argc, char *argv[]) {
+	int res;
+
+	ZB_Init_SIMPLE_DESC(&g_simple_desc);
+	ZB_Init_NODE_DESC(&g_node_desc);
+
+	g_node_desc.logical_type = ZB_COORDINATOR;
+	g_node_desc.complx_desc_avail = 0;
+	g_node_desc.user_desc_avail = 0;
+	g_node_desc.reserved = 0;
+	g_node_desc.aps_flags = 0;
+	g_node_desc.freq_band = 0;
+	g_node_desc.mac_cap = 0;
+	g_node_desc.manifact_code = 0;
+	g_node_desc.max_buf_size = 0x7A;
+	g_node_desc.max_transf_size = 0;
+
+#ifdef ZIGBEE_2006
+	g_node_desc.server_mask = 0;
+#endif
+
+	uchar *p = (uchar *) &g_node_desc;
+	int i;
+
+	sigemptyset(&act.sa_mask);
+	act.sa_handler = handler; /* pointer to action */
+	act.sa_flags = 0;
+
+	res = sigaction(SIGINT, &act, &oact);
+	if (res < 0) {
+		zb_print_error("ERROR: returned by sigaction\n");
+		return -1;
+	}
+
+	if (argc < 2) {
+		zb_print_error("Usage:\n\t%s <uri>\n", argv[0]);
+		exit(1);
+	}
+
+	zbif_handle = ZBIFConnect(argv[1], &cbs, NULL);
+	if (zbif_handle == NULL) {
+		zb_print_error("ERROR: connecting to the ZigBee device\n");
+		exit(1);
+	}
+
+	step = 1; /* ZSDIO */
+
+	pthread_mutex_init(&test_mutex, NULL);
+
+	while (1) {
+		pthread_mutex_lock(&test_mutex);
+		res = test_zb();
+		if (!res) {
+			break;
+		}
+	}
+
+	printf("FINITO!!!!\n");
+
+	while (1) {
+		sleep(1);
+	}
+
+	terminate();
+	exit(0);
+}
+
+void terminate(void) {
+	if (zbif_handle != NULL) {
+		ZBIFDisconnect(zbif_handle);
+	}
+	exit(0);
+}
+
+void my_ZDO_RESET_confirm(ZBIF_HANDLE zbif_handle, uchar status) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_APSME_GET_confirm(ZBIF_HANDLE zbif_handle, uchar status, uchar attr,
+		uchar attr_len, uchar *attr_value) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_NWK_ADDR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		uchar *ieee_addr, ushort nwk_addr, uchar num_assoc_dev,
+		uchar start_index, ushort *nwk_addr_assoc_dev_list) {
+	g_nwk_addr = nwk_addr;
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_IEEE_ADDR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		uchar *ieee_addr, ushort nwk_addr, uchar num_assoc_dev,
+		uchar start_index, ushort *nwk_addr_assoc_dev_list) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_NODE_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, ZB_NODE_DESC *node_desc) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_POWER_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, ZB_POWER_DESC *power_desc) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_SIMPLE_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, ZB_SIMPLE_DESC *simple_desc) {
+	g_profile_id = simple_desc->app_profile_id;
+	ZB_Copy_SIMPLE_DESC(&g_simple_desc, simple_desc);
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_ACTIVE_EP_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, uchar active_ep_count, uchar *active_ep_list) {
+	if (active_ep_count > 0) {
+		g_active_ep = active_ep_list[0];
+	}
+	g_active_ep_count = active_ep_count;
+
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_MATCH_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, uchar match_len, uchar *match_list) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_MATCH_DESC_indication(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		ushort profile_id, uchar nicl, ushort *icllist, uchar nocl,
+		ushort *ocllist) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_APSDE_DATA_indication(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, uchar src_addr_mode, uchar *src_addr,
+		uchar src_ep, ushort profile_id, ushort cluster_id, uchar asdu_len,
+		uchar *asdu, uchar was_broadcast, uchar sec_status) {
+	printf("my_APSDE_DATA_indication\n");
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_DEVICE_ANNCE_indication(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar *ieee_addr, uchar child_type) {
+	//ZDO_NWK_ADDR_request (zbif_handle, ieee_addr, ZDO_REQ_TYPE_SD_RES , 0);
+
+	//ZDO_ACTIVE_EP_DESC_request (zbif_handle, nwk_addr, nwk_addr);
+	//ZDO_SIMPLE_DESC_request (zbif_handle, nwk_addr, nwk_addr, 0x01);
+	/* stores the ieee_address */
+}
+
+void my_APSME_SET_confirm(ZBIF_HANDLE zbif_handle, uchar status, uchar attr) {
+	if (status != ZB_ZDO_SUCCESS) {
+		zb_print_error("ERROR: set attribute 0x%02X\n", attr);
+	}
+
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_START_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr) {
+	if (status == ZB_ZDO_SUCCESS) {
+		printf("Device Started\n");
+		if (DevType == 2) {
+			// ZDO_NLME_SYNC_request(zbif_handle, 1 ); // Sync & Track
+		}
+
+	} else if (status == ZB_NWK_STARTUP_FAILURE) {
+		zb_print_error("ERROR: network startup failure!\n");
+		exit(1);
+	} else {
+		zb_print_error("ERROR: %d returned while starting network\n", status);
+	}
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_ERROR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort cluster_id, uchar expected_len) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_GetSimpleDescriptor(void) {
+}
+
+extern unsigned char g_ieee_addr[IEEE_ADDR_LEN];
+
+void my_Bind(void) {
+
+	/* ZSDIO ieee addr */
+	uchar src_ieee_addr[IEEE_ADDR_LEN] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+			0x06, 0x07 };
+	//uchar src_ieee_addr[IEEE_ADDR_LEN] = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00};
+	ushort ocl[2] = { 0x1200, 0x1201 }; /* Output Cluster List */
+	ushort icl[2] = { 0x1200, 0x1201 }; /* Input Cluster List */
+
+	profile_id = 0xC021;
+	g_active_ep = 0x01;
+
+	int delay = 10;
+
+	printf("Starting bind in %d secs\n", delay);
+
+	sleep(delay);
+
+	zb_print_bytes("IEEE addr ", g_ieee_addr, IEEE_ADDR_LEN);
+
+	printf("Bind in progress ...\n");
+	/* send the bind request! */
+
+	ZDO_END_DEVICE_BIND_request(zbif_handle, 0x0000, // LocalCoordinator
+			g_ieee_addr, g_active_ep, // DEP
+			profile_id, 2, // NumInClusters
+			icl, // InClusterList
+			2, // NumOutClusters
+			ocl // cluster
+			);
+}
+
+void my_ZDO_END_DEVICE_BIND_confirm(ZBIF_HANDLE zbif_handle, uchar status) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+int set_switch_status(int set_on) {
+
+	static uchar tsn = 0;
+
+	/* to turn on/off the switch */
+	uchar switch_cmd[7];
+
+	switch_cmd[0] = 0x21; // MSG transaction
+	switch_cmd[1] = tsn++; // TSN
+	switch_cmd[2] = 4; // length following
+	switch_cmd[3] = 1; // frame control
+	switch_cmd[4] = 0; // 'Move to level' command
+	switch_cmd[5] = 0; // up/down/stop/fade
+
+	if (set_on) {
+		/* so Switch it on */
+		switch_cmd[6] = 1; /* level */
+		printf("Sending light-on command\n");
+	} else {
+		/* so switch it off */
+		switch_cmd[6] = 0; /* level */
+		printf("Sending light-off command\n");
+	}
+
+	ushort cluster_id = 0x0001;
+
+	/* send the actual command */
+	APSDE_DATA_request(zbif_handle, ZB_AM_INDIRECT, /* dst_addr_mode 	*/
+	NULL, /* dst_addr			*/
+	0, /* dst_ep			*/
+	profile_id, cluster_id, 1, /* src_ep 			*/
+	sizeof(switch_cmd), /* asdu_len 		*/
+	switch_cmd, /* asdu				*/
+	0, /* tx_options		*/
+	0 /* radius			*/
+	);
+
+	/* returns the new switch status */
+	return set_on;
+}
+
+int send_data(int set_on) {
+
+	static uchar tsn = 0;
+
+	/* to turn on/off the switch */
+	uchar switch_cmd[7];
+
+	switch_cmd[0] = 0x21; // MSG transaction
+	switch_cmd[1] = tsn++; // TSN
+	switch_cmd[2] = 4; // length following
+	switch_cmd[3] = 1; // frame control
+	switch_cmd[4] = 0; // 'Move to level' command
+	switch_cmd[5] = 0; // up/down/stop/fade
+
+	if (set_on) {
+		/* so Switch it on */
+		switch_cmd[6] = 1; /* level */
+		printf("Sending light-on command\n");
+	} else {
+		/* so switch it off */
+		switch_cmd[6] = 0; /* level */
+		printf("Sending light-off command\n");
+	}
+
+	ushort cluster_id = 0x0001;
+	ushort dst_addr = 0x0001;
+
+	/* send the actual command */
+	APSDE_DATA_request(zbif_handle, ZB_AM_DIRECT, /* dst_addr_mode 	*/
+	(uchar *) &dst_addr, /* dst_addr			*/
+	1, /* dst_ep			*/
+	profile_id, cluster_id, 1, /* src_ep 			*/
+	sizeof(switch_cmd), /* asdu_len 		*/
+	switch_cmd, /* asdu				*/
+	0, /* tx_options		*/
+	0 /* radius			*/
+	);
+
+	/* returns the new switch status */
+	return set_on;
+}
+
+void my_APSDE_DATA_confirm(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, uchar src_ep, uchar status) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+int test_zb(void) {
+	printf("Performing step %d\n", step);
+
+	//uchar ieee_addr[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* Integration's node: no case */
+	//uchar ieee_addr[8] = { 0x00, 0x12, 0x4B, 0x00, 0x00, 0x04, 0x07, 0xB8 };  /* Roberta's node */
+	//uchar ieee_addr[8] = { 0x00, 0x12, 0x4B, 0x00, 0x00, 0x04, 0x07, 0xB8 }; /* Contapassi */
+	uchar ieee_addr[8] = { 0x00, 0x0D, 0xEB, 0x00, 0x00, 0x00, 0x10, 0xEA }; /* Integration's node: with case */
+	//uchar ieee_addr[8] = { 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x08, 0x2E }; /* ZSDIO: Garino */
+	//uchar ieee_addr[8] = { 0x66, 0x00, 0x02, 0x00, 0x00, 0x4B, 0x12, 0x00 }; /* EB Board: Roberta */
+
+	switch (step) {
+
+	case 1:
+		ZDO_RESET_request(zbif_handle, 0);
+		step++;
+		break;
+
+	case 2:
+		APSME_SET_request(zbif_handle, ZB_ATTR_CONFIG_NODE_DESCRIPTOR,
+				sizeof(g_node_desc), (uchar *) &g_node_desc);
+		step++;
+		break;
+
+	case 3: {
+		ushort panid = htozs(g_panid);
+		APSME_SET_request(zbif_handle, ZB_ATTR_CONFIG_PANID, 2,
+				(char *) &panid);
+#ifdef INTEGRATION
+		step++;
+#else
+		step = 8;
+#endif
+		break;
+	}
+
+#ifdef INTEGRATION
+
+		case 4: {
+			unsigned char nwk_mode_and_params[11];
+
+			int Channel = 11;
+
+			unsigned long ScanChannels = 1L << Channel;
+
+			nwk_mode_and_params[0] = (uchar) ScanChannels; // Scan Channels
+			nwk_mode_and_params[1] = (uchar) (ScanChannels >> 8);// Scan Channels
+			nwk_mode_and_params[2] = (uchar) (ScanChannels >> 16);// Scan Channels
+			nwk_mode_and_params[3] = (uchar) (ScanChannels >> 24);// Scan Channels
+			nwk_mode_and_params[4] = 5;// Scan Duration
+			nwk_mode_and_params[5] = 1;// Protocol Version
+			nwk_mode_and_params[6] = 1;// Stack Profile
+			nwk_mode_and_params[7] = 0x0F;// Beacon Order
+			nwk_mode_and_params[8] = 0x0F;// Superframe Order
+			nwk_mode_and_params[9] = 0;// Battery Life Extension
+			nwk_mode_and_params[10] = 0;// Security Level
+
+			printf("Setting the Mode Descriptor\n" );
+
+			APSME_SET_request(zbif_handle, ZIB_CONFIG_NWK_MODE_AND_PARAMS, sizeof(nwk_mode_and_params), nwk_mode_and_params);
+			step++;
+		}
+		break;
+
+		case 5: {
+			unsigned char buffer[20];
+
+			uchar *p = buffer;
+
+			/* 
+			 * configures EP #1
+			 */
+
+			*p++ = 1; // gives 1 for endpoint
+
+			*p++ = LSB_USHORT(profile_id);
+			*p++ = MSB_USHORT(profile_id);
+
+			*p++ = LSB_USHORT(device_id);
+			*p++ = MSB_USHORT(device_id);
+
+			*p++= 0;// version flags
+
+#ifdef DEVICE_SWITCH
+			*p++ = 0; /* switch input cluster count */
+			*p++ = 1; /* switch output cluster count */
+
+			PUT_USHORT(p, 1); /* cluster 1 is output */
+#else
+			*p++ = 2; /* light input cluster count */
+
+			PUT_USHORT(p, 0); /* cluster 0 is input */
+			PUT_USHORT(p, 1); /* cluster 1 is input */
+			*p++ = 1; /* light output cluster count */
+			PUT_USHORT(p, 0); /* cluster 0 is output */
+#endif
+
+			printf("Setting the Simple Descriptor\n" );
+
+			APSME_SET_request(zbif_handle, ZIB_CONFIG_SIMPLE_DESCRIPTOR, p - buffer, buffer);
+			step = 7;
+		}
+		break;
+#else
+	case 4:
+		step = 8;
+		break;
+#endif
+
+	case 7:
+		APSME_GET_request(zbif_handle, ZB_ATTR_CONFIG_NODE_DESCRIPTOR);
+		step++;
+		break;
+
+	case 8: {
+		uchar buf[4];
+		int i;
+		unsigned long channel_mask = 0x00004000;
+		channel_mask = htozl(channel_mask);
+
+		APSME_SET_request(zbif_handle, ZB_ATTR_CONFIG_CHANNEL_MASK, 4,
+				(uchar *) &channel_mask);
+		step = 11;
+		break;
+	}
+
+	case 9:
+		APSME_GET_request(zbif_handle, ZB_ATTR_CONFIG_PANID);
+		step++;
+		break;
+
+	case 10:
+		APSME_GET_request(zbif_handle, ZB_ATTR_CONFIG_CHANNEL_MASK);
+		step++;
+		break;
+
+	case 11:
+		ZDO_START_request(zbif_handle);
+		step = 22;
+		break;
+
+	case 12:
+		sleep(2);
+		ZDO_NWK_ADDR_request(zbif_handle, ieee_addr, ZDO_REQ_TYPE_SD_RES, 0);
+		step++;
+		break;
+
+	case 13:
+		ZDO_IEEE_ADDR_request(zbif_handle, g_nwk_addr, ZDO_REQ_TYPE_SD_RES, 0);
+		step++;
+		break;
+
+	case 14:
+		ZDO_NWK_ADDR_request(zbif_handle, ieee_addr, ZDO_REQ_TYPE_EX_RES, 0);
+		step++;
+		break;
+
+	case 15:
+		ZDO_IEEE_ADDR_request(zbif_handle, g_nwk_addr, ZDO_REQ_TYPE_EX_RES, 0);
+		step++;
+		break;
+
+	case 16:
+		ZDO_IEEE_ADDR_request(zbif_handle, g_nwk_addr, ZDO_REQ_TYPE_EX_RES, 0);
+		step = 22;
+		break;
+
+	case 17:
+		ZDO_NODE_DESC_request(zbif_handle, g_nwk_addr, g_nwk_addr);
+		step++;
+		break;
+
+	case 18:
+		ZDO_POWER_DESC_request(zbif_handle, g_nwk_addr, g_nwk_addr);
+		step++;
+		break;
+
+	case 19:
+		ZDO_ACTIVE_EP_DESC_request(zbif_handle, g_nwk_addr, g_nwk_addr);
+		step++;
+		break;
+
+	case 20:
+		if (g_active_ep_count > 0) {
+			ZDO_SIMPLE_DESC_request(zbif_handle, g_nwk_addr, g_nwk_addr,
+					g_active_ep);
+			step++;
+			break;
+		} else {
+			step++;
+		}
+
+	case 21: {
+		/* use clusters returned by a previously ZDO_SIMPLE_DESC_request */
+
+		ZDO_MATCH_DESC_request(zbif_handle, g_nwk_addr, g_nwk_addr,
+				g_profile_id, g_simple_desc.app_in_cluster_count,
+				g_simple_desc.app_in_cluster_list,
+				g_simple_desc.app_out_cluster_count,
+				g_simple_desc.app_out_cluster_list);
+		step = 22;
+	}
+
+	case 22:
+		my_Bind();
+		step++;
+		break;
+
+	case 23:
+		sleep(4);
+		switch_status = send_data(!switch_status);
+		step++;
+		break;
+
+	default:
+		printf("UNKNOWN: Test Step %d: exiting\n", step);
+		/* stop tests */
+		return 0;
+	}
+	return 1;
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/examples/zbpcapsniffer.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/examples/zbpcapsniffer.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/examples/zbpcapsniffer.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,473 @@
+#include <stdio.h>
+#include <signal.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include "winport.h"
+#endif
+
+#include <getopt.h>
+#include <string.h>
+#include <zigbee.h>
+#include <zb_conn.h>
+#include <zigbee_utils.h>
+#include <zigbee_log.h>
+
+#define PROGRAM_NAME	"zbpcapsniffer"
+
+static void ZBIFReceiveCb(void *handle, uchar *data, const int size);
+
+static const char cmdlineOptions[] = "sc:d:e:hvVl";
+
+void setSnifferMode(ZB_CONN_HANDLE zb_conn_h);
+void setRxOnWhenIdle(ZB_CONN_HANDLE zb_conn_h, unsigned char on);
+void setLogicalChannel(ZB_CONN_HANDLE zb_conn_h, unsigned char channel);
+void setMacPromiscuousMode(ZB_CONN_HANDLE zb_conn_h);
+void resetSnifferCPU(ZB_CONN_HANDLE zb_conn_h);
+
+int verbose = 0;
+char *device_uri = NULL;
+char *server_addr = NULL;
+int channel = 16;
+
+#define VERSION "1.0"
+
+int step;
+struct sigaction act, oact;
+int state = 0;
+ZB_CONN_HANDLE zb_conn_h = NULL;
+
+// PCAP constants
+const static int PCAP_MAGIC = 0xa1b2c3d4;
+const static short PCAP_VERSION_MAJOR = 2;
+const static short PCAP_VERSION_MINOR = 4;
+const static int PCAP_TZ = 0; // thiszone: GMT to local correction
+const static int PCAP_SIGFIGS = 0; // sigfigs: accuracy of timestamps
+const static int PCAP_SNAPLEN = 128; // snaplen: max len of packets, in octets
+const static int PCAP_LINKTYPE = 0xc3; // data link type DLT_IEEE802_15_4 (see <pcap/bpf.h>)
+
+static const char help[] = "Usage: " PROGRAM_NAME " [options...]\n"
+"Options:\n"
+"  -h                       Show this information\n"
+"  -l                       Logmode\n"
+"  -d <zigbee dongle uri>   Uri of the chosen Zigbee Dongle\n"
+"  -v                       Be verbose.\n"
+"  -V                       Show the program version and quit.\n"
+"\n";
+
+static void showHelp();
+static void showVersion();
+
+/* To close everything before terminating */
+
+void handler(int signo);
+void terminate(void);
+ZB_CONN_HANDLE connect_dongle(const char *uri);
+
+void handler(int signo) {
+	terminate();
+}
+
+int logmode = 0;
+
+int main(int argc, char *argv[]) {
+	int ret;
+	int c;
+
+	step = 1;
+
+	struct sigaction act;
+
+	sigemptyset(&act.sa_mask);
+	act.sa_handler = handler; /* pointer to action */
+	act.sa_flags = 0;
+
+	ret = sigaction(SIGINT, &act, NULL);
+	if (ret < 0) {
+		fprintf(stderr, "ERROR: returned by sigaction\n");
+		return -1;
+	}
+
+	ret = sigaction(SIGTERM, &act, NULL);
+	if (ret < 0) {
+		fprintf(stderr, "ERROR: returned by sigaction\n");
+		return -1;
+	}
+
+	opterr = 1;
+
+	while ((c = getopt(argc, argv, cmdlineOptions)) != -1) {
+
+		switch (c) {
+
+		case 'v':
+			verbose = 1;
+			break;
+
+		case 'h':
+			showHelp();
+			break;
+
+		case 'V':
+			showVersion();
+			break;
+
+		case 'l':
+			logmode = 1;
+			break;
+
+		case 'd':
+			device_uri = optarg;
+			break;
+
+		default:
+			showHelp();
+			break;
+		}
+	}
+
+	if (device_uri == NULL) {
+		showHelp();
+	}
+
+	void *pippo = NULL;
+	//const char *params[] = {"dongle=freescale", "speed=115200", "path=/dev/ttyUSB0"};
+	//device_uri = "zigbee:///dev/ttyUSB0?dongle=freescale&speed=115200&channel=16";
+
+	zb_conn_h = connect_dongle(device_uri);
+
+	//zb_conn_h = zb_conn_open(params, pippo, ZBIFReceiveCb);
+
+	if (zb_conn_h == NULL) {
+		printf("Unable to connect to dongle\n");
+		exit(3);
+	}
+
+	if (!logmode) {
+
+		// Write PCAP header
+		fwrite(&PCAP_MAGIC, sizeof(int), 1, stdout);
+		fwrite(&PCAP_VERSION_MAJOR, sizeof(short), 1, stdout);
+		fwrite(&PCAP_VERSION_MINOR, sizeof(short), 1, stdout);
+		fwrite(&PCAP_TZ, sizeof(int), 1, stdout); // thiszone: GMT to local correction
+		fwrite(&PCAP_SIGFIGS, sizeof(int), 1, stdout); // sigfigs: accuracy of timestamps
+		fwrite(&PCAP_SNAPLEN, sizeof(int), 1, stdout); // snaplen: max len of packets, in octets
+		fwrite(&PCAP_LINKTYPE, sizeof(int), 1, stdout); // data link type
+	} else {
+		printf("dongle connected\n");
+	}
+
+	state = 0;
+	resetSnifferCPU(zb_conn_h);
+
+	while (1) {
+		sleep(1);
+	}
+
+	terminate();
+	exit(0);
+}
+
+/*
+ * Promiscuous mode sniffer frame format
+ * Header        [2 bytes] = 86 03
+ * PayloadLength [1 byte ]
+ * LinkQuality   [1 byte ]
+ * TimeStamp     [4 bytes]
+ * msduLength    [1 byte ] 
+ * msdu          [n bytes]
+ */
+
+unsigned char out[255];
+
+void outputZbPacket(unsigned char *data, int size) {
+	int ts_usec = data[4] | data[5] << 8;
+	int ts_sec = data[6] | data[7] << 8;
+
+	//int i32Secs = timestamp / 100000;
+	//int i32MicroSecs = timestamp - i32Secs * 100000;
+
+	int packetLen = data[8];
+	int packetLenPlus2 = packetLen + 2;
+
+	if (!logmode) {
+		// Write PCAP packet header
+		fwrite(&ts_sec, sizeof(int), 1, stdout); // ts_sec: timestamp seconds
+		fwrite(&ts_usec, sizeof(int), 1, stdout); // ts_usec: timestamp microseconds
+		fwrite(&packetLen, sizeof(int), 1, stdout);
+		fwrite(&packetLenPlus2, sizeof(int), 1, stdout); // full frame included 2 FCS octets
+		fwrite(data + 9, 1, data[8], stdout);
+	} else {
+		printf("< ");
+		int i;
+		for (i = 0; i < size; i++) {
+			printf("%02x ", data[i]);
+		}
+		printf("\n");
+
+	}
+
+	fflush(stdout);
+}
+
+void ZBIFReceiveCb(void *handle, uchar *data, const int size) {
+	switch (state) {
+	case 0:
+		state++;
+		setSnifferMode(zb_conn_h);
+		break;
+
+	case 1:
+		state++;
+		setRxOnWhenIdle(zb_conn_h, 0);
+		break;
+
+	case 2:
+		state++;
+		setLogicalChannel(zb_conn_h, channel);
+		break;
+
+	case 3:
+		state++;
+		setMacPromiscuousMode(zb_conn_h);
+		break;
+
+	case 4:
+		state++;
+		setRxOnWhenIdle(zb_conn_h, 1);
+		break;
+
+	case 5:
+		// this is the response to setRxOnWhenIdle()
+		state++;
+		break;
+
+	default:
+		outputZbPacket(data, size);
+		break;
+	}
+}
+
+void terminate(void) {
+	if (zb_conn_h != NULL) {
+		printf("disconnecting\n");
+		zb_conn_close(zb_conn_h);
+	}
+	exit(0);
+}
+
+static void showHelp() {
+	printf("%s", help);
+	exit(0);
+}
+
+static void showVersion() {
+	printf("%s version %s\n", PROGRAM_NAME, VERSION);
+	printf(PROGRAM_NAME "\n");
+	exit(0);
+}
+
+void setSnifferMode(ZB_CONN_HANDLE zb_conn_h) {
+	unsigned char cmd[] = { 0xA3, 0x00, 0x0A, 0x01, 0x01, 0x01, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00 };
+	zb_conn_send(zb_conn_h, cmd, sizeof(cmd));
+}
+
+void setRxOnWhenIdle(ZB_CONN_HANDLE zb_conn_h, unsigned char on) {
+	unsigned char cmd[] = { 0x85, 0x09, 0x08, 0x52, on, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00 };
+	zb_conn_send(zb_conn_h, cmd, sizeof(cmd));
+}
+
+void setLogicalChannel(ZB_CONN_HANDLE zb_conn_h, unsigned char channel) {
+	unsigned char cmd[] = { 0x85, 0x09, 0x08, 0x21, channel, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00 };
+	zb_conn_send(zb_conn_h, cmd, sizeof(cmd));
+}
+
+void setMacPromiscuousMode(ZB_CONN_HANDLE zb_conn_h) {
+	unsigned char cmd[] = { 0x85, 0x09, 0x08, 0x51, 0x01, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00 };
+	zb_conn_send(zb_conn_h, cmd, sizeof(cmd));
+}
+
+void resetSnifferCPU(ZB_CONN_HANDLE zb_conn_h) {
+	unsigned char cmd[] = { 0xA3, 0x08, 0x00 };
+	zb_conn_send(zb_conn_h, cmd, sizeof(cmd));
+	sleep(1);
+}
+
+ZB_CONN_HANDLE connect_dongle(const char *uri) {
+	const char *p = uri;
+	const char *head, *tail, *t, *v;
+	const char *q;
+
+	q = strstr(p, "://");
+	if (q == NULL) {
+		return NULL;
+	}
+
+	tail = p + strlen(uri);
+
+	char *proto;
+
+	proto = (char *) malloc(q - p + 1);
+	memcpy(proto, p, q - p);
+	proto[q - p] = 0;
+
+	p = q + strlen("://");
+
+	t = strchr(p, '?');
+	if (t == NULL) {
+		return NULL;
+	}
+
+	if (strcmp(proto, "zigbee") != 0) {
+		free(proto);
+		return NULL;
+	}
+	free(proto);
+
+	head = p;
+
+	char *hostname = NULL;
+
+	/* stops if it gets a '/' or a ':' */
+	while (p < t) {
+		if ((*p == ':') || (*p == '/')) {
+			break;
+		}
+		p++;
+	}
+
+	v = head;
+
+	if (p > head) {
+		/* build hostname */
+		char *s = "hostname=";
+		hostname = (char *) malloc(p - head + strlen(s) + 1);
+		strcpy(hostname, s);
+		strncat(hostname, v, p - head);
+		hostname[p - head + strlen(s)] = 0;
+	}
+
+	char *port = NULL;
+
+	/* we stopped at : */
+	if (*p == ':') {
+		head = ++p;
+
+		v = head;
+
+		while (p < t) {
+			if (*p == '/') {
+				break;
+			}
+			p++;
+		}
+
+		if (p > v) {
+
+			/* build port */
+			char *s = "port=";
+			port = (char *) malloc(p - v + strlen(s) + 1);
+			strcpy(port, s);
+			strncat(port, v, p - v);
+			port[p - v + strlen(s)] = 0;
+		}
+	}
+	v = p;
+
+	char *path = NULL;
+	if (t > v) {
+		/* the rest is the path */
+		char *s_path = "path=";
+		path = (char *) malloc(t - v + strlen(s_path) + 1);
+		strcpy(path, s_path);
+		strncat(path, v, t - v);
+		path[t - v + strlen(s_path)] = 0;
+	}
+
+	/* extract parameters */
+	head = t + 1;
+
+	/* first pass, checks the num of parameters */
+	int count = 0;
+
+	/* alloc space for 10 params */
+	int params_size = 10;
+
+	char **params;
+
+	params = (char **) malloc(params_size * sizeof(char *));
+
+	if (hostname != NULL) {
+		params[count++] = hostname;
+	}
+
+	if (port != NULL) {
+		params[count++] = port;
+	}
+
+	if (path != NULL) {
+		params[count++] = path;
+	}
+
+	const char *next = t + 1;
+
+	while (next < tail) {
+		head = next;
+		p = strchr(head, '&');
+		if (p != NULL) {
+			next = p;
+		} else {
+			next = tail;
+		}
+
+		p = strchr(head, '=');
+		if (p == NULL) {
+			zb_print_error("ERROR: in param=value pairs\n");
+			return NULL;
+		}
+
+		/* realloc params if necessary */
+		if (count > params_size) {
+			params_size += 5;
+			params = (char **) realloc(params, params_size);
+		}
+
+		/* store the param,value into the array */
+		params[count] = (char *) malloc(next - head + 1);
+		memcpy(params[count], head, next - head);
+		params[count][next - head] = 0;
+
+		if ((next < tail) && (*next == '&')) {
+			next++;
+		}
+		count++;
+	}
+
+	params[count] = NULL;
+
+	const char *dongle = get_param(params, "dongle");
+	const char *channel_str = get_param(params, "channel");
+
+	if (dongle == NULL) {
+		zb_print_error("ERROR: no dongle specified\n");
+		return NULL;
+	}
+
+	if (channel_str != NULL) {
+		int ch = atoi(channel_str);
+		if ((ch < 11) || (ch > 26)) {
+			zb_print_error("ERROR: channel out of range\n");
+			return NULL;
+		}
+		channel = ch;
+	}
+
+	return zb_conn_open(params, NULL, ZBIFReceiveCb);
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/examples/zperf.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/examples/zperf.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/examples/zperf.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,483 @@
+#include <stdio.h>
+#include <signal.h>
+
+#ifndef WIN32
+#include <unistd.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include "winport.h"
+#endif
+
+#include <getopt.h>
+#include <string.h>
+#include <zigbee.h>
+#include <zigbee_utils.h>
+#include <zigbee_log.h>
+
+#define PROGRAM_NAME	"zperf"
+
+typedef struct {
+	unsigned int received; /** received packets */
+	unsigned int lost; /** packets lost */
+	unsigned int wrong_packets; /** badly formatted packets */
+	unsigned int tx_api_errors; /** transmission errors (API) */
+	unsigned int exp_seq_num; /** next packet expected sequence number */
+	unsigned int mode; /** server = 0x0002, client = 0x0001 */
+	unsigned char dst_mode; /** destination mode for sending packets, ZB_AM_DIRECT or ZB_AM_DIRECT_EX */
+	unsigned char dst_addr[8]; /** destination address, according dst_mode */
+} zperf_data_t;
+
+static const char cmdlineOptions[] = "sc:d:e:hvV";
+int send_packet(void);
+
+int verbose = 0;
+char *device_uri = NULL;
+char *server_addr = NULL;
+
+void my_ZDO_NWK_ADDR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		uchar *ieee_addr, ushort nwk_addr, uchar num_assoc_dev,
+		uchar start_index, ushort *nwk_addr_assoc_dev_list);
+
+void my_ZDO_IEEE_ADDR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		uchar *ieee_addr, ushort nwk_addr, uchar num_assoc_dev,
+		uchar start_index, ushort *nwk_addr_assoc_dev_list);
+
+void my_APSME_SET_confirm(ZBIF_HANDLE zbif_handle, uchar status, uchar attr);
+
+void my_ZDO_RESET_confirm(ZBIF_HANDLE zbif_handle, uchar status, uchar restart);
+
+void my_ZDO_START_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr);
+
+void my_APSME_GET_confirm(ZBIF_HANDLE zbif_handle, uchar status, uchar attr,
+		uchar attr_len, uchar *attr_value);
+
+void my_APSDE_DATA_confirm(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, uchar src_ep, uchar status);
+
+void my_APSDE_DATA_indication(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, uchar src_addr_mode, uchar *src_addr,
+		uchar src_ep, ushort profile_id, ushort cluster_id, ushort asdu_len,
+		uchar *asdu, uchar was_broadcast, uchar sec_status);
+
+void my_ZDO_END_DEVICE_BIND_confirm(ZBIF_HANDLE zbif_handle, uchar status);
+
+void my_ZDO_ERROR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort cluster_id, uchar expected_len);
+
+static ZBIFCbs_t cbs = { .ZDO_RESET_confirm = my_ZDO_RESET_confirm,
+		.ZDO_START_confirm = my_ZDO_START_confirm, .ZDO_NWK_ADDR_confirm =
+				my_ZDO_NWK_ADDR_confirm, .ZDO_IEEE_ADDR_confirm =
+				my_ZDO_IEEE_ADDR_confirm, .APSME_SET_confirm =
+				my_APSME_SET_confirm, .APSME_GET_confirm = my_APSME_GET_confirm,
+		.APSDE_DATA_confirm = my_APSDE_DATA_confirm, .APSDE_DATA_indication =
+				my_APSDE_DATA_indication, .ZDO_ERROR_confirm =
+				my_ZDO_ERROR_confirm };
+
+#define VERSION 1.0
+
+int step;
+uchar g_status;
+ushort g_nwk_addr = 0x0001;
+ushort g_profile_id = 0x0104;
+ushort g_device_id = 0x0001;
+uchar g_active_ep_count = 0x00;
+uchar g_active_ep = 0x00;
+ushort g_panid = 0xFFFF;
+
+static zperf_data_t zperf_data;
+
+ZB_SIMPLE_DESC g_simple_desc;
+ZB_NODE_DESC g_node_desc; /* node descriptor to be configured on the local node */
+
+static const char help[] = "Usage: " PROGRAM_NAME " [options...]\n"
+"Options:\n"
+"  -h                       Show this information\n"
+"  -d <zigbee dongle uri>   Uri of the chosen Zigbee Dongle\n"
+"  -s                       Server Mode\n"
+"  -c <dst_addr>            Client Mode (dst_addr may be short or ieee)\n"
+"  -e <endpoint>            Destination End Point\n"
+"  -v                       Be verbose.\n"
+"  -V                       Show the program version and quit.\n"
+"\n";
+
+pthread_mutex_t test_mutex;
+
+static void showHelp();
+static void showVersion();
+
+/* To close everything before terminating */
+void handler(int signo);
+void terminate(void);
+
+void handler(int signo) {
+	terminate();
+}
+
+static ZBIF_HANDLE zbif_handle = NULL;
+struct sigaction act, oact;
+
+int main(int argc, char *argv[]) {
+	int ret;
+	int c;
+
+	step = 1;
+
+	struct sigaction act;
+
+	sigemptyset(&act.sa_mask);
+	act.sa_handler = handler; /* pointer to action */
+	act.sa_flags = 0;
+
+	ret = sigaction(SIGINT, &act, NULL);
+	if (ret < 0) {
+		fprintf(stderr, "ERROR: returned by sigaction\n");
+		return -1;
+	}
+
+	ret = sigaction(SIGTERM, &act, NULL);
+	if (ret < 0) {
+		fprintf(stderr, "ERROR: returned by sigaction\n");
+		return -1;
+	}
+
+	memset((void *) &zperf_data, 0, sizeof(zperf_data));
+
+	zperf_data.exp_seq_num = 1;
+
+	opterr = 1;
+	while ((c = getopt(argc, argv, cmdlineOptions)) != -1) {
+
+		switch (c) {
+
+		case 'v':
+			verbose = 1;
+			break;
+
+		case 'h':
+			showHelp();
+			break;
+
+		case 'V':
+			showVersion();
+			break;
+
+		case 'c':
+			server_addr = optarg;
+			if (strlen(optarg) == 4) {
+				zperf_data.dst_mode = ZB_AM_DIRECT;
+				zperf_data.dst_addr[0] = 0x01;
+				zperf_data.dst_addr[1] = 0x00;
+			} else if (strlen(optarg) == 16) {
+				zperf_data.dst_mode = ZB_AM_DIRECT_EX;
+			} else {
+				showHelp();
+			}
+
+			zperf_data.mode |= 0x0001;
+			break;
+
+		case 'd':
+			device_uri = optarg;
+			break;
+
+		case 's':
+			zperf_data.mode |= 0x0002;
+			break;
+
+		default:
+			showHelp();
+		}
+	}
+
+	if (device_uri == NULL) {
+		showHelp();
+	}
+
+	zbif_handle = ZBIFConnect(device_uri, &cbs, NULL);
+	if (zbif_handle == NULL) {
+		zb_print_error("ERROR: connecting to the ZigBee device\n");
+		exit(1);
+	}
+
+	/* OK, connected */
+	int res;
+
+	pthread_mutex_init(&test_mutex, NULL);
+
+	while (1) {
+		pthread_mutex_lock(&test_mutex);
+		res = test_zb();
+		if (!res) {
+			break;
+		}
+	}
+
+	while (1) {
+		sleep(1);
+	}
+
+	terminate();
+	exit(0);
+}
+
+/* main loop */
+int test_zb(void) {
+#ifdef DDD
+	printf ("performing step %d\n", step);
+#endif
+
+	switch (step) {
+
+	case 1:
+		ZDO_RESET_request(zbif_handle, 0);
+		step++;
+		break;
+
+	case 2:
+		APSME_SET_request(zbif_handle, ZB_ATTR_CONFIG_NODE_DESCRIPTOR,
+				sizeof(g_node_desc), (uchar *) &g_node_desc);
+		step++;
+		break;
+
+	case 3: {
+		ushort panid = htozs(g_panid);
+		APSME_SET_request(zbif_handle, ZB_ATTR_CONFIG_PANID, 2,
+				(char *) &panid);
+		step++;
+		break;
+	}
+
+	case 4: {
+		int sec = 0;
+		APSME_SET_request(zbif_handle, ZB_ATTR_CONFIG_SECURITY, 1,
+				(uchar *) &sec);
+		step++;
+		break;
+	}
+
+	case 5: {
+		uchar buf[4];
+		int i;
+		unsigned long channel_mask = 0x00000800;
+		channel_mask = htozl(channel_mask);
+
+		APSME_SET_request(zbif_handle, ZB_ATTR_CONFIG_CHANNEL_MASK, 4,
+				(uchar *) &channel_mask);
+		step++;
+		break;
+	}
+
+	case 6:
+		ZDO_START_request(zbif_handle);
+		step++;
+		break;
+
+	case 7: {
+		if (zperf_data.mode & 0x0001) {
+			/* client mode enabled */
+			send_packet();
+		} else {
+			step++;
+		}
+		break;
+	}
+
+	default:
+		//printf("UNKNOWN: Test Step %d: exiting\n", step);
+		/* stop tests */
+		return 0;
+	}
+
+	return 1;
+}
+
+int send_packet(void) {
+	static unsigned long seq_number = 1;
+
+	/* to turn on/off the switch */
+	uchar packet[40];
+
+	memset(packet, 0, sizeof(packet));
+
+	ushort cluster_id = 0x0001;
+	ushort profile_id = 0xC044;
+	uchar dst_ep = 0x0001;
+	uchar src_ep = 0x0001;
+
+	unsigned long n = htozl(seq_number++);
+
+	memcpy(packet, &n, 4);
+
+	/* send the actual command */
+	APSDE_DATA_request(zbif_handle, zperf_data.dst_mode, /* dst_addr_mode 	*/
+	zperf_data.dst_addr, /* dst_addr			*/
+	dst_ep, /* dst_ep			*/
+	profile_id, cluster_id, src_ep, /* src_ep 			*/
+	sizeof(packet), /* asdu_len 		*/
+	packet, /* asdu				*/
+	0, /* tx_options		*/
+	1 /* radius			*/
+	);
+	printf("packet sent \n");
+}
+
+void terminate(void) {
+	if (zbif_handle != NULL) {
+		printf("disconnecting\n");
+		ZBIFDisconnect(zbif_handle);
+	}
+	exit(0);
+}
+
+static void showHelp() {
+	printf("%s", help);
+	exit(0);
+}
+
+static void showVersion() {
+	printf("%s version %f\n", PROGRAM_NAME, VERSION);
+	printf("zperf\n");
+	exit(0);
+}
+
+void my_ZDO_RESET_confirm(ZBIF_HANDLE zbif_handle, uchar status, uchar restart) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_APSME_GET_confirm(ZBIF_HANDLE zbif_handle, uchar status, uchar attr,
+		uchar attr_len, uchar *attr_value) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_NWK_ADDR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		uchar *ieee_addr, ushort nwk_addr, uchar num_assoc_dev,
+		uchar start_index, ushort *nwk_addr_assoc_dev_list) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_IEEE_ADDR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		uchar *ieee_addr, ushort nwk_addr, uchar num_assoc_dev,
+		uchar start_index, ushort *nwk_addr_assoc_dev_list) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_NODE_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, ZB_NODE_DESC *node_desc) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_POWER_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, ZB_POWER_DESC *power_desc) {
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_APSDE_DATA_indication(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, uchar src_addr_mode, uchar *src_addr,
+		uchar src_ep, ushort profile_id, ushort cluster_id, ushort asdu_len,
+		uchar *asdu, uchar was_broadcast, uchar sec_status) {
+
+#ifdef DDD
+	printf ("received data\n");
+#endif
+	unsigned char tx_options = 0x00;
+
+	if (asdu_len < 5) {
+		/* wrong packet received */
+		zperf_data.wrong_packets++;
+		return;
+	}
+
+	/* increment received packets counter */
+	zperf_data.received++;
+
+	unsigned int seq_number = (unsigned int) ztohl(*((unsigned long *) asdu));
+
+	if (seq_number < zperf_data.exp_seq_num) {
+
+		/* prints last data */
+		float lost_perc = 100
+				* ((float) zperf_data.lost
+						/ (float) (zperf_data.received + zperf_data.lost));
+		printf("rcvd: %d, lost: %d (%.1f), wrong: %d\n", zperf_data.received,
+				zperf_data.lost, lost_perc, zperf_data.wrong_packets);
+
+		/* reset zperf_data */
+		zperf_data.received = 0;
+		zperf_data.exp_seq_num = 1;
+		zperf_data.lost = 0;
+		zperf_data.wrong_packets = 0;
+	}
+
+#ifdef DDD
+	printf ("seq: %d, exp: %d\n", seq_number, zperf_data.exp_seq_num);
+	printf ("sequence number %d\n", seq_number);
+	printf ("additional byte %d\n", (int) asdu[4]);
+#endif
+
+	if (zperf_data.exp_seq_num != seq_number) {
+		zperf_data.lost++;
+		zperf_data.exp_seq_num = seq_number;
+	}
+
+	zperf_data.exp_seq_num++;
+
+#ifdef DDD
+	printf ("clusteid %04x\n", (int) cluster_id);
+	printf ("profileid %04x\n", (int) profile_id);
+#endif
+
+	if (zperf_data.mode & 0x0002) {
+		/* server mode */
+
+		/* check if the response packet should be sent */
+		if ((asdu_len >= 5) && (asdu[4] == 2)) {
+			printf("SEND ANSWER \n");
+			APSDE_DATA_request(zbif_handle, src_addr_mode, src_addr, src_ep,
+					profile_id, cluster_id, dst_ep, asdu_len, asdu, tx_options,
+					1);
+		}
+	}
+	//pthread_mutex_unlock(&test_mutex);
+}
+
+void my_APSME_SET_confirm(ZBIF_HANDLE zbif_handle, uchar status, uchar attr) {
+	if (status != ZB_ZDO_SUCCESS) {
+		zb_print_error("ERROR: set attribute 0x%02X\n", attr);
+	}
+
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_START_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr) {
+	if (status == ZB_ZDO_SUCCESS) {
+		printf("device started\n");
+	} else if (status == ZB_NWK_STARTUP_FAILURE) {
+		zb_print_error("ERROR: network startup failure!\n");
+		exit(1);
+	} else {
+		zb_print_error("ERROR: %d returned while starting network\n", status);
+	}
+
+	printf("Waiting 5 seconds\n");
+	sleep(10);
+	printf("Starting ....\n");
+
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_APSDE_DATA_confirm(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, uchar src_ep, uchar status) {
+	if (status != ZB_SUCCESS) {
+		zperf_data.tx_api_errors++;
+	}
+	printf("DATA_confirm\n");
+	pthread_mutex_unlock(&test_mutex);
+}
+
+void my_ZDO_ERROR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort cluster_id, uchar expected_len) {
+	pthread_mutex_unlock(&test_mutex);
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/fragment.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/fragment.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/fragment.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,94 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef _ZIGBEE_FRAGMENT_H_
+#define _ZIGBEE_FRAGMENT_H_
+
+#include "upnp/ThreadPool.h"
+#include "upnp/TimerThread.h"
+
+// Previous value = 145
+#define	HOST_FRAGMENT_BUFFER_SIZE				 250
+
+// Such a value should depend on the profileID --> TODO!!!
+#define ZA_MAX_HOPS 6
+
+void ezspFragmentInit(int8u receiveBufferLength, int8u *receiveBuffer);
+
+// Transmitting ********************************
+
+EmberStatus ezspSendFragmentedMessage(ZBIF_HANDLE zbif_handle,
+		EmberOutgoingMessageType type, int16u indexOrDestination,
+		EmberApsFrame *apsFrame, int8u maxFragmentSize, int8u messageLength,
+		int8u *messageContents);
+
+EmberStatus ezspFragmentSourceRouteHandler(void);
+
+boolean ezspIsOutgoingFragment(ZBIF_HANDLE zbif_handle, EmberApsFrame *apsFrame,
+		EmberStatus status);
+
+void ezspFragmentedMessageSentHandler(EmberStatus status);
+
+// Receiving ********************************
+
+boolean ezspIsIncomingFragment(ZBIF_HANDLE zbif_handle, EmberApsFrame *apsFrame,
+		EmberNodeId sender, int8u *messageLength, int8u **messageContents);
+
+//void ezspFragmentTick(void);
+
+//====================
+//====================
+//====================
+//====================
+
+/**
+ Set of constants used in thread management.
+ */
+#define ZBSZSP_MAX_THREADS					10
+#define ZBSZSP_MIN_THREADS					10
+#define ZBSZSP_JOBS_PER_THREAD					10
+#define ZBSZSP_THREAD_IDLE_TIME 				5000
+#define ZBSZSP_MAX_JOBS_TOTAL 					10
+
+/// Mutex
+pthread_mutex_t mux;
+
+/// Thread management
+ThreadPool threadPool;
+ThreadPoolJob job;
+
+///	Timers management 				
+
+typedef void *TIMERPROC;
+typedef struct {
+	int timer_id;
+	unsigned int *timer;
+	int eventId;
+} timer_data_t;
+
+typedef struct {
+	int fTimeout;
+	timer_data_t *timerData;
+} context_t;
+
+context_t timerContext;
+
+int initTimers(void);
+
+unsigned int *setTimer(int timer_id, int time, void *callback);
+
+int killTimer(unsigned int *timer, int eventID);
+
+void onTimer(unsigned int timer_id);
+
+static void free_upnp_timeout(void *event);
+
+static void *timer_Cb(void *input);
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/hdlc_dl.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/hdlc_dl.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/hdlc_dl.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,70 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+/**
+ * This file contains relevant constants related 
+ * to the reliable serial protocol that permits the host 
+ * to communicate with the ZSDIO
+ * This protocol has been documented in ....
+ */
+
+#ifndef _HDLC_DL_H_
+#define _HDLC_DL_H_
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include "hdlc_ser.h"
+#include "hdlc_net.h"
+
+#ifdef DEBUG_HDLC_DL
+# define DEBUG_HDLC_DL_LOG(a) a
+#else
+# define DEBUG_HDLC_DL_LOG(a)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+	int fd;
+	int fd_dl; /** serial device file descriptor */
+	struct sockaddr_in saddr;
+	struct sockaddr_in laddr;
+	int pair[2]; /* socketpair used in the HDLC protocol */
+	int rx_state;
+	int tx_state;
+	int rx_offs;
+	int hdlc_stats_len_errors;
+	int hdlc_stats_fcs_errors;
+	int hdlc_stats_ooo;
+	int hdlc_stats_unknown_type;
+	int hdlccb_vr;
+	int hdlccb_vs;
+	int (*close)(int); /* data link close function */
+	int (*send)(int, int, const unsigned char *, int); /* data link send function */
+	int (*rcv_loop)(int); /* data link close function */
+} hdlc_status_t;
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0 
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HDLC_DL_H_ */
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/hdlc_net.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/hdlc_net.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/hdlc_net.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,10 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+int hdlc_net_open(const char *dev_name);

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/hdlc_proto.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/hdlc_proto.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/hdlc_proto.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,42 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef _HDLC_PROTO_H_
+#define _HDLC_PROTO_H_
+
+#include "hdlc_dl.h"
+
+#define NR(a) (((a) & 0xE0) >> 5)
+#define NS(a) (((a) & 0x0E) >> 1)
+#define SS(a) (((a) & 0x0C) >> 2)
+
+#define S_FRAME_RR	0x00
+#define S_FRAME_RNR	0x01
+
+#ifdef DEBUG_HDLC_PROTO
+# define DEBUG_HDLC_PROTO_LOG(a) a
+#else
+# define DEBUG_HDLC_PROTO_LOG(a)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int hdlc_open(const char **params);
+int hdlc_close(int handle);
+int hdlc_send(int handle, const unsigned char *data, const int size);
+int hdlc_input(int handle, const unsigned char *frame, const int size);
+int hdlc_fd(int handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HDLC_PROTO_H_ */

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/hdlc_ser.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/hdlc_ser.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/hdlc_ser.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,10 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+int hdlc_ser_open(const char *dev_name);

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/winport.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/winport.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/winport.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,48 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef _WINPORT_H_
+#define _WINPORT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define Sleep sleep
+
+#define TRACE printf
+#define ZeroMemory(a, b) memset(a, 0, (b))
+
+#define INVALID_SOCKET	-1
+#define SOCKET_ERROR	-1
+
+typedef int BOOL;
+typedef unsigned char UCHAR;
+typedef unsigned int UINT;
+typedef void *LPVOID;
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0 
+#endif
+
+typedef int SOCKET;
+
+unsigned int *SetTimer(int timer_id, int time, void *callback);
+int KillTimer(unsigned int *timer);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/zb_conn.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/zb_conn.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/zb_conn.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,49 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef _ZB_CONN_H_
+#define _ZB_CONN_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*ZBIFReceiveCb_t)(void *handle, unsigned char *data,
+		const int size);
+
+typedef struct {
+	int (*open)(const char **params);
+	int (*close)(int handle);
+	int (*write)(int handle, const unsigned char *data, const int size);
+	int (*read)(int handle, unsigned char *data, const int size);
+	int (*fd)(int handle);
+	int handle;
+
+	ZBIFReceiveCb_t zbifCb;
+	void *hh;
+
+	pthread_t tid;
+
+} zb_conn_status_t;
+
+typedef void *ZB_CONN_HANDLE;
+
+ZB_CONN_HANDLE zb_conn_open(const char **params, void *hh,
+		ZBIFReceiveCb_t zbifCb);
+
+int zb_conn_close(ZB_CONN_HANDLE zb_conn_h);
+
+int zb_conn_send(ZB_CONN_HANDLE zb_conn_h, const unsigned char *data,
+		const int size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ZB_CONN_H_ */

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/zigbee.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/zigbee.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/zigbee.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,1778 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+/*
+ * This file contains the API definitions for the Zigbee Network Layer
+ * See ZigBee 2004 specifications 
+ * In some places a initial effort to move to Zigbee 2006 has been done
+ * The ifdef ZIGBEE_2006 has been added for this purpose
+ */
+
+#ifndef _ZIGBEE_H_
+#define _ZIGBEE_H_
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#ifdef __GNUC__
+#include <endian.h>
+#else
+#define __attribute__(a)
+
+#define	__LITTLE_ENDIAN	1234
+#define	__BIG_ENDIAN	4321
+#define	__PDP_ENDIAN	3412
+
+#ifdef __LITTLE_ENDIAN__
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#elif defined(__BIG_ENDIAN__)
+#define __BYTE_ORDER __BIG_ENDIAN
+#else
+#error Not able to check if little endian or big endian
+#endif
+
+#endif /* GNUC */
+
+#include <assert.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define IEEE_ADDR_LEN	8
+
+#define LSB_USHORT(a) ((a) & 0xFF)
+#define MSB_USHORT(a) (((a) >> 8) & 0xFF)
+
+#define PUT_USHORT(q, a) { *q++ = LSB_USHORT(a); *q++ = MSB_USHORT(a); }
+
+#ifndef ZB_LOG
+#ifdef DEBUG_ZIGBEE
+#define ZB_LOG(a)	a
+#else
+#define ZB_LOG(a)
+#endif
+#endif
+
+#define zb_notify		zb_print
+#define zb_message		zb_print
+
+#define zb_not_yet_implemented() printf("NOT YET IMPLEMENTED: %s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__);
+
+#ifdef __GNUC__
+typedef unsigned char uchar;
+#endif
+
+/**
+ * Zigbee node descriptor structure. @see ZDO_NODE_DESC_confirm primitive
+ * @see [1] paragraph XXXXX
+ * @see [2] paragraph 2.3.2.4
+ */
+
+typedef struct {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+	uchar logical_type:3;
+#ifdef ZIGBEE_2006
+	uchar complx_desc_avail:1;
+	uchar user_desc_avail:1;
+	uchar reserved:3;
+#else
+	uchar reserved:5;
+#endif
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#ifdef ZIGBEE_2006
+	uchar reserved:3;
+	uchar user_desc_avail:1;
+	uchar complx_desc_avail:1;
+#else
+	uchar reserved:5;
+#endif
+	uchar logical_type:3;
+#else
+# error	"Please fix <bits/endian.h>"
+#endif
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+	uchar aps_flags:3;
+	uchar freq_band:5;
+#endif
+#if __BYTE_ORDER == __BIG_ENDIAN
+	uchar freq_band:5;
+	uchar aps_flags:3;
+#endif
+	uchar mac_cap; /* bitfield */
+	ushort manifact_code;
+	uchar max_buf_size;
+	ushort max_transf_size;
+#ifdef ZIGBEE_2006
+ushort server_mask;
+#endif
+
+}__attribute__((packed)) ZB_NODE_DESC;
+
+typedef struct {
+	uchar ExtendedPANId[8];
+	uchar ExtendedAddress[8];
+	ushort NetworkAddress;
+	uchar devTypeRxOnRelation;
+	uchar PermitJoining;
+	uchar Depth;
+	uchar LQI;
+}__attribute__((packed)) ZB_NEIGHBOR_TABLE_LIST;
+
+/**
+ * Zigbee power descriptor structure. @see ZDO_POWER_DESC_confirm primitive
+ * @see ZigBee 2004 specifications 1.3.3.5
+ */
+
+typedef struct {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+uchar curr_pw_mode:4;
+uchar avail_pw_src:4;
+#endif
+#if __BYTE_ORDER == __BIG_ENDIAN
+uchar avail_pw_src:4;
+uchar curr_pw_mode:4;
+#endif
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+uchar curr_pw_src:4;
+uchar curr_pw_src_level:4;
+#endif
+#if __BYTE_ORDER == __BIG_ENDIAN
+uchar curr_pw_src_level:4;
+uchar curr_pw_src:4;
+#endif
+}__attribute__((packed)) ZB_POWER_DESC;
+
+/**
+ * Zigbee simple descriptor structure. @see ZDO_SIMPLE_DESC_confirm primitive
+ * @see ZigBee 2004 specifications, clause 1.3.3.6
+ */
+
+typedef struct {
+	uchar ep; /** Endpoint 						*/
+	ushort app_profile_id; /** Application Profile Identifier	*/
+	ushort app_device_id; /** Application Device Identifier 	*/
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+	uchar app_device_ver:4; /** Application Device Version 		*/
+	uchar reserved:4;
+#endif
+#if __BYTE_ORDER == __BIG_ENDIAN
+	uchar reserved:4;
+	uchar app_device_ver:4;
+#endif
+	uchar app_in_cluster_count;
+	ushort *app_in_cluster_list;
+	uchar app_out_cluster_count;
+	ushort *app_out_cluster_list;
+}__attribute__((packed)) ZB_SIMPLE_DESC;
+
+typedef struct {
+	uchar src_addr[8];
+	uchar src_ep;
+	ushort cluster_id;
+	uchar dst_addr[8];
+	uchar dst_ep;
+}__attribute__((packed)) ZB_BIND_STRUCT;
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+#define htozl(a) (a)
+#define ztohl(a) (a)
+
+#define htozs(a) (a)
+#define ztohs(a) (a)
+#define ztohs_p(p) 
+
+#endif
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+
+#define htozl(a) \
+	(((((unsigned long int) (a)) >> 24) & 0x000000FF) | \
+	((((unsigned long int) (a)) >> 8) & 0x0000FF00) | \
+	((((unsigned long int) (a)) << 8) & 0x00FF0000) | \
+	((((unsigned long int) (a)) << 24) & 0xFF000000))
+
+#define ztohl(a) (htozl(a))
+
+#define htozs(a) \
+	(((((unsigned long int) (a)) >> 8) & 0x00FF) | \
+	((((unsigned long int) (a)) << 8) & 0xFF00))
+
+#define ztohs(a) (htozs(a))
+#define ztohs_p(p) { \
+	unsigned char ____t; \
+	t = *p; \
+	*p = *(p + 1); \
+	*(p + 1) = t;
+}
+
+#endif
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+
+typedef union {
+	struct {
+		uchar *parent_ieee_addr;
+		uchar *tc_master_key;
+	}tcmk;
+
+	struct {
+		uchar key_seq_num;
+		uchar *nwk_key;
+		uchar use_parent;
+		uchar *parent_ieee_addr;
+	}nwk_key;
+
+	struct {
+		uchar *partner_ieee_addr;
+		uchar initiator;
+		uchar *key;
+	}link_key;
+
+}__attribute__((packed)) ZB_TRANSPORT_KEY_DATA;
+
+#endif
+
+/**
+ * ZigBee node descriptor logical types
+ */
+
+#define ZB_COORDINATOR				0x01	/** node is a coordinator	*/
+#define ZB_ROUTER				0x02	/** node is a router 		*/
+#define ZB_END_DEVICE				0x03	/** node is an end-device	*/
+
+/**
+ * ZigBee node descriptor frequency bands
+ */
+
+#define ZB_FREQ_BAND_868			0x01	/** 868 - 868.6 MHz		*/
+#define ZB_FREQ_BAND_902			0x04	/** 902 - 928 MHz		*/
+#define ZB_FREQ_BAND_2400			0x08	/** 2400 - 2483.5 MHz 	*/
+
+/**
+ * ZigBee node descriptor capabilities bitfields
+ */
+
+#define ZB_CAP_ALT_PAN_COORD		0x01	/** set if alternate PAN coordinator 	*/
+#define ZB_CAP_DEV_FFD				0x02	/** set if FFD, otherwise RFD			*/
+#define ZB_CAP_PW_SOURCE			0x04	/** set if using power source, otherwise battery */
+#define ZB_CAP_RCV_ON				0x08	/** set if receiver on when idle		*/
+#define ZB_CAP_SEC					0x40	/** set if security is implemented		*/
+
+/** 
+ * ZigBee status codes returned by the Network Layer
+ * primitives. From Table 3.1 of the ZigBee 2006 specifications
+ */
+
+#define ZB_SUCCESS						0x00	
+#define ZB_NWK_INVALID_PARAMETER		0xC1	
+#define ZB_NWK_INVALID_REQUEST			0xC2	
+#define ZB_NWK_NOT_PERMITTED			0xC3	
+#define ZB_NWK_STARTUP_FAILURE			0xC4	
+#define ZB_NWK_ALREADY_PRESENT			0xC5	
+#define ZB_NWK_SYNC_FAILURE				0xC6	
+#define ZB_NWK_NEIGHBOR_TABLE_FULL		0xC7	
+#define ZB_NWK_UNKNOWN_DEVICE			0xC8	
+#define ZB_NWK_UNSUPPORTED_ATTRIBUTE	0xC9		
+#define ZB_NWK_NO_NETWORKS				0xCA	
+#define ZB_NWK_LEAVE_UNCONFIRMED		0xCB	
+#define ZB_NWK_MAX_FRM_CNTR				0xCC	
+#define ZB_NWK_NO_KEY					0xCD	
+#define ZB_NWK_BAD_CCM_OUTPUT			0xCE	
+#define ZB_NWK_NO_ROUTING_CAPACITY		0xCF	
+#define ZB_NWK_ROUTE_DISCOVERY_FAILED	0xD0	
+#define ZB_NWK_ROUTE_ERROR				0xD1	
+#define ZB_NWK_BT_TABLE_FULL			0xD2	
+#define ZB_NWK_FRAME_NOT_BUFFERED		0xD3	
+
+/** 
+ * ZigBee status codes returned by the confirm 
+ * (from Table 88 of the ZigBee 2004 specs)
+ */
+
+#define ZB_ZDO_SUCCESS					0x00
+#define ZB_ZDO_INV_REQUESTTYPE			0x80
+#define ZB_ZDO_DEVICE_NOT_FOUND			0x81
+#define ZB_ZDO_INVALID_EP				0x82
+#define ZB_ZDO_NOT_ACTIVE				0x83	
+#define ZB_ZDO_NOT_SUPPORTE				0x84
+#define ZB_ZDO_TIMEOUT					0x85
+#define ZB_ZDO_NO_MATCH					0x86
+#define ZB_ZDO_TABLE_FULL				0x87
+#define ZB_ZDO_NO_ENTRY					0x88
+#define ZB_ZDO_NO_REPLY					0x8E
+
+/* custom error codes */
+#define	ZB_ZDO_UNKNOWN_CLUSTER_ID		0x9A
+#define	ZB_ZDO_UNSUPPORTED_CLUSTER_ID	0x9B
+#define	ZB_MGMT_LEAVE_INDICATION		0x9C
+
+/**
+ * Request type used in *_ADDR_request commands
+ */
+
+#define ZDO_REQ_TYPE_SD_RES			0x00 	/** single device response	*/
+#define ZDO_REQ_TYPE_EX_RES			0x01 	/** extended response 		*/
+
+/**
+ * Data request modes
+ */
+
+#define ZB_AM_INDIRECT				0x00	/** indirect address mode, no address no ep					*/
+
+#ifdef ZIGBEE_2006
+#define ZB_AM_DIRECT_GROUP			0x01	/** direct address mode. Group address, no ep provided		*/
+#define ZB_AM_DIRECT				0x02	/** direct address mode. Short address and ep used			*/
+#define ZB_AM_DIRECT_EX				0x03	/** direct address mode. Extended address and ep			*/
+#else
+#define ZB_AM_DIRECT				0x01	/** direct address mode. Short address and ep used			*/
+#define ZB_AM_DIRECT_EX				0x02	/** indirect address mode. Extended address and ep			*/
+#endif
+
+/**
+ * APS Fragmentation
+ */
+#define ZA_FRAGMENT_TRIGGER			90		/** the trigger size for using fragmentation				*/
+#define ZA_FRAGMENT_OVERHEAD		2		/** 2 bytes are added to the header when sending a fragment	*/
+
+/* NON standard attributes */
+#define ZB_ATTR_GET_CHANNEL_MASK			0xC3
+#define ZB_ATTR_CONFIG_PANID				0xFF
+#define ZB_ATTR_CONFIG_EXTENDEDPANID		0xFE
+#define ZB_ATTR_CONFIG_STARTUPCONTROL		0xFD
+#define ZB_ATTR_CONFIG_NODE_DESCRIPTOR		0xF0
+#define ZB_ATTR_CONFIG_SIMPLE_DESCRIPTOR	0xEF
+#define ZB_ATTR_CONFIG_CHANNEL_MASK			0xEE
+#define ZB_ATTR_GET_EUI64					0xED
+#define ZB_ATTR_CONFIG_SECURITY				0xE0
+#define ZB_ATTR_CONFIG_SECURITY_LEVEL		0x0D	//Mod@@		refer to EZSP ---
+#define ZB_TC_KEY_REQUEST_POLICY			0x05	//Mod@@		refer to EZSP ---	//FIXME!! modify into ZB_ATTR_TC_KEY_REQUEST_POLICY
+#define ZB_APP_KEY_REQUEST_POLICY			0x06	//Mod@@		refer to EZSP ---	//FIXME!!
+#define ZB_ATTR_PRECONF_TC_LINK_KEY			0x07	//Mod@@		refer to EZSP ---	//FIXME!!	Move this to Security related info
+#define ZB_ATTR_NWK_KEY						0x08	//Mod@@		refer to EZSP ---	//FIXME!!
+#define ZB_ATTR_KEY_TABLE_ENTRY				0x72	//Mod@@		refer to EZSP ---	//FIXME!!
+#define ZB_ATTR_CONFIG_FRAGMENT_WINDOW_SIZE	0x1C
+#define ZB_ATTR_CONFIG_FRAGMENT_DELAY_MS 	0x1D
+#define ZB_ATTR_KEY_TABLE_SIZE				0x1E	//Added to manage key table
+
+/* security status used in APSDE_DATA_indication() */
+
+#define ZB_UNSECURED                    0x00
+#define ZB_SECURED_NWK_KEY              0x01
+#define ZB_SECURED_LINK_KEY             0x02
+
+/* tx options bitfield used in APSDE_DATA_request() */
+
+#define ZB_APS_TXOPTIONS_SEC_ENABLED_TRANSMISSION		0x01	/** Security enabled transmission	(Not used)		*/
+#define ZB_APS_TXOPTIONS_USE_NWK_KEY					0x02	/** Use NWK key										*/
+#define ZB_APS_TXOPTIONS_ACK_TRANSMISSION				0x04	/** Acknowledged transmission						*/
+#define ZB_APS_TXOPTIONS_FRAGMENTATION_PERMITTED		0x08	/** Fragmentation permitted							*/
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+
+/* Transport key types */
+
+#define ZB_TC_MASTER_KEY				0x00	/** Trust Center Master key */
+#define ZB_NWK_KEY						0x01	/** Network Key */
+#define ZB_APP_MASTER_KEY				0x02	/** Application Master Key */
+#define ZB_APP_LINK_KEY					0x03	/** Application Link Key */
+
+#define ZB_TRANSPORT_KEY_LEN			16
+
+#endif
+
+typedef void *ZBIF_HANDLE;
+
+typedef struct {
+	void (*ZDO_RESET_confirm)(ZBIF_HANDLE, uchar, uchar);
+	void (*ZDO_START_confirm)(ZBIF_HANDLE, uchar, ushort);
+	void (*ZDO_NWK_ADDR_confirm)(ZBIF_HANDLE, uchar, uchar *, ushort, uchar,
+			uchar, ushort *);
+	void (*ZDO_IEEE_ADDR_confirm)(ZBIF_HANDLE, uchar, uchar *, ushort, uchar,
+			uchar, ushort *);
+	void (*ZB_MGMT_LQI_response)(ZBIF_HANDLE, uchar srcAddrMode,
+			uchar* src_addr, uchar *);
+	void (*ZDO_NODE_DESC_confirm)(ZBIF_HANDLE, uchar, ushort, ZB_NODE_DESC *);
+	void (*ZDO_POWER_DESC_confirm)(ZBIF_HANDLE, uchar, ushort, ZB_POWER_DESC *);
+	void (*ZDO_SIMPLE_DESC_confirm)(ZBIF_HANDLE, uchar, ushort,
+			ZB_SIMPLE_DESC *);
+	void (*ZDO_ACTIVE_EP_DESC_confirm)(ZBIF_HANDLE, uchar, ushort, uchar,
+			uchar *);
+	void (*ZDO_MATCH_DESC_confirm)(ZBIF_HANDLE, uchar, ushort, uchar, uchar *);
+	void (*ZDO_MATCH_DESC_indication)(ZBIF_HANDLE, ushort, ushort, uchar,
+			ushort *, uchar, ushort *);
+	void (*ZDO_END_DEVICE_BIND_confirm)(ZBIF_HANDLE, uchar);
+	void (*ZDO_DEVICE_ANNCE_indication)(ZBIF_HANDLE, ushort, uchar *, uchar);
+	void (*ZIGBEE_STACK_STATUS_indication)(ZBIF_HANDLE, uchar);
+	void (*APSDE_DATA_confirm)(ZBIF_HANDLE, uchar, uchar *, uchar, uchar, uchar);
+	void (*APSDE_DATA_indication)(ZBIF_HANDLE, uchar, uchar *, uchar, uchar,
+			uchar *, uchar, ushort, ushort, ushort, uchar *, uchar, uchar);
+	void (*ZDP_MGMT_BIND_response)(ZBIF_HANDLE, uchar, ushort, ushort, ushort,
+			ZB_BIND_STRUCT *);
+	void (*APSME_BIND_confirm)(ZBIF_HANDLE, uchar, uchar *, uchar, ushort,
+			uchar *, uchar);
+	void (*ZDP_BIND_response)(ZBIF_HANDLE, uchar);
+	void (*ZDP_UNBIND_response)(ZBIF_HANDLE, uchar);
+	void (*APSME_GET_confirm)(ZBIF_HANDLE, uchar, uchar, uchar, uchar *);
+	void (*APSME_SET_confirm)(ZBIF_HANDLE, uchar, uchar);
+	void (*MGMT_PERMIT_JOINING_response)(ZBIF_HANDLE, uchar);
+	void (*MGMT_LEAVE_response)(ZBIF_HANDLE, uchar);
+	void (*MGMT_LEAVE_confirm)(ZBIF_HANDLE, uchar *, uchar);
+#ifdef INCLUDE_ZIGBEE_SECURITY
+	void (* APSME_UPDATE_DEVICE_indication) (ZBIF_HANDLE, uchar *, uchar *, uchar, ushort);
+	void (* APSME_REMOVE_DEVICE_confirm) (ZBIF_HANDLE, uchar);
+#if 0
+	void (* APSME_TRANSPORT_KEY_request) (ZBIF_HANDLE, uchar *, uchar, ZB_TRANSPORT_KEY_DATA *);
+#endif
+	void (* APSME_TRANSPORT_KEY_confirm) (ZBIF_HANDLE, uchar);
+	void (* APSME_TRANSPORT_KEY_indication) (ZBIF_HANDLE, uchar *, uchar, ZB_TRANSPORT_KEY_DATA *);
+	void (* NLME_JOIN_indication) (ZBIF_HANDLE, ushort, uchar *, uchar, uchar);
+#endif
+	void (*ZDO_ERROR_confirm)(ZBIF_HANDLE, uchar, ushort, uchar);
+} ZBIFCbs_t;
+
+typedef struct {
+	void (*ZDO_RESET_request)(ZBIF_HANDLE, uchar);
+	void (*ZDO_START_request)(ZBIF_HANDLE);
+	void (*ZDP_MGMT_NWK_UPDATE_request)(ZBIF_HANDLE, unsigned long int, ushort);
+	void (*ZDO_NWK_ADDR_request)(ZBIF_HANDLE, uchar *, uchar, uchar);
+	void (*ZDO_IEEE_ADDR_request)(ZBIF_HANDLE, ushort, uchar, uchar);
+	void (*ZB_MGMT_LQI_request)(ZBIF_HANDLE, ushort, uchar);
+	void (*ZDO_NODE_DESC_request)(ZBIF_HANDLE, ushort, ushort);
+	void (*ZDO_POWER_DESC_request)(ZBIF_HANDLE, ushort, ushort);
+	void (*ZDO_SIMPLE_DESC_request)(ZBIF_HANDLE, ushort, ushort, uchar);
+	void (*ZDO_ACTIVE_EP_DESC_request)(ZBIF_HANDLE, ushort, ushort);
+	void (*ZDO_MATCH_DESC_request)(ZBIF_HANDLE, ushort, ushort, ushort, uchar,
+			ushort *, uchar, ushort *);
+	void (*ZDO_MATCH_DESC_response)(ZBIF_HANDLE, uchar, ushort, uchar, uchar *);
+	void (*ZDO_END_DEVICE_BIND_request)(ZBIF_HANDLE, ushort, uchar *, uchar,
+			ushort, uchar, ushort *, uchar, ushort *);
+	void (*APSDE_DATA_request)(ZBIF_HANDLE, uchar, uchar *, uchar, ushort,
+			ushort, uchar, uchar, uchar *, uchar, uchar);
+	void (*ZDP_MGMT_BIND_Request)(ZBIF_HANDLE, ushort, ushort);
+	void (*APSME_BIND_request)(ZBIF_HANDLE, uchar *, uchar, ushort, uchar *,
+			uchar);
+	void (*ZDP_BIND_request)(ZBIF_HANDLE, ushort, uchar *, uchar, ushort,
+			uchar *, uchar);
+	void (*ZDP_UNBIND_request)(ZBIF_HANDLE, ushort, uchar *, uchar, ushort,
+			uchar *, uchar);
+	void (*APSME_UNBIND_request)(ZBIF_HANDLE, uchar *, uchar, ushort, uchar *,
+			uchar);
+	void (*APSME_GET_request)(ZBIF_HANDLE, uchar);
+	void (*APSME_SET_request)(ZBIF_HANDLE, uchar, uchar, uchar *);
+	void (*MGMT_PERMIT_JOINING_request)(ZBIF_HANDLE, ushort, int);
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+	void (*APSME_REMOVE_DEVICE_request) (ZBIF_HANDLE, uchar *, uchar *);
+	void (*APSME_TRANSPORT_KEY_request) (ZBIF_HANDLE, uchar *, uchar, ZB_TRANSPORT_KEY_DATA *);
+	void (*MGMT_LEAVE_request) (ZBIF_HANDLE, uchar *, uchar, uchar, uchar, uchar);
+#endif
+
+	void (*ZDO_ERROR_response)(ZBIF_HANDLE, uchar, ushort, uchar);
+	void (*ZIGBEE_request)(ZBIF_HANDLE, uchar, void *);
+} ZBIFFunctions_t;
+
+/**
+ * Connect to the specified device
+ *
+ * @param device
+ * 	The device for connecting to. The device depends on the 
+ * 	way the code has been compiled. 
+ * 	It may be an IP address or a local serial device
+ *
+ * @param zbif_receive_cb	
+ * 	callback function called each time a new message arrives.
+ *
+ * @returns
+ * 	The device descriptor or -1 if error
+ */
+
+ZBIF_HANDLE ZBIFConnect(const char *uri, ZBIFCbs_t *zbCbs, void *hh);
+
+/**
+ * Disconnect from the specified device descriptor
+ * The device descriptor returned by the ZBIFConnect() must be provided
+ */
+
+int ZBIFDisconnect(ZBIF_HANDLE zbif_handle);
+
+void ZDO_RESET_request(ZBIF_HANDLE zbif_handle, uchar options);
+
+void ZDO_RESET_confirm(ZBIF_HANDLE zbif_handle, uchar status, uchar restart);
+
+void ZDO_START_request(ZBIF_HANDLE zbif_handle);
+
+void ZDO_START_confirm(ZBIF_HANDLE zbif_handle, uchar status, ushort nwk_addr);
+
+void ZDP_MGMT_NWK_UPDATE_request(ZBIF_HANDLE zbif_handle,
+		unsigned long int scanChannel, ushort scanDuration);
+
+/**
+ *
+ * @param ieee_addr
+ * 	points to 8 byte buffer representing the destination node IEEE address
+ *
+ * @param request_type
+ * 	ZDO_REQ_TYPE_SD_RES (0x00) for single device response,  
+ * 	ZDO_REQ_TYPE_EX_RES (0x01) for extended response
+ *
+ * @param start_index
+ * 	used only if extended response is selected
+ *
+ * @see ZigBee 2004 specification paragraph 1.4.3.1.1
+ */
+
+void ZDO_NWK_ADDR_request(ZBIF_HANDLE zbif_handle, uchar *ieee_addr,
+		uchar request_type, uchar start_index);
+
+/**
+ *
+ * Called as response to a ZDO_NWK_ADDR_request(). 
+ *
+ * @param status
+ * 	return status. May be ZDO_SUCCESS, ZDO_INV_REQUESTTYPE, ZDO_DEVICE_NOT_FOUND
+ */
+
+void ZDO_NWK_ADDR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		uchar *ieee_addr, ushort nwk_addr, uchar num_assoc_dev,
+		uchar start_index, ushort *nwk_addr_assoc_dev_list);
+
+/**
+ *
+ * Request the IEEE address. This function is called by the ZigBee application
+ *
+ * @param nwk_addr
+ * 	Network address to find (16 bit)
+ *
+ * @param request_type
+ * 	00 for single device response, 01 for extended response
+ *
+ * @param start_index
+ * 	used only if extended response is selected
+ */
+
+void ZDO_IEEE_ADDR_request(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar request_type, uchar start_index);
+
+/**
+ * returns the requested IEEE address. This is generated by the ZigBee Network Layer 
+ *
+ * @param status
+ * 	return status. May be ZDO_SUCCESS, ZDO_INV_REQUESTTYPE, ZDO_DEVICE_NOT_FOUND
+ */
+
+void ZDO_IEEE_ADDR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		uchar *ieee_addr, ushort nwk_addr, uchar num_assoc_dev,
+		uchar start_index, ushort *nwk_addr_assoc_dev_list);
+
+void ZB_MGMT_LQI_request(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar start_index);
+
+void ZB_MGMT_LQI_response(ZBIF_HANDLE zbif_handle, uchar srcAddrMode,
+		uchar* src_addr, uchar * asdu);
+
+/**
+ * Inquires the 'node descriptor' of the remote device
+ *
+ * @param nwk_addr
+ * 	Network address of interest (16 bit)
+ */
+
+void ZDO_NODE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr);
+
+/**
+ * returns the requested node descriptor. This is generated by the ZigBee Network Layer 
+ *
+ * @param status
+ * 	return status. May be ZDO_SUCCESS, ZDO_DEVICE_NOT_FOUND
+ *
+ * @param note_desc
+ * 	this is the returned node descriptor. This descriptor is described in [1], clause 1.3.3.4 or 
+ * 	in [2] at clause 2.3.2.4
+ *
+ */
+
+void ZDO_NODE_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, ZB_NODE_DESC *node_desc);
+
+/**
+ * Inquires the power descriptor of the remote device
+ *
+ * @param nwk_addr
+ * 	Network address of interest (16 bit)
+ */
+
+void ZDO_POWER_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr);
+
+/**
+ * returns the requested power descriptor. This is generated by the ZigBee Network Layer 
+ *
+ * @param status
+ * 	return status. May be ZDO_SUCCESS, ZDO_DEVICE_NOT_FOUND
+ *
+ * @param desc
+ * 	this is the returned node descriptor. This descriptor is described in [1], clause 1.3.3.5
+ *
+ */
+
+void ZDO_POWER_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, ZB_POWER_DESC *power_desc);
+
+/**
+ * Inquires the simple descriptor of the remote device
+ * corresponding the supplied endpoint 
+ *
+ * @param nwk_addr
+ * 	Network address of interest (16 bit)
+ *
+ * @param endpoint
+ * 	8 bit endpoint (range 0x01 - 0xF0)
+ */
+
+void ZDO_SIMPLE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, uchar endpoint);
+
+/**
+ * returns the requested simple descriptor. This is generated by the ZigBee Network Layer 
+ *
+ * @param status
+ * 	return status. May be ZDO_SUCCESS, ZDO_INVALID_EP, ZDO_NOT_ACTIVE, ZDO_DEVICE_NOT_FOUND
+ *
+ * @param desc
+ * 	this is the returned node descriptor. This descriptor is described in [1], clause 1.3.3.5
+ * 	The descr may be NULL if the status is ZDO_INVALID_EP or ZDO_NOT_ACTIVE
+ *
+ */
+
+void ZDO_SIMPLE_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, ZB_SIMPLE_DESC *simple_desc);
+
+/**
+ * Inquires the list of endpoinds on the remote device with
+ * simple descriptor
+ *
+ * @param nwk_addr
+ * 	Network address of interest (16 bit)
+ *
+ * @param endpoint
+ * 	8 bit endpoint (range 0x01 - 0xF0)
+ */
+
+void ZDO_ACTIVE_EP_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr);
+
+/**
+ * Returns the requested simple descriptor. This is generated by the ZigBee Network Layer 
+ *
+ * @param status
+ * 	return status. May be ZDO_SUCCESS, ZDO_DEVICE_NOT_FOUND
+ *
+ * @param desc
+ * 	this is the returned node descriptor. This descriptor is described in [1], clause 1.3.3.5
+ *
+ */
+
+void ZDO_ACTIVE_EP_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, uchar active_ep_count, uchar *active_ep_list);
+
+/**
+ * 
+ * @param nwk_addr
+ * 	Network address of interest (16 bit)
+ *
+ * @param profile_id
+ * 	profile id that is requested to be matched at destination
+ *
+ * @param nicl
+ * 	number of input clusters
+ *
+ * @param icllist
+ * 	array of 16 bit integers representing the list of cluters
+ *
+ * @param nocl
+ * 	number of output clusters
+ */
+
+void ZDO_MATCH_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, ushort profile_id, uchar nicl, ushort *icllist,
+		uchar nocl, ushort *ocllist);
+
+/**
+ * returns the requested matching descriptor. This is generated by the ZigBee Network Layer 
+ *
+ * @param status
+ * 	return status. May be ZDO_SUCCESS, ZDO_DEVICE_NOT_FOUND
+ *
+ * @param match_len
+ * 	Count of endpoints on the remote device that match the requested criteria
+ *
+ * @param match_list
+ * 	List of bytes. Each byte represents an 8 bit enpoint
+ *
+ */
+
+void ZDO_MATCH_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, uchar match_len, uchar *match_list);
+
+void ZDO_MATCH_DESC_indication(ZBIF_HANDLE zbif_handle, ushort src_addr,
+		ushort profile_id, uchar nicl, ushort *icllist, uchar nocl,
+		ushort *ocllist);
+
+void ZDO_MATCH_DESC_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort dst_addr, uchar match_len, uchar *match_list);
+
+/**
+ * Implements the End_Device_Bind_req primitive described in ZigBee 2006, clause 2.4.3.2.1 
+ */
+
+void ZDO_END_DEVICE_BIND_request(ZBIF_HANDLE zbif_handle, ushort binding_target,
+		uchar *src_ieee_addr, uchar src_ep, ushort profile_id, uchar nicl,
+		ushort *icllist, uchar nocl, ushort *ocllist);
+
+/**
+ * Implements the End_Device_Bind_rsp primitive described in ZigBee 2006, clause 2.4.4.2.1
+ *
+ * @param status
+ * 	return status. May be ZDO_SUCCESS, ZDO_NOT_SUPPORTED, ZDO_TIMEOUT or ZDO_NO_MATCH
+ *
+ */
+
+void ZDO_END_DEVICE_BIND_confirm(ZBIF_HANDLE zbif_handle, uchar status);
+
+void ZDO_DEVICE_ANNCE_indication(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar *ieee_addr, uchar capability);
+
+void ZIGBEE_STACK_STATUS_indication(ZBIF_HANDLE zbif_handle, uchar status);
+
+/*
+ * APS messages
+ */
+
+/**
+ *
+ * @param dst_addr_mode
+ * 	In the case the value is 0x02, the dst_addr is a 64 bit IEEE address
+ */
+
+void APSDE_DATA_request(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, ushort profile_id, ushort cluster_id,
+		uchar src_ep, uchar asdu_len, uchar *asdu, uchar tx_options,
+		uchar radius);
+
+/**
+ *
+ * @param status
+ * 	returned status may be ZDO_SUCCESS, ZDO_NO_BOUND_DEVICE, ZDO_SECURITY_FAIL
+ */
+
+void APSDE_DATA_confirm(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, uchar src_ep, uchar status);
+
+/**
+ *
+ *
+ * @param sec_status
+ * 	This is the security status. It may be ZDO_SS_UNSECURED, ZDO_SS_SECURED_NWK_KEY, 
+ * 	ZDO_SECURED_LINK_KEY
+ */
+
+void APSDE_DATA_indication(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, uchar src_addr_mode, uchar *src_addr,
+		uchar src_ep, ushort profile_id, ushort cluster_id, ushort asdu_len,
+		uchar *asdu, uchar was_broadcast, uchar sec_status);
+
+void ZDP_MGMT_BIND_Request(ZBIF_HANDLE zbif_handle, ushort remote_dest_addr,
+		ushort startIndex);
+
+void APSME_BIND_request(ZBIF_HANDLE zbif_handle, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep);
+
+void ZDP_BIND_Request(ZBIF_HANDLE zbif_handle, ushort remote_dest_addr,
+		uchar *src_ieee_addr, uchar src_ep, ushort cluster_id,
+		uchar *dst_ieee_addr, uchar dst_ep);
+
+void ZDP_UNBIND_Request(ZBIF_HANDLE zbif_handle, ushort remote_dest_addr,
+		uchar *src_ieee_addr, uchar src_ep, ushort cluster_id,
+		uchar *dst_ieee_addr, uchar dst_ep);
+
+/**
+ * @param status
+ * 	returned status may be ZDO_SUCCESS, ZDO_ILLEGAL_DEVICE, 
+ * 	ZDO_ILLEGAL_REQUEST, ZDO_TABLE_FULL, ZDO_INVALID_BINDING,
+ * 	ZDO_NOT_SUPPORTED
+ */
+
+void ZDP_MGMT_BIND_Response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort bindingTableEntries, ushort StartIndex,
+		ushort BindingTableListCount, ZB_BIND_STRUCT * BindingTableList);
+
+void APSME_BIND_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		uchar *src_ieee_addr, uchar src_ep, ushort cluster_id,
+		uchar *dst_ieee_addr, uchar dst_ep);
+
+void ZDP_BIND_response(ZBIF_HANDLE zbif_handle, uchar status);
+
+void ZDP_UNBIND_response(ZBIF_HANDLE zbif_handle, uchar status);
+
+void APSME_UNBIND_request(ZBIF_HANDLE zbif_handle, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep);
+
+/**
+ *
+ * @param status
+ * 	returned status may be ZDO_SUCCESS, ZDO_ILLEGAL_DEVICE, 
+ * 	ZDO_ILLEGAL_REQUEST, ZDO_TABLE_FULL, ZDO_INVALID_BINDING
+ */
+
+void APSME_UNBIND_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		uchar *src_ieee_addr, uchar src_ep, ushort cluster_id,
+		uchar *dst_ieee_addr, uchar dst_ep);
+
+/**
+ * Attempt to read the requested attribute
+ *
+ * @param attr
+ * 	Requested attribute
+ */
+
+void APSME_GET_request(ZBIF_HANDLE zbif_handle, uchar attr);
+
+/**
+ * Returns the requested attribute 
+ *
+ * @param status
+ * 	returned status. May be ZDO_SUCCESS, ZDO_UNSUPPORTED_ATTRIBUTE
+ *
+ * @param attr
+ * 	Requested attribute
+ *
+ * @param attr_len
+ *	length of the returned attribute
+ *
+ * @param attr_value
+ * 	returned attribute value.
+ *
+ */
+
+void APSME_GET_confirm(ZBIF_HANDLE zbif_handle, uchar status, uchar attr,
+		uchar attr_len, uchar *attr_value);
+
+/**
+ * Attempt to set the requested attribute
+ *
+ *
+ * @param attr
+ * 	Requested attribute
+ *
+ * @param attr_len
+ *	length of the returned attribute
+ *
+ * @param attr_value
+ * 	returned attribute value.
+ */
+
+void APSME_SET_request(ZBIF_HANDLE zbif_handle, uchar attr, uchar attr_len,
+		uchar *attr_value);
+
+void MGMT_PERMIT_JOINING_request(ushort nwk_addr, int permitDuration);
+
+void MGMT_PERMIT_JOINING_response(ZBIF_HANDLE zbif_handle, uchar status);
+
+/**
+ *
+ * Result from a set attribute request
+ *
+ * @param status
+ * 	returned status. May be ZDO_SUCCESS, ZDO_INVALID_PARAMETER, ZDO_UNSUPPORTED_ATTRIBUTE
+ *
+ * @param attr
+ * 	requested attribute
+ */
+
+void APSME_SET_confirm(ZBIF_HANDLE zbif_handle, uchar status, uchar attr);
+
+void MGMT_LEAVE_response(ZBIF_HANDLE zbif_handle, uchar status);
+
+void MGMT_LEAVE_confirm(ZBIF_HANDLE zbif_handle, uchar *dev_ieee_addr,
+		uchar status);
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+
+void APSME_UPDATE_DEVICE_indication (
+		ZBIF_HANDLE zbif_handle,
+		uchar *src_ieee_addr,
+		uchar *dev_ieee_addr,
+		uchar status,
+		ushort dev_nwk_addr
+);
+
+void APSME_REMOVE_DEVICE_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *parent_ieee_addr,
+		uchar *child_ieee_addr
+);
+
+void APSME_REMOVE_DEVICE_confirm (
+		ZBIF_HANDLE zbif_handle,
+		uchar status
+);
+
+void APSME_TRANSPORT_KEY_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *dst_ieee_addr,
+		uchar key_type,
+		ZB_TRANSPORT_KEY_DATA *transport_key_data
+);
+
+void APSME_TRANSPORT_KEY_confirm (
+		ZBIF_HANDLE zbif_handle,
+		uchar status
+);
+
+void APSME_TRANSPORT_KEY_indication (
+		ZBIF_HANDLE zbif_handle,
+		uchar *dst_ieee_addr,
+		uchar key_type,
+		ZB_TRANSPORT_KEY_DATA *transport_key_data
+);
+
+void NLME_JOIN_indication (
+		ZBIF_HANDLE zbif_handle,
+		ushort nwk_addr,
+		uchar *ieee_addr,
+		uchar capability_info,
+		uchar secure_join
+);
+
+void MGMT_LEAVE_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *dev_ieee_addr,
+		uchar remove_children,
+		uchar rejoin,
+		uchar reuse_address,
+		uchar silent
+);
+
+#endif
+
+/**
+ * TODO: document it!
+ */
+
+void ZDO_ERROR_confirm(ZBIF_HANDLE zbif_handle, uchar status, ushort cluster_id,
+		uchar expected_len);
+
+/**
+ * TODO: document it!
+ */
+
+void ZDO_ERROR_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort cluster_id, uchar expected_len);
+
+typedef struct {
+	uchar ieee_addr[IEEE_ADDR_LEN];
+	uchar request_type;
+	uchar start_index;
+} ZDO_NWK_ADDR_request_t;
+
+#if 0
+void ZIGBEE_request (
+		ZBIF_HANDLE zbif_handle,
+		int request_type,
+		void *request_data
+);
+
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * cplusplus class
+ */
+
+#ifdef __cplusplus
+
+#include <pthread.h>
+
+class CZbIf {
+friend void *dispatch_thread(void *arg);
+
+pthread_mutex_t zb_mutex;
+
+private:
+uchar out_buf[256];
+ZBIF_HANDLE zbif_handle;
+ZBIFFunctions_t *zbif_funcs;
+
+public:
+CZbIf(void);
+
+virtual ~CZbIf();
+
+/**
+ * Connect to the specified device
+ *
+ * @param device
+ * 	The device for connecting to. The device depends on the 
+ * 	way the code has been compiled. 
+ * 	It may be an IP address or a local serial device
+ *
+ * @param zbif_receive_cb	
+ * 	callback function called each time a new message arrives.
+ *
+ * @returns
+ * 	The device descriptor or -1 if error
+ */
+
+int ZBIFConnect (
+		const char *uri
+);
+
+/**
+ * Disconnect from the specified device descriptor
+ * The device descriptor returned by the ZBIFConnect() must be provided
+ */
+
+int ZBIFDisconnect (
+		void
+);
+
+/**
+ * Called each time a message arrives from the dongle
+ */
+
+public:
+
+/**
+ * This performs a soft or hard reset of the zigbee stack
+ */
+
+public:
+void ZDO_RESET_request (
+		uchar options
+);
+
+virtual void ZDO_RESET_confirm (
+		uchar status,
+		uchar restart
+);
+
+void ZDO_START_request (
+		void
+);
+
+virtual void ZDO_START_confirm (
+		uchar status,
+		ushort nwk_addr
+);
+
+void ZDP_MGMT_NWK_UPDATE_request(
+		unsigned long int scanChannel,
+		ushort scanDuration
+);
+
+/**
+ *
+ * @param ieee_addr
+ * 	points to 8 byte buffer representing the destination node IEEE address
+ *
+ * @param request_type
+ * 	ZDO_REQ_TYPE_SD_RES (0x00) for single device response,  
+ * 	ZDO_REQ_TYPE_EX_RES (0x01) for extended response
+ *
+ * @param start_index
+ * 	used only if extended response is selected
+ *
+ * @see ZigBee 2004 specification paragraph 1.4.3.1.1
+ */
+
+void ZDO_NWK_ADDR_request (
+		uchar *ieee_addr,
+		uchar request_type,
+		uchar start_index
+);
+
+/**
+ * Called as response to a ZDO_NWK_ADDR_request(). 
+ *
+ * @param status
+ * 	return status. May be ZDO_SUCCESS, ZDO_INV_REQUESTTYPE, ZDO_DEVICE_NOT_FOUND
+ */
+
+virtual void ZDO_NWK_ADDR_confirm (
+		uchar status,
+		uchar *ieee_addr,
+		ushort nwk_addr,
+		uchar num_assoc_dev,
+		uchar start_index,
+		ushort *nwk_addr_assoc_dev_list
+);
+
+/**
+ *
+ * Request the IEEE address. This function is called by the ZigBee application
+ *
+ * @param nwk_addr
+ * 	Network address to find (16 bit)
+ *
+ * @param request_type
+ * 	00 for single device response, 01 for extended response
+ *
+ * @param start_index
+ * 	used only if extended response is selected
+ */
+
+void ZDO_IEEE_ADDR_request (
+		ushort nwk_addr,
+		uchar request_type,
+		uchar start_index
+);
+
+/**
+ * returns the requested IEEE address. This is generated by the ZigBee Network Layer 
+ *
+ * @param status
+ * 	return status. May be ZDO_SUCCESS, ZDO_INV_REQUESTTYPE, ZDO_DEVICE_NOT_FOUND
+ */
+
+virtual void ZDO_IEEE_ADDR_confirm (
+		uchar status,
+		uchar *ieee_addr,
+		ushort nwk_addr,
+		uchar num_assoc_dev,
+		uchar start_index,
+		ushort *nwk_addr_assoc_dev_list
+);
+
+void ZB_MGMT_LQI_request (
+		ushort nwk_addr,
+		uchar start_index
+);
+
+virtual void ZB_MGMT_LQI_response (
+		uchar srcAddrMode, uchar* src_addr, uchar * asdu
+);
+
+/**
+ * Inquires the 'node descriptor' of the remote device
+ *
+ * @param nwk_addr
+ * 	Network address of interest (16 bit)
+ */
+
+void ZDO_NODE_DESC_request (
+		ushort dst_addr,
+		ushort nwk_addr
+);
+
+/**
+ * returns the requested node descriptor. This is generated by the ZigBee Network Layer 
+ *
+ * @param status
+ * 	return status. May be ZDO_SUCCESS, ZDO_DEVICE_NOT_FOUND
+ *
+ * @param note_desc
+ * 	this is the returned node descriptor. This descriptor is described in [1], clause 1.3.3.4 or 
+ * 	in [2] at clause 2.3.2.4
+ *
+ */
+
+virtual void ZDO_NODE_DESC_confirm (
+		uchar status,
+		ushort nwk_addr,
+		ZB_NODE_DESC *node_desc
+);
+
+/**
+ * Inquires the power descriptor of the remote device
+ *
+ * @param nwk_addr
+ * 	Network address of interest (16 bit)
+ */
+
+void ZDO_POWER_DESC_request (
+		ushort dst_addr,
+		ushort nwk_addr
+);
+
+/**
+ * returns the requested power descriptor. This is generated by the ZigBee Network Layer 
+ *
+ * @param status
+ * 	return status. May be ZDO_SUCCESS, ZDO_DEVICE_NOT_FOUND
+ *
+ * @param descr
+ * 	this is the returned node descriptor. This descriptor is described in [1], clause 1.3.3.5
+ *
+ */
+
+virtual void ZDO_POWER_DESC_confirm (
+		uchar status,
+		ushort nwk_addr,
+		ZB_POWER_DESC *power_desc
+);
+
+/**
+ * Inquires the simple descriptor of the remote device
+ * corresponding the supplied endpoint 
+ *
+ * @param nwk_addr
+ * 	Network address of interest (16 bit)
+ *
+ * @param endpoint
+ * 	8 bit endpoint (range 0x01 - 0xF0)
+ */
+
+void ZDO_SIMPLE_DESC_request (
+		ushort dst_addr,
+		ushort nwk_addr,
+		uchar endpoint
+);
+
+/**
+ * returns the requested simple descriptor. This is generated by the ZigBee Network Layer 
+ *
+ * @param status
+ * 	return status. May be ZDO_SUCCESS, ZDO_INVALID_EP, ZDO_NOT_ACTIVE, ZDO_DEVICE_NOT_FOUND
+ *
+ * @param descr
+ * 	this is the returned node descriptor. This descriptor is described in [1], clause 1.3.3.5
+ * 	The descr may be NULL if the status is ZDO_INVALID_EP or ZDO_NOT_ACTIVE
+ *
+ */
+
+virtual void ZDO_SIMPLE_DESC_confirm (
+		uchar status,
+		ushort nwk_addr,
+		ZB_SIMPLE_DESC *simple_desc
+);
+
+/**
+ * Inquires the list of endpoinds on the remote device with
+ * simple descriptor
+ *
+ * @param nwk_addr
+ * 	Network address of interest (16 bit)
+ *
+ * @param endpoint
+ * 	8 bit endpoint (range 0x01 - 0xF0)
+ */
+
+void ZDO_ACTIVE_EP_DESC_request (
+		ushort dst_addr,
+		ushort nwk_addr
+);
+
+/**
+ * Returns the requested simple descriptor. This is generated by the ZigBee Network Layer 
+ *
+ * @param status
+ * 	return status. May be ZDO_SUCCESS, ZDO_DEVICE_NOT_FOUND
+ *
+ * @param descr
+ * 	this is the returned node descriptor. This descriptor is described in [1], clause 1.3.3.5
+ *
+ */
+
+virtual void ZDO_ACTIVE_EP_DESC_confirm (
+		uchar status,
+		ushort nwk_addr,
+		uchar active_ep_count,
+		uchar *active_ep_list
+);
+
+/**
+ * 
+ * @param nwk_addr
+ * 	Network address of interest (16 bit)
+ *
+ * @param profile_id
+ * 	profile id that is requested to be matched at destination
+ *
+ * @param nicl
+ * 	number of input clusters
+ *
+ * @param icllist
+ * 	array of 16 bit integers representing the list of cluters
+ *
+ * @param nocl
+ * 	number of output clusters
+ */
+
+void ZDO_MATCH_DESC_request (
+		ushort dst_addr,
+		ushort nwk_addr,
+		ushort profile_id,
+		uchar nicl,
+		ushort *icllist,
+		uchar nocl,
+		ushort *ocllist
+);
+
+/**
+ * returns the requested matching descriptor. This is generated by the ZigBee Network Layer 
+ *
+ * @param status
+ * 	return status. May be ZDO_SUCCESS, ZDO_DEVICE_NOT_FOUND
+ *
+ * @param match_len
+ * 	Count of endpoints on the remote device that match the requested criteria
+ *
+ * @param match_list
+ * 	List of bytes. Each byte represents an 8 bit enpoint
+ *
+ */
+
+virtual void ZDO_MATCH_DESC_confirm (
+		uchar status,
+		ushort nwk_addr,
+		uchar match_len,
+		uchar *match_list
+);
+
+/**
+ * 
+ * @param nwk_addr
+ * 	Network address of interest (16 bit)
+ *
+ * @param profile_id
+ * 	profile id that is requested to be matched at destination
+ *
+ * @param nicl
+ * 	number of input clusters
+ *
+ * @param icllist
+ * 	array of 16 bit integers representing the list of cluters
+ *
+ * @param nocl
+ * 	number of output clusters
+ */
+
+virtual void ZDO_MATCH_DESC_indication (
+		ushort src_addr,
+		ushort profile_id,
+		uchar nicl,
+		ushort *icllist,
+		uchar nocl,
+		ushort *ocllist
+);
+
+/**
+ * returns the requested matching descriptor. This is generated by the ZigBee Network Layer 
+ *
+ * @param status
+ * 	return status. May be ZDO_SUCCESS, ZDO_DEVICE_NOT_FOUND
+ *
+ * @param match_len
+ * 	Count of endpoints on the remote device that match the requested criteria
+ *
+ * @param match_list
+ * 	List of bytes. Each byte represents an 8 bit enpoint
+ *
+ */
+
+void ZDO_MATCH_DESC_response (
+		uchar status,
+		ushort nwk_addr,
+		uchar match_len,
+		uchar *match_list
+);
+
+/**
+ * Implements the End_Device_Bind_req primitive described in ZigBee 2006, clause 
+ */
+void ZDO_END_DEVICE_BIND_request (
+		ushort binding_target,
+		uchar *src_ieee_addr,
+		uchar src_ep,
+		ushort profile_id,
+		uchar nicl,
+		ushort *icllist,
+		uchar nocl,
+		ushort *ocllist
+);
+
+/**
+ * Implements the End_Device_Bind_rsp primitive described in ZigBee 2004, clause 1.4.4.2.1
+ *
+ * @param status
+ * 	return status. May be ZDO_SUCCESS, ZDO_NOT_SUPPORTED, ZDO_TIMEOUT or ZDO_NO_MATCH
+ *
+ */
+
+virtual void ZDO_END_DEVICE_BIND_confirm (
+		uchar status
+);
+
+virtual void ZDO_DEVICE_ANNCE_indication (
+		ushort nwk_addr,
+		uchar *ieee_addr,
+		uchar capability
+);
+
+//	Asynchronous indication of ZigBee Stack Status
+virtual void ZIGBEE_STACK_STATUS_indication (
+		uchar status
+);
+
+/*
+ * NLME messages
+ */
+
+/*
+ *
+ * Reference [1] 2.3.10.1
+ *
+ * @param track
+ * 	Indicates if the syncronization should be mantained for future beacons or not
+ */
+
+void NLME_SYNC_request (
+		uchar track
+);
+
+/**
+ * Reference [1] 2.3.10.3
+ */
+
+virtual void NLME_SYNC_confirm (
+		uchar status
+);
+
+/**
+ *
+ * Reference [1] 2.3.10.2
+ *
+ * Called by the Network layer in case of loss of syncronization
+ */
+
+virtual void NLME_SYNC_indication (
+		void
+);
+
+/*
+ * APS messages
+ */
+
+/**
+ *
+ * @param dst_addr_mode
+ * 	In the case the value is 0x02, the dst_addr is a 64 bit IEEE address
+ */
+
+void APSDE_DATA_request (
+		uchar dst_addr_mode,
+		uchar *dst_addr,
+		uchar dst_ep,
+		ushort profile_id,
+		ushort cluster_id,
+		uchar src_ep,
+		uchar asdu_len,
+		uchar *asdu,
+		uchar tx_options,
+		uchar radius
+);
+
+/**
+ *
+ * @param status
+ * 	returned status may be ZDO_SUCCESS, ZDO_NO_BOUND_DEVICE, ZDO_SECURITY_FAIL
+ */
+
+virtual void APSDE_DATA_confirm (
+		uchar dst_addr_mode,
+		uchar *dst_addr,
+		uchar dst_ep,
+		uchar src_ep,
+		uchar status
+);
+
+/**
+ *
+ *
+ * @param sec_status
+ * 	This is the security status. It may be ZDO_SS_UNSECURED, ZDO_SS_SECURED_NWK_KEY, 
+ * 	ZDO_SECURED_LINK_KEY
+ */
+
+virtual void APSDE_DATA_indication (
+		uchar dst_addr_mode,
+		uchar *dst_addr,
+		uchar dst_ep,
+		uchar src_addr_mode,
+		uchar *src_addr,
+		uchar src_ep,
+		ushort profile_id,
+		ushort cluster_id,
+		ushort asdu_len,
+		uchar *asdu,
+		uchar was_broadcast,
+		uchar sec_status
+);
+
+/**
+ */
+
+void APSME_BIND_request (
+		uchar *src_ieee_addr,
+		uchar src_ep,
+		ushort cluster_id,
+		uchar *dst_ieee_addr,
+		uchar dst_ep
+);
+
+void ZDP_MGMT_BIND_Request (
+		ushort remote_dest_addr,
+		ushort startIndex
+);
+
+void ZDP_BIND_request (
+		ushort remote_dest_addr,
+		uchar *src_ieee_addr,
+		uchar src_ep,
+		ushort cluster_id,
+		uchar *dst_ieee_addr,
+		uchar dst_ep
+);
+
+void ZDP_UNBIND_request (
+		ushort remote_dest_addr,
+		uchar *src_ieee_addr,
+		uchar src_ep,
+		ushort cluster_id,
+		uchar *dst_ieee_addr,
+		uchar dst_ep
+);
+
+/**
+ * @param status
+ * 	returned status may be ZDO_SUCCESS, ZDO_ILLEGAL_DEVICE, 
+ * 	ZDO_ILLEGAL_REQUEST, ZDO_TABLE_FULL, ZDO_INVALID_BINDING,
+ * 	ZDO_NOT_SUPPORTED
+ */
+
+virtual void ZDP_MGMT_BIND_Response(
+		uchar status,
+		ushort bindingTableEntries,
+		ushort StartIndex,
+		ushort BindingTableListCount,
+		ZB_BIND_STRUCT * BindingTableList
+);
+
+virtual void APSME_BIND_confirm (
+		uchar status,
+		uchar *src_ieee_addr,
+		uchar src_ep,
+		ushort cluster_id,
+		uchar *dst_ieee_addr,
+		uchar dst_ep
+);
+
+virtual void ZDP_BIND_response(
+		uchar status
+);
+
+virtual void ZDP_UNBIND_response(
+		uchar status
+);
+
+void APSME_UNBIND_request (
+		uchar *src_ieee_addr,
+		uchar src_ep,
+		ushort cluster_id,
+		uchar *dst_ieee_addr,
+		uchar dst_ep
+);
+
+/**
+ *
+ * @param status
+ * 	returned status may be ZDO_SUCCESS, ZDO_ILLEGAL_DEVICE, 
+ * 	ZDO_ILLEGAL_REQUEST, ZDO_TABLE_FULL, ZDO_INVALID_BINDING
+ */
+
+virtual void APSME_UNBIND_confirm (
+		uchar status,
+		uchar *src_ieee_addr,
+		uchar src_ep,
+		ushort cluster_id,
+		uchar *dst_ieee_addr,
+		uchar dst_ep
+);
+
+/**
+ * Attempt to read the requested attribute
+ *
+ * @param attr
+ * 	Requested attribute
+ */
+
+void APSME_GET_request (
+		uchar attr
+);
+
+/**
+ * Returns the requested attribute 
+ *
+ * @param status
+ * 	returned status. May be ZDO_SUCCESS, ZDO_UNSUPPORTED_ATTRIBUTE
+ *
+ * @param attr
+ * 	Requested attribute
+ *
+ * @param attr_len
+ *	length of the returned attribute
+ *
+ * @param attr_value
+ * 	returned attribute value.
+ *
+ */
+
+virtual void APSME_GET_confirm (
+		uchar status,
+		uchar attr,
+		uchar attr_len,
+		uchar *attr_value
+);
+
+/**
+ * Attempt to set the requested attribute
+ *
+ *
+ * @param attr
+ * 	Requested attribute
+ *
+ * @param attr_len
+ *	length of the returned attribute
+ *
+ * @param attr_value
+ * 	returned attribute value.
+ */
+
+void APSME_SET_request (
+		uchar attr,
+		uchar attr_len,
+		uchar *attr_value
+);
+
+/**
+ *
+ * Result from a set attribute request
+ *
+ * @param status
+ * 	returned status. May be ZDO_SUCCESS, ZDO_INVALID_PARAMETER, ZDO_UNSUPPORTED_ATTRIBUTE
+ *
+ * @param attr
+ * 	requested attribute
+ */
+
+virtual void APSME_SET_confirm (
+		uchar status,
+		uchar attr
+);
+
+virtual void MGMT_PERMIT_JOINING_request (
+		ushort nwk_addr,
+		int permitDuration
+);
+
+virtual void MGMT_PERMIT_JOINING_response (
+		uchar status
+);
+
+virtual void MGMT_LEAVE_response (
+		uchar status
+);
+
+virtual void MGMT_LEAVE_confirm (
+		uchar *dev_ieee_addr,
+		uchar status
+);
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+
+/**
+ * TODO: document it!
+ */
+
+virtual void APSME_UPDATE_DEVICE_indication (
+		uchar *src_ieee_addr,
+		uchar *dev_ieee_addr,
+		uchar status,
+		ushort dev_nwk_addr
+);
+
+void APSME_REMOVE_DEVICE_request (
+		uchar *parent_ieee_addr,
+		uchar *child_ieee_addr
+);
+
+virtual void APSME_REMOVE_DEVICE_confirm (
+		uchar status
+);
+
+void APSME_TRANSPORT_KEY_request (
+		uchar *dst_ieee_addr,
+		uchar key_type,
+		ZB_TRANSPORT_KEY_DATA *transport_key_data
+);
+
+virtual void APSME_TRANSPORT_KEY_confirm (
+		uchar status
+);
+
+virtual void APSME_TRANSPORT_KEY_indication (
+		uchar *dst_ieee_addr,
+		uchar key_type,
+		ZB_TRANSPORT_KEY_DATA *transport_key_data
+);
+
+virtual void NLME_JOIN_indication (
+		ushort nwk_addr,
+		uchar *ieee_addr,
+		uchar capability_info,
+		uchar secure_join
+);
+
+virtual void MGMT_LEAVE_request (
+		uchar *dev_ieee_addr,
+		uchar remove_children,
+		uchar rejoin,
+		uchar reuse_address,
+		uchar silent
+);
+#endif
+
+virtual void ZDO_ERROR_confirm (
+		uchar status,
+		ushort cluster_id,
+		uchar expected_len
+);
+
+/**
+ * TODO: document it!
+ */
+
+void ZDO_ERROR_response (
+		uchar status,
+		ushort cluster_id,
+		uchar expected_len
+);
+
+}; /* class CZbIf */
+
+#endif
+
+#endif /* _ZIGBEE_H_ */

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/zigbee_log.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/zigbee_log.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/zigbee_log.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,58 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef _ZIGBEE_LOG_H_
+#define _ZIGBEE_LOG_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef DEBUG_ZIGBEE_API
+#define zb_print_error(...)				\
+		do {								\
+			fprintf(stderr, __VA_ARGS__);	\
+		} while (0)
+#else
+#define zb_print_error(...)				\
+		do {								\
+			;								\
+		} while (0)
+#endif
+
+#ifdef DEBUG_ZIGBEE_API
+#define zb_print(...)				\
+		do {							\
+			printf(__VA_ARGS__);		\
+		} while (0)
+#else
+#define zb_print(...)				\
+		do {							\
+			;							\
+		} while (0)
+#endif
+
+#ifndef ZB_LOG
+#ifdef DEBUG_ZIGBEE
+#define ZB_LOG(a)	a
+#else
+#define ZB_LOG(a)
+#endif
+#endif
+
+void zb_print_bytes(const char *str, const unsigned char *data, const int size);
+int crc16(const unsigned char *data, const int size);
+
+const char *get_param(const char *params[], char *name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/zigbee_ser.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/zigbee_ser.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/zigbee_ser.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,97 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef _ZIGBEE_SER_H_
+#define _ZIGBEE_SER_H_
+
+#define ZB_ZDO_RESET_REQUEST				0x40D0
+#define ZB_ZDO_RESET_CONFIRM				0x80D0
+
+#define ZB_ZDO_START_REQUEST				0x40D1
+#define ZB_ZDO_START_CONFIRM				0x80D1
+
+/** 
+ * ZigBee Device Profile messages 
+ */
+
+#define ZB_ZDO_NWK_ADDR_REQUEST				0x4000
+#define ZB_ZDO_NWK_ADDR_CONFIRM				0x8000
+#define ZB_ZDO_IEEE_ADDR_REQUEST			0x4001
+#define ZB_ZDO_IEEE_ADDR_CONFIRM			0x8001
+#define ZB_ZDO_NODE_DESC_REQUEST			0x4002
+#define ZB_ZDO_NODE_DESC_CONFIRM			0x8002
+#define ZB_ZDO_POWER_DESC_REQUEST			0x4003
+#define ZB_ZDO_POWER_DESC_CONFIRM			0x8003
+#define ZB_ZDO_SIMPLE_DESC_REQUEST			0x4004
+#define ZB_ZDO_SIMPLE_DESC_CONFIRM			0x8004
+#define ZB_ZDO_SIMPLE_DESC_INDICATION		0x0004
+#define ZB_ZDO_SIMPLE_DESC_RESPONSE			0x2004
+#define ZB_ZDO_ACTIVE_EP_DESC_REQUEST		0x4005
+#define ZB_ZDO_ACTIVE_EP_DESC_CONFIRM		0x8005
+#define ZB_ZDO_ACTIVE_EP_DESC_INDICATION	0x0005
+#define ZB_ZDO_ACTIVE_EP_DESC_RESPONSE		0x2005
+#define ZB_ZDO_MATCH_DESC_REQUEST			0x4006
+#define ZB_ZDO_MATCH_DESC_CONFIRM			0x8006
+#define ZB_ZDO_MATCH_DESC_INDICATION		0x0006	
+#define ZB_ZDO_MATCH_DESC_RESPONSE			0x2006	
+
+#define ZB_ZDO_END_DEVICE_BIND_REQUEST		0x4020
+#define ZB_ZDO_END_DEVICE_BIND_CONFIRM		0x8020
+
+#define ZB_MGMT_PERMIT_JOINING_RESPONSE		0x8036
+#define ZB_MGMT_LQI_REQUEST					0x0031
+#define ZB_MGMT_LQI_RESPONSE				0x8031
+
+#define ZB_ZDO_DEVICE_ANNCE_INDICATION		0x0013
+
+/** 
+ * ZigBee APS-ME/DE API 
+ */
+
+#define ZB_APSDE_DATA_REQUEST				0x40A0
+#define ZB_APSDE_DATA_CONFIRM				0x80A0
+#define ZB_APSDE_DATA_INDICATION	 		0x00A0
+
+#define ZB_ZDP_MGMT_BIND_RESPONSE			0x8033
+
+#define ZB_APSME_BIND_REQUEST				0x40B0
+
+#define ZB_ZDP_BIND_RESPONSE				0x80B0
+#define ZB_ZDP_UNBIND_RESPONSE				0x80B8
+
+#define ZB_APSME_UNBIND_REQUEST				0x40B1
+#define ZB_APSME_UNBIND_CONFIRM				0x80B1
+
+#define ZB_APSME_GET_REQUEST				0x40B2
+#define ZB_APSME_GET_CONFIRM				0x80B2
+
+#define ZB_APSME_SET_REQUEST				0x40B3
+#define ZB_APSME_SET_CONFIRM				0x80B3
+
+#define ZB_APSME_REMOVE_DEVICE_REQUEST		0x40B4
+#define ZB_APSME_REMOVE_DEVICE_CONFIRM		0x80B4
+#define ZB_APSME_TRANSPORT_KEY_REQUEST		0x40B5
+#define ZB_APSME_TRANSPORT_KEY_CONFIRM		0x80B5
+#define ZB_APSME_TRANSPORT_KEY_INDICATION	0x00B5
+#define ZB_NLME_JOIN_REQUEST				0x40C0
+#define ZB_NLME_JOIN_INDICATION				0x00C0
+#define ZB_MGMT_LEAVE_REQUEST				0x40C1
+#define ZB_MGMT_LEAVE_RESPONSE				0x8430
+#define ZB_MGMT_LEAVE_CONFIRM				0x80C1
+
+#define ZB_APSME_UPDATE_DEVICE_INDICATION	0x00B6
+#define ZB_REMOVE_DEVICE_REQUEST			0x40B7
+#define ZB_REMOVE_DEVICE_CONFIRM			0x80B7
+
+/* error message */
+
+#define ZB_ERROR_CONFIRM					0x80D2
+#define ZB_ERROR_RESPONSE					0x20D2
+
+#endif /* _ZIGBEE_SER_H_ */

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/zigbee_utils.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/zigbee_utils.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/include/zigbee_utils.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,118 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef __ZIGBEE_UTILS_H__
+#define __ZIGBEE_UTILS_H__
+/*
+ * This file contains utility functions for debugging this implementation
+ */
+
+/* Printing functions */
+
+#include "zigbee.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int ZB_Init_SIMPLE_DESC(ZB_SIMPLE_DESC *simple_desc);
+int ZB_Init_NODE_DESC(ZB_NODE_DESC *node_desc);
+int ZB_Copy_SIMPLE_DESC(ZB_SIMPLE_DESC *simple_desc_dst,
+		ZB_SIMPLE_DESC *simple_desc_src);
+
+void swap_bytes(uchar *buf, int len);
+
+void ZBPrint_ZDO_START_confirm(uchar status, ushort nwk_addr);
+
+void ZBPrint_ZDO_NWK_ADDR_confirm(uchar status, uchar *ieee_addr,
+		ushort nwk_addr, uchar num_assoc_dev, uchar start_index,
+		ushort *nwk_addr_assoc_dev_list);
+
+void ZBPrint_ZDO_IEEE_ADDR_confirm(uchar status, uchar *ieee_addr,
+		ushort nwk_addr, uchar num_assoc_dev, uchar start_index,
+		ushort *nwk_addr_assoc_dev_list);
+
+void ZBPrint_ZDO_NODE_DESC_confirm(uchar status, ushort nwk_addr,
+		ZB_NODE_DESC *node_desc);
+
+void ZBPrint_ZDO_POWER_DESC_confirm(uchar status, ushort nwk_addr,
+		ZB_POWER_DESC *power_desc);
+
+void ZBPrint_ZDO_SIMPLE_DESC_confirm(uchar status, ushort nwk_addr,
+		ZB_SIMPLE_DESC *simple_desc);
+
+void ZBPrint_ZDO_ACTIVE_EP_DESC_confirm(uchar status, ushort nwk_addr,
+		uchar active_ep_count, uchar *active_ep_list);
+
+void ZBPrint_ZDO_DEVICE_ANNCE_indication(ushort nwk_addr, uchar *ieee_addr,
+		uchar capability);
+
+void ZBPrint_ZDO_MATCH_DESC_confirm(uchar status, ushort nwk_addr,
+		uchar match_len, uchar *match_list);
+
+void ZBPrint_ZDO_MATCH_DESC_indication(ushort nwk_addr, ushort profile_id,
+		uchar nicl, ushort *icllist, uchar nocl, ushort *ocllist);
+
+void ZBPrint_ZDO_END_DEVICE_BIND_confirm(uchar status);
+
+void ZBPrint_MGMT_PERMIT_JOINING_response(uchar status);
+
+void ZBPrint_MGMT_LEAVE_response(uchar status);
+
+void ZBPrint_MGMT_LEAVE_confirm(uchar *ieee_addr, uchar rejoin);
+
+void ZBPrint_APSME_GET_confirm(uchar status, uchar attr, uchar attr_len,
+		uchar *attr_value);
+
+void ZBPrint_APSME_SET_confirm(uchar status, uchar attr);
+
+void ZBPrint_APSDE_DATA_confirm(uchar dst_addr_mode, uchar *dst_addr,
+		uchar dst_ep, uchar src_ep, uchar status);
+
+void ZBPrint_APSDE_DATA_request(uchar dst_addr_mode, uchar *dst_addr,
+		uchar dst_ep, ushort profile_id, ushort cluster_id, uchar src_ep,
+		uchar asdu_len, uchar *asdu, uchar tx_options, uchar radius);
+
+void ZBPrint_APSDE_DATA_indication(uchar dst_addr_mode, uchar *dst_addr,
+		uchar dst_ep, uchar src_addr_mode, uchar *src_addr, uchar src_ep,
+		ushort profile_id, ushort cluster_id, ushort asdu_len, uchar *asdu,
+		uchar was_broadcast, uchar sec_status);
+
+void ZBPrint_ZDO_ERROR_confirm(uchar status, ushort cluster_id,
+		uchar expected_len);
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+
+void ZBPrint_NLME_JOIN_indication (
+		ushort nwk_addr,
+		uchar *ieee_addr,
+		uchar capability_info,
+		uchar secure_join
+);
+
+void ZBPrint_NLME_LEAVE_request (
+		uchar *dev_ieee_addr,
+		uchar remove_children,
+		uchar rejoin,
+		uchar reuse_address,
+		uchar silent
+);
+
+void ZBPrint_NLME_LEAVE_confirm (
+		uchar *dev_ieee_addr,
+		uchar status
+);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/scripts/sdiodriver
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/scripts/sdiodriver (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/scripts/sdiodriver Fri Oct 19 18:37:43 2012
@@ -1,0 +1,54 @@
+#!/bin/sh
+#
+# Handle System V init conventions...
+#
+
+EXTRA_PATH=/usr/ti
+case $1 in
+start | restart | force-reload )
+	action="start";
+	;;
+stop)
+	action="stop";
+	;;
+modload)
+	action="modload";
+	;;
+*)
+	action="start";
+esac
+
+
+if test $action  = modload ; then
+	cat /proc/interrupts | grep 'MMC' > /dev/null
+
+	if [ "0$?" -eq "0" ] ; then
+
+		echo MMC driver present
+		cat /proc/modules | grep 'pxahcd' > /dev/null
+		if [ "0$?" -eq "0" ] ; then
+			echo ZSDIO driver already installed 
+		fi
+		exit 0
+	fi
+
+	SDIO_DRIVER_PATH=$EXTRA_PATH/lib/modules/drivers/sdio
+
+	insmod $SDIO_DRIVER_PATH/sdcore.o
+	insmod $SDIO_DRIVER_PATH/pxahcd.o
+	insmod $SDIO_DRIVER_PATH/sdmmc.o
+	insmod $SDIO_DRIVER_PATH/sduart.o
+
+	if ! [ -c /dev/ttyS200 ] ; then
+		mknod /dev/ttyS200 c 4 200
+	fi
+fi
+
+if test $action  = stop ; then
+	rmmod sduart
+	rmmod sdmmc
+	rmmod pxahcd
+	rmmod sdcore
+fi
+
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/Makefile
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/Makefile (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/Makefile Fri Oct 19 18:37:43 2012
@@ -1,0 +1,155 @@
+INCLUDE_DIR	= ../include
+
+CFLAGS	+= -g -c -Wall -I$(INCLUDE_DIR) -DHDLC_USE_INET_SOCKET -I. -DZIGBEE_SECURITY_ENABLED
+
+VERSION=1.2
+
+HDLC_DL_DEVICES =
+DONGLE = 
+
+ifeq ($(strip $(BUILD_INTEGRATION)),y)
+CFLAGS 	+= -DBUILD_INTEGRATION
+DONGLE += bisync.o integration_if.o
+endif
+
+ifeq ($(strip $(BUILD_ZSDIO)),y)
+CFLAGS 	+= -DBUILD_ZSDIO
+DONGLE += zsdio_if.o hdlc_proto.o
+
+ifeq ($(strip $(BUILD_FOR_INET)),y)
+CFLAGS 	+= -DINCLUDE_HDLC_NET
+DONGLE += hdlc_net.o
+endif
+
+ifeq ($(strip $(BUILD_FOR_SERIAL)),y)
+CFLAGS 	+= -DINCLUDE_HDLC_SERIAL
+DONGLE += hdlc_ser.o
+endif
+
+endif
+
+ifeq ($(strip $(BUILD_TELEGESIS)),y)
+CFLAGS 	+= -DBUILD_TELEGESIS
+DONGLE	+= telegesis.o
+endif
+
+ifeq ($(strip $(BUILD_EZSP)),y)
+
+OPTIONS= \
+	-Wcast-align -Wformat -Wimplicit -Wimplicit-int                 \
+	-Wimplicit-function-declaration -Winline -Wlong-long -Wmain     \
+	-Wnested-externs -Wno-import -Wparentheses -Wpointer-arith      \
+	-Wredundant-decls -Wreturn-type -Wstrict-prototypes -Wswitch    \
+	-Wunused \
+	-DGATEWAY_APP \
+	-DEZSP_HOST \
+	-DEZSP_UART \
+	-DEMBER_STACK_PROFILE=$(EMBER_STACK_PROFILE) \
+	-DPLATFORM_HEADER=\"hal/micro/generic/compiler/gcc.h\"   \
+	-DCONFIGURATION_HEADER=\"ezsp_config.h\"
+
+EMBER_DIR = ../../EZSP
+
+INCLUDES= -I$(EMBER_DIR) -I$(EMBER_DIR)/stack 
+
+EZSP_OBJS = \
+	$(EMBER_DIR)/app/util/ezsp/ezsp-enum-decode.o \
+	$(EMBER_DIR)/app/util/serial/linux-serial.o \
+	$(EMBER_DIR)/app/util/ezsp/ezsp.o \
+	$(EMBER_DIR)/app/util/ezsp/ezsp-utils.o \
+	$(EMBER_DIR)/app/util/ezsp/serial-interface-uart.o \
+	$(EMBER_DIR)/app/util/ezsp/ezsp-callbacks.o \
+	$(EMBER_DIR)/app/util/ezsp/ezsp-frame-utilities.o \
+	$(EMBER_DIR)/app/ezsp-uart-host/ash-host.o \
+	$(EMBER_DIR)/app/ezsp-uart-host/ash-host-io.o \
+	$(EMBER_DIR)/app/ezsp-uart-host/ash-host-queues.o \
+	$(EMBER_DIR)/app/ezsp-uart-host/ash-host-ui.o \
+	$(EMBER_DIR)/hal/micro/generic/ash-common.o \
+	$(EMBER_DIR)/hal/micro/generic/crc.o \
+	$(EMBER_DIR)/hal/micro/generic/system-timer.o \
+	$(EMBER_DIR)/hal/micro/generic/random.o \
+	$(EMBER_DIR)/app/util/security/trust-center.o \
+	$(EMBER_DIR)/app/util/source-route-host.o \
+	$(EMBER_DIR)/app/util/source-route-common.o \
+	$(EMBER_DIR)/app/util/security/node.o \
+	$(EMBER_DIR)/app/util/ezsp/appResetAndInitNCP.o \
+	
+
+CFLAGS += $(OPTIONS) $(INCLUDES) -g
+CXXFLAGS += $(INCLUDES) -g
+
+CFLAGS	+= -DBUILD_EZSP 
+DONGLE	+= ezsp_ser.o ezsp_if.o $(EZSP_OBJS) 
+
+endif
+
+ifeq ($(strip $(BUILD_FREESCALE)),y)
+CFLAGS += -DBUILD_FREESCALE
+DONGLE += freescale_ser.o freescale_if.o
+endif
+
+ifeq ($(strip $(BUILD_MICRO_SD)),y)
+CFLAGS += -DBUILD_MICRO_SD
+DONGLE += MicroSD_ser.o MicroSD_if.o SDIO.o MicroSD_utils.o time_ce.o 
+endif
+
+ifeq ($(strip $(BUILD_XBEE2)),y)
+CFLAGS 	+= -DBUILD_XBEE2
+DONGLE += xbee2.o
+endif
+
+TARGETS = libzigbee.a 
+
+all: $(TARGETS) zigbee_c.o zigbee_cpp.o
+
+libhdlc.a: hdlc_proto.o $(HDLC_DL_DEVICES) 
+	@echo AR $@ $?
+	@$(AR) r $@ $?
+
+libzigbee.a: $(DONGLE) zigbee_c.o zigbee.o zb_conn.o zigbee_utils.o zigbee_log.o
+	@echo AR $@ $?
+	@$(AR) r $@ $?
+
+
+libzigbee.so: $(DONGLE) zigbee_c.o zigbee.o zb_conn.o zigbee_utils.o zigbee_log.o
+	g++ -shared -o $@  $(DONGLE) zigbee_c.o zigbee.o zb_conn.o zigbee_utils.o zigbee_log.o -L. -lthreadutil
+
+
+hdlc_ser.o: hdlc_ser.c
+	$(CC) $(CFLAGS) hdlc_ser.c
+
+hdlc_net.o: hdlc_net.c
+	$(CC) $(CFLAGS) hdlc_net.c
+
+utils.o: utils.c
+	$(CC) $(CFLAGS) utils.c
+
+hdlc_proto.o: hdlc_proto.c
+	$(CC) $(CFLAGS) hdlc_proto.c
+
+zsdio_if.o: zsdio_if.c $(INCLUDE_DIR)/zigbee.h
+	$(CC) $(CFLAGS) zsdio_if.c 
+
+integration_if.o: integration_if.c $(INCLUDE_DIR)/zigbee.h
+
+bisync.o: bisync.c
+	$(CC) $(CFLAGS) bisync.c 
+
+zb_conn.o: zb_conn.c
+	$(CC) $(CFLAGS) zb_conn.c 
+	
+zigbee_cpp.o: zigbee.cpp $(INCLUDE_DIR)/zigbee.h
+	$(CXX) $(CXXFLAGS) $< 
+
+ezsp_if.o: ezsp_if.c $(INCLUDE_DIR)/zigbee.h
+	$(CC) $(CFLAGS) -I$(THREADUTILS_DIR) -lpthread -lthreadutil $< 
+
+zigbee_c.o: zigbee_c.c $(INCLUDE_DIR)/zigbee.h
+	$(CC) $(CFLAGS) $< 
+	
+clean:
+	@rm -rf *~ $(TARGETS) $(EZSP_OBJS) *.o *.a
+
+install:
+	$(STRIP) hdlc.a
+	#install -m 644 hdlc.a $(PREFIX)/usr/$(EXTRA_DIR)/lib

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_if.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_if.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_if.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,1803 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h> 
+#include "zb_conn.h"
+#include <zigbee.h>
+#include "zigbee_local.h"
+#include "zigbee_log.h"
+
+#ifdef DEBUG_ZIGBEE_API
+#include "zigbee_utils.h"
+#endif
+
+#include "MicroSD_utils.h"
+#include "MicroSD_ser.h"
+#include "MicroSD_if.h"
+#include "SerialProtocolTypes.h"
+#include "SerialProtocolGlobalDefine.h"
+#include "SerialProtocolInner.h"
+
+static uchar out_buf[MAX_OTA_LEN];
+static uchar vect[MAX_OTA_LEN];
+
+extern int zigbeeLogTrace;
+extern FILE *zigbeeTraceLogFile;
+
+// parametri di configurazione
+uchar devType;
+uchar panID[PAN_length];
+
+uchar startCmd[MAX_OTA_LEN];
+uchar startCmd2[MAX_OTA_LEN];
+uchar simpledescconf[MAX_OTA_LEN];
+uchar cmd[MAX_OTA_LEN];
+
+int lenStartCmd;
+
+int multisimpledesc_flag = 0;
+
+int maxWinSize;
+int maxInterframeDelay;
+
+#define FORWARD_ADDR 65535 // 0xFFFF
+void MicroSD_ParseNExec(ZBIF_HANDLE zbif_handle, uchar *p, int size);
+
+// #ifndef ZIGBEE_USE_DATA_STRUCTURES
+void MicroSD_ZDO_START_request(ZBIF_HANDLE zbif_handle);
+void MicroSD_ZDO_MATCH_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, ushort profile_id, uchar nicl, ushort *icllist,
+		uchar nocl, ushort *ocllist);
+void MicroSD_ZDO_IEEE_ADDR_request(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar request_type, uchar start_index);
+void MicroSD_ZDO_NWK_ADDR_request(ZBIF_HANDLE zbif_handle, uchar *ieee_addr,
+		uchar request_type, uchar start_index);
+void MicroSD_ZDO_NODE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr);
+void MicroSD_ZDO_SIMPLE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, uchar endpoint);
+void MicroSD_ZDO_ACTIVE_EP_DESC_request(ZBIF_HANDLE zbif_handle,
+		ushort dst_addr, ushort nwk_addr);
+void MicroSD_ZDO_POWER_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr);
+void MicroSD_ZDO_END_DEVICE_BIND_request(ZBIF_HANDLE zbif_handle,
+		ushort binding_target, uchar *src_ieee_addr, uchar src_ep,
+		ushort profile_id, uchar nicl, ushort *icllist, uchar nocl,
+		ushort *ocllist);
+void MicroSD_APSDE_DATA_request(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, ushort profile_id, ushort cluster_id,
+		uchar src_ep, uchar asdu_len, uchar *asdu, uchar tx_options,
+		uchar radius);
+void MicroSD_ZDO_RESET_request(ZBIF_HANDLE zbif_handle, uchar options);
+void MicroSD_ZDO_MATCH_DESC_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort dst_addr, uchar match_len, uchar *match_list);
+void MicroSD_APSME_BIND_request(ZBIF_HANDLE zbif_handle, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep);
+void MicroSD_APSME_UNBIND_request(ZBIF_HANDLE zbif_handle, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep);
+void MicroSD_APSME_GET_request(ZBIF_HANDLE zbif_handle, uchar attr);
+void MicroSD_APSME_SET_request(ZBIF_HANDLE zbif_handle, uchar attr,
+		uchar attr_len, uchar *attr_value);
+void MicroSD_MGMT_PERMIT_JOINING_request(ZBIF_HANDLE zbif_handle,
+		ushort nwk_addr, int permitDuration);
+#ifdef INCLUDE_ZIGBEE_SECURITY
+void MicroSD_APSME_REMOVE_DEVICE_request (ZBIF_HANDLE zbif_handle, uchar *parent_ieee_addr, uchar *child_ieee_addr);
+void MicroSD_APSME_TRANSPORT_KEY_request (ZBIF_HANDLE zbif_handle, uchar *dst_ieee_addr, uchar key_type, ZB_TRANSPORT_KEY_DATA *transport_key_data);
+void MicroSD_NLME_LEAVE_request (ZBIF_HANDLE zbif_handle, uchar *dev_ieee_addr, uchar remove_children, uchar rejoin, uchar reuse_address, uchar silent);
+#endif
+void MicroSD_ZDO_ERROR_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort cluster_id, uchar expected_len);
+// #endif
+
+void MicroSD_ZB_MGMT_LQI_request(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar start_index);
+
+void mangageAdditionalSettings() {
+	int i;
+
+	printf("mangageAdditionalSettings -> START \n");
+	printf("mangageAdditionalSettings buf=\n");
+	for (i = 0; i < 5; i++)
+		printf(" %x", out_buf[i]);
+	printf("\n");
+
+}
+
+void mangageGetIEEE(ZBIFCbs_t *zbif_cbs, ZBIF_HANDLE zbif_handle) {
+	unsigned char cmd[SIZE_IEEE_ADDRESS];
+	int i, j;
+
+	printf("mangageGetIEEE -> START \n");
+	printf("mangageGetIEEE buf=\n");
+	for (i = 0; i < 12; i++)
+		printf(" %x", out_buf[i]);
+	printf("\n");
+
+	for (i = 0, j = (SIZE_IEEE_ADDRESS - 1); i < SIZE_IEEE_ADDRESS; i++, j--)
+		cmd[i] = out_buf[POS_CMD_DATA + j];
+
+	zbif_cbs->APSME_GET_confirm(zbif_handle, 0x00, ZB_ATTR_GET_EUI64, 8, cmd);
+	printf("MicroSD_APSME_GET_request -> END \n");
+}
+
+void manageStarDevice(ZBIFCbs_t *zbif_cbs, ZBIF_HANDLE zbif_handle) {
+	uchar status;
+	ushort nwk_addr;
+
+	printf("manageStarDevice -> START \n");
+
+	status = out_buf[RSP_STARTNWK_POS_STATUS];
+	nwk_addr =
+			BUILD_UINT16(out_buf[RSP_STARTNWK_POS_SHORT_ADDR+1], out_buf[RSP_STARTNWK_POS_SHORT_ADDR]);
+	printf("manageStarDevice -> status = %x nwk_addr = %d \n", status,
+			nwk_addr);
+
+	zbif_cbs->ZDO_START_confirm(zbif_handle, status, nwk_addr);
+
+	// ZBIFCbs_t *zbif_cbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+	/* if (zbif_cbs->ZDO_START_confirm) {
+	 zbif_cbs->ZDO_START_confirm ((void *)zbif_cbs, status, nwk_addr);
+	 } */
+
+	printf("manageStarDevice -> END \n");
+}
+
+void manageMatchResponse(ZBIFCbs_t *zbif_cbs, ZBIF_HANDLE zbif_handle) {
+	ushort nwk_addr;
+	uchar match_len;
+	uchar *match_list;
+	uchar status = STATUS_OK;
+
+	if (out_buf[RSP_STARTNWK_POS_IDT] == 0xFF
+			&& out_buf[RSP_STARTNWK_POS_IDT + 1] == 0xFF
+			&& out_buf[RSP_STARTNWK_POS_IDT + 2] == 0xFF) {
+		status = STATUS_KO;
+	}
+
+	if (status == STATUS_KO) {
+		nwk_addr = -1;
+		match_len = 0;
+		match_list = NULL;
+	} else {
+		nwk_addr =
+				BUILD_UINT16(out_buf[RSP_STARTNWK_POS_IDT+1], out_buf[RSP_STARTNWK_POS_IDT]);
+		match_len = 1;
+		match_list = (uchar *) malloc(1);
+		match_list[0] = out_buf[RSP_STARTNWK_POS_IDT + 2];
+	}
+
+	zbif_cbs->ZDO_MATCH_DESC_confirm(zbif_handle, status, nwk_addr, match_len,
+			match_list);
+	/* ZBIFCbs_t *zbif_cbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+	 if (zbif_cbs->ZDO_MATCH_DESC_confirm) {
+	 zbif_cbs->ZDO_MATCH_DESC_confirm ((void *)zbif_cbs, status, nwk_addr, match_len, match_list);
+	 } */
+
+	if (match_list != NULL)
+		free(match_list);
+}
+
+void manageIEEEResponse(ZBIFCbs_t *zbif_cbs, ZBIF_HANDLE zbif_handle) {
+	uchar status;
+	uchar ieee_addr[SIZE_IEEE_ADDRESS];
+	ushort nwk_addr;
+	uchar num_assoc_dev;
+	uchar start_index;
+	ushort *nwk_addr_assoc_dev_list;
+	int i, j;
+
+	status = out_buf[RSP_IEEE_POS_STATUS];
+	if (status == STATUS_OK) {
+		nwk_addr =
+				BUILD_UINT16(out_buf[RSP_IEEE_POS_NWK+1], out_buf[RSP_IEEE_POS_NWK]);
+		for (i = 0; i < SIZE_IEEE_ADDRESS; i++)
+			ieee_addr[i] = out_buf[RSP_IEEE_POS_IEEE + i];
+		num_assoc_dev = out_buf[RSP_IEEE_POS_NUMDEV];
+		start_index = out_buf[RSP_IEEE_POS_START];
+		if (num_assoc_dev > 0) {
+			nwk_addr_assoc_dev_list = (ushort *) malloc(num_assoc_dev);
+			for (i = 0, j = 0; i < num_assoc_dev; i++, j = j + 2) {
+				nwk_addr_assoc_dev_list[i] =
+						BUILD_UINT16(out_buf[RSP_IEEE_POS_LISTDEV+1+j], out_buf[RSP_IEEE_POS_LISTDEV+j]);
+			}
+		}
+	}
+
+	/* ZBIFCbs_t *zbif_cbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+	 if (zbif_cbs->ZDO_IEEE_ADDR_confirm) {
+	 zbif_cbs->ZDO_IEEE_ADDR_confirm ((void *)zbif_cbs, status, ieee_addr, nwk_addr, num_assoc_dev, start_index, nwk_addr_assoc_dev_list);
+	 } */
+	zbif_cbs->ZDO_IEEE_ADDR_confirm(zbif_handle, status, ieee_addr, nwk_addr,
+			num_assoc_dev, start_index, nwk_addr_assoc_dev_list);
+
+	if (nwk_addr_assoc_dev_list && num_assoc_dev > 0) {
+		free(nwk_addr_assoc_dev_list);
+	}
+}
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+void manageLeave(ZBIFCbs_t *zbif_cbs, ZBIF_HANDLE zbif_handle) {
+	uchar dev_ieee_addr[SIZE_IEEE_ADDRESS];
+	uchar status;
+	int i;
+
+	status = out_buf[RSP_LEAVE_POS_STATUS];
+	if (out_buf[POS_LEN] == 0x01) {
+		for (i=0; i<SIZE_IEEE_ADDRESS; i++) dev_ieee_addr[i] = (uchar)0xFF;
+	}
+	else {
+		for (i=0; i<SIZE_IEEE_ADDRESS; i++) dev_ieee_addr[i] = out_buf[RSP_LEAVE_POS_IEEE];
+	}
+
+	/* ZBIFCbs_t *zbif_cbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+	 if (zbif_cbs->NLME_LEAVE_confirm) {
+	 zbif_cbs->NLME_LEAVE_confirm ((void *)zbif_cbs, (uchar *)dev_ieee_addr, status);
+	 } */
+	zbif_cbs->NLME_LEAVE_confirm (zbif_handle, (uchar *)dev_ieee_addr, status);
+}
+#endif
+
+void manageNwkAddress(ZBIFCbs_t *zbif_cbs, ZBIF_HANDLE zbif_handle) {
+	uchar status;
+	uchar ieee_addr[SIZE_IEEE_ADDRESS];
+	ushort nwk_addr;
+	uchar num_assoc_dev;
+	uchar start_index;
+	ushort *nwk_addr_assoc_dev_list;
+	int i, j;
+
+	status = out_buf[RSP_NWK_POS_STATUS];
+	if (status == STATUS_OK) {
+		nwk_addr =
+				BUILD_UINT16(out_buf[RSP_NWK_POS_NWK+1], out_buf[RSP_NWK_POS_NWK]);
+		for (i = 0; i < SIZE_IEEE_ADDRESS; i++)
+			ieee_addr[i] = out_buf[RSP_NWK_POS_IEEE + i];
+		num_assoc_dev = out_buf[RSP_NWK_POS_NUMDEV];
+		start_index = out_buf[RSP_NWK_POS_START];
+		if (num_assoc_dev > 0) {
+			nwk_addr_assoc_dev_list = (ushort *) malloc(num_assoc_dev);
+			for (i = 0, j = 0; i < num_assoc_dev; i++, j = j + 2) {
+				nwk_addr_assoc_dev_list[i] =
+						BUILD_UINT16(out_buf[RSP_NWK_POS_LISTDEV+1+j], out_buf[RSP_NWK_POS_LISTDEV+j]);
+			}
+		}
+	}
+
+	/* ZBIFCbs_t *zbif_cbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+	 if (zbif_cbs->ZDO_NWK_ADDR_confirm) {
+	 zbif_cbs->ZDO_NWK_ADDR_confirm ((void *)zbif_cbs, status, ieee_addr, nwk_addr, num_assoc_dev, start_index, nwk_addr_assoc_dev_list);
+	 } */
+	zbif_cbs->ZDO_NWK_ADDR_confirm(zbif_handle, status, ieee_addr, nwk_addr,
+			num_assoc_dev, start_index, nwk_addr_assoc_dev_list);
+
+	if (nwk_addr_assoc_dev_list && num_assoc_dev > 0)
+		free(nwk_addr_assoc_dev_list);
+}
+
+void manageDeviceAnnce(ZBIFCbs_t *zbif_cbs, ZBIF_HANDLE zbif_handle) {
+	ushort nwk_addr;
+	uchar ieee_addr[SIZE_IEEE_ADDRESS];
+	uchar capability;
+	int i, j;
+
+	printf("manageDeviceAnnce buf=\n");
+	for (i = 0; i < 15; i++)
+		printf(" %x", out_buf[i]);
+	printf("\n");
+
+	for (i = 0, j = 7; i < SIZE_IEEE_ADDRESS; i++, j--)
+		ieee_addr[j] = out_buf[POS_CMD_DATA + i];
+	nwk_addr =
+			BUILD_UINT16(out_buf[POS_CMD_DATA+SIZE_IEEE_ADDRESS+1], out_buf[POS_CMD_DATA+SIZE_IEEE_ADDRESS]);
+	printf("manageDeviceAnnce -> nwk_addr = %d \n", nwk_addr);
+
+	capability =
+			out_buf[POS_CMD_DATA + SIZE_IEEE_ADDRESS + SHORT_ADDRESS_length];
+
+	/* ZBIFCbs_t *zbif_cbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+	 if (zbif_cbs->ZDO_DEVICE_ANNCE_indication) {
+	 zbif_cbs->ZDO_DEVICE_ANNCE_indication ((void *)zbif_cbs, nwk_addr, ieee_addr, capability);
+	 } */
+	zbif_cbs->ZDO_DEVICE_ANNCE_indication(zbif_handle, nwk_addr, ieee_addr,
+			capability);
+}
+
+void manageNodeDesc(ZBIFCbs_t *zbif_cbs, ZBIF_HANDLE zbif_handle) {
+	uchar status;
+	ushort nwk_addr;
+	ZB_NODE_DESC *node_desc;
+
+	node_desc = (ZB_NODE_DESC *) malloc(sizeof(ZB_NODE_DESC));
+
+	status = out_buf[RSP_NODE_POS_STATUS];
+	if (status != STATUS_KO) {
+		nwk_addr =
+				BUILD_UINT16(out_buf[RSP_NODE_POS_NWK+1], out_buf[RSP_NODE_POS_NWK]);
+		node_desc->logical_type = out_buf[RSP_NODE__POS_LOGTYPE];
+		node_desc->complx_desc_avail = out_buf[RSP_NODE__POS_COMPLEXDESCAVAIL];
+		node_desc->user_desc_avail = out_buf[RSP_NODE__POS_USERDESCAVAIL];
+		node_desc->reserved = out_buf[RSP_NODE__POS_RESERVED];
+		node_desc->aps_flags = out_buf[RSP_NODE__POS_APS];
+		node_desc->freq_band = out_buf[RSP_NODE__POS_FREQUENCY];
+		node_desc->mac_cap = out_buf[RSP_NODE__POS_CAPABILITY];
+		node_desc->manifact_code =
+				BUILD_UINT16(out_buf[RSP_NODE__POS_MANUFACT+1], out_buf[RSP_NODE__POS_MANUFACT]);
+		node_desc->max_buf_size = out_buf[RSP_NODE__POS_MAXBUFFERSIZE];
+		node_desc->max_transf_size =
+				BUILD_UINT16(out_buf[RSP_NODE__POS_MAXINTRANSFER+1], out_buf[RSP_NODE__POS_MAXINTRANSFER]);
+		node_desc->server_mask =
+				BUILD_UINT16(out_buf[RSP_NODE__POS_SERVERMASK+1], out_buf[RSP_NODE__POS_SERVERMASK]);
+	}
+
+	/* ZBIFCbs_t *zbif_cbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+	 if (zbif_cbs->ZDO_NODE_DESC_confirm) {
+	 zbif_cbs->ZDO_NODE_DESC_confirm ((void *)zbif_cbs, status, nwk_addr, node_desc);
+	 } */
+	zbif_cbs->ZDO_NODE_DESC_confirm(zbif_handle, status, nwk_addr, node_desc);
+
+	if (node_desc)
+		free(node_desc);
+}
+
+void manageSimpleDesc(ZBIFCbs_t *zbif_cbs, ZBIF_HANDLE zbif_handle) {
+	uchar status;
+	ushort nwk_addr;
+	ZB_SIMPLE_DESC *simple_desc;
+	int pos, i;
+
+	// for (i=0; i<40; i++) printf("%x ", out_buf[i]);
+	// printf("\n");
+
+	simple_desc = (ZB_SIMPLE_DESC *) malloc(sizeof(ZB_SIMPLE_DESC));
+
+	status = out_buf[RSP_SIMPLE_POS_STATUS];
+	if (status != STATUS_KO) {
+		nwk_addr =
+				BUILD_UINT16(out_buf[RSP_SIMPLE_POS_NWK+1], out_buf[RSP_SIMPLE_POS_NWK]);
+		simple_desc->ep = out_buf[RSP_SIMPLE__POS_EP];
+		simple_desc->app_profile_id =
+				BUILD_UINT16(out_buf[RSP_SIMPLE__POS_APPPROFID], out_buf[RSP_SIMPLE__POS_APPPROFID+1]);
+		simple_desc->app_device_id =
+				BUILD_UINT16(out_buf[RSP_SIMPLE__POS_APPDEVID+1], out_buf[RSP_SIMPLE__POS_APPDEVID]);
+		simple_desc->app_device_ver = out_buf[RSP_SIMPLE__POS_APPDEVVER];
+		simple_desc->reserved = out_buf[RSP_SIMPLE__POS_RESERVED];
+
+		// decodifica clusters
+		simple_desc->app_in_cluster_count = out_buf[RSP_SIMPLE__POS_CLUSTER];
+		pos = RSP_SIMPLE__POS_CLUSTER + 1;
+		if (simple_desc->app_in_cluster_count > 0) {
+			simple_desc->app_in_cluster_list = (ushort *) malloc(
+					simple_desc->app_in_cluster_count);
+			for (i = 0; i < simple_desc->app_in_cluster_count; i++) {
+				simple_desc->app_in_cluster_list[i] =
+						BUILD_UINT16(out_buf[pos+1], out_buf[pos]);
+				pos = pos + 2;
+			}
+		}
+
+		simple_desc->app_out_cluster_count = out_buf[pos];
+		pos = pos + 1;
+		if (simple_desc->app_out_cluster_count > 0) {
+			simple_desc->app_out_cluster_list = (ushort *) malloc(
+					simple_desc->app_out_cluster_count);
+			for (i = 0; i < simple_desc->app_out_cluster_count; i++) {
+				simple_desc->app_out_cluster_list[i] =
+						BUILD_UINT16(out_buf[pos+1], out_buf[pos]);
+				pos = pos + 2;
+			}
+		}
+
+	}
+
+	/* ZBIFCbs_t *zbif_cbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+	 if (zbif_cbs->ZDO_SIMPLE_DESC_confirm) {
+	 zbif_cbs->ZDO_SIMPLE_DESC_confirm ((void *)zbif_cbs, status, nwk_addr, simple_desc);
+	 } */
+	zbif_cbs->ZDO_SIMPLE_DESC_confirm(zbif_handle, status, nwk_addr,
+			simple_desc);
+
+	if (simple_desc) {
+		if (simple_desc->app_in_cluster_list
+				&& simple_desc->app_in_cluster_count > 0)
+			free(simple_desc->app_in_cluster_list);
+		if (simple_desc->app_out_cluster_list
+				&& simple_desc->app_out_cluster_count > 0)
+			free(simple_desc->app_out_cluster_list);
+		free(simple_desc);
+	}
+}
+
+void manageActiveEpDesc(ZBIFCbs_t *zbif_cbs, ZBIF_HANDLE zbif_handle) {
+	uchar status;
+	ushort nwk_addr;
+	uchar active_ep_count;
+	uchar *active_ep_list;
+	int i;
+
+	status = out_buf[RSP_ACTIVEEP_POS_STATUS];
+	if (status != STATUS_KO) {
+		nwk_addr =
+				BUILD_UINT16(out_buf[RSP_ACTIVEEP_POS_NWK+1], out_buf[RSP_ACTIVEEP_POS_NWK]);
+		active_ep_count = out_buf[RSP_ACTIVEEP_POS_EPCNT];
+		if (active_ep_count > 0) {
+			active_ep_list = (uchar *) malloc(active_ep_count);
+			for (i = 0; i < active_ep_count; i++)
+				active_ep_list[i] = out_buf[RSP_ACTIVEEP_POS_EPLIST];
+		}
+	}
+
+	/* ZBIFCbs_t *zbif_cbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+	 if (zbif_cbs->ZDO_ACTIVE_EP_DESC_confirm) {
+	 zbif_cbs->ZDO_ACTIVE_EP_DESC_confirm ((void *)zbif_cbs, status, nwk_addr, active_ep_count, active_ep_list);
+	 } */
+	zbif_cbs->ZDO_ACTIVE_EP_DESC_confirm(zbif_handle, status, nwk_addr,
+			active_ep_count, active_ep_list);
+
+	if (active_ep_list && active_ep_count > 0) {
+		free(active_ep_list);
+	}
+}
+
+void managePowerDesc(ZBIFCbs_t *zbif_cbs, ZBIF_HANDLE zbif_handle) {
+	uchar status;
+	ushort nwk_addr;
+	ZB_POWER_DESC *power_desc;
+
+	power_desc = (ZB_POWER_DESC *) malloc(sizeof(ZB_POWER_DESC));
+
+	status = out_buf[RSP_POWER_POS_STATUS];
+	if (status != STATUS_KO) {
+		nwk_addr =
+				BUILD_UINT16(out_buf[RSP_POWER_POS_NWK+1], out_buf[RSP_POWER_POS_NWK]);
+		power_desc->curr_pw_mode = out_buf[RSP_POWER_POS_PMODE];
+		power_desc->avail_pw_src = out_buf[RSP_POWER_POS_PSOURCES];
+		power_desc->curr_pw_src = out_buf[RSP_POWER_POS_CPS];
+		power_desc->curr_pw_src_level = out_buf[RSP_POWER_POS_CPSL];
+	}
+
+	/* ZBIFCbs_t *zbif_cbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+	 if (zbif_cbs->ZDO_POWER_DESC_confirm) {
+	 zbif_cbs->ZDO_POWER_DESC_confirm ((void *)zbif_cbs, status, nwk_addr, power_desc);
+	 } */
+	zbif_cbs->ZDO_POWER_DESC_confirm(zbif_handle, status, nwk_addr, power_desc);
+
+	if (power_desc) {
+		free(power_desc);
+	}
+}
+
+void manageEndDeviceBind(ZBIFCbs_t *zbif_cbs, ZBIF_HANDLE zbif_handle) {
+	uchar status = STATUS_OK;
+
+	/* ZBIFCbs_t *zbif_cbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+	 if (zbif_cbs->ZDO_END_DEVICE_BIND_confirm) {
+	 zbif_cbs->ZDO_END_DEVICE_BIND_confirm ((void *)zbif_cbs, status);
+	 } */
+	zbif_cbs->ZDO_END_DEVICE_BIND_confirm(zbif_handle, status);
+}
+
+void manageSendDataConfirm(ZBIFCbs_t *zbif_cbs, ZBIF_HANDLE zbif_handle) {
+	uchar dst_addr_mode;
+	uchar dst_addr[SIZE_IEEE_ADDRESS];
+	uchar dst_ep;
+	uchar src_ep;
+	uchar status;
+	int i;
+
+	status = out_buf[RSP_SENDDATA_STATUS_POS];
+	if (status != STATUS_KO) {
+		dst_addr_mode = out_buf[RSP_SENDDATA_DST_ADDRMODE_POS];
+		if (dst_addr_mode == DEST_ADDR_MODE_16_BIT) {
+			for (i = 0; i < SHORT_ADDRESS_length; i++)
+				dst_addr[i] = out_buf[RSP_SENDDATA_DST_SHORTADDR_POS + i];
+		} else {
+			for (i = 0; i < SIZE_IEEE_ADDRESS; i++)
+				dst_addr[i] = out_buf[RSP_SENDDATA_DST_IEEEADDR_POS + i];
+		}
+		dst_ep = out_buf[RSP_SENDDATA_DST_EP_POS];
+		src_ep = out_buf[RSP_SENDDATA_SRC_EP_POS];
+	}
+
+	/* ZBIFCbs_t *zbif_cbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+	 if (zbif_cbs->APSDE_DATA_confirm) {
+	 zbif_cbs->APSDE_DATA_confirm ((void *)zbif_cbs, dst_addr_mode, dst_addr, dst_ep, src_ep, status);
+	 } */
+	zbif_cbs->APSDE_DATA_confirm(zbif_handle, dst_addr_mode, dst_addr, dst_ep,
+			src_ep, status);
+}
+
+void manageIncomingData(ZBIFCbs_t *zbif_cbs, ZBIF_HANDLE zbif_handle) {
+	uchar dst_addr_mode;
+	uchar dst_addr[SHORT_ADDRESS_length];
+	uchar dst_ep;
+	uchar src_addr_mode;
+	uchar src_addr[SHORT_ADDRESS_length];
+	uchar src_ep;
+	ushort profile_id;
+	ushort cluster_id;
+	ushort asdu_len;
+	uchar *asdu;
+	uchar was_broadcast;
+	uchar sec_status;
+	int i;
+
+	// dest address
+	dst_addr_mode = DEST_ADDR_MODE_16_BIT;
+	dst_addr[0] = out_buf[FWD_DATA_DSTNWKADDR_POS + 1];
+	dst_addr[1] = out_buf[FWD_DATA_DSTNWKADDR_POS];
+	dst_ep = out_buf[FWD_DATA_LEP_POS];
+	// source address
+	src_addr_mode = DEST_ADDR_MODE_16_BIT;
+	src_addr[0] = out_buf[FWD_DATA_NWKADDR_POS + 1];
+	src_addr[1] = out_buf[FWD_DATA_NWKADDR_POS];
+	src_ep = out_buf[FWD_DATA_EP_POS];
+	// profile id
+	profile_id =
+			BUILD_UINT16(out_buf[FWD_DATA_PROFID_POS+1], out_buf[FWD_DATA_PROFID_POS]);
+	// cluster id
+	cluster_id =
+			BUILD_UINT16(out_buf[FWD_DATA_CID_POS +1], out_buf[FWD_DATA_CID_POS]);
+
+	was_broadcast = out_buf[FWD_DATA_BROADCAST_POS];
+	sec_status = out_buf[FWD_DATA_SECSTATUS_POS];
+	asdu_len = out_buf[FWD_DATA_LENPAYLOAD_POS];
+	if (asdu_len > 0) {
+		asdu = (uchar *) malloc(asdu_len);
+		for (i = 0; i < asdu_len; i++)
+			asdu[i] = out_buf[FWD_DATA_PAYLOAD_POS + i];
+	}
+
+	// ZBIFCbs_t *zbif_cbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+	// if (zbif_cbs->APSDE_DATA_indication) {
+	zbif_cbs->APSDE_DATA_indication(zbif_handle, dst_addr_mode,
+			(uchar *) dst_addr, dst_ep, src_addr_mode, (uchar *) src_addr,
+			src_ep, profile_id, cluster_id, asdu_len, asdu, was_broadcast,
+			sec_status);
+	// }
+
+	if (asdu_len > 0 && asdu != NULL)
+		free(asdu);
+}
+
+void MicroSD_ZDO_START_request(ZBIF_HANDLE zbif_handle) {
+	FILE * zigbeeTraceLogFile;
+	unsigned char crc;
+	int res, i;
+	printf("MicroSD_ZDO_START_request -> start! \n");
+	//zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+
+	// compongo il comando K per partire come router sul canale 12 Pan 0
+	/* vect[0] = SYNCH_CHAR;
+	 vect[1] = CMD_PCK_RESPONSE_ZIGBEE;
+	 vect[2] = 0x4B;
+	 vect[3] = 0x16;
+	 vect[4] = 0x18;
+	 vect[5] = 0x00;
+	 vect[6] = 0x00;
+	 vect[7] = 0x10;
+	 vect[8] = 0x00;
+	 vect[9] = 0x00;
+	 vect[10] = 0x00;
+	 vect[11] = 0x00;
+	 vect[12] = 0x0C;
+	 vect[13] = 0x0F;
+	 vect[14] = 0x05;
+	 vect[15] = 0x02;
+	 vect[16] = 0x00;
+	 vect[17] = 0x09;
+	 vect[18] = 0x00;
+	 vect[19] = 0x0C;
+	 vect[20] = 0x02;
+	 vect[21] = 0x00;
+	 vect[22] = 0x0A;
+	 vect[23] = 0x09;
+	 vect[24] = 0x00;
+	 vect[25] = 0x00; lenStartCmd
+
+	 crc = calculateCRC(vect, 26);
+	 vect[26] = crc; */
+
+	printf("MicroSD_ZDO_START_request -> startCmd2 = ");
+	for (i = 0; i < 12; i++) {
+		printf("%X ", startCmd2[i]);
+	}
+	printf("\n");
+
+	crc = calculateCRC(startCmd2, 12);
+	startCmd2[12] = crc;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	res = microSD_transmit((int) zb_conn_h, (unsigned char*) startCmd2, 13);
+	if (res < 0) {
+		printf("MicroSD_ZDO_START_request -> 1 - microSD_transmit failed...\n");
+		// fprintf(zigbeeTraceLogFile, "ZDO_START_request -> SDIO_Write() failed...\n");
+	} else {
+		printf("MicroSD_ZDO_START_request -> 1 - microSD_transmit ok...\n");
+	}
+
+	printf("MicroSD_ZDO_START_request -> lenStartCmd = %d \n", lenStartCmd);
+	printf("MicroSD_ZDO_START_request -> startCmd = ");
+	for (i = 0; i < LEN_CMD_K_PICCOLO; i++) {
+		printf("%X ", startCmd[i]);
+	}
+	printf("\n");
+
+	crc = calculateCRC(startCmd, LEN_CMD_K_PICCOLO);
+	startCmd[LEN_CMD_K_PICCOLO] = crc;
+
+	printf("MicroSD_ZDO_START_request -> startCmd (con CRC) = ");
+	for (i = 0; i < LEN_CMD_K_PICCOLO + 1; i++) {
+		printf("%X ", startCmd[i]);
+	}
+	printf("\n");
+
+	// ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	res = microSD_transmit((int) zb_conn_h, (unsigned char*) startCmd,
+			LEN_CMD_K_PICCOLO + 1);
+	if (res < 0) {
+		printf("MicroSD_ZDO_START_request -> 2 - microSD_transmit failed...\n");
+		// fprintf(zigbeeTraceLogFile, "ZDO_START_request -> SDIO_Write() failed...\n");
+	} else {
+		printf("MicroSD_ZDO_START_request -> 2 - microSD_transmit ok...\n");
+	}
+
+	// fclose(zigbeeTraceLogFile);
+	printf("MicroSD_ZDO_START_request -> end! \n");
+}
+
+void MicroSD_ZDO_MATCH_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, ushort profile_id, uchar nicl, ushort *icllist,
+		uchar nocl, ushort *ocllist) {
+	unsigned char crc;
+	int len, res, pos;
+	BOOL broadcast = TRUE;
+	int i;
+
+	if (zigbeeLogTrace == LOG_DEBUG)
+		zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+
+	// controllo che ci sia un indirizzo valido senno' faccio la match in broadcast
+	if (dst_addr < FORWARD_ADDR && nwk_addr < FORWARD_ADDR) {
+		broadcast = FALSE;
+	}
+
+	// calcolo la lunghezza
+	len = 3 + (nicl * 2) + (nocl * 2); // byte di broadcast + 2 byte per ogni cluster
+	if (broadcast) {
+		len = len + 2; // aggiungo l'indirizzo del destinatario
+	}
+
+	vect[0] = SYNCH_CHAR;
+	vect[1] = CMD_PCK_RESPONSE_ZIGBEE;
+	vect[2] = RSP_MATCH;
+	vect[3] = len;
+	// valorizzo il byte broadcast/unicat
+	if (broadcast) {
+		vect[4] = 0x01;
+	} else {
+		vect[4] = 0x00;
+	}
+	pos = 5;
+	// se broadcast aggiungo l'indizzo di rete
+	if (!broadcast) {
+		vect[5] = DIVIDE_UINT16(nwk_addr, 0);
+		vect[6] = DIVIDE_UINT16(nwk_addr, 1);
+		pos = pos + 2;
+	}
+	// aggiungo il profile id
+	vect[pos] = DIVIDE_UINT16(profile_id, 0);
+	vect[pos + 1] = DIVIDE_UINT16(profile_id, 1);
+	pos = pos + 2;
+	// aggiungo i cluster in input
+	vect[pos] = nicl;
+	pos++;
+	if (nicl > 0) {
+		for (i = 0; i < nicl; i++) {
+			vect[pos] = DIVIDE_UINT16(icllist[i], 0);
+			vect[pos + 1] = DIVIDE_UINT16(icllist[i], 1);
+			pos = pos + 2;
+		}
+	}
+	// aggiungo i cluster in output
+	vect[pos] = nocl;
+	pos++;
+	if (nocl > 0) {
+		for (i = 0; i < nocl; i++) {
+			vect[pos] = DIVIDE_UINT16(ocllist[i], 0);
+			vect[pos + 1] = DIVIDE_UINT16(ocllist[i], 1);
+			pos = pos + 2;
+		}
+	}
+
+	// aggiungo il CRC
+	crc = calculateCRC(vect, len + CMD_HEADER_length); // lunghezza messaggio = len (dati) + CMD_HEADER_length
+	vect[len + CMD_HEADER_length] = crc;
+
+	// infine la scrittura sulla seriale
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	res = microSD_transmit(zb_conn_h, (unsigned char*) vect,
+			len + CMD_HEADER_length + 1);
+	if (res < 0) {
+		if (zigbeeLogTrace == LOG_DEBUG)
+			fprintf(zigbeeTraceLogFile,
+					"ZDO_MATCH_DESC_request -> SDIO_Write() failed...\n");
+	}
+
+	if (zigbeeLogTrace == LOG_DEBUG)
+		fclose(zigbeeTraceLogFile);
+}
+
+void MicroSD_ZDO_IEEE_ADDR_request(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar request_type, uchar start_index) {
+	int res;
+	unsigned char crc;
+	if (zigbeeLogTrace == LOG_DEBUG)
+		zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+
+	vect[0] = SYNCH_CHAR;
+	vect[1] = CMD_PCK_RESPONSE_ZIGBEE;
+	vect[2] = RSP_IEEE_SEARCH;
+	vect[3] = 0x04;
+	vect[4] = DIVIDE_UINT16(nwk_addr, 0);
+	vect[5] = DIVIDE_UINT16(nwk_addr, 1);
+	vect[6] = request_type;
+	vect[7] = start_index;
+
+	crc = calculateCRC(vect, 8);
+	vect[8] = crc;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	res = microSD_transmit(zb_conn_h, (unsigned char*) vect, 9);
+	if (res < 0) {
+		fprintf(zigbeeTraceLogFile,
+				"ZDO_IEEE_ADDR_request -> SDIO_Write() failed...\n");
+	}
+
+	if (zigbeeLogTrace == LOG_DEBUG)
+		fclose(zigbeeTraceLogFile);
+}
+
+void MicroSD_ZDO_NWK_ADDR_request(ZBIF_HANDLE zbif_handle, uchar *ieee_addr,
+		uchar request_type, uchar start_index) {
+	int res, i;
+	unsigned char crc;
+
+	if (zigbeeLogTrace == LOG_DEBUG)
+		zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+
+	vect[0] = SYNCH_CHAR;
+	vect[1] = CMD_PCK_RESPONSE_ZIGBEE;
+	vect[2] = RSP_NWK_REQ;
+	vect[3] = 10;
+	for (i = 0; i < SIZE_IEEE_ADDRESS; i++)
+		vect[4 + i] = ieee_addr[i];
+	vect[4 + SIZE_IEEE_ADDRESS] = request_type;
+	vect[4 + SIZE_IEEE_ADDRESS + 1] = start_index;
+
+	// aggiungo il CRC
+	crc = calculateCRC(vect, 14); // lunghezza messaggio = len (dati) + CMD_HEADER_length
+	vect[14] = crc;
+
+	// infine la scrittura sulla seriale
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	res = microSD_transmit(zb_conn_h, (unsigned char*) vect, 15);
+	if (res < 0) {
+		if (zigbeeLogTrace == LOG_DEBUG)
+			fprintf(zigbeeTraceLogFile,
+					"ZDO_NWK_ADDR_request -> SDIO_Write() failed...\n");
+	}
+
+	if (zigbeeLogTrace == LOG_DEBUG)
+		fclose(zigbeeTraceLogFile);
+}
+
+void MicroSD_ZDO_NODE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr) {
+	int res;
+	unsigned char crc;
+
+	if (zigbeeLogTrace == LOG_DEBUG)
+		zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+
+	vect[0] = SYNCH_CHAR;
+	vect[1] = CMD_PCK_RESPONSE_ZIGBEE;
+	vect[2] = RSP_NODEDESC_REQ;
+	vect[3] = 0x04;
+	vect[4] = DIVIDE_UINT16(dst_addr, 0);
+	vect[5] = DIVIDE_UINT16(dst_addr, 1);
+	vect[6] = DIVIDE_UINT16(nwk_addr, 0);
+	;
+	vect[7] = DIVIDE_UINT16(nwk_addr, 1);
+	;
+
+	crc = calculateCRC(vect, 8);
+	vect[8] = crc;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	res = microSD_transmit(zb_conn_h, (unsigned char*) vect, 9);
+	if (res < 0) {
+		fprintf(zigbeeTraceLogFile,
+				"ZDO_NODE_DESC_request -> SDIO_Write() failed...\n");
+	}
+
+	if (zigbeeLogTrace == LOG_DEBUG)
+		fclose(zigbeeTraceLogFile);
+}
+
+void MicroSD_ZDO_SIMPLE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, uchar endpoint) {
+	int res;
+	unsigned char crc;
+
+	if (zigbeeLogTrace == LOG_DEBUG)
+		zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+
+	vect[0] = SYNCH_CHAR;
+	vect[1] = CMD_PCK_RESPONSE_ZIGBEE;
+	vect[2] = RSP_SIMPLEDESC_REQ;
+	vect[3] = 0x05;
+	vect[4] = DIVIDE_UINT16(dst_addr, 0);
+	vect[5] = DIVIDE_UINT16(dst_addr, 1);
+	vect[6] = DIVIDE_UINT16(nwk_addr, 0);
+	vect[7] = DIVIDE_UINT16(nwk_addr, 1);
+	vect[8] = endpoint;
+
+	crc = calculateCRC(vect, 9);
+	vect[9] = crc;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	res = microSD_transmit(zb_conn_h, (unsigned char*) vect, 10);
+	if (res < 0) {
+		fprintf(zigbeeTraceLogFile,
+				"ZDO_SIMPLE_DESC_request -> SDIO_Write() failed...\n");
+	}
+
+	if (zigbeeLogTrace == LOG_DEBUG)
+		fclose(zigbeeTraceLogFile);
+}
+
+void MicroSD_ZDO_ACTIVE_EP_DESC_request(ZBIF_HANDLE zbif_handle,
+		ushort dst_addr, ushort nwk_addr) {
+	int res;
+	unsigned char crc;
+
+	if (zigbeeLogTrace == LOG_DEBUG)
+		zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+
+	vect[0] = SYNCH_CHAR;
+	vect[1] = CMD_PCK_RESPONSE_ZIGBEE;
+	vect[2] = RSP_ACTIVEEP_LIST;
+	vect[3] = 0x04;
+	vect[4] = DIVIDE_UINT16(dst_addr, 0);
+	vect[5] = DIVIDE_UINT16(dst_addr, 1);
+	vect[6] = DIVIDE_UINT16(nwk_addr, 0);
+	vect[7] = DIVIDE_UINT16(nwk_addr, 1);
+
+	crc = calculateCRC(vect, 8);
+	vect[8] = crc;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	res = microSD_transmit(zb_conn_h, (unsigned char*) vect, 9);
+	if (res < 0) {
+		fprintf(zigbeeTraceLogFile,
+				"ZDO_ACTIVE_EP_DESC_request -> SDIO_Write() failed...\n");
+	}
+
+	if (zigbeeLogTrace == LOG_DEBUG)
+		fclose(zigbeeTraceLogFile);
+}
+
+void MicroSD_ZDO_POWER_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr) {
+	int res;
+	unsigned char crc;
+
+	if (zigbeeLogTrace == LOG_DEBUG)
+		zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+
+	vect[0] = SYNCH_CHAR;
+	vect[1] = CMD_PCK_RESPONSE_ZIGBEE;
+	vect[2] = RSP_POWER_REQ;
+	vect[3] = 0x04;
+	vect[4] = DIVIDE_UINT16(dst_addr, 0);
+	vect[5] = DIVIDE_UINT16(dst_addr, 1);
+	vect[6] = DIVIDE_UINT16(nwk_addr, 0);
+	vect[7] = DIVIDE_UINT16(nwk_addr, 1);
+
+	crc = calculateCRC(vect, 8);
+	vect[8] = crc;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	res = microSD_transmit(zb_conn_h, (unsigned char*) vect, 9);
+	if (res < 0) {
+		fprintf(zigbeeTraceLogFile,
+				"ZDO_POWER_DESC_request -> SDIO_Write() failed...\n");
+	}
+
+	if (zigbeeLogTrace == LOG_DEBUG)
+		fclose(zigbeeTraceLogFile);
+}
+
+void MicroSD_ZDO_END_DEVICE_BIND_request(ZBIF_HANDLE zbif_handle,
+		ushort binding_target, uchar *src_ieee_addr, uchar src_ep,
+		ushort profile_id, uchar nicl, ushort *icllist, uchar nocl,
+		ushort *ocllist) {
+	int res, len, pos, i;
+	unsigned char crc;
+
+	if (zigbeeLogTrace == LOG_DEBUG)
+		zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+
+	len = 15 + (nicl * 2) + (nocl * 2);
+	vect[0] = SYNCH_CHAR;
+	vect[1] = CMD_PCK_RESPONSE_ZIGBEE;
+	vect[2] = RSP_ENDDEVBIND_REQ;
+	vect[3] = len;
+	for (i = 0; i < SIZE_IEEE_ADDRESS; i++)
+		vect[4 + i] = src_ieee_addr[i];
+	vect[12] = DIVIDE_UINT16(binding_target, 0);
+	vect[13] = DIVIDE_UINT16(binding_target, 1);
+	vect[14] = DIVIDE_UINT16(src_ep, 1);
+	vect[15] = DIVIDE_UINT16(profile_id, 0);
+	vect[16] = DIVIDE_UINT16(profile_id, 1);
+	vect[17] = nicl;
+	pos = 18;
+	if (nicl > 0) {
+		for (i = 0; i < nicl; i++) {
+			vect[pos] = DIVIDE_UINT16(icllist[i], 0);
+			vect[pos + 1] = DIVIDE_UINT16(icllist[i], 1);
+			pos = pos + 2;
+		}
+	}
+	vect[pos] = nocl;
+	pos++;
+	if (nocl > 0) {
+		for (i = 0; i < nocl; i++) {
+			vect[pos] = DIVIDE_UINT16(ocllist[i], 0);
+			vect[pos + 1] = DIVIDE_UINT16(ocllist[i], 1);
+			pos = pos + 2;
+		}
+	}
+
+	// aggiungo il CRC
+	crc = calculateCRC(vect, len + CMD_HEADER_length); // lunghezza messaggio = len (dati) + CMD_HEADER_length
+	vect[len + CMD_HEADER_length] = crc;
+
+	// infine la scrittura sulla seriale
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	res = microSD_transmit(zb_conn_h, (unsigned char*) vect,
+			len + CMD_HEADER_length + 1);
+	if (res < 0) {
+		if (zigbeeLogTrace == LOG_DEBUG)
+			fprintf(zigbeeTraceLogFile,
+					"ZDO_END_DEVICE_BIND_request -> SDIO_Write() failed...\n");
+	}
+
+	if (zigbeeLogTrace == LOG_DEBUG)
+		fclose(zigbeeTraceLogFile);
+}
+
+void MicroSD_APSDE_DATA_request(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, ushort profile_id, ushort cluster_id,
+		uchar src_ep, uchar asdu_len, uchar *asdu, uchar tx_options,
+		uchar radius) {
+	int res, len, pos, i;
+	unsigned char crc;
+
+	if (zigbeeLogTrace == LOG_DEBUG)
+		zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+
+	vect[0] = SYNCH_CHAR;
+	vect[1] = SENDDATA_PCK_RESPONSE_ZIGBEE;
+	vect[2] = src_ep;
+	vect[3] = dst_addr_mode;
+	if (dst_addr_mode == DEST_ADDR_MODE_16_BIT) {
+		// for (i=0; i<SHORT_ADDRESS_length; i++) vect[4+i] = dst_addr[i];
+		vect[4] = dst_addr[1];
+		vect[5] = dst_addr[0];
+		for (i = 0; i < (SIZE_IEEE_ADDRESS - SHORT_ADDRESS_length); i++)
+			vect[4 + SHORT_ADDRESS_length + i] = 0xFF;
+	} else {
+		for (i = 0; i < SIZE_IEEE_ADDRESS; i++)
+			vect[4 + i] = dst_addr[i];
+	}
+	vect[12] = dst_ep;
+	vect[13] = DIVIDE_UINT16(cluster_id, 0);
+	vect[14] = DIVIDE_UINT16(cluster_id, 1);
+	vect[15] = tx_options;
+	vect[16] = radius;
+	vect[17] = asdu_len;
+	if (asdu_len > 0) {
+		for (i = 0; i < asdu_len; i++)
+			vect[18 + i] = asdu[i];
+	}
+
+	len = asdu_len + DATA_HEADER_length;
+
+	// aggiungo il CRC
+	crc = calculateCRC(vect, len); // lunghezza messaggio = len (dati) + DATA_HEADER_length
+	vect[len] = crc;
+
+	// infine la scrittura sulla seriale
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	res = microSD_transmit(zb_conn_h, (unsigned char*) vect, len + 1);
+	if (res < 0) {
+		if (zigbeeLogTrace == LOG_DEBUG)
+			fprintf(zigbeeTraceLogFile,
+					"APSDE_DATA_request -> SDIO_Write() failed...\n");
+	}
+
+	if (zigbeeLogTrace == LOG_DEBUG)
+		fclose(zigbeeTraceLogFile);
+}
+
+void MicroSD_ZDO_RESET_request(ZBIF_HANDLE zbif_handle, uchar options) {
+	int res;
+	unsigned char crc;
+
+	// if (zigbeeLogTrace == LOG_DEBUG) zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+
+	vect[0] = SYNCH_CHAR;
+	vect[1] = CMD_PCK_RESPONSE_ZIGBEE;
+	vect[2] = RSP_RESET_REQ;
+	vect[3] = 0x01;
+	vect[4] = 0X00;
+
+	crc = calculateCRC(vect, 5);
+	vect[5] = crc;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	res = microSD_transmit(zb_conn_h, (unsigned char*) vect, 6);
+	if (res < 0) {
+		printf("MicroSD_ZDO_RESET_request -> microSD_transmit() failed...\n");
+	}
+
+	// if (zigbeeLogTrace == LOG_DEBUG) fclose(zigbeeTraceLogFile);
+
+	//usleep(5000*1000);
+
+	//  Store the type of reset that must be performed
+
+	//  This variable is used to know if restart the Gateway or just init it
+	uchar restartGW = 0x00; //by default if restart the network
+	restartGW = (options & 0x01);
+
+	//printf("MicroSD_ZDO_RESET_request -> invio la confirm! options = %d \n", restartGW);
+	ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+	if (zbifCbs->ZDO_RESET_confirm) {
+		zbifCbs->ZDO_RESET_confirm(zbif_handle, 0x00, restartGW);
+	}
+}
+
+void MicroSD_ZDO_MATCH_DESC_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort dst_addr, uchar match_len, uchar *match_list) {
+}
+
+void MicroSD_APSME_BIND_request(ZBIF_HANDLE zbif_handle, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep) {
+	int res, i;
+	unsigned char crc;
+
+	printf("APSME_BIND_request --> START \n");
+
+	vect[0] = SYNCH_CHAR;
+	vect[1] = CMD_PCK_RESPONSE_ZIGBEE;
+	vect[2] = RSP_APSME_BIND_REQ;
+	vect[3] = 12;
+	vect[4] = src_ep;
+	vect[5] = DIVIDE_UINT16(cluster_id, 0);
+	vect[6] = DIVIDE_UINT16(cluster_id, 1);
+	for (i = 0; i < SIZE_IEEE_ADDRESS; i++)
+		vect[7 + i] = dst_ieee_addr[i];
+	vect[15] = dst_ep;
+
+	crc = calculateCRC(vect, 16);
+	vect[16] = crc;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	res = microSD_transmit(zb_conn_h, (unsigned char*) vect, 17);
+	if (res < 0) {
+		printf("MicroSD_APSME_BIND_request -> microSD_transmit() failed...\n");
+	}
+
+	printf("APSME_BIND_request --> END \n");
+}
+
+void MicroSD_APSME_UNBIND_request(ZBIF_HANDLE zbif_handle, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep) {
+	int res, i;
+	unsigned char crc;
+
+	printf("MicroSD_APSME_UNBIND_request--> START \n");
+
+	vect[0] = SYNCH_CHAR;
+	vect[1] = CMD_PCK_RESPONSE_ZIGBEE;
+	vect[2] = RSP_APSME_UNBIND_REQ;
+	vect[3] = 12;
+	vect[4] = src_ep;
+	vect[5] = DIVIDE_UINT16(cluster_id, 0);
+	vect[6] = DIVIDE_UINT16(cluster_id, 1);
+	for (i = 0; i < SIZE_IEEE_ADDRESS; i++)
+		vect[7 + i] = dst_ieee_addr[i];
+	vect[15] = dst_ep;
+
+	crc = calculateCRC(vect, 16);
+	vect[16] = crc;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	res = microSD_transmit(zb_conn_h, (unsigned char*) vect, 17);
+	if (res < 0) {
+		printf(
+				"MicroSD_APSME_UNBIND_request -> microSD_transmit() failed...\n");
+	}
+
+	printf("MicroSD_APSME_UNBIND_request --> END \n");
+
+}
+
+void MicroSD_APSME_GET_request(ZBIF_HANDLE zbif_handle, uchar attr) {
+	int res;
+	unsigned char crc;
+
+	vect[0] = SYNCH_CHAR;
+	vect[1] = CMD_PCK_RESPONSE_ZIGBEE;
+	vect[2] = RSP_IEEE_GET;
+	vect[3] = 0x00;
+
+	crc = calculateCRC(vect, 4);
+	vect[4] = crc;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	res = microSD_transmit(zb_conn_h, (unsigned char*) vect, 5);
+	if (res < 0) {
+		printf("MicroSD_ZDO_RESET_request -> microSD_transmit() failed...\n");
+	}
+
+	/* ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+	 unsigned char cmd[8] = { 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00 };
+	 printf("MicroSD_APSME_GET_request -> START \n");
+	 zbifCbs->APSME_GET_confirm(zbif_handle, 0x00, attr, 8, cmd); */
+}
+
+void MicroSD_ZB_MGMT_LQI_request(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar start_index) {
+	return;
+}
+
+void MicroSD_APSME_SET_request(ZBIF_HANDLE zbif_handle, uchar attr,
+		uchar attr_len, uchar *attr_value) {
+	int i, pos, posAttr, posSimpleDesc;
+
+	switch (attr) {
+	case ZB_ATTR_CONFIG_NODE_DESCRIPTOR: {
+		for (i = 0; i < MAX_OTA_LEN; i++)
+			startCmd[i] = 0x00;
+		for (i = 0; i < MAX_OTA_LEN; i++)
+			startCmd2[i] = 0x00;
+
+		startCmd[0] = 0x02;
+		startCmd[1] = CMD_PCK_RESPONSE_ZIGBEE;
+		startCmd[K_CMD_POS_CMD] = 0x6B; // comando k piccolo
+		startCmd[K_CMD_POS_LEN] = 8; // comando k piccolo
+
+		startCmd2[0] = 0x02;
+		startCmd2[1] = CMD_PCK_RESPONSE_ZIGBEE;
+		startCmd2[K_CMD_POS_CMD] = RSP_SET_ADD_PAR;
+		startCmd2[K_CMD_POS_LEN] = 8; // comando k piccolo
+
+		// Store the logical_type (it will we used when calling the start network...)
+		ZB_NODE_DESC *g_node_desc = (ZB_NODE_DESC *) attr_value;
+		if (g_node_desc->logical_type == ZB_COORDINATOR) {
+			startCmd[K_CMD_POS_COMPACT] = COMMAND_COORDINATOR;
+		} else {
+			startCmd[K_CMD_POS_COMPACT] = COMMAND_ROUTER_NO_SOFT_START;
+		}
+
+		// Autogen a return!
+		ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+		if (zbifCbs->APSME_SET_confirm) {
+			zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+		}
+		return;
+	}
+	case ZB_ATTR_CONFIG_PANID: {
+		startCmd[K_CMD_POS_RANGE] = 0x00;
+		startCmd[K_CMD_POS_PAN] = attr_value[1];
+		startCmd[K_CMD_POS_PAN + 1] = attr_value[0];
+
+		ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+		if (zbifCbs->APSME_SET_confirm) {
+			zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+		}
+		return;
+	}
+
+	case ZB_ATTR_CONFIG_EXTENDEDPANID: {
+		for (i = 0; i < SIZE_IEEE_ADDRESS; i++)
+			startCmd2[K_CMD_POS_EXTPAN + i] = attr_value[i];
+
+		ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+		if (zbifCbs->APSME_SET_confirm) {
+			zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+		}
+		return;
+	}
+
+	case ZB_ATTR_CONFIG_FRAGMENT_WINDOW_SIZE: {
+		if (attr_len == 2) {
+			maxWinSize = attr_value[0];
+
+			printf(
+					"MicroSD_APSME_SET_request - ZB_ATTR_CONFIG_FRAGMENT_WINDOW_SIZE - maxWinSize = %d \n",
+					maxWinSize);
+
+			// Autogen a response since the fragmentation is not currently implemented in Freescale
+			ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+			if (zbifCbs->APSME_SET_confirm) {
+				zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+			}
+		}
+		return;
+	}
+
+	case ZB_ATTR_CONFIG_FRAGMENT_DELAY_MS: {
+		if (attr_len == 2) {
+			maxInterframeDelay = attr_value[0];
+
+			printf(
+					"MicroSD_APSME_SET_request - ZB_ATTR_CONFIG_FRAGMENT_DELAY_MS - maxInterframeDelay = %d \n",
+					maxInterframeDelay);
+
+			/* cmd[0] = SYNCH_CHAR;
+			 cmd[1] = CMD_PCK_RESPONSE_ZIGBEE;
+			 cmd[2] = RSP_SET_PAGING;
+			 cmd[3] = 0x03;
+			 cmd[4] = maxWinSize;
+			 cmd[5] = DIVIDE_UINT16(maxInterframeDelay, 0);
+			 cmd[6] = DIVIDE_UINT16(maxInterframeDelay, 1);
+
+			 int crc = calculateCRC(cmd, 7);
+			 cmd[7] = crc;
+
+			 printf("MicroSD_APSME_SET_request - ZB_ATTR_CONFIG_FRAGMENT_DELAY_MS cmd (con CRC) = ");
+			 for (i = 0; i < 8; i++) {
+			 printf("%X ", cmd[i]);
+			 }
+			 printf("\n");
+
+			 ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+			 int res = microSD_transmit((int) zb_conn_h, (unsigned char*) cmd, 8); */
+
+			// Autogen a response since the fragmentation is not currently implemented in Freescale
+			ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+			if (zbifCbs->APSME_SET_confirm) {
+				zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+			}
+		}
+		return;
+	}
+
+	case ZB_ATTR_CONFIG_SECURITY: {
+		if (attr_len == 1) {
+			int securityLevel = (int) attr_value[0];
+			// startCmd2[K_CMD_POS_SECURITY] = securityLevel;
+
+			printf(
+					"MicroSD_APSME_SET_request - ZB_ATTR_CONFIG_SECURITY - securityLevel = %d \n",
+					securityLevel);
+
+			/* cmd[0] = SYNCH_CHAR;
+			 cmd[1] = CMD_PCK_RESPONSE_ZIGBEE;
+			 cmd[2] = RSP_SET_SECURITY;
+			 cmd[3] = 0x01;
+			 cmd[4] = securityLevel;
+
+			 int crc = calculateCRC(cmd, 5);
+			 cmd[5] = crc;
+
+			 printf("MicroSD_APSME_SET_request - ZB_ATTR_CONFIG_SECURITY cmd (con CRC) = ");
+			 for (i = 0; i < 6; i++) {
+			 printf("%X ", cmd[i]);
+			 }
+			 printf("\n");
+
+			 ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+			 int res = microSD_transmit((int) zb_conn_h, (unsigned char*) cmd, 6); */
+
+			ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+			if (zbifCbs->APSME_SET_confirm) {
+				zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+			}
+		}
+		return;
+	}
+
+	case ZB_TC_KEY_REQUEST_POLICY:
+	case ZB_APP_KEY_REQUEST_POLICY:
+	case 0x00: //EZSP_TRUST_CENTER_POLICY
+	{
+		//Those two values are just some policy setting valid for EZSP but not for Freescale!
+		ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+		if (zbifCbs->APSME_SET_confirm) {
+			zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+		}
+		return;
+	}
+
+	case ZB_ATTR_PRECONF_TC_LINK_KEY: {
+		if (attr_len == 16) {
+			// Here it is passed the preconfiguredTCLinkKey!
+			zb_print(
+					"MicroSD_APSME_SET_request - ZB_ATTR_PRECONF_TC_LINK_KEY\n");
+
+			cmd[0] = SYNCH_CHAR;
+			cmd[1] = CMD_PCK_RESPONSE_ZIGBEE;
+			cmd[2] = RSP_SET_DEFAULT_TC_LINK_KEY;
+			cmd[3] = 0x10;
+			for (i = 0; i < 16; i++)
+				cmd[4 + i] = attr_value[i]; // attr_value[15 - i];
+
+			int crc = calculateCRC(cmd, 20);
+			cmd[20] = crc;
+
+			printf(
+					"MicroSD_APSME_SET_request - ZB_ATTR_PRECONF_TC_LINK_KEY cmd (con CRC) = ");
+			for (i = 0; i < 21; i++) {
+				printf("%X ", cmd[i]);
+			}
+			printf("\n");
+
+			ZB_CONN_HANDLE zb_conn_h =
+					((zbif_status_t *) zbif_handle)->zb_conn_h;
+			int res = microSD_transmit((int) zb_conn_h, (unsigned char*) cmd,
+					21);
+
+			ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+			if (zbifCbs->APSME_SET_confirm) {
+				zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+			}
+		}
+		return;
+	}
+
+	case ZB_ATTR_NWK_KEY: {
+		if (attr_len == 16) {
+			// Here it is passed the networkKey!
+			printf("MicroSD_APSME_SET_request - ZB_ATTR_NWK_KEY\n");
+
+			cmd[0] = SYNCH_CHAR;
+			cmd[1] = CMD_PCK_RESPONSE_ZIGBEE;
+			cmd[2] = RSP_SET_DEFAULT_LINK_KEY;
+			cmd[3] = 0x10;
+			for (i = 0; i < 16; i++)
+				cmd[4 + i] = attr_value[i]; // attr_value[15 - i];
+
+			int crc = calculateCRC(cmd, 20);
+			cmd[20] = crc;
+
+			printf(
+					"MicroSD_APSME_SET_request - ZB_ATTR_NWK_KEY cmd (con CRC) = ");
+			for (i = 0; i < 21; i++) {
+				printf("%X ", cmd[i]);
+			}
+			printf("\n");
+
+			ZB_CONN_HANDLE zb_conn_h =
+					((zbif_status_t *) zbif_handle)->zb_conn_h;
+			int res = microSD_transmit((int) zb_conn_h, (unsigned char*) cmd,
+					21);
+
+			ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+			if (zbifCbs->APSME_SET_confirm) {
+				zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+			}
+		}
+		return;
+	}
+
+	case ZB_ATTR_CONFIG_SIMPLE_DESCRIPTOR: {
+		// setto un simple descriptor
+		simpledescconf[0] = SYNCH_CHAR;
+		simpledescconf[1] = CMD_PCK_RESPONSE_ZIGBEE;
+		simpledescconf[2] = RSP_SET_DESCRIPTOR;
+
+		simpledescconf[4] = attr_value[0]; //endpoint
+		simpledescconf[5] = attr_value[2]; //profile
+		simpledescconf[6] = attr_value[1]; //profile
+		// cluster in
+		simpledescconf[7] = attr_value[6]; //numclusterin
+		posSimpleDesc = 8; // punto di inizio della lista di clusterin
+		posAttr = 8;
+		if (attr_value[6] != 0x00) {
+			for (i = 0; i < attr_value[6]; i++) {
+				/* simpledescconf[posSimpleDesc] = attr_value[posAttr];
+				 simpledescconf[posSimpleDesc + 1] = attr_value[posAttr + 1]; */
+				simpledescconf[posSimpleDesc] = attr_value[posAttr + 1];
+				simpledescconf[posSimpleDesc + 1] = attr_value[posAttr];
+				posSimpleDesc = posSimpleDesc + 2;
+				posAttr = posAttr + 2;
+			}
+		}
+		simpledescconf[posSimpleDesc] = attr_value[7]; //  cluster output
+		posSimpleDesc = posSimpleDesc + 1;
+		if (attr_value[7] != 0x00) {
+			for (i = 0; i < attr_value[7]; i++) {
+				/* simpledescconf[posSimpleDesc] = attr_value[posAttr];
+				 simpledescconf[posSimpleDesc + 1] = attr_value[posAttr + 1]; */
+				simpledescconf[posSimpleDesc] = attr_value[posAttr + 1];
+				simpledescconf[posSimpleDesc + 1] = attr_value[posAttr];
+				posSimpleDesc = posSimpleDesc + 2;
+				posAttr = posAttr + 2;
+			}
+		}
+		simpledescconf[3] = posSimpleDesc - 4;
+
+		printf("MicroSD_APSME_SET_request(simple_desc) -> len = %d \n", pos);
+		printf("MicroSD_APSME_SET_request(simple_desc) -> simpledescconf = ");
+		for (i = 0; i < posSimpleDesc; i++) {
+			printf("%X ", simpledescconf[i]);
+		}
+		printf("\n");
+
+		int crc = calculateCRC(simpledescconf, posSimpleDesc);
+		simpledescconf[posSimpleDesc] = crc;
+
+		printf(
+				"MicroSD_APSME_SET_request(simple_desc) -> simpledescconf (con CRC) = ");
+		for (i = 0; i < posSimpleDesc + 1; i++) {
+			printf("%X ", simpledescconf[i]);
+		}
+		printf("\n");
+
+		// usleep(200*1000);
+
+		ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+		int res = microSD_transmit((int) zb_conn_h,
+				(unsigned char*) simpledescconf, posSimpleDesc + 1);
+
+		// usleep(200*1000);
+
+		ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+		if (zbifCbs->APSME_SET_confirm) {
+			zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+		}
+
+		/*if (multisimpledesc_flag == 0)
+		 {
+		 multisimpledesc_flag = 1;
+		 startCmd[K_CMD_POS_EP] = attr_value[0];
+		 startCmd[K_CMD_POS_PROFID] = attr_value[2];
+		 startCmd[K_CMD_POS_PROFID + 1] = attr_value[1];
+
+		 printf("SimpleDescriptor - ");
+		 int c=0;
+		 for (c=0; c<( 8 + attr_value[6]*2 + attr_value[7]*2); c++)
+		 printf("%02x",attr_value[c]);
+		 printf("SimpleDescriptor - END\n");
+
+
+		 // cluster in
+		 startCmd[K_CMD_POS_NCLUSTER_IN] = attr_value[6];
+		 pos = K_CMD_POS_START_CLUSTERS;
+
+		 printf("input cluster - %d\n", attr_value[6]);
+
+		 posAttr = 8;
+		 if (attr_value[6] != 0x00) {
+		 for (i = 0; i < attr_value[6]; i++) {
+		 startCmd[pos] = attr_value[posAttr];
+		 startCmd[pos + 1] = attr_value[posAttr + 1];
+
+		 printf("input cluster - %02x%02x\n",startCmd[pos],startCmd[pos+1]);
+
+		 pos = pos + 2;
+		 posAttr = posAttr + 2;
+		 }
+		 }
+
+
+		 printf("output cluster - %d\n", attr_value[7]);
+
+		 startCmd[pos] = attr_value[7]; //  cluster output
+		 pos = pos + 1;
+		 if (attr_value[7] != 0x00) {
+		 for (i = 0; i < attr_value[7]; i++) {
+		 startCmd[pos] = attr_value[posAttr];
+		 startCmd[pos + 1] = attr_value[posAttr + 1];
+
+		 printf("output cluster - %02x%02x\n",startCmd[pos],startCmd[pos+1]);
+
+		 pos = pos + 2;
+		 posAttr = posAttr + 2;
+		 }
+		 }
+		 lenStartCmd = pos;
+		 startCmd[lenStartCmd] = 0x00; // user descriptor
+		 lenStartCmd++;
+
+		 ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+		 if (zbifCbs->APSME_SET_confirm) {
+		 zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+		 }
+		 }
+		 else
+		 {
+		 // Mando il simple descriptor se ne ricevo un altro oltre a quello da mettere nel comando K
+		 multisimpledesc_flag = 1;
+		 simpledescconf[0] = 0x02;
+		 simpledescconf[1] = 0xF1;
+		 simpledescconf[2] = 'T';
+
+		 simpledescconf[4] = attr_value[0]; //endpoint
+		 simpledescconf[5] = attr_value[2]; //profile
+		 simpledescconf[6] = attr_value[1]; //profile
+
+		 // cluster in
+		 simpledescconf[7] = attr_value[6]; //numclusterin
+		 pos = 8; // punto di inizio della lista di clusterin
+		 posAttr = 8;
+		 if (attr_value[6] != 0x00) {
+		 for (i = 0; i < attr_value[6]; i++) {
+		 simpledescconf[pos] = attr_value[posAttr];
+		 simpledescconf[pos + 1] = attr_value[posAttr + 1];
+		 pos = pos + 2;
+		 posAttr = posAttr + 2;
+		 }
+		 }
+		 simpledescconf[pos] = attr_value[7]; //  cluster output
+		 pos = pos + 1;
+		 if (attr_value[7] != 0x00) {
+		 for (i = 0; i < attr_value[7]; i++) {
+		 simpledescconf[pos] = attr_value[posAttr];
+		 simpledescconf[pos + 1] = attr_value[posAttr + 1];
+		 pos = pos + 2;
+		 posAttr = posAttr + 2;
+		 }
+		 }
+
+		 simpledescconf[3] = pos - 4;
+
+		 pos = pos - 4;
+
+		 //lenStartCmd = pos;
+		 //simpledescconf[lenStartCmd] = 0x00; // user descriptor
+		 //lenStartCmd++;
+		 // Mando il messaggio sulla seriale
+
+		 printf("MicroSD_APSME_SET_request(simple_desc) -> len = %d \n", pos);
+		 printf("MicroSD_APSME_SET_request(simple_desc) -> simpledescconf = ");
+		 for (i = 0; i < (pos+4); i++) {
+		 printf("%X ", simpledescconf[i]);
+		 }
+		 printf("\n");
+
+		 int crc = calculateCRC(simpledescconf, pos+4);
+		 simpledescconf[pos+4] = crc;
+
+		 printf("MicroSD_APSME_SET_request(simple_desc) -> simpledescconf (con CRC) = ");
+		 for (i = 0; i < pos + 1 + 4; i++) {
+		 printf("%X ", simpledescconf[i]);
+		 }
+		 printf("\n");
+
+		 ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+		 int res = microSD_transmit((int) zb_conn_h, (unsigned char*) simpledescconf,
+		 pos + 4 + 1);
+
+		 ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+		 if (zbifCbs->APSME_SET_confirm) {
+		 zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+		 } */
+		// }
+		return;
+	}
+
+	case ZB_ATTR_CONFIG_STARTUPCONTROL: {
+		zb_print("MicroSD_APSME_SET_request - ZB_ATTR_CONFIG_STARTUPCONTROL\n");
+		// Autogen a return!
+		ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+		if (zbifCbs->APSME_SET_confirm) {
+			zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+		}
+		return;
+	}
+
+	case ZB_ATTR_CONFIG_CHANNEL_MASK:
+		if (attr_len == 4) {
+			// Store the channel mask!
+			startCmd[K_CMD_POS_CHANNEL] = attr_value[3];
+			startCmd[K_CMD_POS_CHANNEL + 1] = attr_value[2];
+			startCmd[K_CMD_POS_CHANNEL + 2] = attr_value[1];
+			startCmd[K_CMD_POS_CHANNEL + 3] = attr_value[0];
+
+			ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+			if (zbifCbs->APSME_SET_confirm) {
+				zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+			}
+			return;
+		}
+
+		return;
+	}
+}
+
+void MicroSD_MGMT_PERMIT_JOINING_request(ZBIF_HANDLE zbif_handle,
+		ushort nwk_addr, int permitDuration) {
+}
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+void MicroSD_APSME_REMOVE_DEVICE_request (ZBIF_HANDLE zbif_handle, uchar *parent_ieee_addr, uchar *child_ieee_addr) {
+}
+
+void MicroSD_APSME_TRANSPORT_KEY_request (ZBIF_HANDLE zbif_handle, uchar *dst_ieee_addr, uchar key_type, ZB_TRANSPORT_KEY_DATA *transport_key_data) {
+}
+
+void MicroSD_NLME_LEAVE_request (ZBIF_HANDLE zbif_handle, uchar *dev_ieee_addr, uchar remove_children, uchar rejoin, uchar reuse_address, uchar silent) {
+	int res;
+	int len = 4;
+	bool leaveASeStesso = true;
+	unsigned char vect[MAX_OTA_LEN];
+	if (zigbeeLogTrace == LOG_DEBUG) zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+
+	if (dev_ieee_addr != NULL) leaveASeStesso = false;
+
+	if (!leaveASeStesso) len = 12;
+
+	vect[0] = SYNCH_CHAR;
+	vect[1] = CMD_PCK_RESPONSE_ZIGBEE;
+	vect[2] = RSP_LEAVE;
+	vect[3] = len;
+	vect[4] = remove_children;
+	vect[5] = rejoin;
+	vect[6] = reuse_address;
+	vect[7] = silent;
+	if (!leaveASeStesso) {
+		for (int i=0; i<SIZE_IEEE_ADDRESS; i++) vect[8+i] = dev_ieee_addr[i];
+	}
+
+	// aggiungo il CRC
+	crc = calculateCRC(vect, len+CMD_HEADER_length);// lunghezza messaggio = len (dati) + CMD_HEADER_length
+	vect[len+CMD_HEADER_length] = crc;
+
+	// infine la scrittura sulla seriale
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	res = microSD_transmit(zb_conn_h, (unsigned char*) vect, len+CMD_HEADER_length+1);
+	if (res < 0) {
+		if (zigbeeLogTrace == LOG_DEBUG) fprintf(zigbeeTraceLogFile, "NLME_LEAVE_request -> SDIO_Write() failed...\n");
+	}
+
+	if (zigbeeLogTrace == LOG_DEBUG) fclose(zigbeeTraceLogFile);
+}
+#endif
+
+void MicroSD_ZDO_ERROR_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort cluster_id, uchar expected_len) {
+
+}
+
+void MicroSD_ParseNExec(ZBIF_HANDLE zbif_handle, uchar *p, int size) {
+	int i;
+	uchar status;
+	ushort nwk_addr;
+
+	ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+	if (zbifCbs == NULL) {
+		zb_print_bytes(
+				"Received those bytes but without callback, ignoring them >>>> ",
+				p, size);
+		/* error! */
+		return;
+	}
+
+	for (i = 0; i < MAX_OTA_LEN; i++) {
+		out_buf[i] = p[i];
+	}
+
+	if (out_buf[POS_SYNCH_CHAR] == 0x02) {
+
+		if (isSendData(out_buf[POS_MSG_TYPE])) {
+			// risposta a invio dati
+			manageSendDataConfirm(zbifCbs, zbif_handle);
+		} else {
+			if (isForwardData(out_buf[POS_MSG_TYPE])) {
+				// dati OTA da inoltrare
+				manageIncomingData(zbifCbs, zbif_handle);
+			} else {
+				if (isCommand(out_buf[POS_MSG_TYPE])) {
+					// risposta comando
+					byte command = out_buf[POS_CMD];
+					switch (command) {
+					case RSP_START_NETWORK:
+						manageStarDevice(zbifCbs, zbif_handle);
+						break;
+					case RSP_MATCH:
+						manageMatchResponse(zbifCbs, zbif_handle);
+						break;
+					case RSP_IEEE_SEARCH:
+						manageIEEEResponse(zbifCbs, zbif_handle);
+						break;
+#ifdef INCLUDE_ZIGBEE_SECURITY
+						case RSP_LEAVE:
+						manageLeave(zbifCbs, zbif_handle);
+						break;
+#endif
+					case RSP_NWK_REQ:
+						manageNwkAddress(zbifCbs, zbif_handle);
+						break;
+					case RSP_DEV_ANNCE:
+						manageDeviceAnnce(zbifCbs, zbif_handle);
+						break;
+					case RSP_NODEDESC_REQ:
+						manageNodeDesc(zbifCbs, zbif_handle);
+						break;
+					case RSP_SIMPLEDESC_REQ:
+						manageSimpleDesc(zbifCbs, zbif_handle);
+						break;
+					case RSP_ACTIVEEP_LIST:
+						manageActiveEpDesc(zbifCbs, zbif_handle);
+						break;
+					case RSP_POWER_REQ:
+						managePowerDesc(zbifCbs, zbif_handle);
+						break;
+					case RSP_ENDDEVBIND_REQ:
+						manageEndDeviceBind(zbifCbs, zbif_handle);
+						break;
+					case RSP_IEEE_GET:
+						mangageGetIEEE(zbifCbs, zbif_handle);
+						break;
+					case RSP_SET_ADD_PAR:
+						mangageAdditionalSettings();
+						break;
+					}
+				}
+			}
+		}
+	}
+
+}
+
+void MicroSD_ReceiveCb(ZBIF_HANDLE zbif_handle, uchar *data, const int size) {
+
+	if (zbif_handle == NULL) {
+		printf("\n");
+		return;
+	}
+
+	MicroSD_ParseNExec(zbif_handle, data, size);
+}
+
+ZBIFFunctions_t zbMicroSDFunctions = { MicroSD_ZDO_RESET_request,
+		MicroSD_ZDO_START_request, MicroSD_ZDO_NWK_ADDR_request,
+		MicroSD_ZDO_IEEE_ADDR_request, MicroSD_ZB_MGMT_LQI_request,
+		MicroSD_ZDO_NODE_DESC_request, MicroSD_ZDO_POWER_DESC_request,
+		MicroSD_ZDO_SIMPLE_DESC_request, MicroSD_ZDO_ACTIVE_EP_DESC_request,
+		MicroSD_ZDO_MATCH_DESC_request, MicroSD_ZDO_MATCH_DESC_response,
+		MicroSD_ZDO_END_DEVICE_BIND_request, MicroSD_APSDE_DATA_request,
+		MicroSD_APSME_BIND_request, MicroSD_APSME_UNBIND_request,
+		MicroSD_APSME_GET_request, MicroSD_APSME_SET_request,
+		MicroSD_MGMT_PERMIT_JOINING_request,
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+		MicroSD_APSME_REMOVE_DEVICE_request,
+		MicroSD_APSME_TRANSPORT_KEY_request,
+		MicroSD_NLME_LEAVE_request,
+#endif
+		MicroSD_ZDO_ERROR_response };
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_if.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_if.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_if.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,18 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef _MICROSD_IF_H_
+#define _MICROSD_IF_H_
+
+extern ZBIFFunctions_t zbMicroSDFunctions;
+
+extern void MicroSD_ReceiveCb(ZBIF_HANDLE zbif_handle, uchar *data,
+		const int size);
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_ser.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_ser.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_ser.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,588 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include "zigbee.h"
+#include "SDIO.h"
+#include "SerialProtocolGlobalDefine.h"
+#include "SerialProtocolInner.h"
+#include "time_CE.h"
+
+#include "MicroSD_utils.h"
+#include "MicroSD_ser.h"
+
+static microSD_status_t *dongle;
+
+int zigbeeLogTrace = LOG_NONE;
+FILE *zigbeeTraceLogFile;
+
+pthread_mutex_t mux;
+
+/*
+ Funzione che legge dalla porta seriale e interpreta il tipo di messaggio per inviarlo direttamente
+ alla funzione (se il tipo messaggio corrisponde) o per salvarlo in una lista dinamica
+ */
+int zigbeeReadFromSerial(unsigned char *Rsp) {
+	int totRead, i, localCnt, localTot, logPrintCount, residualHeaderToRead,
+			dataLen, res, first;
+#ifdef COMPILE_HOTP
+	int totHotpToRead;
+#endif
+	time_t_ce current_time, expiration_time;
+	byte crcFromSerial, crcCalcolato;
+
+	// inizializzo
+	totRead = 0;
+	for (i = 0; i < MAX_OTA_LEN; i++) {
+		Rsp[i] = 0x00;
+	}
+
+	res = NO_DATA_READ; // inizializzo res
+
+	// fase 1: leggo i primi due bytes dell'header
+	current_time = time_ce(0);
+	expiration_time = current_time;
+	expiration_time += (long int) difftime_ce(TIME_SPAN_RSP_CMD, 0);
+
+	localCnt = 0;
+	localTot = 0;
+	first = 0;
+	do {
+#ifdef WINDOWS   
+		localCnt=SDIO_Read((unsigned char*)Rsp+localTot, 1);
+#else
+		localCnt = SDIO_Read(Rsp + localTot, 1);
+#endif
+		if (localCnt > 0) {
+
+			// printf("[Lettura header] Tot bytes letti: %d ", localCnt);
+			// printf("Bytes letti: ");
+			// for (logPrintCount = localTot; logPrintCount < (localTot+localCnt); logPrintCount++) printf("%x ", Rsp[logPrintCount]);
+			if (zigbeeLogTrace == LOG_DEBUG) {
+				zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+				fprintf(zigbeeTraceLogFile,
+						"[Lettura header] Tot bytes letti: %d ", localCnt);
+				fprintf(zigbeeTraceLogFile, "Bytes letti: ");
+				for (logPrintCount = localTot;
+						logPrintCount < (localTot + localCnt); logPrintCount++)
+					fprintf(zigbeeTraceLogFile, "%x ", Rsp[logPrintCount]);
+				/* if (localTot == 0) {
+				 tmBuffer = localtime_ce(&current_time);
+				 fprintf(zigbeeTraceLogFile, " - Timestamp %d %d %d ", tmBuffer->tm_hour, tmBuffer->tm_min, tmBuffer->tm_sec); 
+				 } */
+				fprintf(zigbeeTraceLogFile, "\n");
+				fclose(zigbeeTraceLogFile);
+			}
+
+			printf(
+					"zigbeeReadFromSerial -> [Lettura header] Tot bytes letti: %d ",
+					localCnt);
+			printf("Bytes letti: ");
+			for (logPrintCount = localTot;
+					logPrintCount < (localTot + localCnt); logPrintCount++)
+				printf("%x ", Rsp[logPrintCount]);
+			printf("\n");
+
+			if (localTot == 0 && Rsp[0] == 0x02) {
+				localTot = localTot + localCnt;
+				totRead = localTot;
+			} else {
+				if (localTot == 1
+						&& (isCommand(Rsp[1]) || isSendData(Rsp[1])
+								|| isForwardData(Rsp[1]))) {
+					localTot = localTot + localCnt;
+					totRead = localTot;
+				} else {
+					localTot = 0;
+					totRead = 0;
+					if (isHeaderError(Rsp[1])) {
+						return HEADER_CORRUPTED;
+					}
+				}
+			}
+
+		} else {
+			// cntHeader == 0 esco subito
+			if (localCnt < 0) {
+				if (zigbeeLogTrace == LOG_DEBUG || zigbeeLogTrace == LOG_ERROR) {
+					zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt",
+							"a");
+					fprintf(zigbeeTraceLogFile,
+							"SDIO_Read < 0 in lettura header \n");
+					for (i = 0; i < MAX_OTA_LEN; i++)
+						fprintf(zigbeeTraceLogFile, "%x ", Rsp[i]);
+					fprintf(zigbeeTraceLogFile, "\n");
+					fprintf(zigbeeTraceLogFile,
+							"zigbeeReadFromSerial() END \n");
+					fclose(zigbeeTraceLogFile);
+				}
+				printf(
+						"zigbeeReadFromSerial -> SDIO_Read < 0 in lettura header \n");
+				return MINISD_ACCESS_ERROR;
+			}
+			if (localTot == 0)
+				break;
+		}
+		current_time = time_ce(0);
+	} while (localTot < 2 && current_time < expiration_time);
+
+	if (totRead < 2)
+		return NO_DATA_READ;
+
+	// fase 2: determino il tipo di messaggio letto e calcolo quanto header devo ancora leggere
+	if (isCommand(Rsp[1])) {
+		residualHeaderToRead = CMD_HEADER_length - 2;
+	} else {
+		if (isSendData(Rsp[1])) {
+			residualHeaderToRead = DATA_RSP_HEADER_length - 2;
+		} else {
+			residualHeaderToRead = FWD_HEADER_length - 2;
+		}
+	}
+
+	// fase 3: leggo il resto dell'header
+	current_time = time_ce(0);
+	expiration_time = current_time;
+	expiration_time += (long int) difftime_ce(TIME_SPAN_RSP_CMD, 0);
+
+	localCnt = 0;
+	localTot = 0;
+	do {
+#ifdef LOG_CONSOLE
+		printf("* zigbeeReadFromSerial -> lettura header SDIO_Read di %d bytes \n", (residualHeaderToRead-localTot));
+#endif
+		localCnt = SDIO_Read((unsigned char*) Rsp + totRead,
+				(residualHeaderToRead - localTot));
+
+		if (localCnt > 0) {
+
+			if (zigbeeLogTrace == LOG_DEBUG) {
+				zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+				fprintf(zigbeeTraceLogFile,
+						"[Lettura header] Tot bytes letti: %d ", localCnt);
+				fprintf(zigbeeTraceLogFile, "Bytes letti: ");
+				for (logPrintCount = totRead;
+						logPrintCount < (totRead + localCnt); logPrintCount++)
+					fprintf(zigbeeTraceLogFile, "%x ", Rsp[logPrintCount]);
+				fprintf(zigbeeTraceLogFile, "\n");
+				fclose(zigbeeTraceLogFile);
+			}
+
+			printf(
+					"zigbeeReadFromSerial -> [Lettura header] Tot bytes letti: %d ",
+					localCnt);
+			printf("Bytes letti: ");
+			for (logPrintCount = totRead; logPrintCount < (totRead + localCnt);
+					logPrintCount++)
+				printf("%x ", Rsp[logPrintCount]);
+			printf("\n");
+
+			localTot = localTot + localCnt;
+			totRead = totRead + localTot;
+		} else {
+			if (localCnt < 0) {
+				if (zigbeeLogTrace == LOG_DEBUG || zigbeeLogTrace == LOG_ERROR) {
+					zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt",
+							"a");
+					fprintf(zigbeeTraceLogFile,
+							"SDIO_Read < 0 in lettura header \n");
+					for (i = 0; i < MAX_OTA_LEN; i++)
+						fprintf(zigbeeTraceLogFile, "%x ", Rsp[i]);
+					fprintf(zigbeeTraceLogFile, "\n");
+					fprintf(zigbeeTraceLogFile,
+							"zigbeeReadFromSerial() END \n");
+					fclose(zigbeeTraceLogFile);
+				}
+				printf(
+						"zigbeeReadFromSerial -> SDIO_Read < 0 in lettura header \n");
+				return MINISD_ACCESS_ERROR;
+			}
+		}
+
+		current_time = time_ce(0);
+	} while (localTot < residualHeaderToRead && current_time < expiration_time);
+
+	// verifico di aver letto tutto l'header
+	if (localTot < residualHeaderToRead) {
+		if (zigbeeLogTrace == LOG_DEBUG || zigbeeLogTrace == LOG_ERROR) {
+			zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+			fprintf(zigbeeTraceLogFile,
+					"Header incompleto - letti %d bytes - attesi %d bytes \n",
+					totRead, (residualHeaderToRead + 2));
+			for (i = 0; i < MAX_OTA_LEN; i++)
+				fprintf(zigbeeTraceLogFile, "%x ", Rsp[i]);
+			fprintf(zigbeeTraceLogFile, "\n");
+			fprintf(zigbeeTraceLogFile, "zigbeeReadFromSerial() END \n");
+			fclose(zigbeeTraceLogFile);
+		}
+		printf("zigbeeReadFromSerial -> Header incompleto \n");
+		return UNCOMPLETED_MSG;
+	}
+
+	// fase 4: leggo il payload
+	dataLen = Rsp[(residualHeaderToRead + 2) - 1]; // il bytes che indica la lunghezza del payload e' sempre l'ultimo dell'header
+
+	if (zigbeeLogTrace == LOG_DEBUG) {
+		zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+		fprintf(zigbeeTraceLogFile,
+				"[Lettura payload] Len Payload: Decimale[%d] Hex[%x] \n",
+				dataLen, Rsp[(residualHeaderToRead + 2) - 1]);
+		fclose(zigbeeTraceLogFile);
+	}
+	fprintf(
+			"zigbeeReadFromSerial ->  [Lettura payload] Len Payload: Decimale[%d] Hex[%x] \n",
+			dataLen, Rsp[(residualHeaderToRead + 2) - 1]);
+
+	if (dataLen == 0) {
+		if (zigbeeLogTrace == LOG_DEBUG || zigbeeLogTrace == LOG_ERROR) {
+			zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+			fprintf(zigbeeTraceLogFile, "NULL_PAYLOAD \n");
+			for (i = 0; i < MAX_OTA_LEN; i++)
+				fprintf(zigbeeTraceLogFile, "%x ", Rsp[i]);
+			fprintf(zigbeeTraceLogFile, "\n");
+			fprintf(zigbeeTraceLogFile, "zigbeeReadFromSerial() END \n");
+			fclose(zigbeeTraceLogFile);
+		}
+		printf("zigbeeReadFromSerial -> NULL_PAYLOAD \n");
+		return NULL_PAYLOAD;
+	}
+
+	if (dataLen > MAX_PAYLOAD_DATA) {
+		if (zigbeeLogTrace == LOG_DEBUG || zigbeeLogTrace == LOG_ERROR) {
+			zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+			fprintf(zigbeeTraceLogFile, "PAYLOAD_EXCEEDED_LIMIT \n");
+			for (i = 0; i < MAX_OTA_LEN; i++)
+				fprintf(zigbeeTraceLogFile, "%x ", Rsp[i]);
+			fprintf(zigbeeTraceLogFile, "\n");
+			fprintf(zigbeeTraceLogFile, "zigbeeReadFromSerial() END \n");
+			fprintf(zigbeeTraceLogFile, "\n");
+			fclose(zigbeeTraceLogFile);
+		}
+		printf("zigbeeReadFromSerial -> PAYLOAD_EXCEEDED_LIMIT  \n");
+		return PAYLOAD_EXCEEDED_LIMIT;
+	}
+
+	current_time = time_ce(0);
+	expiration_time = current_time;
+	expiration_time += (long int) difftime_ce(TIME_SPAN_RSP_FWD, 0);
+
+	localCnt = 0;
+	localTot = 0;
+	do {
+#ifdef LOG_CONSOLE
+		printf("* readFromSerial -> lettura payload SDIO_Read di %d bytes \n", (dataLen-localTot));
+#endif
+		localCnt = SDIO_Read((unsigned char*) Rsp + totRead,
+				(dataLen - localTot));
+
+		if (localCnt > 0) {
+			if (zigbeeLogTrace == LOG_DEBUG) {
+				zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+				fprintf(zigbeeTraceLogFile,
+						"[Lettura payload] Tot bytes letti: %d ", localCnt);
+				fprintf(zigbeeTraceLogFile, "Bytes letti: ");
+				for (logPrintCount = totRead;
+						logPrintCount < (totRead + localCnt); logPrintCount++)
+					fprintf(zigbeeTraceLogFile, "%x ", Rsp[logPrintCount]);
+				fprintf(zigbeeTraceLogFile, "\n");
+				fclose(zigbeeTraceLogFile);
+			}
+
+			printf(
+					"zigbeeReadFromSerial -> [Lettura payload] Tot bytes letti: %d ",
+					localCnt);
+			printf("Bytes letti: ");
+			for (logPrintCount = totRead; logPrintCount < (totRead + localCnt);
+					logPrintCount++)
+				printf("%x ", Rsp[logPrintCount]);
+			printf("\n");
+		}
+
+		if (localCnt < 0) {
+			if (zigbeeLogTrace == LOG_DEBUG || zigbeeLogTrace == LOG_ERROR) {
+				zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+				fprintf(zigbeeTraceLogFile, "SDIO_Read < 0 in lettura dati \n");
+				for (i = 0; i < MAX_OTA_LEN; i++)
+					fprintf(zigbeeTraceLogFile, "%x ", Rsp[i]);
+				fprintf(zigbeeTraceLogFile, "\n");
+				fprintf(zigbeeTraceLogFile, "zigbeeReadFromSerial() END \n");
+				fprintf(zigbeeTraceLogFile, "\n");
+				fclose(zigbeeTraceLogFile);
+			}
+			printf(
+					"zigbeeReadFromSerial -> SDIO_Read < 0 in lettura header \n");
+			return MINISD_ACCESS_ERROR;
+		}
+
+		localTot = localTot + localCnt;
+		totRead = totRead + localTot;
+		current_time = time_ce(0);
+	} while (localTot < dataLen && current_time < expiration_time);
+
+	// l'header sicuramente l'ho letto, controllo di aver letto tutto il payload
+	if (localTot < dataLen) {
+		if (zigbeeLogTrace == LOG_DEBUG || zigbeeLogTrace == LOG_ERROR) {
+			zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+			fprintf(zigbeeTraceLogFile, "Payload incompleto ");
+			for (i = 0; i < MAX_OTA_LEN; i++)
+				fprintf(zigbeeTraceLogFile, "%x ", Rsp[i]);
+			fprintf(zigbeeTraceLogFile, "\n");
+			fprintf(zigbeeTraceLogFile, "zigbeeReadFromSerial() END \n");
+			fclose(zigbeeTraceLogFile);
+		}
+		printf("zigbeeReadFromSerial -> Payload incompleto \n");
+		return UNCOMPLETED_MSG;
+	}
+
+	// fase 5: gestione dell'HOTP
+	/*
+	 Effettuo questa fase solo se ho abilitato l'HOTP e se devo gestire un msg A1, A2 o A3
+	 Il msg A4 (hotpInit) non ha bisogno di questa fase poiche' l'HOTP risiede nel payload
+	 */
+#ifdef COMPILE_HOTP
+	if (hotpUsed && Rsp[1] != HOTP_CONFIG) {
+		if (isForwardData(Rsp[1])) {
+			totHotpToRead = HOTP_LEN;
+		}
+		else {
+			totHotpToRead = HOTP_RSP_length;
+		}
+
+		current_time = time_ce(0);
+		expiration_time = current_time;
+		expiration_time += (long int)difftime_ce( TIME_SPAN_RSP_FWD, 0);
+
+		localCnt = 0;
+		localTot = 0;
+		do {
+			localCnt = SDIO_Read((unsigned char*) Rsp+totRead, totHotpToRead-localTot);
+
+			if (localCnt > 0) {
+				if (zigbeeLogTrace == LOG_DEBUG) {
+					zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+					fprintf(zigbeeTraceLogFile, "[Lettura hotp] Tot bytes letti: %d ", localCnt);
+					fprintf(zigbeeTraceLogFile, "Bytes letti: ");
+					for (logPrintCount = totRead; logPrintCount < (totRead+localCnt); logPrintCount++)
+					fprintf(zigbeeTraceLogFile, "%x ", Rsp[logPrintCount]);
+					fprintf(zigbeeTraceLogFile, "\n");
+					fclose(zigbeeTraceLogFile);
+				}
+				printf("zigbeeReadFromSerial -> [Lettura hotp] Tot bytes letti: %d ", localCnt);
+				printf("Bytes letti: ");
+				for (logPrintCount = totRead; logPrintCount < (totRead+localCnt); logPrintCount++) printf("%x ", Rsp[logPrintCount]);
+				printf("\n");
+			}
+
+			if (localCnt < 0) {
+				if (zigbeeLogTrace == LOG_DEBUG || zigbeeLogTrace == LOG_ERROR) {
+					zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+					fprintf(zigbeeTraceLogFile, "SDIO_Read < 0 in lettura hotp \n");
+					for (i=0; i<MAX_OTA_LEN; i++) fprintf(zigbeeTraceLogFile, "%x ", Rsp[i]);
+					fprintf(zigbeeTraceLogFile, "\n");
+					fprintf(zigbeeTraceLogFile, "zigbeeReadFromSerial() END \n");
+					fclose(zigbeeTraceLogFile);
+				}
+				printf("zigbeeReadFromSerial -> SDIO_Read < 0 in lettura hotp \n");
+				return MINISD_ACCESS_ERROR;
+			}
+			localTot = localTot + localCnt;
+			totRead = totRead + localTot;
+
+			current_time = time_ce(0);
+		}while (localTot < totHotpToRead && current_time < expiration_time);
+
+		// header e payload sono letti, controllo di aver letto l'HOTP
+		if (localTot < totHotpToRead) {
+			if (zigbeeLogTrace == LOG_DEBUG || zigbeeLogTrace == LOG_ERROR) {
+				zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+				fprintf(zigbeeTraceLogFile, "HOTP incompleto ");
+				for (i=0; i<MAX_OTA_LEN; i++) fprintf(zigbeeTraceLogFile, "%x ", Rsp[i]);
+				fprintf(zigbeeTraceLogFile, "\n");
+				fprintf(zigbeeTraceLogFile, "zigbeeReadFromSerial() END \n");
+				fclose(zigbeeTraceLogFile);
+			}
+			printf("zigbeeReadFromSerial -> HOTP incompleto \n");
+			return UNCOMPLETED_MSG;
+		}
+	}
+#endif
+
+	// fase 6: gestione del CRC
+	current_time = time_ce(0);
+	expiration_time = current_time;
+	expiration_time += (long int) difftime_ce(TIME_SPAN_RSP_FWD, 0);
+
+	crcFromSerial = 0x00;
+	localCnt = 0;
+	localTot = 0;
+	do {
+#ifdef LOG_CONSOLE
+		printf("* readFromSerial -> lettura CRC SDIO_Read di %d bytes \n", (CRC_length-localTot));
+#endif
+		localCnt = SDIO_Read((unsigned char*) Rsp + totRead,
+				CRC_length - localTot);
+
+		if (localCnt > 0) {
+			if (zigbeeLogTrace == LOG_DEBUG) {
+				zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+				fprintf(zigbeeTraceLogFile,
+						"[Lettura CRC] Tot bytes letti: %d ", localCnt);
+				fprintf(zigbeeTraceLogFile, "Bytes letti: ");
+				for (logPrintCount = totRead;
+						logPrintCount < (totRead + localCnt); logPrintCount++)
+					fprintf(zigbeeTraceLogFile, "%x ", Rsp[logPrintCount]);
+				fprintf(zigbeeTraceLogFile, "\n");
+				fclose(zigbeeTraceLogFile);
+			}
+
+			printf("zigbeeReadFromSerial -> [Lettura CRC] Tot bytes letti: %d ",
+					localCnt);
+			printf("Bytes letti: ");
+			for (logPrintCount = totRead; logPrintCount < (totRead + localCnt);
+					logPrintCount++)
+				printf("%x ", Rsp[logPrintCount]);
+			printf("\n");
+		}
+
+		if (localCnt < 0) {
+			if (zigbeeLogTrace == LOG_DEBUG || zigbeeLogTrace == LOG_ERROR) {
+				zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+				fprintf(zigbeeTraceLogFile, "SDIO_Read < 0 in lettura CRC \n");
+				for (i = 0; i < MAX_OTA_LEN; i++)
+					fprintf(zigbeeTraceLogFile, "%x ", Rsp[i]);
+				fprintf(zigbeeTraceLogFile, "\n");
+				fprintf(zigbeeTraceLogFile, "zigbeeReadFromSerial() END \n");
+				fclose(zigbeeTraceLogFile);
+			}
+			printf("zigbeeReadFromSerial -> SDIO_Read < 0 in lettura CRC \n");
+			return MINISD_ACCESS_ERROR;
+		}
+
+		localTot = localTot + localCnt;
+		totRead = totRead + localTot;
+		current_time = time_ce(0);
+	} while (localTot < CRC_length && current_time < expiration_time);
+
+	// header, payload e hotp sono letti, controllo di aver letto il CRC
+	if (localTot < CRC_length) {
+		if (zigbeeLogTrace == LOG_DEBUG || zigbeeLogTrace == LOG_ERROR) {
+			zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+			fprintf(zigbeeTraceLogFile, "CRC incompleto \n");
+			for (i = 0; i < MAX_OTA_LEN; i++)
+				fprintf(zigbeeTraceLogFile, "%x ", Rsp[i]);
+			fprintf(zigbeeTraceLogFile, "\n");
+			fprintf(zigbeeTraceLogFile, "zigbeeReadFromSerial() END \n");
+			fclose(zigbeeTraceLogFile);
+		}
+		printf("zigbeeReadFromSerial -> CRC incompleto \n");
+		return UNCOMPLETED_MSG;
+	}
+
+	crcFromSerial = Rsp[totRead - CRC_length];
+	crcCalcolato = calculateCRC(Rsp, totRead - CRC_length);
+
+	if (zigbeeLogTrace == LOG_DEBUG) {
+		zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+		fprintf(zigbeeTraceLogFile,
+				"zigbeeReadFromSerial() crc da seriale %d crcCalcolato %d \n",
+				crcFromSerial, crcCalcolato);
+		fclose(zigbeeTraceLogFile);
+	}
+	printf("zigbeeReadFromSerial() crc da seriale %d crcCalcolato %d \n",
+			crcFromSerial, crcCalcolato);
+
+	if (crcFromSerial != crcCalcolato) {
+		if (zigbeeLogTrace == LOG_DEBUG || zigbeeLogTrace == LOG_ERROR) {
+			zigbeeTraceLogFile = fopen("SerialLibraryTraceLog.txt", "a");
+			fprintf(zigbeeTraceLogFile, "CRC_ERROR \n");
+			for (i = 0; i < MAX_OTA_LEN; i++)
+				fprintf(zigbeeTraceLogFile, "%x ", Rsp[i]);
+			fprintf(zigbeeTraceLogFile, "\n");
+			fprintf(zigbeeTraceLogFile, "zigbeeReadFromSerial() END \n");
+			fclose(zigbeeTraceLogFile);
+		}
+		// countCrcError++;
+		printf("CRC_ERROR \n");
+		return CRC_ERROR;
+	}
+
+	// fase 7: ci sono dati! :)
+	return DATA_READ;
+}
+
+int microSD_open(const char **params) {
+
+	char *device = get_param(params, "pathMicroSD"); // {DEFAULT_ZIGBEEDEVICE};
+	if (device == NULL) {
+		device = 0;
+	}
+
+	dongle = (microSD_status_t *) malloc(sizeof(microSD_status_t));
+	dongle->fd = SDIO_Open(device, 115200, 1, 1);
+
+	//Initialize the mux
+	pthread_mutex_init(&mux, NULL);
+	if (dongle->fd == OK)
+		return (int) dongle;
+	else
+		return -100;
+}
+
+int microSD_close(int handle) {
+	SDIO_Close();
+	if (dongle != NULL)
+		free(dongle);
+	return 0;
+}
+
+int microSD_transmit(int handle, const unsigned char *data, int size) {
+	int res, i;
+	pthread_mutex_lock(&mux);
+	printf("microSD_transmit -> start -> size = %d \n", size);
+	printf("microSD_transmit -> vect = ");
+	if (size > 0) {
+		for (i = 0; i < size; i++)
+			printf("%x ", data[i]);
+	}
+	printf("\n");
+	res = SDIO_Write((unsigned char *) data, size);
+	printf("microSD_transmit -> end \n");
+	pthread_mutex_unlock(&mux);
+	return res;
+}
+
+int microSD_receive(int handle, unsigned char *buf, const int size) {
+	int res;
+
+	pthread_mutex_lock(&mux);
+	res = zigbeeReadFromSerial(buf);
+	pthread_mutex_unlock(&mux);
+
+	usleep(200 * 1000);
+
+	if (res == NO_DATA_READ) {
+		return 0;
+	} else {
+		if (res == DATA_READ) {
+			return 200;
+		} else {
+			return -1;
+		}
+	}
+}
+
+int microSD_fd(int handle) {
+	return dongle->fd;
+}

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_ser.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_ser.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_ser.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,24 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef _MICROSD_SER_H_
+#define _MICROSD_SER_H_
+
+typedef struct {
+	int fd;
+	int state;
+} microSD_status_t;
+
+int microSD_open(const char **params);
+int microSD_close(int handle);
+int microSD_transmit(int handle, const unsigned char *data, int size);
+int microSD_receive(int handle, unsigned char *buf, const int size);
+int microSD_fd(int handle);
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_utils.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_utils.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_utils.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,115 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "SerialProtocolInner.h"
+#include "MicroSD_utils.h"
+
+#ifdef COMPILE_HOTP
+#ifdef HOTP
+BOOL utilHotpUsed = TRUE;
+#else
+BOOL utilHotpUsed = FALSE;
+#endif
+#else
+BOOL utilHotpUsed = FALSE;
+#endif
+
+BOOL isOxF_Command(byte number, char elem) {
+	byte toCheck = elem;
+	if (toCheck == number)
+		return TRUE;
+	return FALSE;
+}
+
+BOOL isCommand(char elem) {
+#ifdef COMPILE_HOTP
+	if (utilHotpUsed) {
+		if (isOxF_Command(CMD_PCK_RESPONSE_HOTP, elem) || isOxF_Command(HOTP_CONFIG, elem)) return TRUE;
+	}
+	else {
+		if (isOxF_Command(CMD_PCK_RESPONSE_ZIGBEE, elem)) return TRUE;
+	}
+#else
+	if (isOxF_Command(CMD_PCK_RESPONSE_ZIGBEE, elem))
+		return TRUE;
+#endif
+
+	return FALSE;
+}
+
+BOOL isSendData(char elem) {
+#ifdef COMPILE_HOTP
+	if (utilHotpUsed) {
+		if (isOxF_Command(SENDDATA_PCK_RESPONSE_HOTP, elem)) return TRUE;
+	}
+	else {
+		if (isOxF_Command(SENDDATA_PCK_RESPONSE_ZIGBEE, elem)) return TRUE;
+	}
+#else
+	if (isOxF_Command(SENDDATA_PCK_RESPONSE_ZIGBEE, elem))
+		return TRUE;
+#endif
+	return FALSE;
+}
+
+BOOL isForwardData(char elem) {
+#ifdef COMPILE_HOTP
+	if (utilHotpUsed) {
+		if (isOxF_Command(FROMSERIAL_PCK_HOTP, elem)) return TRUE;
+	}
+	else {
+		if (isOxF_Command(FROMSERIAL_PCK_ZIGBEE, elem)) return TRUE;
+	}
+#else
+	if (isOxF_Command(FROMSERIAL_PCK_ZIGBEE, elem))
+		return TRUE;
+#endif
+	return FALSE;
+}
+
+BOOL isHeaderError(char elem) {
+	if (isOxF_Command(HEADER_ERROR, elem))
+		return TRUE;
+	return FALSE;
+}
+
+byte calculateCRC(byte *msg_ptr, int len) {
+	byte x;
+	byte xorResult;
+
+	xorResult = 0;
+
+	for (x = 0; x < len; x++, msg_ptr++)
+		xorResult = xorResult ^ *msg_ptr;
+
+	return (xorResult);
+}
+
+byte DIVIDE_UINT16(unsigned short word, byte indByteWord) {
+	byte singleByte;
+
+	switch (indByteWord) {
+	case 0:
+		singleByte = (byte) ((word >> 8) & 0x00FF);
+		break;
+	case 1:
+		singleByte = (byte) (word & 0x00FF);
+		break;
+	default:
+		singleByte = 0;
+		break;
+	}
+	return singleByte;
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_utils.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_utils.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/MicroSD_utils.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,32 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#pragma once
+#include "stdafx.h"
+
+#ifdef LINUX_ANDROID
+#include <unistd.h>
+#include "SerialProtocolTypes.h"
+#endif
+
+#ifdef LINUX
+#include <unistd.h>
+#include "SerialProtocolTypes.h"
+#endif
+
+BOOL isOxF_Command(byte number, char elem);
+BOOL isCommand(char elem);
+BOOL isSendData(char elem);
+BOOL isForwardData(char elem);
+byte calculateCRC(byte *msg_ptr, int len);
+BOOL isHeaderError(char elem);
+byte DIVIDE_UINT16(unsigned short word, byte indByteWord);
+
+#define BUILD_UINT16(loByte, hiByte) \
+        ((unsigned short)((loByte & 0x00FF) + ((hiByte & 0x00FF) << 8)))

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/README
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/README (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/README Fri Oct 19 18:37:43 2012
@@ -1,0 +1,13 @@
+
+For each new dongle type <type> add the following files:
+
+<type>_if.c	Contains the prototypes and the specific implementation
+ 			of the ZDO primitives
+
+			i.e. <type>_ZDO_RESET_request(..)
+
+			At the end there is the function table assignemts table
+
+<type>_if.h	Contains the function table extern
+
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/SDIO.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/SDIO.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/SDIO.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,1009 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#define _GNU_SOURCE
+
+#include <fcntl.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <math.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#ifdef LINUX_ANDROID
+#include <linux/fs.h>
+#include <android/log.h>
+#endif
+#include "SDIO.h"
+#include "SerialProtocolTypes.h"
+
+//Dublin
+//#define LOG_CONSOLE
+
+#define MICRO_SD
+
+int DriveInfoLen;
+int TagW, InsIdxW, CustomerLenW, DataPayloadLenW;
+unsigned char CustomerW[CUSTOMER_VECTOR_length]; // = new byte[10];
+unsigned char DataPayloadW[DATA_PAYLOAD_VECTOR_length]; //  = new byte[480];
+unsigned char CustomerR[CUSTOMER_VECTOR_length]; // = new byte[10];
+unsigned char DataPayloadR[DATA_PAYLOAD_VECTOR_length]; // = new byte[480];
+int TagR, StatusR, CustomerLenR, DataPayloadLenR;
+unsigned char ProcessID = 0x01;
+unsigned char FrameCounter = 0x01;
+long DriveInfo[DRIVE_INFO_VECTOR_length]; // =new long[480];
+
+int ret_value;
+int Count = 0;
+long Loop_Len = 10;
+
+unsigned char dat_in[DATA_VECTOR_length]; // = new byte[512];
+unsigned char dat_out[DATA_VECTOR_length]; // = new byte[512];
+
+#ifdef MICRO_SD
+int oft_id = 0x1F0;
+int oft_data = 0x00;
+
+unsigned char CID[16] = { 0x53, 0x12, 0x4D, (unsigned char) 0xC8, 0x43, 0x50,
+		(unsigned char) 0x8B, 0x54, 0x45, 0x03, 0x43, 0x49, 0x09, 0x4E, 0x25,
+		0x53 };
+unsigned char VID[16] = { (unsigned char) 0xAD, 0x53, 0x50,
+		(unsigned char) 0xF2, 0x44, 0x40, 0x66, 0x54, 0x6B, 0x45, 0x43, 0x52,
+		0x32, 0x53, (unsigned char) 0xA1, 0x50 };
+#else
+int oft_id = 0x00;
+int oft_data = 0x10;
+
+unsigned char CID[16] = {0x49, 0x4F, 0x2A, (unsigned char)0x57, 0x52, 0x49, (unsigned char)0x54, 0x45, 0x2A, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x2A};
+unsigned char VID[16] = {(unsigned char)0x52, 0x45, 0x53, (unsigned char)0x50, 0x4F, 0x4E, 0x53, 0x45, 0x2A, 0x46, 0x52, 0x4F, 0x4D, 0x2A, (unsigned char)0x49, 0x4F};
+#endif
+
+unsigned char OSC_index = 1;
+//(1)44M+-2M(Internal) (2)16M(External) (3)26M(External) (4)32M(External)
+unsigned char Baud_Rate_index = 7;
+//(1)4800 (2)9600 (3)19200 (4)38400 (5)57600 (6)76800 (7)115200 (8)812500
+unsigned char Parity_Check_index = 1;
+//(1)Disable (2)Odd (3)Even
+unsigned char Flow_Ctrl_index = 1;
+//(1)Disable (2)Handshake"
+unsigned char Handshake_Length = 0; //(HEX:0x00-0xFE):
+unsigned char Delay_length = 0;
+
+int totToRead;
+int indexRead = 0;
+int counter6 = 0;
+int counter7 = 0;
+
+char *pathFile;
+
+#ifdef STD_FILE_FUNCTIONS
+FILE *deviceFile; // puntatore al file
+#else
+int deviceFile; // puntatore al file
+#endif
+
+#define MAX_COUNTER_SEEK 65000
+int counterSeek = 0;
+
+//#define LOG_CONSOLE
+#define LOG_ERROR_CONSOLE
+
+/*
+ Inizio metodi interni
+ */
+
+int Check_IO_VID() {
+	int i;
+
+#ifdef LOG_CONSOLE
+	for(i=0; i<0x10; i++) {
+		printf("***** ReadCommand -> Check_IO_VID VID[%d]=%x - dat_out[%d]=%x \n", i, VID[i], (oft_id + i), dat_out[oft_id + i]);
+	}
+#endif 
+
+	for (i = 0; i < 0x10; i++) {
+		if (VID[i] != dat_out[oft_id + i])
+			return 200;
+	}
+	return 0;
+}
+
+int Check_CMD_Status(int ret_value) {
+
+	if (ret_value == 100) {
+		return OPEN_DISK_FAILURE;
+	} else if (ret_value == 101) {
+		return CLOSE_DISK_FAILURE;
+	} else if (ret_value == 102) {
+		return WRITE_DISK_FAILURE;
+	} else if (ret_value == 103) {
+		return READ_DISK_FAILURE;
+	} else if (ret_value == 104) {
+		return NO_DATA_TRASMISSION;
+	} else if (ret_value == 105) {
+		return NO_DATA_RECEPTION;
+	} else if (ret_value == 200) {
+		return NO_IO_RESPONSE;
+	} else if (ret_value == 300) {
+		return DATA_PAYLOAD_length_ERROR;
+	} else if (ret_value == 301) {
+		return CUSTOMER_length_ERROR;
+	} else if (ret_value == 400) {
+		return NO_APPLICATION_DEVICE;
+	} else if (ret_value == 401) {
+		return NO_SMART_IO_CRD_FILE;
+	}
+
+	return 0;
+}
+
+int Check_IO_Status() {
+	int status = StatusR & 0xFF;
+
+	if (status == (unsigned char) 0x60) {
+		return STATUS_BUSY;
+	} else if (status == (unsigned char) 0xC0) {
+		return STATUS_INVALID_TAG;
+	} else if (status == (unsigned char) 0xC1) {
+		return STATUS_INVALID_INSNO;
+	} else if (status == (unsigned char) 0xC2) {
+		return STATUS_length_ERROR;
+	} else if (status == (unsigned char) 0xC3) {
+		return STATUS_PARAMETER_ERROR;
+	} else if (status == (unsigned char) 0xC4) {
+		return STATUS_PARITY_CHECK_ERROR;
+	} else if (status != (unsigned char) 0x00) {
+		return STATUS_UNK_ERROR;
+	}
+
+	return 0;
+}
+
+static void *pagealign_alloc(size_t size) {
+	void *ret;
+#ifdef LINUX_ANDROID
+	ret = mmap(NULL, size, PROT_READ | PROT_WRITE,
+			MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE | MAP_LOCKED,
+			-1, 0);
+#else
+	// printf("pagealign_alloc -> passo di qui! \n");
+	ret = mmap(NULL, size, PROT_READ | PROT_WRITE,
+			MAP_PRIVATE | MAP_ANONYMOUS | 0 | 0, -1, 0);
+#endif			
+	if (ret == MAP_FAILED) {
+#ifdef LINUX_ANDROID	
+		__android_log_print(ANDROID_LOG_DEBUG, "pagealign", "Mmap Error %d ", errno);
+#endif
+		ret = NULL;
+	}
+	return ret;
+}
+
+static void pagealign_free(void *addr, size_t size) {
+	int ret = munmap(addr, size);
+	if (ret == -1) {
+#ifdef LINUX_ANDROID
+		__android_log_write(ANDROID_LOG_DEBUG, "pagefree", "Error");
+#endif
+	}
+}
+
+// versione della WriteCommand con write()
+int WriteCommand() {
+	// int ret = diskIO.write(dat_in);
+	void *write_buf = NULL;
+	struct stat stat;
+	ssize_t ret;
+	int i, device, cnt;
+	uint8_t *data;
+	int Count = 0;
+	BOOL error = FALSE;
+
+	// write_buf = pagealign_alloc(DATA_VECTOR_length);
+	if (posix_memalign((void **) &write_buf, DATA_VECTOR_length,
+			DATA_VECTOR_length) != 0) {
+#ifdef LOG_ERROR_CONSOLE
+		printf("***** WriteCommand -> posix_memalign failed \n");
+#endif
+		return -1;
+	}
+
+	data = (uint8_t*) write_buf;
+
+	if (data == NULL) {
+#ifdef LOG_ERROR_CONSOLE
+		printf("***** WriteCommand -> data NULL \n");
+#endif
+		if (write_buf != NULL)
+			free(write_buf);
+		return -1;
+	}
+
+	for (i = 0; i < DATA_VECTOR_length; i++) {
+		data[i] = dat_in[i];
+	}
+
+	device = open(pathFile, O_RDWR | O_DIRECT);
+	if (device == -1) {
+		printf("***** WriteCommand -> open smart_io.crd failed \n");
+		error = TRUE;
+	}
+
+	if (!error) {
+		ret = write(device, data, DATA_VECTOR_length);
+		counterSeek++;
+		if (ret == -1) {
+#ifdef LOG_ERROR_CONSOLE
+			printf("***** WriteCommand -> errore scrittura su file \n");
+#endif
+			error = TRUE;
+		}
+
+	}
+
+	if (write_buf != NULL)
+		free(write_buf); // pagealign_free(write_buf, DATA_VECTOR_length);
+	if (device != -1)
+		close(device);
+
+	if (error)
+		return -1;
+	return 0;
+}
+// #endif
+
+// #ifndef STD_FILE_FUNCTIONS
+// versione con fread()
+int ReadCommand() {
+
+	int returnVal = -2;
+	int device;
+	struct stat stat;
+	void *read_buf = NULL;
+	int blk_size;
+	uint64_t num_blks;
+	size_t test_size;
+	int test_areas, i;
+	const uint8_t *data;
+
+	int k = 0;
+	do {
+		k++;
+		Count++;
+
+		device = open(pathFile, O_RDWR | O_DIRECT);
+		if (device == -1) {
+			printf("***** ReadCommand -> open smart_io.crd failed \n");
+			return -1;
+		}
+
+		if (posix_memalign((void **) &read_buf, DATA_VECTOR_length,
+				DATA_VECTOR_length) != 0) {
+#ifdef LOG_ERROR_CONSOLE
+			printf("***** ReadCommand -> posix_memalign failed \n");
+#endif
+			if (device != -1)
+				close(device);
+			return -1;
+		}
+
+		returnVal = read(device, read_buf, DATA_VECTOR_length);
+		counterSeek++;
+
+		if (returnVal == -1) {
+#ifdef LOG_ERROR_CONSOLE
+			printf("***** ReadCommand -> read KO \n");
+#endif
+			if (read_buf != NULL)
+				free(read_buf); // pagealign_free(read_buf, DATA_VECTOR_length);
+			if (device != -1)
+				close(device);
+			return returnVal;
+		}
+
+		data = (const uint8_t*) read_buf;
+		if (data == NULL) {
+#ifdef LOG_ERROR_CONSOLE
+			printf("***** ReadCommand -> data NULL \n");
+#endif
+			if (read_buf != NULL)
+				free(read_buf); // pagealign_free(read_buf, DATA_VECTOR_length);
+			if (device != -1)
+				close(device);
+			return -1;
+		}
+
+		for (i = 0; i < DATA_VECTOR_length; i++) {
+			dat_out[i] = data[i];
+		}
+		// free(read_buf);
+		if (read_buf != NULL)
+			free(read_buf); // pagealign_free(read_buf, DATA_VECTOR_length);
+		if (device != -1)
+			close(device);
+		// FINE READ
+
+		if (Count > Loop_Len) {
+			Count = 0;
+		}
+		if (k > Loop_Len) {
+#ifdef LOG_CONSOLE 
+			printf("***** ReadCommand -> k > Loop_Len k:%d Loop_Len:%d \n", k, Loop_Len);
+#endif
+			return 200;
+		}
+#ifdef LOG_CONSOLE
+		printf("***** ReadCommand -> dat_in[0x06] = %x dat_out[0x06] = %x \n", dat_in[oft_data+0x06], dat_out[oft_data+0x06]);
+		printf("***** ReadCommand -> dat_in[0x07] = %x dat_out[0x07] = %x \n", dat_in[oft_data+0x07], dat_out[oft_data+0x07]);
+#endif
+
+	} while (!(dat_in[oft_data + 0x06] == dat_out[oft_data + 0x06])
+			|| !(dat_in[oft_data + 0x07] == dat_out[oft_data + 0x07])
+			|| !(Check_IO_VID() == 0));
+
+	return 0;
+}
+
+int WriteIOCommand() {
+	int ret_value, i;
+
+	// pulizia vettore
+	// for (i=0; i<DATA_VECTOR_length; i++) dat_in[i] = 0x00;
+
+	if (DataPayloadLenW > 480)
+		return 300;
+	if (CustomerLenW > 10)
+		return 301;
+
+	dat_in[oft_id + 0x00] = CID[0x00];
+	dat_in[oft_id + 0x01] = CID[0x01];
+	dat_in[oft_id + 0x02] = CID[0x02];
+	dat_in[oft_id + 0x03] = CID[0x03];
+	dat_in[oft_id + 0x04] = CID[0x04];
+	dat_in[oft_id + 0x05] = CID[0x05];
+	dat_in[oft_id + 0x06] = CID[0x06];
+	dat_in[oft_id + 0x07] = CID[0x07];
+	dat_in[oft_id + 0x08] = CID[0x08];
+	dat_in[oft_id + 0x09] = CID[0x09];
+	dat_in[oft_id + 0x0A] = CID[0x0A];
+	dat_in[oft_id + 0x0B] = CID[0x0B];
+	dat_in[oft_id + 0x0C] = CID[0x0C];
+	dat_in[oft_id + 0x0D] = CID[0x0D];
+	dat_in[oft_id + 0x0E] = CID[0x0E];
+	dat_in[oft_id + 0x0F] = CID[0x0F];
+
+	dat_in[oft_data + 0x00] = (unsigned char) ((TagW >> 8) & 0xFF); // ((TagW >>> 8) & 0xFF);
+	dat_in[oft_data + 0x01] = (unsigned char) ((TagW) & 0xFF); //
+
+	dat_in[oft_data + 0x02] = (unsigned char) ((InsIdxW >> 8) & 0xFF); // ((InsIdxW >>> 8) & 0xFF);
+	dat_in[oft_data + 0x03] = (unsigned char) ((InsIdxW) & 0xFF);
+
+	dat_in[oft_data + 0x04] = (unsigned char) ((DataPayloadLenW >> 8) & 0xFF); // ((DataPayloadLenW >>> 8) & 0xFF);
+	dat_in[oft_data + 0x05] = (unsigned char) ((DataPayloadLenW) & 0xFF);
+
+	// for (int i=0; i<16; i++) printf("WriteIOCommand() -> dat_in[oft_data + %d] = %x \n", i, dat_in[oft_data + i]);
+#ifdef LOG_CONSOLE
+	/* printf("WriteIOCommand() -> dat_in[oft_data + 0x00] = %x \n", dat_in[oft_data + 0x00]);
+	 printf("WriteIOCommand() -> dat_in[oft_data + 0x01] = %x \n", dat_in[oft_data + 0x01]);
+	 printf("WriteIOCommand() -> dat_in[oft_data + 0x02] = %x \n", dat_in[oft_data + 0x02]);
+	 printf("WriteIOCommand() -> dat_in[oft_data + 0x03] = %x \n", dat_in[oft_data + 0x03]);
+	 printf("WriteIOCommand() -> dat_in[oft_data + 0x04] = %x \n", dat_in[oft_data + 0x04]);
+	 printf("WriteIOCommand() -> dat_in[oft_data + 0x05] = %x \n", dat_in[oft_data + 0x05]);
+
+	 printf("WriteIOCommand() -> dat_in[oft_id + 0x00] = %x \n", dat_in[oft_id + 0x00]);
+	 printf("WriteIOCommand() -> dat_in[oft_id + 0x01] = %x \n", dat_in[oft_id + 0x01]);
+	 printf("WriteIOCommand() -> dat_in[oft_id + 0x02] = %x \n", dat_in[oft_id + 0x02]);
+	 printf("WriteIOCommand() -> dat_in[oft_id + 0x03] = %x \n", dat_in[oft_id + 0x03]);
+	 printf("WriteIOCommand() -> dat_in[oft_id + 0x04] = %x \n", dat_in[oft_id + 0x04]);
+	 printf("WriteIOCommand() -> dat_in[oft_id + 0x05] = %x \n", dat_in[oft_id + 0x05]);
+	 printf("WriteIOCommand() -> dat_in[oft_id + 0x06] = %x \n", dat_in[oft_id + 0x06]);
+	 printf("WriteIOCommand() -> dat_in[oft_id + 0x07] = %x \n", dat_in[oft_id + 0x07]);
+	 printf("WriteIOCommand() -> dat_in[oft_id + 0x08] = %x \n", dat_in[oft_id + 0x08]);
+	 printf("WriteIOCommand() -> dat_in[oft_id + 0x09] = %x \n", dat_in[oft_id + 0x09]);
+	 printf("WriteIOCommand() -> dat_in[oft_id + 0x0A] = %x \n", dat_in[oft_id + 0x0A]);
+	 printf("WriteIOCommand() -> dat_in[oft_id + 0x0B] = %x \n", dat_in[oft_id + 0x0B]);
+	 printf("WriteIOCommand() -> dat_in[oft_id + 0x0C] = %x \n", dat_in[oft_id + 0x0C]);
+	 printf("WriteIOCommand() -> dat_in[oft_id + 0x0D] = %x \n", dat_in[oft_id + 0x0D]);
+	 printf("WriteIOCommand() -> dat_in[oft_id + 0x0E] = %x \n", dat_in[oft_id + 0x0E]);
+	 printf("WriteIOCommand() -> dat_in[oft_id + 0x0F] = %x \n", dat_in[oft_id + 0x0F]); */
+#endif
+
+	for (i = 0; i < CustomerLenW; i++)
+		dat_in[oft_data + 0x06 + i] = CustomerW[i];
+	for (i = 0; i < DataPayloadLenW; i++) {
+		// __android_log_print(ANDROID_LOG_DEBUG, "WriteIOCommand", "DataPayloadW[%d] = %x", i, DataPayloadW[i]);
+		dat_in[oft_data + 0x10 + i] = DataPayloadW[i];
+	}
+
+#ifdef LOG_CONSOLE
+	printf("**** WriteIOCommand -> invoco WriteCommand \n");
+#endif
+	ret_value = WriteCommand();
+
+	usleep(20 * 1000);
+
+	if (ret_value != 0) {
+
+		return ret_value;
+	}
+
+	return 0;
+}
+
+int ReadIOCommand() {
+	int ret_value, i;
+
+	// for (i=0; i<DATA_VECTOR_length; i++) dat_out[i] = 0x00;
+#ifdef LOG_CONSOLE
+	printf("**** ReadIOCommand -> chiamo ReadCommand() \n");
+#endif
+	ret_value = ReadCommand();
+	if (ret_value != 0)
+		return ret_value;
+
+	TagR = (dat_out[oft_data + 0x00] << 8)
+			| ((dat_out[oft_data + 0x01]) & 0xFF);
+	StatusR = (dat_out[oft_data + 0x02] << 8)
+			| ((dat_out[oft_data + 0x03]) & 0xFF);
+#ifdef LOG_CONSOLE 
+	printf("ReadIOCommand() -> oft_data = %d \n", oft_data);
+	printf("ReadIOCommand() -> TagR -> dat_out[oft_data + 0x00] = %x \n", dat_out[oft_data + 0x00]);
+	printf("ReadIOCommand() -> TagR -> dat_out[oft_data + 0x01] = %x \n", dat_out[oft_data + 0x01]);
+	printf("ReadIOCommand() -> StatusR -> dat_out[oft_data + 0x02] = %x \n", dat_out[oft_data + 0x02]);
+	printf("ReadIOCommand() -> StatusR -> dat_out[oft_data + 0x03] = %x \n", dat_out[oft_data + 0x03]);
+	printf("ReadIOCommand() -> DataPayloadLenR -> dat_out[oft_data + 0x04] = %x \n", dat_out[oft_data + 0x04]);
+	printf("ReadIOCommand() -> DataPayloadLenR -> dat_out[oft_data + 0x05] = %x \n", dat_out[oft_data + 0x05]);
+	printf("ReadIOCommand() -> dat_out[0x06] = %x \n", dat_out[oft_data + 0x06]);
+	printf("ReadIOCommand() -> dat_out[0x07] = %x \n", dat_out[oft_data + 0x07]);
+	printf("StatusR = %d \n", StatusR);
+#endif  
+	DataPayloadLenR = (dat_out[oft_data + 0x04] << 8)
+			| (dat_out[oft_data + 0x05] & 0xFF);
+	CustomerLenR = 0x0A;
+
+	if (CustomerLenR > 0)
+		for (i = 0; i < CustomerLenR; i++)
+			CustomerR[i] = (unsigned char) dat_out[oft_data + 0x06 + i];
+
+	if (DataPayloadLenR > 480)
+		DataPayloadLenR = 480;
+
+	for (i = 0; i < DataPayloadLenR; i++)
+		DataPayloadR[i] = (unsigned char) dat_out[oft_data + 0x10 + i];
+
+	usleep(20 * 1000);
+
+	return 0;
+}
+
+int ListDev() {
+
+	int loop, success, i;
+
+	loop = 0;
+	success = 0;
+	DriveInfoLen = 0x00;
+	while (loop++ < 3) { //CMD_RETRY_COUNT
+		TagW = 0x0000;
+		InsIdxW = 0x00F0;
+		DataPayloadLenW = 0x00;
+		CustomerLenW = 0x02;
+
+		for (i = 0; i < 0x0A; i++)
+			CustomerW[i] = 0x00;
+		for (i = 0; i < 0x1E0; i++)
+			DataPayloadW[i] = 0x00;
+
+		CustomerW[0x00] = ProcessID;
+		CustomerW[0x01] = FrameCounter++;
+
+		ret_value = WriteIOCommand();
+		if (ret_value != 0)
+			return ret_value;
+
+		ret_value = ReadIOCommand();
+		if (ret_value == 200)
+			continue;
+
+		if (ret_value != 0)
+			return ret_value;
+
+		for (i = 0; i < DataPayloadLenR; i++)
+			DriveInfo[i] = DataPayloadR[i];
+		DriveInfoLen = DataPayloadLenR;
+
+		success = 1;
+		break;
+	}
+
+	if (success == 0)
+		return 400;
+
+	return 0;
+}
+
+int Polling_IO_Response(int sleep_time, int polling_cnt) {
+	int checkCmdStatus;
+	int k = polling_cnt;
+	while (k > 0) {
+		// __android_log_print(ANDROID_LOG_DEBUG, "Polling_IO_Response", "prima di ReadIOCommand");
+#ifdef LOG_CONSOLE      
+		printf("**** Polling_IO_Response -> invoco ReadIOCommand k = %d \n", k);
+#endif
+		ret_value = ReadIOCommand();
+		// __android_log_print(ANDROID_LOG_DEBUG, "Polling_IO_Response", "dopo ReadIOCommand");
+		checkCmdStatus = Check_CMD_Status(ret_value);
+#ifdef LOG_CONSOLE
+		// printf("Polling_IO_Response -> ret_value = %d \n", ret_value);
+#endif
+		// __android_log_print(ANDROID_LOG_DEBUG, "Polling_IO_Response", "dopo Check_CMD_Status");
+		if (checkCmdStatus != 0) {
+			if (ret_value == 200)
+				return 0;
+			return -1;
+		}
+
+		if (((StatusR & 0xFF) != 0x60))
+			return 1;
+		k--;
+	}
+	return -1;
+}
+
+int SendIOCommand(int Tag, int Ins, int Len, unsigned char *data) {
+	int success, i, checkCommandStatus, checkIoStatus;
+	int loop = 0;
+
+	while (loop++ < CMD_RETRY_COUNT) {
+		TagW = Tag;
+		InsIdxW = Ins;
+		CustomerLenW = 0x02;
+		DataPayloadLenW = Len;
+
+		CustomerW[0x00] = ProcessID;
+		CustomerW[0x01] = FrameCounter++;
+
+		if (DataPayloadLenW > 0)
+			for (i = 0; i < DataPayloadLenW; i++)
+				DataPayloadW[i] = data[i];
+
+		// __android_log_print(ANDROID_LOG_DEBUG, "SendIOCommand", "prima di WriteIOCommand");
+#ifdef LOG_CONSOLE
+		printf("*** SendIOCommand -> chiamo WriteIOCommand loop = %d \n", loop);
+#endif
+		ret_value = WriteIOCommand();
+
+		if (ret_value == -1) {
+#ifdef LOG_ERROR_CONSOLE
+			printf("*** SendIOCommand -> WriteIOCommand fail \n");
+#endif
+			return -1;
+		}
+		// __android_log_print(ANDROID_LOG_DEBUG, "SendIOCommand", "dopo WriteIOCommand");
+
+		// __android_log_print(ANDROID_LOG_DEBUG, "SendIOCommand", "prima di Check_CMD_Status");
+		checkCommandStatus = Check_CMD_Status(ret_value);
+		// __android_log_print(ANDROID_LOG_DEBUG, "SendIOCommand", "dopo Check_CMD_Status");
+		if (checkCommandStatus != 0)
+			return checkCommandStatus;
+
+		// __android_log_print(ANDROID_LOG_DEBUG, "SendIOCommand", "prima di sleep");
+		usleep(100 * 1000);
+		// __android_log_print(ANDROID_LOG_DEBUG, "SendIOCommand", "dopo sleep");
+
+		// __android_log_print(ANDROID_LOG_DEBUG, "SendIOCommand", "prima di Polling_IO_Response");
+#ifdef LOG_CONSOLE              
+		printf("*** SendIOCommand -> chiamo Polling_IO_Response \n");
+#endif
+		success = Polling_IO_Response(SLEEP_TIME, POLLING_COUNT);
+#ifdef LOG_CONSOLE              
+		printf("*** SendIOCommand -> Polling_IO_Response result = %d \n", success);
+#endif
+		// __android_log_print(ANDROID_LOG_DEBUG, "SendIOCommand", "dopo Polling_IO_Response");
+
+		if (success == -1) {
+#ifdef LOG_ERROR_CONSOLE
+			printf("*** SendIOCommand -> Polling_IO_Response fail \n");
+#endif
+			return -1;
+		} else if (success == 0)
+			continue;
+
+		// __android_log_print(ANDROID_LOG_DEBUG, "SendIOCommand", "prima di Check_IO_Status");
+		checkIoStatus = Check_IO_Status();
+		// __android_log_print(ANDROID_LOG_DEBUG, "SendIOCommand", "dopo Check_IO_Status");
+
+		if (checkIoStatus != 0) {
+#ifdef LOG_ERROR_CONSOLE
+			printf("*** SendIOCommand -> checkIoStatus fail %d \n",
+					checkIoStatus);
+#endif
+			return checkIoStatus;
+		}
+		break;
+	}
+
+	return 0;
+}
+
+#ifdef MICRO_SD
+int Set_IO_Device_Configuration() {
+	int Baud_Rate = 0;
+	float FEQ = 0;
+	int PCON_temp, TH_err_temp, i;
+	unsigned char TH1, PCON, Dou_Rate, Parity_Check = 0, Flow_Control = 0,
+			OSC_Select = 0;
+	unsigned char Delay_Select, Length_Select = 0;
+	int TH_temp[4];
+	int Baud_temp[4];
+	int TH_err[4];
+	float TH1_Error;
+	int success;
+	unsigned char data[7];
+
+	//------------------------------------------------------------
+	// Set OSC
+	//------------------------------------------------------------
+	if (OSC_index == 1) {
+		OSC_Select = 0x07;
+		FEQ = 44;
+	} else if (OSC_index == 2) {
+		OSC_Select = 0x10;
+		FEQ = 16;
+	} else if (OSC_index == 3) {
+		OSC_Select = 0x10;
+		FEQ = 26;
+	} else if (OSC_index == 4) {
+		OSC_Select = 0x10;
+		FEQ = 32;
+	}
+
+	//------------------------------------------------------------
+	// Set Baud Rate
+	//------------------------------------------------------------
+	if (Baud_Rate_index == 1) {
+		Baud_Rate = 4800;
+	} else if (Baud_Rate_index == 2) {
+		Baud_Rate = 9600;
+	} else if (Baud_Rate_index == 3) {
+		Baud_Rate = 19200;
+	} else if (Baud_Rate_index == 4) {
+		Baud_Rate = 38400;
+	} else if (Baud_Rate_index == 5) {
+		Baud_Rate = 57600;
+	} else if (Baud_Rate_index == 6) {
+		Baud_Rate = 76800;
+	} else if (Baud_Rate_index == 7) {
+		Baud_Rate = 115200;
+	} else if (Baud_Rate_index == 8) {
+		Baud_Rate = 812500;
+	}
+
+	//------------------------------------------------------------
+	// Set Parity Check Mode
+	//------------------------------------------------------------
+	if (Parity_Check_index == 1) {
+		Parity_Check = 0x00;
+	} else if (Parity_Check_index == 2) {
+		Parity_Check = (unsigned char) 0xB1;
+	} else if (Parity_Check_index == 3) {
+		Parity_Check = (unsigned char) 0xB2;
+	}
+
+	//------------------------------------------------------------
+	// Set Flow Ctrl
+	//------------------------------------------------------------
+	if (Flow_Ctrl_index == 1) {
+		Flow_Control = 0x00;
+	} else if (Flow_Ctrl_index == 2) {
+		Flow_Control = 0xB2;
+		Length_Select = Handshake_Length;
+	}
+
+	Delay_Select = Delay_length;
+	//calculate TH1 & PCON
+	PCON = 1;
+	TH_temp[0] = (int) (256
+			- ceil((PCON * FEQ * 1000000.0 / (32 * 2 * Baud_Rate)))); // (int) (256 - Math.ceil( (PCON * FEQ * 1000000.0 / (32 * 2 * Baud_Rate))));
+	Baud_temp[0] = (int) (ceil(
+			FEQ * 1000000.0 * PCON / (32 * 2 * (256 - TH_temp[0])))); // (int) (Math.ceil(FEQ * 1000000.0 * PCON / (32 * 2 * (256 - TH_temp[0]))));
+	TH_err[0] = fabs(Baud_temp[0] - Baud_Rate); // Math.abs(Baud_temp[0] - Baud_Rate);
+
+	TH_temp[1] = TH_temp[0] + 1;
+	Baud_temp[1] = (int) (ceil(
+			FEQ * 1000000.0 * PCON / (32 * 2 * (256 - TH_temp[1])))); // (int) (Math.ceil(FEQ * 1000000.0 * PCON /(32 * 2 * (256 - TH_temp[1]))));
+	TH_err[1] = fabs(Baud_temp[1] - Baud_Rate); // Math.abs(Baud_temp[1] - Baud_Rate);
+
+	PCON = 2;
+	TH_temp[2] = (int) (256
+			- ceil((PCON * FEQ * 1000000.0 / (32 * 2 * Baud_Rate)))); // (int) (256 - Math.ceil( (PCON * FEQ * 1000000.0 / (32 * 2 * Baud_Rate))));
+	Baud_temp[2] = (int) (ceil(
+			FEQ * 1000000.0 * PCON / (32 * 2 * (256 - TH_temp[2])))); // (int) (Math.ceil(FEQ * 1000000.0 * PCON / (32 * 2 * (256 - TH_temp[2]))));
+	TH_err[2] = fabs(Baud_temp[2] - Baud_Rate); // Math.abs(Baud_temp[2] - Baud_Rate);
+
+	TH_temp[3] = TH_temp[2] + 1;
+	Baud_temp[3] = (int) (ceil(
+			FEQ * 1000000.0 * PCON / (32 * 2 * (256 - TH_temp[3])))); // (int) (Math.ceil(FEQ * 1000000.0 * PCON /(32 * 2 * (256 - TH_temp[3]))));
+	TH_err[3] = fabs(Baud_temp[3] - Baud_Rate); // Math.abs(Baud_temp[3] - Baud_Rate);
+
+	TH_err_temp = TH_err[0];
+	TH1 = (unsigned char) TH_temp[0];
+	PCON_temp = 0;
+	TH1_Error = (int) ((1 - (Baud_temp[0] * 1.0 / Baud_Rate)) * 100.0);
+	for (i = 1; i < 4; i++) {
+		if (TH_err_temp > TH_err[i]) {
+			TH_err_temp = TH_err[i];
+			TH1 = (unsigned char) TH_temp[i];
+			TH1_Error = (int) ((1 - (Baud_temp[i] * 1.0 / Baud_Rate)) * 100.0);
+			PCON_temp = i;
+		}
+	}
+
+	if (PCON_temp == 0 || PCON_temp == 1) {
+		Dou_Rate = 0x00;
+	} else {
+		Dou_Rate = (unsigned char) 0xFF;
+	}
+
+	// #ifdef MICRO_SD
+	data[0x00] = TH1;
+	data[0x01] = Dou_Rate;
+	data[0x02] = Parity_Check;
+	data[0x03] = Flow_Control;
+	data[0x04] = OSC_Select;
+	data[0x05] = Delay_Select;
+	data[0x06] = Length_Select;
+
+#ifdef LINUX_ANDROID       
+	__android_log_print(ANDROID_LOG_DEBUG, "Set_IO_Device_Configuration", "prima di SendIOCommand");
+#endif	   
+	success = SendIOCommand(0x0200, 0x00C0, 7, data);
+#ifdef LINUX_ANDROID
+	__android_log_print(ANDROID_LOG_DEBUG, "Set_IO_Device_Configuration", "dopo SendIOCommand");
+#endif
+	return success;
+}
+#else
+int Set_IO_Device_Configuration() {
+	int success;
+	unsigned char data[7];
+
+	// set baud-rate
+	switch (Baud_Rate_index) {
+		case 1: // 4800
+		data[0x00] = 0x98;
+		data[0x01] = 0;
+		break;
+		case 2:// 9600
+		data[0x00] = 0xCC;
+		data[0x01] = 0;
+		break;
+		case 3:// 19200
+		data[0x00] = 0xE6;
+		data[0x01] = 0;
+		break;
+		case 4:// 38400
+		data[0x00] = 0xF3;
+		data[0x01] = 0;
+		break;
+		case 5:// 57600
+		data[0x00] = 0xEF;
+		data[0x01] = 0xFF;
+		break;
+		case 7:// 115200
+		data[0x00] = 0xF7;
+		data[0x01] = 0xFF;
+		break;
+	}
+
+	// Parity Check
+	if (Parity_Check_index == 1) {data[0x02]=0x00;}
+	else if(Parity_Check_index == 2) {data[0x02]=(unsigned char)0xB1;}
+	else if(Parity_Check_index == 3) {data[0x02]=(unsigned char)0xB2;}
+
+	// Flow Controll
+	if (Flow_Ctrl_index == 1) {data[0x03]=0x00;}
+	else if(Flow_Ctrl_index == 2) {
+		data[0x03]=0xB2;
+	}
+
+	// Altri parametri
+	data[0x04] = 0x20;
+	data[0x05] = 0x00;
+	data[0x06] = 0x20;
+
+	success = SendIOCommand(0x0200, 0x00C0, 7, data);
+	return success;
+}
+#endif
+
+int Ini_CSR_Device() {
+	// TODO: Add your control notification handler code here
+	int success;
+	success = SendIOCommand(0x0200, 0x0010, 0x0000, 0);
+	return success;
+}
+
+int SDIO_Write(unsigned char *data, int len) {
+	int res;
+	// totToRead = DATA_VECTOR_length;
+
+	res = SendIOCommand(0x0200, 0x0012, len, data);
+	if (res == 0) {
+		printf("\nSDIO_Write - res = 0\n");
+		return len;
+	} else {
+		printf("\nSDIO_Write - res != 0\n");
+		return -1;
+	}
+
+}
+
+int SDIO_Read(unsigned char *data, int len) {
+	int res, returnVal, i;
+	int temp = 0;
+	BOOL cond = TRUE;
+
+	returnVal = len;
+
+#ifdef LOG_CONSOLE 
+	printf("** SDIO_Read -> len = %d \n", len);
+#endif
+
+	while (len > 0 && (cond || counter6 > 0)) {
+		// lettura dalla seriale
+		if (counter6 == 0) {
+#ifdef LOG_CONSOLE        
+			printf("** SDIO_Read -> chiamo SendIOCommand \n");
+#endif
+			res = SendIOCommand(0x0200, 0x0011, 0, 0);
+			if (res == 0) {
+				counter6 = DataPayloadLenR;
+				counter7 = 0;
+			} else {
+#ifdef LOG_ERROR_CONSOLE
+				printf("** SDIO_Read res = %d \n", res);
+#endif
+				return -1; // errore SendIOCommand
+			}
+			cond = FALSE;
+		}
+		// valorizzo il vettore da tornare alla funzione chiamante
+		if (counter6 > 0) {
+			if (len < counter6) {
+				temp = len;
+			} else {
+				temp = counter6;
+			}
+#ifdef LOG_CONSOLE  
+			printf("** SDIO_Read -> [leggo %d bytes da DataPayloadR] len = %d counter6 = %d counter7 = %d \n", temp, len, counter6, counter7);
+#endif
+			// memcpy(data+(returnVal-len), DataPayloadR+counter7, temp);
+			for (i = 0; i < temp; i++)
+				data[i + (returnVal - len)] = DataPayloadR[i + counter7];
+			counter6 = counter6 - temp;
+			counter7 = counter7 + temp;
+			len = len - temp;
+#ifdef LOG_CONSOLE  
+			printf("** SDIO_Read -> [ho letto %d bytes da DataPayloadR] len = %d counter6 = %d counter7 = %d \n", temp, len, counter6, counter7);
+#endif
+		}
+	}
+
+	if (returnVal > 0)
+		returnVal = returnVal - len;
+	return returnVal;
+}
+
+int SDIO_Open(char *device, int baudRate, int parityCheck, int rtsFlowControl) {
+	int res, i;
+	FILE *fp;
+	int foundFile = 0;
+
+	// inizializzo i vettori
+	for (i = 0; i < DATA_VECTOR_length; i++) {
+		dat_in[i] = 0x00;
+		dat_out[i] = 0x00;
+	}
+
+#ifdef LINUX_ANDROID
+	__android_log_print(ANDROID_LOG_DEBUG, "SDIO_Open", "Start method");
+#endif
+	switch (baudRate) {
+
+	case 4800:
+		Baud_Rate_index = 1;
+		break;
+	case 9600:
+		Baud_Rate_index = 2;
+		break;
+	case 19200:
+		Baud_Rate_index = 3;
+		break;
+	case 38400:
+		Baud_Rate_index = 4;
+		break;
+	case 57600:
+		Baud_Rate_index = 5;
+		break;
+	case 76800:
+		Baud_Rate_index = 6;
+		break;
+	case 115200:
+		Baud_Rate_index = 7;
+		break;
+	case 812500:
+		Baud_Rate_index = 8;
+		break;
+	}
+
+	Parity_Check_index = parityCheck;
+	Flow_Ctrl_index = rtsFlowControl;
+
+	printf("\n\n***********\ndevice: %s\n***************\n\n", device);
+
+	// controllo file smart_io.crd @todo
+	fp = fopen(device, "r");
+	if (fp != NULL) {
+		fclose(fp);
+	} else {
+		printf("fopen smart_io.crd failed \n");
+		return -390;
+	}
+
+	//path file fine, store it
+	pathFile = device;
+	printf("\n\n***********\nPathFile: %s\n***************\n\n", pathFile);
+
+#ifdef LINUX_ANDROID   
+	__android_log_print(ANDROID_LOG_DEBUG, "SDIO_Open", "File aperto");
+#endif   
+	// ListDev
+	res = ListDev();
+#ifdef LINUX_ANDROID
+	__android_log_print(ANDROID_LOG_DEBUG, "SDIO_Open", "ListDev() eseguita -> res = %d", res);
+#endif  
+	if (res == -1)
+		return -1;
+	if (Check_CMD_Status(res) != 0)
+		return Check_CMD_Status(res);
+
+	// Set_IO_Device_Configuration
+	res = Set_IO_Device_Configuration();
+#ifdef LINUX_ANDROID
+	__android_log_print(ANDROID_LOG_DEBUG, "SDIO_Open", "Set_IO_Device_Configuration() eseguita -> res = %d", res);
+#endif
+	if (res != 0)
+		return res;
+	printf("Set_IO_Device_Configuration OK! \n");
+
+	// Ini_CSR_Device
+	res = Ini_CSR_Device();
+#ifdef LINUX_ANDROID   
+	__android_log_print(ANDROID_LOG_DEBUG, "SDIO_Open", "Ini_CSR_Device() eseguita -> res = %d", res);
+#endif   
+	if (res != 0)
+		return res;
+	printf("Ini_CSR_Device OK! \n");
+
+	return 1;
+}
+
+int SDIO_Close() {
+	int res;
+	totToRead = DATA_VECTOR_length;
+	res = SendIOCommand(0x0200, 0x00FF, 0x0000, 0);
+
+	return res;
+}

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/SDIO.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/SDIO.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/SDIO.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,49 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#pragma once
+
+#define DATA_VECTOR_length 512
+#define CUSTOMER_VECTOR_length 10
+#define DATA_PAYLOAD_VECTOR_length 480
+#define DRIVE_INFO_VECTOR_length 480
+
+#define SLEEP_TIME 100
+#define POLLING_COUNT 200
+#define CMD_RETRY_COUNT 2
+
+// errori
+#define OPEN_DISK_FAILURE 100
+#define CLOSE_DISK_FAILURE 101
+#define WRITE_DISK_FAILURE 102
+#define READ_DISK_FAILURE 103
+#define NO_DATA_TRASMISSION 104
+#define NO_DATA_RECEPTION 105
+#define NO_IO_RESPONSE 200
+#define DATA_PAYLOAD_length_ERROR 300
+#define CUSTOMER_length_ERROR 301
+#define NO_APPLICATION_DEVICE 400
+#define NO_SMART_IO_CRD_FILE 401
+
+// valori errati dello status
+#define STATUS_BUSY 1000
+#define STATUS_INVALID_TAG 1001
+#define STATUS_INVALID_INSNO 1002
+#define STATUS_length_ERROR 1003
+#define STATUS_PARAMETER_ERROR 1004
+#define STATUS_PARITY_CHECK_ERROR 1005
+#define STATUS_UNK_ERROR 1006
+
+// definizioni di tipi
+#define uint8_t byte
+#define uint64_t unsigned long
+
+// codici della SDIO_Command
+#define CMD_WRITE 0x0012
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/SerialProtocolGlobalDefine.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/SerialProtocolGlobalDefine.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/SerialProtocolGlobalDefine.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,82 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#pragma once
+
+#define CLUSTER_length 2 // numero byte del cluster
+#define IDT_length 3     // numero byte identificativo del terminale indirizzo di rete (2 bytes) + endpoint (1 byte)
+#define SHORT_ADDRESS_length 2 // numero byte del short address
+#define PAN_length 2 // numero byte del short address
+#define DATA_HEADER_length 18 //9                                // lunghezza dell'header di un messaggio dati
+#define DATA_RSP_HEADER_length 9                                 // lunghezza dell'header della risposta di un messaggio dati
+#define FWD_HEADER_length 17 // 11                               // lunghezza dell'header di un messaggio inoltro dati
+#define MAX_PAYLOAD_DATA 73 // 89                                // massima lunghezza del payload in un messaggio dati (100 - DATA_HEADER_length - HOTP - CRC)
+#define MAX_OTA_LEN 100 // FWD_HEADER_length+MAX_PAYLOAD_DATA+9    // max numero di bytes (header seriale + payload OTA effettivo + CRC) 
+#define MAX_USER_DESCRIPTOR_length 16                       // lunghezza massima dello user descriptor
+#define MAX_RAW_MESSAGE 100 // massimo numero di byte di un messaggio raw
+#define MAX_EP_DEVICE 5 // massimo numero di end point per un dispositivo
+// TIPI DI CONFIGURAZIONE DEL DISPOSITIVO
+/*
+ Questi valori devono essere utilizzati se si richiama la funzione di configurazione globale startDevice
+ per determinare in che modo configurare il dispositivo.
+ Il firmware per cui e' stata pensata la libreria ha l'opzione SOFT_START abilitata.
+ Quest'opzione permette a un dispositivo che si vuole configurare come Router di partire come Coordinatore in caso non 
+ si riesca a trovare un Coordinatore a cui associarsi.
+ Questo comportamento puo' essere disabilitato utilizzando il codice COMMAND_ROUTER_NO_SOFT_START oppure si puo' lasciare
+ optando per COMMAND_ROUTER_SOFT_START.
+ Se si utilizza un firmware senza l'opzione SOFT_START si puo' utilizzare la COMMAND_ROUTER_NO_SOFT_START.
+ */
+#define COMMAND_COORDINATOR 0x18          // configurazione come coordinatore      
+#define COMMAND_ROUTER_NO_SOFT_START 0x08 // configurazione come router e non permette il soft start
+#define COMMAND_ROUTER_SOFT_START 0x09    // configurazione come router e permette il soft start
+// Lettura dalla seriale
+#define DATA_READ 1               // ho letto dei dati dalla seriale
+#define NO_DATA_READ 0            // non ho letto alcun dato dalla seriale
+// Modalita' di log
+#define LOG_DEBUG 1               // log completo
+#define LOG_ERROR 0               // log solo degli errori
+#define LOG_NONE  -1              // NESSUN LOG	
+
+// Valori di ritorno delle funzioni
+#define OK 0                       // tutto OK! :)
+#define CHANNEL_CONFIG_ERROR -1    // configurazione canale fallita
+#define PAN_CONFIG_ERROR -2        // configurazione PAN fallita
+#define START_NTW_FAILED -3        // start network fallita
+#define PROFID_EP_CONFIG_FAILED -4 // configurazione di Profile ID e END POINT fallita
+#define SOFTSTART_CONFIG_FAILED -5 // configurazione del SOFT START fallita
+#define NO_RESPONSE -6             // nessuna risposta dalla rete ZigBee
+#define USER_DESC_CONFIG_ERROR -7  // configurazione dello user descriptor fallita
+#define WRONG_HOTP -8              // errore HOTP
+#define MINISD_ACCESS_ERROR -9     // problemi accesso alla MiniSD
+#define WRONG_RESPONSE -10         // risposta diversa da quella attesa 
+#define MSG_NOT_SENT -11           // ho fatto un invio dati e il firmware mi notifica di non aver inviato il messaggio over the air
+#define PAYLOAD_EXCEEDED_LIMIT -12 // payload troppo grande
+#define DATA_READ_UNDEFINED_ERROR -13 // Errore sconosciuto durante la lettura dalla seriale
+#define NULL_PAYLOAD -14           // Payload nullo durante la lettura dalla seriale
+#define NO_DATA_WRITE -15          // Quando invio un messaggio sulla seriale in controller della MiniSD (SDIO_Write mi torna 0 invece che il numero di bytes inviati)
+#define CRC_ERROR -16              // CRC errato
+#define NWK_UNK -17                // network address sconosciuto
+#define HEADER_CORRUPTED -18       // header corrotto quando invio un comando o un messaggio dati
+#define CRC_FW_ERROR -19           // CRC errato (segnalato dal firmware)
+#define CMD_FAILED -20             // Comando inviato, il firmware mi torna un codice di fallimento
+#define SIMAUTH_ERROR -21          // Errore dialogo SIM-SD: sim non autorizzata
+#define SDAUTH_ERROR  -22          // Errore dialogo SIM-SD: sd non autorizzata
+#define UNCOMPLETED_MSG  -23       // La lattura del messaggio non e' stata completata nei tempi previsti dai timer interni alla libreria seriale
+#define MEMORY_ERROR  -24          // Errore di memoria durante l'accesso alle liste dinamiche
+#define MAX_DESCRIPTOR_EXCEEDED_ERROR -25 // superato il massimo numero di descrittori permesso dal firmware
+#define MAX_CLUSTER_IN_EXCEEDED_ERROR -26 // superato il massimo numero di cluster in input
+#define MAX_CLUSTER_OUT_EXCEEDED_ERROR -27 // superato il massimo numero di cluster in OUTPUT
+// VALORI DEFAULT USABILI NELLE APPLICAZIONI
+
+// apertura porta serial
+#define DEFAULT_PARITYCHECK NOPARITY               // Valore di default per il parametro parityCheck nel metodo openDevice
+#define DEFAULT_RTSFLOWCONTROL RTS_CONTROL_DISABLE // Valore di default per il parametro rtsFlowControl nel metodo openDevice
+#define DEFAULT_DEVICEINDEX 0                      // Valore di default per il parametro deviceIndex nel metodo openDevice
+#define DEFAULT_BAUDRATE 115200                    // Valore di default per il parametro baudRate nel metodo openDevice
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/SerialProtocolInner.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/SerialProtocolInner.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/SerialProtocolInner.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,256 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#pragma once
+
+#include "SerialProtocolGlobalDefine.h"
+
+#define CHANNEL_LEN 4    // numero byte del canale
+#define PAN_LEN 2        // numero byte della PAN
+#define RANGE_PAN_LEN 2  // numero byte del range di PAN
+#define EP_LEN 1         // numero byte dell'end point
+#define PROFILE_ID_LEN 2 // numero byte del profile ID
+#define SLEEP_POST_SEND 200 // Sleep dopo l'invio 
+#define CMD_HEADER_length 4                                 // lunghezza dell'header di un comando
+#define MAX_PAYLOAD_CMD (MAX_OTA_LEN - CMD_HEADER_length)   // massima lunghezza del payload in un messaggio comando (100 - CMD_HEADER_length)
+#define POS_length_DATA_FWD (FWD_HEADER_length-1) // Posizione della lunghezza dati nell'header seriale del messaggio inoltro dati (F3 A3)
+#define POS_length_DATA (DATA_HEADER_length-1) // Posizione della lunghezza dati nell'header seriale del messaggio dati
+#define POS_length_CMD  (CMD_HEADER_length-1) // Posizione della lunghezza dati nell'header seriale del messaggio comando
+#define SYNCH_CHAR 0x02
+#define CRC_length 1
+#define HOTP_RSP_length 1
+#define HOTP_LEN 8                                          // lunghezza dell'HOTP
+#define POS_SYNCH_CHAR 0 // posizione carattere di sincronizzazione in header messaggio invio/inoltro dati F2/F3
+#define POS_MSG_TYPE   1 // posizione tipo messaggio in header messaggio invio/inoltro dati F2/F3
+#define POS_LEP 2        // posizione LEP in header messaggio invio/inoltro dati F2/F3
+#define POS_IDT 3        // posizione IDT in header messaggio invio/inoltro dati F2/F3
+#define POS_CLUSTER 6    // posizione cluster in header messaggio invio/inoltro dati F2/F3
+#define POS_LQI 8        // posizione LQI in header messaggio inoltro dati F3
+#define POS_RSSI 9       // posizione RSSI in header messaggio inoltro dati F3
+#define POS_CMD 2        // posizione dell'identificativo del comando nell'header dei comandi
+#define POS_LEN 3        // posizione della lunghezza del payload nei comandi
+#define POS_CMD_DATA 4   // posizione iniziale dei dati nel pacchetto risposta comando
+// TIPI DI MESSAGGIO (risposta comando, risposta invio dati, inoltro dati alla seriale)
+// tipi di comando ZigBee
+#define CMD_PCK_RESPONSE_ZIGBEE 0xF1      // Risposta ad un comando
+#define SENDDATA_PCK_RESPONSE_ZIGBEE 0xF2 // Risposta ad un invio dati su seriale
+#define FROMSERIAL_PCK_ZIGBEE 0xF3        // Inoltro dati dal firmware alla seriale\
+
+#define HEADER_ERROR 0xFF                 // Header error
+// tipi di comando Hotp
+#define CMD_PCK_RESPONSE_HOTP 0xA1        // Risposta ad un comando
+#define SENDDATA_PCK_RESPONSE_HOTP 0xA2   // Risposta ad un invio dati su seriale
+#define FROMSERIAL_PCK_HOTP 0xA3          // Inoltro dati dal firmware alla seriale
+#define HOTP_CONFIG 0xA4                  // Configurazione dell'HOTP
+// RISPOSTE AI COMANDI
+#define HOTP_OK 0x00                  // HOTP ok
+#define HOTP_ERRATO 0xFF              // HOTP errato
+#define RSP_START_NETWORK 0x53        // Risposta alla Start Network: codice comando
+#define RSP_IEEE_SEARCH 0x45          // Risposta alla richiesta del IEEE di un dispositivo
+#define RSP_START_NETWORK_COORD 0x09  // Risposta alla Start Network: rsp prevista config coordinatore
+#define RSP_START_NETWORK_ROUTER 0x01 // Risposta alla Start Network: rsp prevista config router
+#define RSP_MATCH 0x4D                // Match Description Response
+#define RSP_LEAVE 0x4C                // Risposta alla richiesta di LEAVE
+#define RSP_SET_DESCRIPTOR 0x54       // Risposta alla richiesta di set Descriptor
+#define RSP_DEV_ANNCE 0x46            // Risposta alla richiesta di DeviceAnnce
+#define RSP_NODEDESC_REQ 0x47         // Risposta alla richiesta di NodeDescription
+#define RSP_SIMPLEDESC_REQ 0x49       // Risposta alla richiesta di SimpleDescription
+#define RSP_ACTIVEEP_LIST 0x4F        // Risposta alla richiesta della lista degli end point di un nodo attivo
+#define RSP_STATUS_OK 0x00            // OK
+#define RSP_STATUS_KO 0xFF            // KO
+#define RSP_STATUS_CRC_ERROR 0xFE     // CRC errato nell'invio di un messaggio OTA
+#define RSP_NWK_REQ 0x4E              // Risposta alla richiesta di NetworkAddress
+#define RSP_POWER_REQ 0x67            // Risposta alla richiesta di NetworkAddress
+#define RSP_ENDDEVBIND_REQ 0x69       // Risposta alla richiesta di NetworkAddress
+#define RSP_RESET_REQ 0x66       // Risposta alla richiesta di NetworkAddress
+#define RSP_IEEE_GET  0xAC       // Risposta alla richiesta del proprio IEEE Address
+#define RSP_SET_ADD_PAR  0x9C       // Risposta al comando che setta l'extended pan id
+#define RSP_SET_PAGING 0x88       // Risposta al comando che setta il FRAGMENT WINDOWS SIZE e il FRAGMENT DELAY
+#define RSP_SET_SECURITY 0x89       // Risposta al comando che setta il SECURITY LEVEL
+#define RSP_SET_DEFAULT_TC_LINK_KEY 0x90 
+#define RSP_SET_DEFAULT_LINK_KEY    0x91 
+#define RSP_APSME_BIND_REQ          0x92
+#define RSP_APSME_UNBIND_REQ        0x93
+
+// TIMER
+#define TIME_SPAN_RSP_CMD 5          // timer attesa risposta comando
+#define TIME_SPAN_RSP_FWD 5          // timer attesa messaggio inoltro dati
+#define TIME_SPAN_RSP_SNDDATA 2      // timer attesa risposta invio dati
+#define TIME_SPAN_START_NTW 10       // timer attesa Start Network
+#define TIME_SPAN_MATCH_RESPONSE 10  // timer attesa Match Description Response
+#define POS_IEEE_SEARCH_IEEE 0 // posizione del IEEE nel payload della risposta al comando di ricerca del IEEE address
+#define POS_NWK_SEARCH_IEEE 8 // posizione del nwkAddress nel payload della risposta al comando di ricerca del IEEE address
+#define SIZE_IEEE_ADDRESS 8 // dimensione del IEEE address
+/*
+ INIZIO define e strutture dati delle risposte su seriale previste per i comandi e l'invio di messaggi dati
+ */
+#define RSP_NOT_RECEIVED -3 // non ho ricevuto su seriale la risposta al comando o all'invio dati
+#define RSP_ERRATA -2       // risposta ricevuta ma errata
+#define RSP_HOTP_ERRATA -1  // risposta ricevuta ma HOTP errato
+#define RSP_OK 0            // risposta OK
+#define MAX_FIFO_length 10 // Max elementi che possono essere contenuti nella FIFO
+#define MAX_DESCRIPTOR 5 // Max numero di descrittori permesso dal firmware 
+#define MAX_CLUSTER    5 // Max numero di CLUSTER (input o output) permesso dal firmware 
+/*
+ Struttra dati per gestire la lista dinamica
+ */
+/* typedef struct _lista lista;
+
+ typedef struct _lista {
+ unsigned char Msg[MAX_OTA_LEN]; 
+ lista *next; 
+ } lista; */
+
+/*
+ Struttura dati che ingloba la risposta all'invio di un comando (F1/A1)
+ cmd: comando di cui arriva la risposta (es 0x53: start network, 0x4D: match description request
+ payload: risposta
+ hotp_res: risultato dell'HOTP
+ */
+typedef struct _cmdResponse {
+	int totRead;
+	unsigned char cmd;
+	unsigned char payload[MAX_PAYLOAD_CMD];
+	unsigned char hotp_res;
+} cmdResponse;
+
+typedef struct _sendDataResponse {
+	int totRead;
+	unsigned char lep;
+	unsigned char idt[IDT_length];
+	unsigned char cid[CLUSTER_length];
+	unsigned char lenStatus;
+	unsigned char status[MAX_PAYLOAD_DATA];
+	unsigned char hotpRes;
+} sendDataResponse;
+/*
+ FINE define e strutture dati delle risposte su seriale previste per i comandi e l'invio di messaggi dati
+ */
+
+// #define COMPILE_HOTP
+// #define HOTP
+#define STATUS_OK 0x00
+#define STATUS_KO 0xFF
+
+// COMANDO 0X53 - risposta alla start network
+#define RSP_STARTNWK_POS_STATUS      POS_CMD_DATA
+#define RSP_STARTNWK_POS_RES         POS_CMD_DATA+1
+#define RSP_STARTNWK_POS_SHORT_ADDR  POS_CMD_DATA+4
+#define RSP_STARTNWK_POS_PAN         POS_CMD_DATA+2
+
+// 0x4D - risposta alla match description request
+#define RSP_STARTNWK_POS_IDT         POS_CMD_DATA
+
+// COMANDO 0X45 - risposta alla IEEE req
+#define RSP_IEEE_POS_STATUS        POS_CMD_DATA
+#define RSP_IEEE_POS_NWK           POS_CMD_DATA+1
+#define RSP_IEEE_POS_IEEE          POS_CMD_DATA+3
+#define RSP_IEEE_POS_NUMDEV        POS_CMD_DATA+11
+#define RSP_IEEE_POS_START         POS_CMD_DATA+12
+#define RSP_IEEE_POS_LISTDEV       POS_CMD_DATA+13
+
+// COMANDO 0X4L - risposta alla leave
+#define RSP_LEAVE_POS_STATUS       POS_CMD_DATA
+#define RSP_LEAVE_POS_IEEE         POS_CMD_DATA+1
+
+// COMANDO 0X4E - risposta alla Nwkaddr
+#define RSP_NWK_POS_STATUS        POS_CMD_DATA
+#define RSP_NWK_POS_NWK           POS_CMD_DATA+1
+#define RSP_NWK_POS_IEEE          POS_CMD_DATA+3
+#define RSP_NWK_POS_NUMDEV        POS_CMD_DATA+11
+#define RSP_NWK_POS_START         POS_CMD_DATA+12
+#define RSP_NWK_POS_LISTDEV       POS_CMD_DATA+13
+
+// COMANDO 0X47 - risposta alla NodeDesc
+#define RSP_NODE_POS_STATUS            POS_CMD_DATA
+#define RSP_NODE_POS_NWK               POS_CMD_DATA+1
+#define RSP_NODE__POS_LOGTYPE          POS_CMD_DATA+3
+#define RSP_NODE__POS_COMPLEXDESCAVAIL POS_CMD_DATA+4
+#define RSP_NODE__POS_USERDESCAVAIL    POS_CMD_DATA+5
+#define RSP_NODE__POS_RESERVED         POS_CMD_DATA+6
+#define RSP_NODE__POS_APS              POS_CMD_DATA+7
+#define RSP_NODE__POS_FREQUENCY        POS_CMD_DATA+8
+#define RSP_NODE__POS_CAPABILITY       POS_CMD_DATA+9
+#define RSP_NODE__POS_MANUFACT         POS_CMD_DATA+10
+#define RSP_NODE__POS_MAXBUFFERSIZE    POS_CMD_DATA+12
+#define RSP_NODE__POS_MAXINTRANSFER    POS_CMD_DATA+13
+#define RSP_NODE__POS_SERVERMASK       POS_CMD_DATA+15
+#define RSP_NODE__POS_MAXOUT           POS_CMD_DATA+17
+#define RSP_NODE__POS_DESCRCAP         POS_CMD_DATA+19
+
+// COMANDO 0X49 - risposta alla SimpleDesc
+#define RSP_SIMPLE_POS_STATUS            POS_CMD_DATA
+#define RSP_SIMPLE_POS_NWK               POS_CMD_DATA+1
+#define RSP_SIMPLE__POS_EP               POS_CMD_DATA+3
+#define RSP_SIMPLE__POS_APPPROFID        POS_CMD_DATA+4
+#define RSP_SIMPLE__POS_APPDEVID         POS_CMD_DATA+6
+#define RSP_SIMPLE__POS_APPDEVVER        POS_CMD_DATA+8
+#define RSP_SIMPLE__POS_RESERVED         POS_CMD_DATA+9
+#define RSP_SIMPLE__POS_CLUSTER          POS_CMD_DATA+10
+
+// COMANDO 0X4F - risposta alla ActiveEpDesc
+#define RSP_ACTIVEEP_POS_STATUS           POS_CMD_DATA
+#define RSP_ACTIVEEP_POS_NWK              POS_CMD_DATA+1
+#define RSP_ACTIVEEP_POS_EPCNT            POS_CMD_DATA+3
+#define RSP_ACTIVEEP_POS_EPLIST           POS_CMD_DATA+4
+
+// COMANDO 0X67 - risposta alla PowerDesc
+#define RSP_POWER_POS_STATUS           POS_CMD_DATA
+#define RSP_POWER_POS_NWK              POS_CMD_DATA+1
+#define RSP_POWER_POS_PMODE            POS_CMD_DATA+3
+#define RSP_POWER_POS_PSOURCES         POS_CMD_DATA+4
+#define RSP_POWER_POS_CPS              POS_CMD_DATA+5
+#define RSP_POWER_POS_CPSL             POS_CMD_DATA+6
+
+// send data
+#define DEST_ADDR_MODE_16_BIT 2
+#define DEST_ADDR_MODE_64_BIT 3
+
+#define RSP_SENDDATA_STATUS_POS         9
+#define RSP_SENDDATA_DST_ADDRMODE_POS  10
+#define RSP_SENDDATA_DST_IEEEADDR_POS  11
+#define RSP_SENDDATA_DST_SHORTADDR_POS  3
+#define RSP_SENDDATA_DST_EP_POS         5
+#define RSP_SENDDATA_SRC_EP_POS         2
+
+// receive data
+#define FWD_DATA_DSTNWKADDR_POS  2
+#define FWD_DATA_LEP_POS         4
+#define FWD_DATA_NWKADDR_POS     5
+#define FWD_DATA_EP_POS          7
+#define FWD_DATA_CID_POS         8
+#define FWD_DATA_PROFID_POS      10
+#define FWD_DATA_BROADCAST_POS   14
+#define FWD_DATA_SECSTATUS_POS   15
+#define FWD_DATA_LENPAYLOAD_POS  16
+#define FWD_DATA_PAYLOAD_POS     17
+
+// comando K
+#define K_CMD_POS_CMD 2
+#define K_CMD_POS_LEN 3
+#define K_CMD_POS_COMPACT 4
+#define K_CMD_POS_CHANNEL 5
+#define K_CMD_POS_RANGE 9
+#define K_CMD_POS_PAN 10
+#define K_CMD_POS_EP 12
+#define K_CMD_POS_PROFID 13
+#define K_CMD_POS_NCLUSTER_IN 15
+#define K_CMD_POS_START_CLUSTERS 16
+
+// comando 9C
+#define LEN_CMD_K_PICCOLO       12
+#define K_CMD_POS_EXTPAN        POS_CMD_DATA
+/* #define K_CMD_POS_FRAGMENT_WIN   4
+ #define K_CMD_POS_FRAGMENT_DELAY 5
+ #define K_CMD_POS_SECURITY       6
+ #define K_CMD_POS_STARTUP        7
+ #define K_CMD_POS_EXTPAN         8
+ #define K_CMD_POS_TCPRECONFIGKEY 16
+ #define K_CMD_POS_NWK_KEY        32 */
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/SerialProtocolTypes.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/SerialProtocolTypes.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/SerialProtocolTypes.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,27 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#pragma once
+
+#ifndef FALSE
+#define FALSE               0
+#endif
+
+#ifndef TRUE
+#define TRUE                1
+#endif
+
+// #define NULL                0
+
+// definizioni di tipi
+typedef unsigned char byte;
+// typedef unsigned char boolean;
+typedef int BOOL;
+typedef unsigned char BYTE;
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/bisync.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/bisync.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/bisync.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,288 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef _VXWORKS
+# include <time.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <fcntl.h>
+# include <termios.h>
+# include <string.h>
+# include <errno.h>
+# include <sys/select.h>
+# include <sys/time.h>
+# include <sys/types.h>
+# include <unistd.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include "zigbee_log.h"
+#include "bisync.h"
+
+#define IDLE			0
+#define WAIT_FOR_SYN1	1
+#define WAIT_FOR_SYN2	2
+#define WAIT_FOR_STX	3
+#define DATA_RCVD		4
+#define DLE_RCVD		5
+
+#define NUL 0x00
+#define STX 0x02
+#define ETX 0x03
+#define SYN 0x16
+#define DLE 0x10
+
+/**
+ * Opens the serial device and initializes the status
+ * fields related to the framing handling
+ */
+
+int bisync_open(const char **params) {
+	int fd;
+
+	bisync_status_t *status = (bisync_status_t *) malloc(
+			sizeof(bisync_status_t));
+
+	const char *device = get_param(params, "path");
+	if (device == NULL) {
+		return 0;
+	}
+
+#ifndef _VXWORKS
+	struct termios current_termios;
+	int ospeed;
+
+	fd = open(device, O_RDWR | O_NOCTTY);
+
+	if (fd == -1) {
+		return 0;
+	}
+
+	/* empty in and out serial buffers */
+	if (tcflush(fd, TCIOFLUSH)) {
+		close(fd);
+		return 0;
+	}
+	/* get config attributes */
+	if (tcgetattr(fd, &current_termios) == -1) {
+		close(fd);
+		return 0;
+	}
+
+	/* actual serial port baud rate */
+	ospeed = cfgetospeed(&current_termios);
+
+	current_termios.c_iflag = 0;
+	current_termios.c_oflag = 0; /* Raw output modes */
+	current_termios.c_cflag = 0; /* Raw output modes */
+
+	/* 
+	 * Do not echo characters because if you connect
+	 * to a host it or your
+	 * modem will echo characters for you.
+	 * Don't generate signals.
+	 */
+
+	current_termios.c_lflag = 0;
+
+	/* 
+	 * control flow - enable receiver - ignore modem
+	 * control lines
+	 */
+
+	current_termios.c_cflag = CREAD | CLOCAL;
+
+	current_termios.c_cflag |= CS8;
+
+	/*
+	 * This is Non Canonical mode set.
+	 * by setting c_cc[VMIN]=0 and c_cc[VTIME] = 10
+	 * each read operation will wait for 10*1/10 = 1 sec
+	 * If single byte is received, read function returns.
+	 * if timer expires, read() returns 0.
+	 * Minimum bytes to read
+	 */
+
+	current_termios.c_cc[VMIN] = 0;
+
+	/*
+	 * Time between two bytes read (VTIME x 0.10 s)
+	 * 10 seconds may not be the correct maximum value
+	 * If the card becomes mute the reader will tell us
+	 * If the reader becomes mute (crash or serial comm pb.) we won't know
+	 */
+
+	cfsetospeed(&current_termios, B115200);
+	cfsetispeed(&current_termios, 0); /* 0 corresponds to output speed */
+
+	if (tcsetattr(fd, TCSANOW, &current_termios) == -1) {
+		perror("tcsetattr():");
+		close(fd);
+		return -1;
+	}
+#else
+	fd = open (device, O_RDWR, 0644);
+	if (fd == -1) {
+		print_error (__FILE__, __LINE__, "ERROR: While opening device %s", device);
+		return 0;
+	}
+#endif
+
+	status->fd = fd;
+	printf("fd = %d\n", fd);
+	return (int) status;
+}
+
+/**
+ * Closes the serial communication
+ */
+
+int bisync_close(int handle) {
+	bisync_status_t *status = (bisync_status_t *) handle;
+	return close(status->fd);
+}
+
+int bisync_transmit(int handle, const unsigned char *data, int size) {
+	int i;
+	unsigned char obuf[512];
+	unsigned char *p;
+	int res;
+
+	zb_print_bytes("bisync_transmit", data, size);
+
+	bisync_status_t *status = (bisync_status_t *) handle;
+
+	int fd = status->fd;
+	printf("fd = %d\n", fd);
+	p = obuf;
+
+	*p++ = SYN; /* first SYN character */
+	*p++ = SYN; /* second SYN character */
+	*p++ = STX; /* STX character */
+
+	for (i = 0; i < size; i++) {
+		switch (data[i]) {
+		case SYN: /* if any one of these characters */
+		case STX:
+		case ETX:
+		case DLE:
+			*p++ = DLE; /* prefix this char with DLE */
+			/*break;*//* omitted intentionally */
+
+		default:
+			*p++ = data[i];
+			/*break;*//*omitted intentionally */
+		}
+	}
+	*p++ = ETX;
+	zb_print_bytes("bisync_transmit", obuf, p - obuf);
+	res = write(fd, obuf, p - obuf);
+	return res;
+}
+
+int bisync_fd(int handle) {
+	bisync_status_t *status = (bisync_status_t *) handle;
+	return status->fd;
+}
+
+int bisync_receive(int handle, unsigned char *buf, const int size) {
+	unsigned char chr; /* used to read a byte from the input stream */
+	static unsigned char *inp; /* pointer used to write buffer */
+	static unsigned char rx_count;
+	int sts;
+
+	bisync_status_t *status = (bisync_status_t *) handle;
+	int fd = status->fd;
+
+	status->state = IDLE;
+	printf("In receive\n");
+
+	while (1) {
+		sts = read(fd, &chr, 1);
+		printf("sts %d\n", sts);
+		if (sts <= 0) {
+			continue;
+		}
+		switch (status->state) {
+		case IDLE:
+		case WAIT_FOR_SYN1:
+			if (chr == SYN) {
+				status->state = WAIT_FOR_SYN2;
+			}
+			break;
+
+		case WAIT_FOR_SYN2:
+			if (chr == SYN) {
+				status->state = WAIT_FOR_STX;
+			} else {
+				status->state = WAIT_FOR_SYN1;
+			}
+			break;
+
+		case WAIT_FOR_STX:
+			if (chr == STX) {
+				/* STX char so move to waiting for data - i.e. message body */
+				inp = buf;
+				rx_count = 0;
+				status->state = DATA_RCVD;
+			} else if (chr != SYN) {
+				/* not a SYN, so back to the beginning */
+				status->state = WAIT_FOR_SYN1;
+			}
+			break;
+
+		case DATA_RCVD:
+			switch (chr) {
+			case DLE:
+				status->state = DLE_RCVD;
+				break;
+
+			case SYN:
+				status->state = WAIT_FOR_SYN2;
+				break;
+
+			case ETX:
+				zb_print_bytes("bisync_receive", buf, rx_count);
+				status->state = WAIT_FOR_SYN1;
+				return rx_count;
+				break;
+
+			default:
+				if (inp < &buf[size - 1]) {
+					*inp++ = chr;
+					rx_count++;
+				}
+				break;
+			}
+			break;
+
+		case DLE_RCVD:
+			/* this char should be stored */
+			if (inp < &buf[size - 1]) {
+				*inp++ = chr;
+				rx_count++;
+				status->state = DATA_RCVD;
+			}
+			break;
+
+		default:
+			/* no default statement */
+			break;
+
+		}
+	}
+}

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/bisync.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/bisync.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/bisync.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,65 @@
+/*
+ ** ============================================================================
+ **
+ ** FILE
+ **  $Id: bisync.h,v 1.1.2.1 2008/04/15 10:11:44 portinar Exp $  
+ **
+ ** DESCRIPTION
+ **  Header file for the Bisync UART driver
+ **
+ ** CREATED
+ **  Ian Marsden
+ **
+ ** COPYRIGHT
+ ** Copyright 2006 Integration Associates Inc.  All rights reserved.
+ **
+ ** LIMITED USE LICENSE.  By using this software, the user agrees to the terms of the 
+ **                       following license.  If the user does not agree to these terms, 
+ **                       then this software should be returned within 30 days and a full 
+ **                       refund of the purchase price or license fee will provided.  
+ **                       Integration Associates hereby grants a license to the user on the 
+ **                       following terms and conditions:  The user may use, copy, modify, 
+ **                       revise, translate, abridge, condense, expand, collect, compile, 
+ **                       link, recast, distribute, transform or adapt this software solely 
+ **                       in connection with the development of products incorporating 
+ **                       integrated circuits sold by Integration Associates.  Any other use 
+ **                       for any other purpose is expressly prohibited with the prior written 
+ **                       consent of Integration Associates.
+ **
+ ** Any copy or modification made must satisfy the following conditions:
+ ** 
+ ** 1. Both the copyright notice and this permission notice appear in all copies of the software, 
+ **    derivative works or modified versions, and any portions thereof, and that both notices 
+ **    appear in supporting documentation.
+ **
+ ** 2. All copies of the software shall contain the following acknowledgement: "Portions of this 
+ **    software are used under license from Integration Associates Inc. and are copyrighted."
+ **
+ ** 3  Neither the name of Integration Associates Inc. nor any of its subsidiaries may be used 
+ **    to endorse or promote products derived from this software without specific prior written 
+ **    permission.
+ **
+ ** THIS SOFTWARE IS PROVIDED BY "AS IS" AND ALL WARRANTIES OF ANY KIND, INCLUDING THE IMPLIED 
+ ** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR USE, ARE EXPRESSLY DISCLAIMED.  THE DEVELOPER 
+ ** SHALL NOT BE LIABLE FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.  
+ ** THIS SOFTWARE MAY NOT BE USED IN PRODUCTS INTENDED FOR USE IN IMPLANTATION OR OTHER DIRECT 
+ ** LIFE SUPPORT APPLICATIONS WHERE MALFUNCTION MAY RESULT IN THE DIRECT PHYSICAL HARM OR INJURY 
+ ** TO PERSONS.  ALL SUCH IS USE IS EXPRESSLY PROHIBITED.
+ ** ============================================================================
+ */
+
+#ifndef BISYNC_DOT_H
+#define BISYNC_DOT_H
+
+typedef struct {
+	int fd;
+	int state;
+} bisync_status_t;
+
+int bisync_open(const char **params);
+int bisync_close(int handle);
+int bisync_transmit(int handle, const unsigned char *data, int size);
+int bisync_receive(int handle, unsigned char *buf, const int size);
+int bisync_fd(int handle);
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/bisync_tokens.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/bisync_tokens.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/bisync_tokens.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,191 @@
+/*
+ ** ============================================================================
+ **
+ ** FILE
+ **  $Id: bisync_tokens.h,v 1.1.2.1 2008/04/15 10:11:44 portinar Exp $
+ **
+ ** COPYRIGHT
+ ** Copyright 2005, 2006, 2007 Integration Associates Inc.  All rights reserved.
+ **
+ ** LIMITED USE LICENSE.  By using this software, the user agrees to the terms of the 
+ **                       following license.  If the user does not agree to these terms, 
+ **                       then this software should be returned within 30 days and a full 
+ **                       refund of the purchase price or license fee will provided.  
+ **                       Integration Associates hereby grants a license to the user on the 
+ **                       following terms and conditions:  The user may use, copy, modify, 
+ **                       revise, translate, abridge, condense, expand, collect, compile, 
+ **                       link, recast, distribute, transform or adapt this software solely 
+ **                       in connection with the development of products incorporating 
+ **                       integrated circuits sold by Integration Associates.  Any other use 
+ **                       for any other purpose is expressly prohibited with the prior written 
+ **                       consent of Integration Associates.
+ **
+ ** Any copy or modification made must satisfy the following conditions:
+ ** 
+ ** 1. Both the copyright notice and this permission notice appear in all copies of the software, 
+ **    derivative works or modified versions, and any portions thereof, and that both notices 
+ **    appear in supporting documentation.
+ **
+ ** 2. All copies of the software shall contain the following acknowledgement: "Portions of this 
+ **    software are used under license from Integration Associates Inc. and are copyrighted."
+ **
+ ** 3  Neither the name of Integration Associates Inc. nor any of its subsidiaries may be used 
+ **    to endorse or promote products derived from this software without specific prior written 
+ **    permission.
+ **
+ ** THIS SOFTWARE IS PROVIDED BY "AS IS" AND ALL WARRANTIES OF ANY KIND, INCLUDING THE IMPLIED 
+ ** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR USE, ARE EXPRESSLY DISCLAIMED.  THE DEVELOPER 
+ ** SHALL NOT BE LIABLE FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.  
+ ** THIS SOFTWARE MAY NOT BE USED IN PRODUCTS INTENDED FOR USE IN IMPLANTATION OR OTHER DIRECT 
+ ** LIFE SUPPORT APPLICATIONS WHERE MALFUNCTION MAY RESULT IN THE DIRECT PHYSICAL HARM OR INJURY 
+ ** TO PERSONS.  ALL SUCH IS USE IS EXPRESSLY PROHIBITED.
+ ** 
+ ** ============================================================================
+ **/
+
+#ifndef BISYNC_TOKENS_H
+#define BISYNC_TOKENS_H
+
+/*
+ ** ============================================================================
+ ** System include files
+ ** ============================================================================
+ */
+
+/*
+ ** ============================================================================
+ ** Project include files
+ ** ============================================================================
+ */
+
+/*
+ ** ============================================================================
+ ** Definitions 
+ ** ============================================================================
+ */
+
+/****************************************
+ * ZDO Message Types
+ ****************************************/
+
+#define ZDO_NWK_ADDR_REQUEST                    (unsigned char) 0xC0
+#define ZDO_NWK_ADDR_CONFIRM                    (unsigned char) 0xC1
+#define ZDO_IEEE_ADDR_REQUEST                   (unsigned char) 0xC2
+#define ZDO_IEEE_ADDR_CONFIRM                   (unsigned char) 0xC3
+#define ZDO_NODE_DESC_REQUEST                   (unsigned char) 0xC4
+#define ZDO_NODE_DESC_CONFIRM                   (unsigned char) 0xC5
+#define ZDO_POWER_DESC_REQUEST                  (unsigned char) 0xC6
+#define ZDO_POWER_DESC_CONFIRM                  (unsigned char) 0xC7
+#define ZDO_SIMPLE_DESC_REQUEST                 (unsigned char) 0xC8
+#define ZDO_SIMPLE_DESC_CONFIRM                 (unsigned char) 0xC9
+#define ZDO_ACTIVE_EP_DESC_REQUEST              (unsigned char) 0xCA
+#define ZDO_ACTIVE_EP_DESC_CONFIRM              (unsigned char) 0xCB
+#define ZDO_MATCH_DESC_REQUEST                  (unsigned char) 0xCC
+#define ZDO_MATCH_DESC_CONFIRM                  (unsigned char) 0xCD
+#define ZDO_COMPLEX_DESC_REQUEST                (unsigned char) 0xCE
+#define ZDO_COMPLEX_DESC_CONFIRM                (unsigned char) 0xCF
+#define ZDO_USER_DESC_REQUEST                   (unsigned char) 0xD0
+#define ZDO_USER_DESC_CONFIRM                   (unsigned char) 0xD1
+#define ZDO_DISCOVERY_CACHE_REQUEST             (unsigned char) 0xD2
+#define ZDO_DISCOVERY_CACHE_CONFIRM             (unsigned char) 0xD3
+#define ZDO_END_DEVICE_ANNCE_REQUEST            (unsigned char) 0xD4
+#define ZDO_USER_DESC_SET_REQUEST               (unsigned char) 0xE8
+#define ZDO_USER_DESC_SET_CONFIRM               (unsigned char) 0xE9
+#define ZDO_SYSTEM_SERVER_DISCOVERY_REQUEST     (unsigned char) 0x30
+#define ZDO_SYSTEM_SERVER_DISCOVERY_CONFIRM     (unsigned char) 0x31 
+#define ZDO_DISCOVERY_STORE_REQUEST             (unsigned char) 0x32
+#define ZDO_DISCOVERY_STORE_CONFIRM             (unsigned char) 0x33
+#define ZDO_REMOVE_NODE_CACHE_REQUEST           (unsigned char) 0x34
+#define ZDO_REMOVE_NODE_CACHE_CONFIRM           (unsigned char) 0x35
+#define ZDO_FIND_NODE_CACHE_REQUEST             (unsigned char) 0x36
+#define ZDO_FIND_NODE_CACHE_CONFIRM             (unsigned char) 0x37
+
+#define ZDO_END_DEVICE_BIND_REQUEST             (unsigned char) 0xD6
+#define ZDO_END_DEVICE_BIND_CONFIRM             (unsigned char) 0xD7
+#define ZDO_BIND_REQUEST                        (unsigned char) 0xD8
+#define ZDO_BIND_CONFIRM                        (unsigned char) 0xD9
+#define ZDO_UNBIND_REQUEST                      (unsigned char) 0xDA
+#define ZDO_UNBIND_CONFIRM                      (unsigned char) 0xDB
+#define ZDO_BIND_REGISTER_REQUEST               (unsigned char) 0x38
+#define ZDO_BIND_REGISTER_CONFIRM               (unsigned char) 0x39
+#define ZDO_REPLACE_DEVICE_REQUEST              (unsigned char) 0x3A
+#define ZDO_REPLACE_DEVICE_CONFIRM              (unsigned char) 0x3B
+#define ZDO_BIND_BACKUP_REQUEST                 (unsigned char) 0x3C
+#define ZDO_BIND_BACKUP_CONFIRM                 (unsigned char) 0x3D
+
+#define ZDO_MGMT_NWK_DISC_REQUEST               (unsigned char) 0xDC
+#define ZDO_MGMT_NWK_DISC_CONFIRM               (unsigned char) 0xDD
+#define ZDO_MGMT_LQI_REQUEST                    (unsigned char) 0xDE
+#define ZDO_MGMT_LQI_CONFIRM                    (unsigned char) 0xDF
+#define ZDO_MGMT_RTG_REQUEST                    (unsigned char) 0xE0
+#define ZDO_MGMT_RTG_CONFIRM                    (unsigned char) 0xE1
+#define ZDO_MGMT_BIND_REQUEST                   (unsigned char) 0xE2
+#define ZDO_MGMT_BIND_CONFIRM                   (unsigned char) 0xE3
+#define ZDO_MGMT_LEAVE_REQUEST                  (unsigned char) 0xE4
+#define ZDO_MGMT_LEAVE_CONFIRM                  (unsigned char) 0xE5
+#define ZDO_MGMT_DIRECT_JOIN_REQUEST            (unsigned char) 0xE6
+#define ZDO_MGMT_DIRECT_JOIN_CONFIRM            (unsigned char) 0xE7
+#define ZDO_MGMT_PERMIT_JOINING_REQUEST         (unsigned char) 0xEA
+#define ZDO_MGMT_PERMIT_JOINING_CONFIRM         (unsigned char) 0xEB
+#define ZDO_MGMT_CACHE_REQUEST                  (unsigned char) 0x3E
+#define ZDO_MGMT_CACHE_CONFIRM                  (unsigned char) 0x3F
+
+#define ZDO_NLME_PERMIT_JOINING_REQUEST         (unsigned char) 0x21
+#define ZDO_NLME_PERMIT_JOINING_CONFIRM         (unsigned char) 0x22
+#define ZDO_NLME_SYNC_REQUEST                   (unsigned char) 0x23
+#define ZDO_NLME_SYNC_CONFIRM                   (unsigned char) 0x24
+#define ZDO_NLME_LEAVE_REQUEST                  (unsigned char) 0x25
+#define ZDO_NLME_LEAVE_CONFIRM                  (unsigned char) 0x26
+#define ZDO_NLME_NETWORK_DISCOVERY_REQUEST      (unsigned char) 0x27
+#define ZDO_NLME_NETWORK_DISCOVERY_CONFIRM      (unsigned char) 0x28
+#define ZDO_RESET_REQUEST                       (unsigned char) 0x29
+#define ZDO_RESET_CONFIRM                       (unsigned char) 0x2A
+#define ZDO_SET_REQUEST                         (unsigned char) 0x2B
+#define ZDO_SET_CONFIRM                         (unsigned char) 0x2C
+#define ZDO_START_REQUEST                       (unsigned char) 0x2D
+#define ZDO_START_CONFIRM                       (unsigned char) 0x2E
+#define ZDO_NLME_LEAVE_INDICATION               (unsigned char) 0x2F
+#define ZDO_NLME_SYNC_INDICATION                (unsigned char) 0x20
+#define ZDO_GET_REQUEST                         (unsigned char) 0xEC
+#define ZDO_GET_CONFIRM                         (unsigned char) 0xED
+#define ZDO_EVENT_REQUEST                       (unsigned char) 0xEE
+#define ZDO_EVENT_INDICATION                    (unsigned char) 0xEF
+#define ZDO_NLME_ROUTE_DISCOVERY_REQUEST        (unsigned char) 0xFC
+#define ZDO_NLME_ROUTE_DISCOVERY_CONFIRM        (unsigned char) 0xFD
+#define ZDO_NLME_ROUTE_ERROR_INDICATION         (unsigned char) 0xFE
+
+#define AF_INDIRECT_REQUEST                     (unsigned char) 0xF0
+#define AF_INDIRECT_CONFIRM                     (unsigned char) 0xF1
+#define AF_DATA_INDICATION                      (unsigned char) 0xF2
+#define AF_DIRECT_REQUEST                       (unsigned char) 0xF3
+#define AF_DIRECT_CONFIRM                       (unsigned char) 0xF4
+#define AF_DIRECT_INDICATION                    (unsigned char) 0xF5
+#define AF_IEEE_REQUEST                         (unsigned char) 0xF6
+#define AF_IEEE_CONFIRM                         (unsigned char) 0xF7
+#define AF_IEEE_INDICATION                      (unsigned char) 0xF8
+#define AF_GROUP_REQUEST                        (unsigned char) 0xF9
+#define AF_GROUP_CONFIRM                        (unsigned char) 0xFA
+#define AF_GROUP_INDICATION                     (unsigned char) 0xFB
+#define ZCL_PRIMITIVE                           (unsigned char) 0xFB
+#define AF_ADD_GROUP_REQUEST                    (unsigned char) 0x9A
+#define AF_ADD_GROUP_CONFIRM                    (unsigned char) 0x9B
+#define AF_REMOVE_GROUP_REQUEST                 (unsigned char) 0x9C
+#define AF_REMOVE_GROUP_CONFIRM                 (unsigned char) 0x9D
+#define AF_REMOVE_ALL_GROUPS_REQUEST            (unsigned char) 0x9E
+#define AF_REMOVE_ALL_GROUPS_CONFIRM            (unsigned char) 0x9F
+
+#define APSME_TRANSPORT_KEY_REQUEST				(unsigned char) 0xB4
+
+/*
+ ** ============================================================================
+ ** Function Prototypes
+ ** ============================================================================
+ */
+
+#endif /* BISYNC_TOKENS_H */
+
+/*
+ ** ============================================================================
+ ** End of $Id: bisync_tokens.h,v 1.1.2.1 2008/04/15 10:11:44 portinar Exp $
+ ** ============================================================================
+ */

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_common.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_common.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_common.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,95 @@
+// *******************************************************************
+//  common.h
+//
+//  sample app for Ember Stack API
+//
+//  Copyright 2005 by Ember Corporation. All rights reserved.              *80*
+// *******************************************************************
+
+#include PLATFORM_HEADER //compiler/micro specifics, types
+#include "stack/include/ember-types.h"
+#include "stack/include/error.h"
+#include "hal/hal.h"
+#include "app/util/ezsp/ezsp-protocol.h"
+#include "app/util/ezsp/ezsp.h"
+#include "app/util/ezsp/ezsp-utils.h"
+#include "app/util/serial/serial.h"
+#include "app/util/source-route-host.h"
+
+// *******************************************************************
+// XXX: HW Specific Support
+#define NO_BOOTLOADER
+// *******************************************************************
+
+// *******************************************************************
+// Ember endpoint and interface configuration
+
+// The application profile ID we use.  This profile ID is assigned to
+// Ember Corp. and can only be used during development.
+//#define PROFILE_ID 0xC00F
+
+//ProfileID defined in Annex F of the gateway spec
+#define PROFILE_ID 0xa1e0
+#define GW_DEVICE_ID 0x0000
+#define DEVICE_VERSION 0x01
+#define ENDPOINT 0x08
+
+// Cluster list defined by the gateway spec
+#define GW_MNG_CLUSTER_ID 0x0100			//Gateway Management Cluster
+#define GW_DATA_IFC_CLUSTER_ID 0x0200		//Gateway Data Interface Cluster
+#define COMMON_DATA_SINK_CLUSTER_ID 0x0300	//Common Data Sink Cluster
+
+#if 0
+
+// Numeric index for the first endpoint. Applications can use any
+// endpoints between 1 and 238.
+// 0 = ZDO, 239 = SPDO, 240 = EDO, 241-255 reserved
+// This application uses only one endpoint. This constant makes the code
+// easier to read.
+
+// End Ember endpoint and interface configuration
+// *******************************************************************
+
+// *******************************************************************
+// Application specific constants and globals
+
+// All nodes running the application will belong to the
+// SENSOR MULTICAST group and will use the same location in the 
+// multicast table.
+
+#define MULTICAST_ID            0x1111
+#define MULTICAST_TABLE_INDEX   0
+
+// The nodes will store the sink address, and only the sink
+// address, in the address table. The sink nodes will add entries to
+// the address table for all sensor nodes.
+
+#define SINK_ADDRESS_TABLE_INDEX             0
+
+#define HELLO_MSG_SIZE 5
+
+// serial ports
+#endif
+
+#define APP_SERIAL   0
+
+#if 0
+
+// it is not recommended to ever hard code the network settings
+// applications should always scan to determine the channel and panid
+// to use. However, in some instances, this can aid in debugging
+#define USE_HARDCODED_NETWORK_SETTINGS
+
+#ifdef USE_HARDCODED_NETWORK_SETTINGS
+#define APP_CHANNEL (20)
+#define APP_PANID   (0x01ff)
+#define APP_EXTENDED_PANID {'s','e','n','s','o','r',0,0}
+#define APP_POWER   (-1)
+#else
+// when not using hardcoded settings, it is possible to ensure that
+// devices join to each other by setting an extended PAN ID below. 
+// Leaving the extended PAN ID as "0" means "use any"
+#define APP_EXTENDED_PANID {0,0,0,0,0,0,0,0}
+#endif //USE_HARDCODED_NETWORK_SETTINGS
+#endif
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_config.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_config.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_config.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,87 @@
+// *******************************************************************
+// Stack Profile Parameters
+
+//#define EMBER_STACK_PROFILE           2
+
+// *******************************************************************
+// Security
+//
+// There are three ways security can be configured:
+// 1) no security
+// 2) security with a preconfigured link key (both devices must have the key)
+// 3) security with no preconfigured link key 
+//
+// *NOTE*:  MAC Security has been deprecated and therefore there is no way to
+// to do a secure join (the Association Commands will be sent in the clear).
+// However if using a preconfigured Link key then the Network Key will be sent
+// from the Trust Center to the joining device using APS Encryption (using the
+// Link Key).  If not using a preconfigured Link Key then the Network and Link 
+// Key will both be sent in the clear.  
+//
+// This application is configured to use security and join using a 
+// preconfigured link key.  See app/util/security/trust-center-host.c
+//
+// The Network Key should be randomly generated so as to prevent a 
+// device that obtains the key in one network from being able to gain access
+// to another.   It also helps to prevent identical deployments (on the same
+// channel and panId) from being able to read each other's packets.
+//
+// The link key is preconfigured on each device with a call to setSecurityKey
+// in app/sensor/common.c.
+//
+// EMBER_SECURITY_LEVEL=5 turns security on.
+// EMBER_SECURITY_LEVEL=0 turns security off.
+//
+
+// To turn security on and use preconfigured Link Keys
+// #define EMBER_SECURITY_LEVEL  5
+// #define USE_PRECONFIGURED_KEY TRUE
+
+// To turn security on with no preconfigured Link Keys
+// #define EMBER_SECURITY_LEVEL  5
+// #define USE_PRECONFIGURED_KEY FALSE
+
+// To run without security
+// #define EMBER_SECURITY_LEVEL  0
+// #define USE_PRECONFIGURED_KEY TRUE
+
+#define EMBER_SECURITY_LEVEL     0 
+#define USE_PRECONFIGURED_KEY    TRUE
+
+// *******************************************************************
+// Ember static memory requirements
+//
+// There are constants that define the amount of static memory
+// required by the stack. If the application does not set them then
+// the default values from ember-configuration-defaults.h are used.
+//
+// for example, this changes the default number of buffers to 8
+// #define EMBER_PACKET_BUFFER_COUNT 8
+
+// sink nodes need 15 address table entries - non-sinks only need one
+#if defined(SINK_APP) || defined(GATEWAY_APP)
+#define EMBER_ADDRESS_TABLE_SIZE 15
+#else
+#define EMBER_ADDRESS_TABLE_SIZE 1
+#endif
+#define EMBER_MULTICAST_TABLE_SIZE 1
+#define EMBER_NEIGHBOR_TABLE_SIZE 8
+
+// *******************************************************************
+// Application Handlers
+//
+// By default, a number of stub handlers are automatically provided
+// that have no effect.  If the application would like to implement any
+// of these handlers itself, it needs to define the appropriate macro
+
+#define EZSP_APPLICATION_HAS_BUTTON_HANDLER
+
+#if defined(SINK_APP) || defined(GATEWAY_APP)
+#define EZSP_APPLICATION_HAS_ROUTE_RECORD_HANDLER
+#define EMBER_SOURCE_ROUTE_TABLE_SIZE 15
+#endif
+
+#if (defined(SLEEPY_SENSOR_APP)) || (defined(MOBILE_SENSOR_APP))
+#define EZSP_APPLICATION_HAS_POLL_COMPLETE_HANDLER
+#endif
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_if.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_if.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_if.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,3424 @@
+/**
+ * High level interface to the ZigBee protocol stack
+ * The stack actually runs on the INT or on a external
+ * board connected to the system by means of a serial
+ * connection
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include "zb_conn.h"
+#include "zigbee.h"
+#include "zigbee_local.h"
+//#include "ezsp_if.h"
+#include "zigbee_log.h"
+
+#ifdef DEBUG_ZIGBEE_API
+#include "zigbee_utils.h"
+#endif
+
+#define APP_SERIAL 0
+
+#define USE_HARDCODED_NETWORK_SETTINGS
+
+/* default params! */
+#define APP_CHANNEL (11)
+#define APP_PANID   (0x01ff)
+#define APP_POWER   (3)
+
+#ifdef USE_HARDCODED_NETWORK_SETTINGS
+//  #define APP_EXTENDED_PANID {'s','e','n','s','o','r', 0, 0}
+// default commissioning ExtendedpanID (00-50-C2-77-10-00-00-00)
+#define APP_EXTENDED_PANID {0x00,0x50,0xC2,0x77,0x10,0x00,0x00,0x00}
+#else
+// when not using hardcoded settings, it is possible to ensure that
+// devices join to each other by setting an extended PAN ID below.
+// Leaving the extended PAN ID as "0" means "use any"
+#define APP_EXTENDED_PANID {0,0,0,0,0,0,0,0}
+
+#endif //USE_HARDCODED_NETWORK_SETTINGS
+#include PLATFORM_HEADER
+
+#include "ezsp_ser.h"
+#include "app/util/ezsp/ezsp-enum.h"
+#include "stack/include/ember-types.h"
+#include "stack/include/error.h"
+#include "app/util/ezsp/ezsp-protocol.h"
+
+uchar DevType;
+
+ushort localShortAddr = 0x0000;
+ushort localIeeeAddr[8];
+
+// This variable is used to know if restart the Gateway or just init it
+boolean restartGW = 0x00; //by default if restart the network
+
+#ifdef ZIGBEE_APS_FRAG_ENABLED
+
+#include "fragment.h"
+#include "ezsp_if.h"
+
+int8u fragmentRxBuffer[HOST_FRAGMENT_BUFFER_SIZE];
+
+// The fragmentation library only supports one fragmented message in process
+// at a time
+boolean fragmentedMessageInProcess = FALSE;
+
+// When fragmenting, need to find the source route and hold it -
+//   want to pass the same source route for each fragment
+int8u globalFragmentSourceRouteRelayCount;
+int16u globalFragmentSourceRouteRelayList[ZA_MAX_HOPS];
+EmberNodeId globalFragmentSourceRouteDestination;
+boolean globalFragmentSourceRouteInfoValid = FALSE;
+
+boolean timersInitiated = FALSE;// Timers initialization
+
+#endif
+
+#define emberKeyContents(key) ((key)->contents)
+
+//EmberInitialSecurityState state;
+
+#ifndef ZA_SECURITY_PRECONFIGURED_KEY
+//  {'Z','i','g','b','e','e',' ','S','e','c','u','r','i','t','y','!'};
+#define ZA_SECURITY_PRECONFIGURED_KEY \
+  {0x5a, 0x69, 0x67, 0x42, 0x65, 0x65, 0x41, 0x6c, \
+   0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x30, 0x39}
+
+#endif 
+
+#ifndef ZA_SECURITY_NETWORK_KEY
+#define ZA_SECURITY_NETWORK_KEY  \
+{0x4c, 0x46, 0x89, 0x6d, 0x68, 0x73, 0x29, 0x52, 0xaf, 0xc3, 0x03, 0x7f, 0xcb, 0x98, 0xe1, 0xd0}
+// {'e','m','b','e','r',' ','E','M','2','5','0',' ','c','h','i','p'}
+#endif 
+
+//EmberKeyData preconfiguredLinkKey = ZA_SECURITY_PRECONFIGURED_KEY;		//Old
+EmberKeyData preconfiguredLinkKey;
+EmberKeyData networkKey = { ZA_SECURITY_NETWORK_KEY };
+
+boolean setPolicyActive = FALSE;
+int securityLevel = 0;
+boolean usePreconfiguredNwkKey = FALSE;
+
+// Forward declarations
+void zaSecurityTrustCenterInit(ZBIF_HANDLE zbif_handle);
+void zaSecurityInit(ZBIF_HANDLE zbif_handle);
+static void zaSecurityPolicyInit(void);
+
+static void EZSP_Autogen(ZBIF_HANDLE zbif_handle, uchar *data, const int size);
+
+static EmberNetworkParameters g_networkParams = { APP_EXTENDED_PANID, APP_PANID,
+		APP_POWER, APP_CHANNEL };
+static unsigned long g_channel_mask = EMBER_ALL_802_15_4_CHANNELS_MASK;
+
+unsigned char out_buf[300];
+extern int8u ezspSleepMode;
+
+/* int8u ezspSleepMode = EZSP_FRAME_CONTROL_IDLE; */
+
+static int8u ezspSequence = 0;
+
+#ifdef IEEE_ADDR_REQUEST_PATCH
+
+//	Data structure required to build a IEEE Address Response containing the list of the node's children, including both ZigBee End Device
+//	and ZigBee Router --> PATCH
+typedef struct {
+	uchar status;
+	uchar ieee_addr[IEEE_ADDR_LEN];
+	ushort nwk_addr;
+	uchar num_assoc_dev;
+	uchar start_index;
+	ushort *nwk_addr_assoc_dev_list;
+	uchar endDeviceCount; // information not included in the response (used for the patch)
+	uchar neighborCount;// information not included in the response (used for the patch)
+	uchar neighborIndex;// information not included in the response (used for the patch)
+}localIEEEAddrResponse;
+
+localIEEEAddrResponse ieeeAddrResponse;
+#endif	/* IEEE_ADDR_REQUEST_PATCH*/
+
+#ifndef ZIGBEE_USE_DATA_STRUCTURES
+
+void EZSP_ZDO_RESET_request(ZBIF_HANDLE zbif_handle, uchar options);
+
+void EZSP_ZDO_START_request(ZBIF_HANDLE zbif_handle);
+
+void EZSP_ZDO_NWK_ADDR_request(ZBIF_HANDLE zbif_handle, uchar *ieee_addr,
+		uchar request_type, uchar start_index);
+
+void EZSP_ZDO_IEEE_ADDR_request(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar request_type, uchar start_index);
+
+void EZSP_ZB_MGMT_LQI_request(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar start_index);
+
+void EZSP_ZDO_NODE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr);
+
+void EZSP_ZDO_POWER_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr);
+
+void EZSP_ZDO_SIMPLE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, uchar endpoint);
+
+void EZSP_ZDO_ACTIVE_EP_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr);
+
+void EZSP_ZDO_MATCH_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, ushort profile_id, uchar nicl, ushort *icllist,
+		uchar nocl, ushort *ocllist);
+
+void EZSP_ZDO_MATCH_DESC_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort dst_addr, uchar match_len, uchar *match_list);
+
+void EZSP_ZDO_END_DEVICE_BIND_request(ZBIF_HANDLE zbif_handle,
+		ushort binding_target, uchar *src_ieee_addr, uchar src_ep,
+		ushort profile_id, uchar nicl, ushort *icllist, uchar nocl,
+		ushort *ocllist);
+
+void EZSP_APSDE_DATA_request(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, ushort profile_id, ushort cluster_id,
+		uchar src_ep, uchar asdu_len, uchar *asdu, uchar tx_options,
+		uchar radius);
+
+void EZSP_APSME_BIND_request(ZBIF_HANDLE zbif_handle, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep);
+
+void EZSP_APSME_UNBIND_request(ZBIF_HANDLE zbif_handle, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep);
+
+void EZSP_APSME_GET_request(ZBIF_HANDLE zbif_handle, uchar attr);
+
+void EZSP_APSME_SET_request(ZBIF_HANDLE zbif_handle, uchar attr, uchar attr_len,
+		uchar *attr_value);
+
+void EZSP_MGMT_PERMIT_JOINING_request(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		int permitDuration);
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+
+void EZSP_APSME_REMOVE_DEVICE_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *parent_ieee_addr,
+		uchar *child_ieee_addr
+);
+
+void EZSP_APSME_TRANSPORT_KEY_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *dst_ieee_addr,
+		uchar key_type,
+		ZB_TRANSPORT_KEY_DATA *transport_key_data
+);
+
+void EZSP_MGMT_LEAVE_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *dev_ieee_addr,
+		uchar remove_children,
+		uchar rejoin,
+		uchar reuse_address,
+		uchar silent
+);
+
+#endif
+
+void EZSP_ZDO_ERROR_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort cluster_id, uchar expected_len);
+#endif /* ZIGBEE_USE_DATA_STRUCTURES */
+
+void EZSP_ZDO_RESET_request(ZBIF_HANDLE zbif_handle, uchar options //0=Restart, 1=just init
+		) {
+	uchar *p;
+
+	// Store the type of reset that must be performed
+	restartGW = (options & 0x01);
+	zb_print("Restart flag set to %x\n", (int) options);
+
+	/*TODO
+	 //initialize the network co-processor (NCP)
+	 appResetAndInitNCP();
+	 */
+
+	/* generates the ZDO_RESET_confirm */
+	p = out_buf;
+
+	ushort op = 0;
+
+	*p++ = LSB_USHORT(op);
+	*p++ = MSB_USHORT(op);
+	*p++ = 0; /* status */
+
+	EZSP_Autogen(zbif_handle, out_buf, p - out_buf);
+}
+
+void EZSP_ZDO_START_request(ZBIF_HANDLE zbif_handle) {
+	uchar *p;
+	EmberStatus status;
+
+#ifdef ZIGBEE_APS_FRAG_ENABLED
+	ezspFragmentInit( HOST_FRAGMENT_BUFFER_SIZE, fragmentRxBuffer);
+	if (!timersInitiated)
+	{
+		initTimers();
+		pthread_mutex_init(&mux, NULL);
+		timersInitiated = TRUE;
+		zb_print("EZSP_ZDO_RESET_request - timers initialization\n");
+	}
+#endif // ZIGBEE_APS_FRAG_ENABLED
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	p = out_buf;
+
+	// Send EZSP ezspSetConfigurationValue command
+	*p++ = ezspSequence++;
+	*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+	*p++ = EZSP_SET_CONFIGURATION_VALUE;
+	*p++ = EZSP_CONFIG_TRUST_CENTER_ADDRESS_CACHE_SIZE;
+
+	ushort value = 3;
+
+	*p++ = LSB_USHORT(value);
+	*p++ = MSB_USHORT(value);
+
+	((zbif_status_t *) zbif_handle)->state = 1;
+
+	/* sends the command */
+	status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+
+	return;
+}
+
+void EZSP_ZDO_NWK_ADDR_request(ZBIF_HANDLE zbif_handle, uchar *ieee_addr,
+		uchar request_type, uchar start_index) {
+	zb_not_yet_implemented()
+}
+
+void EZSP_ZDO_IEEE_ADDR_request(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar request_type, uchar start_index) {
+	uchar *p;
+	EmberStatus status;
+	EmberApsOption apsOptions;
+
+	// set APS options
+	apsOptions = EMBER_APS_OPTION_RETRY
+			| EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY
+			| EMBER_APS_OPTION_ENABLE_ADDRESS_DISCOVERY;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	p = out_buf;
+
+	*p++ = ezspSequence++;
+	*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+	*p++ = EZSP_SEND_UNICAST;
+	*p++ = EMBER_OUTGOING_DIRECT;
+
+	*p++ = LSB_USHORT(nwk_addr);
+	*p++ = MSB_USHORT(nwk_addr);
+
+	ushort profile_id = EMBER_ZDO_PROFILE_ID;
+	ushort cluster_id = IEEE_ADDRESS_REQUEST;
+	ushort group_id = 0x0000;
+
+	// APS frame
+
+	*p++ = LSB_USHORT(profile_id);
+	*p++ = MSB_USHORT(profile_id);
+
+	*p++ = LSB_USHORT(cluster_id);
+	*p++ = MSB_USHORT(cluster_id);
+
+	*p++ = EMBER_ZDO_ENDPOINT; /* src_ep */
+	*p++ = EMBER_ZDO_ENDPOINT; /* dst_ep */
+
+	*p++ = LSB_USHORT(apsOptions);
+	*p++ = MSB_USHORT(apsOptions);
+
+	*p++ = LSB_USHORT(group_id);
+	*p++ = MSB_USHORT(group_id);
+
+	// End of common part
+
+	*p++ = 0;
+
+	*p++ = 0; // message tag
+	*p++ = 5; // message length
+
+	*p++ = 0; // Transaction sequence number
+	*p++ = LSB_USHORT(nwk_addr);
+	*p++ = MSB_USHORT(nwk_addr);
+	*p++ = request_type;
+	*p++ = start_index;
+
+	status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+
+	return;
+}
+
+void EZSP_ZB_MGMT_LQI_request(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar start_index) {
+	uchar *p;
+	EmberStatus status;
+	EmberApsOption apsOptions;
+
+	zb_print("EZSP_ZB_MGMT_LQI_request - Sending a MGMT_LQI_Req\n");
+
+	// set APS options
+	apsOptions = EMBER_APS_OPTION_RETRY
+			| EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY
+			| EMBER_APS_OPTION_ENABLE_ADDRESS_DISCOVERY;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	p = out_buf;
+
+	*p++ = ezspSequence++;
+	*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+	*p++ = EZSP_SEND_UNICAST;
+	*p++ = EMBER_OUTGOING_DIRECT;
+
+	*p++ = LSB_USHORT(nwk_addr);
+	*p++ = MSB_USHORT(nwk_addr);
+
+	ushort profile_id = EMBER_ZDO_PROFILE_ID;
+	ushort cluster_id = MGMT_LQI_REQ;
+	ushort group_id = 0x0000;
+
+	// APS frame
+	*p++ = LSB_USHORT(profile_id);
+	*p++ = MSB_USHORT(profile_id);
+	*p++ = LSB_USHORT(cluster_id);
+	*p++ = MSB_USHORT(cluster_id);
+	*p++ = EMBER_ZDO_ENDPOINT; /* src_ep */
+	*p++ = EMBER_ZDO_ENDPOINT; /* dst_ep */
+	*p++ = LSB_USHORT(apsOptions);
+	*p++ = MSB_USHORT(apsOptions);
+	*p++ = LSB_USHORT(group_id);
+	*p++ = MSB_USHORT(group_id);
+	// End of common part
+	*p++ = 0;
+	*p++ = 0; // message tag
+	*p++ = 5; // message length
+	*p++ = 0xAB; // Transaction sequence number (use a unique value for the moment!)
+	*p++ = start_index; //startIndex
+	status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+	return;
+}
+
+void EZSP_ZDO_NODE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr) {
+	uchar *p;
+	EmberStatus status;
+	EmberApsOption apsOptions;
+
+	zb_print("EZSP_ZB_MGMT_LQI_request - Sending a NODE_DESC_request\n");
+
+	// set APS options
+	apsOptions = EMBER_APS_OPTION_RETRY
+			| EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY
+			| EMBER_APS_OPTION_ENABLE_ADDRESS_DISCOVERY;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	p = out_buf;
+
+	*p++ = ezspSequence++;
+	*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+	*p++ = EZSP_SEND_UNICAST;
+	*p++ = EMBER_OUTGOING_DIRECT;
+
+	*p++ = LSB_USHORT(nwk_addr);
+	*p++ = MSB_USHORT(nwk_addr);
+
+	ushort profile_id = EMBER_ZDO_PROFILE_ID;
+	ushort cluster_id = NODE_DESCRIPTOR_REQUEST;
+	ushort group_id = 0x0000;
+
+	// APS frame
+	*p++ = LSB_USHORT(profile_id);
+	*p++ = MSB_USHORT(profile_id);
+	*p++ = LSB_USHORT(cluster_id);
+	*p++ = MSB_USHORT(cluster_id);
+	*p++ = EMBER_ZDO_ENDPOINT; /* src_ep */
+	*p++ = EMBER_ZDO_ENDPOINT; /* dst_ep */
+	*p++ = LSB_USHORT(apsOptions);
+	*p++ = MSB_USHORT(apsOptions);
+	*p++ = LSB_USHORT(group_id);
+	*p++ = MSB_USHORT(group_id);
+	// End of common part
+	*p++ = 0;
+	*p++ = 0; // message tag
+	*p++ = 5; // message length
+	*p++ = 0x00; // Transaction sequence number
+	*p++ = LSB_USHORT(nwk_addr);
+	*p++ = MSB_USHORT(nwk_addr);
+	status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+	return;
+}
+
+void EZSP_ZDO_POWER_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr) {
+	zb_not_yet_implemented()
+}
+
+void EZSP_ZDO_SIMPLE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, uchar endpoint) {
+	uchar *p;
+	EmberStatus status;
+	EmberApsOption apsOptions;
+
+	// set APS options
+	apsOptions = EMBER_APS_OPTION_RETRY
+			| EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY
+			| EMBER_APS_OPTION_ENABLE_ADDRESS_DISCOVERY;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	p = out_buf;
+
+	*p++ = ezspSequence++;
+	*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+	*p++ = EZSP_SEND_UNICAST;
+	*p++ = EMBER_OUTGOING_DIRECT;
+
+	*p++ = LSB_USHORT(dst_addr);
+	*p++ = MSB_USHORT(dst_addr);
+
+	ushort profile_id = EMBER_ZDO_PROFILE_ID;
+	ushort cluster_id = SIMPLE_DESCRIPTOR_REQUEST;
+	ushort group_id = 0x0000;
+
+	// APS frame //
+
+	*p++ = LSB_USHORT(profile_id);
+	*p++ = MSB_USHORT(profile_id);
+
+	*p++ = LSB_USHORT(cluster_id);
+	*p++ = MSB_USHORT(cluster_id);
+
+	*p++ = EMBER_ZDO_ENDPOINT; // src_ep
+	*p++ = EMBER_ZDO_ENDPOINT; // dst_ep
+
+	*p++ = LSB_USHORT(apsOptions);
+	*p++ = MSB_USHORT(apsOptions);
+
+	*p++ = LSB_USHORT(group_id);
+	*p++ = MSB_USHORT(group_id);
+
+	// End of common part //
+
+	*p++ = 0;
+
+	*p++ = 0; // message tag
+	*p++ = 4; // message length
+
+	*p++ = 0; // Transaction sequence number
+	*p++ = LSB_USHORT(dst_addr);
+	*p++ = MSB_USHORT(dst_addr);
+	*p++ = endpoint;
+
+	status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+
+	return;
+}
+
+void EZSP_ZDO_ACTIVE_EP_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr) {
+	uchar *p;
+	EmberStatus status;
+	EmberApsOption apsOptions;
+
+	//set APS options
+	apsOptions = EMBER_APS_OPTION_RETRY
+			| EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY
+			| EMBER_APS_OPTION_ENABLE_ADDRESS_DISCOVERY;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	p = out_buf;
+
+	*p++ = ezspSequence++;
+	*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+	*p++ = EZSP_SEND_UNICAST;
+	*p++ = EMBER_OUTGOING_DIRECT;
+
+	*p++ = LSB_USHORT(dst_addr);
+	*p++ = MSB_USHORT(dst_addr);
+
+	ushort profile_id = EMBER_ZDO_PROFILE_ID;
+	ushort cluster_id = ACTIVE_ENDPOINTS_REQUEST;
+	ushort group_id = 0x0000;
+
+	/* APS frame */
+
+	*p++ = LSB_USHORT(profile_id);
+	*p++ = MSB_USHORT(profile_id);
+
+	*p++ = LSB_USHORT(cluster_id);
+	*p++ = MSB_USHORT(cluster_id);
+
+	*p++ = EMBER_ZDO_ENDPOINT; /* src_ep */
+	*p++ = EMBER_ZDO_ENDPOINT; /* dst_ep */
+
+	*p++ = LSB_USHORT(apsOptions);
+	*p++ = MSB_USHORT(apsOptions);
+
+	*p++ = LSB_USHORT(group_id);
+	*p++ = MSB_USHORT(group_id);
+
+	/* End of common part */
+
+	*p++ = 0;
+
+	*p++ = 0; // message tag
+	*p++ = 3; // message length
+
+	*p++ = 0; // Transaction sequence number
+	*p++ = LSB_USHORT(dst_addr);
+	*p++ = MSB_USHORT(dst_addr);
+
+	/* sends the command */
+	zb_print_bytes("ACTIVE_EP_REQUEST -> ", out_buf, p - out_buf);
+	status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+
+	return;
+}
+
+void EZSP_ZDO_MATCH_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, ushort profile_id, uchar nicl, ushort *icllist,
+		uchar nocl, ushort *ocllist) {
+	zb_not_yet_implemented()
+}
+
+void EZSP_ZDO_MATCH_DESC_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, uchar match_len, uchar *match_list) {
+	zb_not_yet_implemented()
+}
+
+void EZSP_ZDO_END_DEVICE_BIND_request(ZBIF_HANDLE zbif_handle,
+		ushort binding_target, uchar *src_ieee_addr, uchar src_ep,
+		ushort profile_id, uchar nicl, ushort *icllist, uchar nocl,
+		ushort *ocllist) {
+	uchar *p;
+	EmberStatus status;
+	EmberApsOption apsOptions;
+
+	// set APS options
+	apsOptions = EMBER_APS_OPTION_RETRY
+			| EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY
+			| EMBER_APS_OPTION_ENABLE_ADDRESS_DISCOVERY;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	p = out_buf;
+
+	*p++ = ezspSequence++;
+	*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+	*p++ = EZSP_SEND_UNICAST;
+	*p++ = EMBER_OUTGOING_DIRECT;
+
+	*p++ = LSB_USHORT(binding_target);
+	*p++ = MSB_USHORT(binding_target);
+
+	ushort p_id = EMBER_ZDO_PROFILE_ID;
+	ushort cluster_id = END_DEVICE_BIND_REQUEST;
+	ushort group_id = 0x0000;
+
+	/* APS frame */
+
+	*p++ = LSB_USHORT(p_id);
+	*p++ = MSB_USHORT(p_id);
+
+	*p++ = LSB_USHORT(cluster_id);
+	*p++ = MSB_USHORT(cluster_id);
+
+	*p++ = EMBER_ZDO_ENDPOINT; /* src_ep */
+	*p++ = EMBER_ZDO_ENDPOINT; /* dst_ep */
+
+	*p++ = LSB_USHORT(apsOptions);
+	*p++ = MSB_USHORT(apsOptions);
+
+	*p++ = LSB_USHORT(group_id);
+	*p++ = MSB_USHORT(group_id);
+
+	/* End of common part */
+
+	*p++ = 0;
+
+	*p++ = 0; // message tag
+	*p++ = 20 + nicl + nocl; // message length
+
+	*p++ = 0; // Transaction sequence number
+
+	*p++ = LSB_USHORT(binding_target);
+	*p++ = MSB_USHORT(binding_target);
+
+	memcpy(p, src_ieee_addr, IEEE_ADDR_LEN);
+	p += IEEE_ADDR_LEN;
+
+	*p++ = src_ep;
+
+	*p++ = LSB_USHORT(profile_id);
+	*p++ = MSB_USHORT(profile_id);
+
+	*p++ = nicl;
+
+	int i;
+
+	for (i = 0; i < nicl; i++) {
+		*p++ = LSB_USHORT(icllist[i]);
+		*p++ = MSB_USHORT(icllist[i]);
+	}
+
+	*p++ = nocl;
+
+	for (i = 0; i < nocl; i++) {
+		*p++ = LSB_USHORT(ocllist[i]);
+		*p++ = MSB_USHORT(ocllist[i]);
+	}
+
+	*out_buf = p - out_buf;
+	status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void EZSP_APSDE_DATA_request(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, ushort profile_id, ushort cluster_id,
+		uchar src_ep, uchar asdu_len, uchar *asdu, uchar tx_options,
+		uchar radius) {
+	EmberStatus status;
+	EmberApsOption apsOptions;
+	uchar *p;
+	p = out_buf;
+	ushort group_id = 0x0000;
+
+#ifdef DEBUG_ZIGBEE_API
+	ZBPrint_APSDE_DATA_request (
+			dst_addr_mode,
+			dst_addr,
+			dst_ep,
+			profile_id,
+			cluster_id,
+			src_ep,
+			asdu_len,
+			asdu,
+			tx_options,
+			radius
+	);
+#endif
+
+	/*	default apsOptions value */
+	apsOptions = EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY
+			| EMBER_APS_OPTION_ENABLE_ADDRESS_DISCOVERY;
+
+	if (tx_options & ZB_APS_TXOPTIONS_USE_NWK_KEY)
+		apsOptions |= EMBER_APS_OPTION_ENCRYPTION;
+
+	if (tx_options & ZB_APS_TXOPTIONS_ACK_TRANSMISSION)
+		apsOptions |= EMBER_APS_OPTION_RETRY;
+
+//	if (tx_options & ZB_APS_TXOPTIONS_FRAGMENTATION_PERMITTED)
+//		apsOptions |= EMBER_APS_OPTION_FRAGMENT;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	*p++ = ezspSequence++;
+	*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+
+	if (dst_addr_mode == ZB_AM_DIRECT_GROUP) {
+		/* TODO: implement it! */
+		return;
+	} else if (dst_addr_mode == ZB_AM_DIRECT) {
+
+		ushort dst = *((ushort *) dst_addr);
+
+		/*
+		 * check if BROADCAST or UNICAST frame to be sent.
+		 * TODO: add set bdcast addresses for Routers and RxOnWhenIdledevices
+		 */
+
+		if (dst == 0xFFFF || dst == 0xFFFC) { //FFFC sends in broadcast but only to the routers
+		/* dst address is a bdcast address */
+			*p++ = EZSP_SEND_BROADCAST;
+		} else {
+			/* dst address is a short address */
+			*p++ = EZSP_SEND_UNICAST;
+			*p++ = EMBER_OUTGOING_DIRECT; /* EmberOutgoingMessageType */
+
+#ifdef ZIGBEE_APS_FRAG_ENABLED
+			// check if the current message needs to be sent using fragmentation
+			if ((asdu_len > ZA_FRAGMENT_TRIGGER)&&(tx_options & ZB_APS_TXOPTIONS_FRAGMENTATION_PERMITTED)) {
+
+				/* The fragmentation library only supports one message at a time */
+				if (fragmentedMessageInProcess) {
+					zb_print("EZSP_APSDE_DATA_request - TX Error: can't send fragmented message until previous"
+							"fragmented message completes --> EMBER_MAX_MESSAGE_LIMIT_REACHED\r\n");
+					return; /* TODO: return EMBER_MAX_MESSAGE_LIMIT_REACHED */
+				}
+
+				// TODO: find the source route if necessary
+				// TODO: zaAppFindSourceRoute(indexOrDestination);
+
+				EmberApsFrame apsFrame;
+				apsFrame.profileId = profile_id;
+				apsFrame.clusterId = cluster_id;
+				apsFrame.sourceEndpoint = src_ep;
+				apsFrame.destinationEndpoint = dst_ep;
+				apsFrame.options = apsOptions;
+				apsFrame.groupId = group_id;
+				apsFrame.sequence = 0;
+
+				/* send using fragmentation */
+				status = ezspSendFragmentedMessage (
+						zbif_handle,
+						EMBER_OUTGOING_DIRECT,
+						dst,
+						&apsFrame,
+						(ZA_FRAGMENT_TRIGGER - ZA_FRAGMENT_OVERHEAD),
+						asdu_len,
+						asdu
+				);
+
+				// the message is now sent through ezspSendFragmentedMessage function
+				// zb_conn_send is not required here for fragmentation
+				// --> actual transmission is considered in ezspSendFragmentedMessage/sendNextFragments
+
+				if (status == EMBER_SUCCESS) {
+					zb_print("\nEZSP_APSDE_DATA_request - fragmentedMessageInProcess = TRUE ************\n");
+					fragmentedMessageInProcess = TRUE;
+				}
+				return;
+			}
+#endif /* ZIGBEE_APS_FRAG_ENABLED */
+		}
+
+		/* normal packet processing */
+
+		*p++ = LSB_USHORT(dst);
+		*p++ = MSB_USHORT(dst);
+
+		/* APS Frame */
+		*p++ = LSB_USHORT(profile_id);
+		*p++ = MSB_USHORT(profile_id);
+
+		*p++ = LSB_USHORT(cluster_id);
+		*p++ = MSB_USHORT(cluster_id);
+
+		*p++ = src_ep;
+		*p++ = dst_ep;
+
+		*p++ = LSB_USHORT(apsOptions);
+		*p++ = MSB_USHORT(apsOptions);
+
+		*p++ = LSB_USHORT(group_id);
+		*p++ = MSB_USHORT(group_id);
+
+		/* End of Aps Frame */
+
+		if (dst == 0xFFFF) {
+			*p++ = radius;
+		}
+
+		*p++ = 0; /* Sequence */
+		*p++ = 0; /* message tag */
+		*p++ = asdu_len; /*  message length */
+		//printf("DATA RECEIVED length: %d\n",asdu_len);
+
+		if (asdu_len > 0) {
+			memcpy(p, asdu, asdu_len);
+			p += asdu_len;
+		}
+
+	} else if (dst_addr_mode == ZB_AM_INDIRECT) {
+		zb_not_yet_implemented()
+	} else if (dst_addr_mode == ZB_AM_DIRECT_EX) {
+		zb_not_yet_implemented()
+	} else {
+		/* error! */
+		zb_print_error(
+				"ERROR: unsupported dst_addr_mode: %d", (int) dst_addr_mode);
+		return;
+	}
+	status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void EZSP_APSME_BIND_request(ZBIF_HANDLE zbif_handle, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep) {
+	zb_not_yet_implemented()
+}
+
+void EZSP_APSME_UNBIND_request(ZBIF_HANDLE zbif_handle, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep) {
+	zb_not_yet_implemented()
+}
+
+void EZSP_APSME_GET_request(ZBIF_HANDLE zbif_handle, uchar attr) {
+	uchar *p;
+	p = out_buf;
+
+	if (attr == ZB_ATTR_GET_EUI64) {
+		//Request the EUI 64
+		ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+		EmberStatus status;
+
+		((zbif_status_t *) zbif_handle)->state = (int) attr;
+
+		*p++ = ezspSequence++;
+		*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+		*p++ = 0x26; //ID: 0x26 for getEui64
+
+		status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+		return;
+	} else {
+		//Not managed yet! Move on with the next item
+		zb_print("Attribute %x not supported, ignore it!\n", attr);
+		/* generates the APSME_GET_confirm() */
+		p = out_buf;
+
+		ushort op = 1;
+
+		*p++ = LSB_USHORT(op);
+		*p++ = MSB_USHORT(op);
+
+		*p++ = 0; /* status */
+		*p++ = attr; /* status */
+
+		EZSP_Autogen(zbif_handle, out_buf, p - out_buf);
+	}
+}
+
+void EZSP_APSME_SET_request(ZBIF_HANDLE zbif_handle, uchar attr, uchar attr_len,
+		uchar *attr_value) {
+	uchar *p;
+	p = out_buf;
+	int i = 0;
+
+	if (attr == ZB_ATTR_CONFIG_CHANNEL_MASK) {
+		if (attr_len == 4) {
+			unsigned long v;
+
+			assert(sizeof(v) == attr_len);
+
+			memcpy(&v, attr_value, attr_len);
+			v = ztohl(v);
+
+			zb_print("channel mask %08x\n", (unsigned int) v);
+
+			/* count number of bits set */
+			int count = 0;
+			int first = -1;
+			int i;
+			unsigned long mask = 0x00000001;
+			for (i = 0; i < (sizeof(v) * 8); i++) {
+				if ((first == -1) && (v & mask)) {
+					first = count;
+				}
+				mask <<= 1;
+				count++;
+			}
+
+			if (count != 0) {
+				g_networkParams.radioChannel = first;
+				zb_print("Selected radio channel = %d\n", first);
+				g_channel_mask = v;
+			}
+		}
+	} else if (attr == ZB_ATTR_CONFIG_NODE_DESCRIPTOR) {
+		ZB_NODE_DESC *g_node_desc = (ZB_NODE_DESC *) attr_value;
+		DevType = g_node_desc->logical_type;
+		zb_print(
+				"EZSP_APSME_SET_request - ZB_ATTR_CONFIG_NODE_DESCRIPTOR - dev Type = %02x\n", DevType);
+	} else if (attr == ZB_ATTR_CONFIG_PANID) {
+		if (attr_len == 2) {
+			ushort v = *attr_value | (*(attr_value + 1) << 8);
+			zb_print("PANID %02x\n", v);
+			g_networkParams.panId = v;
+		}
+	} else if (attr == ZB_ATTR_CONFIG_EXTENDEDPANID) {
+		if (attr_len == 8) {
+			uchar v[8];
+			int c;
+			for (c = 0; c < 8; c++) {
+				v[c] = attr_value[7 - c];
+			}
+			zb_print(
+					"EXTENDEDPANID = %x %x %x %x %x %x %x %x \n", v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
+			memcpy(g_networkParams.extendedPanId, v, EXTENDED_PAN_ID_SIZE);
+		}
+	} else if (attr == ZB_ATTR_PRECONF_TC_LINK_KEY) {
+		if (attr_len == 16) {
+			int c;
+			for (c = 0; c < 16; c++) {
+				preconfiguredLinkKey.contents[c] = attr_value[c]; //15 - c
+			}
+		}
+	} else if (attr == ZB_ATTR_NWK_KEY) {
+		int nwkKeyValidityCheck = 0;
+		if (attr_len == 16) {
+			int c;
+			for (c = 0; c < 16; c++) {
+				networkKey.contents[c] = attr_value[c];
+				if (attr_value[c] == 0)
+					nwkKeyValidityCheck++;
+			}
+			if (nwkKeyValidityCheck == 16)
+				usePreconfiguredNwkKey = FALSE;
+			else
+				usePreconfiguredNwkKey = TRUE;
+		}
+	} else if (attr == ZB_ATTR_CONFIG_SECURITY) {
+		securityLevel = (int) attr_value[0];
+		uchar attr_value_[2];
+		if (attr_len == 1) {
+			attr_value_[0] = attr_value[0];
+			attr_value_[1] = 0;
+		}
+		attr_len = 2;
+
+		ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+		EmberStatus status;
+
+		/*
+		 * The variable state in zbif_handle is used to store the 
+		 * attribute Id -> this value is used to properly generate the 
+		 * APSME_SET_confirm once a response is received from the Ember NP
+		 */
+
+		((zbif_status_t *) zbif_handle)->state =
+				(int) ZB_ATTR_CONFIG_SECURITY_LEVEL;
+
+		*p++ = ezspSequence++;
+		*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+		*p++ = EZSP_SET_CONFIGURATION_VALUE;
+		*p++ = ZB_ATTR_CONFIG_SECURITY_LEVEL;
+
+		if (attr_len == 2) {
+			memcpy(p, attr_value_, attr_len);
+			p += attr_len;
+		}
+
+		status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+		return;
+
+	} else if (attr == ZB_TC_KEY_REQUEST_POLICY
+			|| attr == ZB_APP_KEY_REQUEST_POLICY || attr == 0x00) {
+
+		ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+		EmberStatus status;
+
+		/*
+		 * The variable state in zbif_handle is used to store the 
+		 * attribute Id -> this value is used to properly generate the 
+		 * APSME_SET_confirm once a response is received from the Ember NP
+		 */
+
+		setPolicyActive = TRUE;
+		//policyIdConsidered = htozl(attr);
+
+		((zbif_status_t *) zbif_handle)->state = (int) attr;
+
+		*p++ = ezspSequence++;
+		*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+		*p++ = EZSP_SET_POLICY;
+		*p++ = attr;
+
+		memcpy(p, attr_value, attr_len);
+		p += attr_len;
+		zb_print(
+				"ZB_TC_KEY_REQUEST_POLICY - PolicyID %02x, DecisionId %02x (length %02x)\n", attr, *(p-1), attr_len);
+		status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+		return;
+	} else if (attr == ZB_ATTR_KEY_TABLE_ENTRY) {
+
+		ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+		EmberStatus status;
+
+		((zbif_status_t *) zbif_handle)->state = (int) attr;
+
+		*p++ = ezspSequence++;
+		*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+
+		//Check whether a specific entry in the key table has to be set or erased
+		int counter = 0;
+		boolean isEraseKTECommand = TRUE;
+		for (counter = 1; counter < attr_len; counter++) {
+			if (attr_value[counter] != 0) {
+				isEraseKTECommand = FALSE;
+				break;
+			}
+		}
+
+		if (isEraseKTECommand) {
+			*p++ = EZSP_ERASE_KEY_TABLE_ENTRY; //0x76
+
+			memcpy(p, attr_value, attr_len);
+			p += 1;
+			zb_print(
+					"ERASE KEY - AttrId %02x, (length %02x)\n", attr, attr_len);
+			status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+		} else {
+			*p++ = EZSP_SET_KEY_TABLE_ENTRY; //0x72
+
+			memcpy(p, attr_value, attr_len);
+			p += attr_len;
+			zb_print(
+					"EZSP_SET_KEY_TABLE_ENTRY - AttrId %02x, (length %02x)\n", attr, attr_len);
+			status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+		}
+		return;
+
+	} else if (attr == ZB_ATTR_CONFIG_STARTUPCONTROL) {
+		((zbif_status_t *) zbif_handle)->state = (int) attr;
+		// Do nothing, not useful for EZSP!
+	} else if (attr == ZB_ATTR_CONFIG_SIMPLE_DESCRIPTOR) {
+
+		ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+		EmberStatus status;
+
+		((zbif_status_t *) zbif_handle)->state = (int) attr;
+
+		// Prepare an addEndpoint function (page 50)
+		*p++ = ezspSequence++;
+		*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+		*p++ = EZSP_ADD_ENDPOINT;
+		/* Insert the following information
+		 int8u endpoint
+		 int16u profileId
+		 int16u deviceId
+		 int8u appFlags
+		 int8u inputClusterCount
+		 int8u outputClusterCount
+		 int16u[] inputClusterList
+		 int16u[] outputClusterList
+		 */
+
+		memcpy(p, attr_value, attr_len);
+		p += attr_len;
+		/*
+		 printf("Sending out the following bytes: ");
+		 for (i=0; i < p - out_buf; i++)
+		 printf("%2x ",out_buf[i]);
+		 printf("\r\n");
+		 */
+		status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+		return;
+	} else {
+		//Temp - Note that ZB_ATTR_KEY_TABLE_SIZE is managed here!
+		ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+		EmberStatus status;
+
+		/*
+		 * The variable state in zbif_handle is used to store the 
+		 * attribute Id -> this value is used to properly generate the 
+		 * APSME_SET_confirm once a response is received from the Ember NP
+		 */
+
+		((zbif_status_t *) zbif_handle)->state = (int) attr;
+
+		*p++ = ezspSequence++;
+		*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+		*p++ = EZSP_SET_CONFIGURATION_VALUE;
+		*p++ = attr;
+
+		if (attr_len == 2) {
+			memcpy(p, attr_value, attr_len);
+			p += attr_len;
+		}
+
+		status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+		return;
+	}
+
+	/* generates the APSME_SET_confirm() */
+	p = out_buf;
+
+	ushort op = 1;
+
+	*p++ = LSB_USHORT(op);
+	*p++ = MSB_USHORT(op);
+
+	*p++ = 0; /* status */
+	*p++ = attr; /* status */
+
+	EZSP_Autogen(zbif_handle, out_buf, p - out_buf);
+}
+
+void EZSP_APSME_SET_confirm(uchar status, uchar attr) {
+	zb_print("APSME_SET_confirm: status = 0x%02x\n", status);
+	return;
+}
+
+// NOTE: Not used anymore (for the moment we setup then whole message in CManagementAgent.cpp)
+void EZSP_MGMT_PERMIT_JOINING_request(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		int permitDuration) {
+	uchar *p;
+	p = out_buf;
+
+	zb_print(
+			"EZSP_MGMT_PERMIT_JOINING_request - destinationAddress value = %4x\n - permitDuration value = %d\n", nwk_addr, permitDuration);
+	/* OLD VERSION ACTING ONLY AT THE LOCAL NODE...NLNE
+	 // NOTE: The EZSP protocol format is made by:
+	 // Sequence 1 byte
+	 // Frame Control 1 byte
+	 // Frame ID 1 byte
+	 // Parameters
+	 *p++ = ezspSequence;
+	 *p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+	 *p++ = EZSP_PERMIT_JOINING;
+	 *p++ = LSB_USHORT(permitDuration); // duration
+	 // sends the command
+	 status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+	 */
+
+	//NEW VERSION: Sending a Mgmt_Permit_Joining_req
+	*p++ = ezspSequence++;
+	*p++ = LSB_USHORT(permitDuration); // PermitDuration
+	*p++ = 0x00; //TC_Significance, there is no effect on the Trust Center
+
+	// sends the command
+	EZSP_APSDE_DATA_request(zbif_handle, 0x02, (uchar *) &nwk_addr, 0x00,
+			0x0000, 0x0036, 0x00, p - out_buf, out_buf, 0x00, 0xFF);
+}
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+
+/**
+ * TODO: document it!
+ */
+
+void EZSP_APSME_REMOVE_DEVICE_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *parent_ieee_addr,
+		uchar *child_ieee_addr
+) {
+	zb_not_yet_implemented()
+}
+
+void EZSP_APSME_TRANSPORT_KEY_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *dst_ieee_addr,
+		uchar key_type,
+		ZB_TRANSPORT_KEY_DATA *transport_key_data
+) {
+	zb_not_yet_implemented()
+}
+
+void EZSP_MGMT_LEAVE_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *dev_ieee_addr,
+		uchar remove_children,
+		uchar rejoin,
+		uchar reuse_address,
+		uchar silent
+) {
+	zb_not_yet_implemented()
+}
+
+#endif
+
+void EZSP_ZDO_ERROR_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort cluster_id, uchar expected_len) {
+	zb_not_yet_implemented()
+}
+
+/**
+ * This function provides decoding functionalities.
+ * The passed data should not be freed!
+ */
+
+void EZSP_ReceiveCb(ZBIF_HANDLE zbif_handle, uchar *data, const int size) {
+	uchar seq, ctrl, frame_id;
+	uchar *p;
+
+	zb_print("\nEZSP_ReceiveCb\n");
+
+	if (zbif_handle == NULL) {
+		return;
+	}
+
+	ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+	if (zbifCbs == NULL) {
+		/* error! */
+		return;
+	}
+
+	ZB_LOG(zb_print_bytes("EZSP_ReceiveCb ", data, size);)
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	int state = ((zbif_status_t *) zbif_handle)->state;
+
+	p = data;
+
+	seq = *p++;
+	ctrl = *p++;
+	frame_id = *p++;
+
+	zb_print(
+			"frame_id = %s(%02x)\n", (char *) decodeFrameId(frame_id), frame_id);
+	switch (frame_id) {
+
+	case EZSP_NO_CALLBACKS:
+		break;
+
+	case EZSP_TIMER_HANDLER: {
+		uchar timer_id;
+		timer_id = *p++;
+		break;
+	}
+
+	case EZSP_SEND_REPLY: {
+		zb_print("arrived SEND_REPLY\n");
+		break;
+	}
+
+	case EZSP_ADD_ENDPOINT: {
+		zb_print("addEndPoint confirm\n");
+		zbifCbs->APSME_SET_confirm(zbif_handle, *p++, state);
+		break;
+	}
+
+	case EZSP_INCOMING_MESSAGE_HANDLER: {
+		uchar type;
+
+		//uchar *dst_addr_p = NULL;
+		uchar *src_addr_p = NULL;
+
+		uchar dst_addr_p[2];
+
+		uchar was_broadcast = 0;
+		uchar sec_status = 0;
+
+		type = *p++;
+
+		zb_print("type = %d\n", (int) type);
+
+		/* read APS header */
+		ushort profile_id = *p | (*(p + 1) << 8);
+		p += 2;
+		ushort cluster_id = *p | (*(p + 1) << 8);
+		p += 2;
+		uchar src_ep = *p++;
+		uchar dst_ep = *p++;
+		ushort options = *p | (*(p + 1) << 8);
+		p += 2;
+		ushort group_id = *p | (*(p + 1) << 8);
+		p += 2;
+		uchar sequence = *p++;
+
+		zb_print("src_ep %02x\n", src_ep);
+		zb_print("dst_ep %02x\n", dst_ep);
+
+		zb_print("options %04x\n", options);
+		zb_print("group_id %04x\n", group_id);
+		zb_print("sequence %02x\n", sequence);
+
+		uchar lastHopLqi = *p++;
+		uchar lastHopRssi = *p++;
+
+		// patch the source address by converting it into the host byte order convention //
+
+		src_addr_p = p;
+		ushort src_addr = *p | (*(p + 1) << 8);
+		p += 2;
+		memcpy(src_addr_p, &src_addr, sizeof(src_addr));
+
+		uchar bindingIndex = *p++;
+		uchar addressIndex = *p++;
+		ushort asdu_len = *p++;
+
+		zb_print("bindingIndex %02x\n", bindingIndex);
+		zb_print("addressIndex %02x\n", addressIndex);
+		zb_print("profile_id %04x\n", profile_id);
+		zb_print("cluster_id %04x\n", cluster_id);
+
+#ifdef ZIGBEE_APS_FRAG_ENABLED
+
+		EmberApsFrame apsFrame;
+		apsFrame.profileId = profile_id;
+		apsFrame.clusterId = cluster_id;
+		apsFrame.sourceEndpoint = src_ep;
+		apsFrame.destinationEndpoint = dst_ep;
+		apsFrame.options = options;
+		apsFrame.groupId = group_id;
+		apsFrame.sequence = sequence;
+
+		uchar *apsMessage;
+		if (asdu_len > 0) {
+			apsMessage = p;
+		}
+		else {
+			apsMessage = NULL;
+		}
+
+		zb_print("EZSP_ReceiveCb - EZSP_INCOMING_MESSAGE_HANDLER - src_addr = %x\n",src_addr);
+
+		if (ezspIsIncomingFragment(zbif_handle, &apsFrame, src_addr, &asdu_len, &apsMessage)) {
+			zb_print("EZSP_ReceiveCb - EZSP_INCOMING_MESSAGE_HANDLER - ezspIsIncomingFragment != 0 -> RETURN");
+			return;
+		} else {
+			/* TODO: Modify */
+			p = apsMessage;
+		}
+
+#endif /* ZIGBEE_APS_FRAG_ENABLED */
+
+		if (zbifCbs->APSDE_DATA_indication) {
+			sec_status = 0;
+
+			uchar src_addr_mode = 0x02;
+			uchar dst_addr_mode = 0x02;
+
+			zb_print(
+					"\ntype = %d **************APSDE_DATA_indication*******************\n", type);
+
+			if (type == EMBER_INCOMING_UNICAST) {
+				src_addr_mode = ZB_AM_DIRECT;
+
+				dst_addr_p[0] = LSB_USHORT(localShortAddr);
+				dst_addr_p[1] = MSB_USHORT(localShortAddr);
+			} else if (type == EMBER_INCOMING_UNICAST_REPLY) {
+				src_addr_mode = 0; //TODO	Modify!!!
+				zb_print("Unicast reply\n");
+			} else if (type == EMBER_INCOMING_MULTICAST) {
+				src_addr_mode = 0; //TODO	Modify!!!
+				zb_print("Incoming Multicast\n");
+			} else if (type == EMBER_INCOMING_BROADCAST) {
+				// Broadcast.
+				zb_print("Incoming Broadcast\n");
+				zb_print(
+						"Incoming: local broadcast message ->  src_addr = %d - localShortAddr = %d \n", src_addr, localShortAddr);
+				was_broadcast = 1;
+				dst_addr_p[0] = 0xFF;
+				dst_addr_p[1] = 0xFF;
+			} else if (type == EMBER_INCOMING_BROADCAST_LOOPBACK) {
+				// Broadcast sent by the local device.
+				zb_print("Incoming Broadcast Loopback\n");
+				zb_print(
+						"\nIncoming: local broadcast message -> Discarded! \n");
+#ifdef FILTER_LOCALBROADCAST_LOOPBACK_MSGS
+				zb_print("\nIncoming: local broadcast message -> Discarded! \n");
+				return;
+#endif
+			} else {
+				zb_print("Incoming: unknown packet type\n");
+			}
+
+			zb_print("src_ep %02x\n", src_ep);
+			zb_print("dst_ep %02x\n", dst_ep);
+			//zb_print ("dst_addr %04x\n", dst_addr);
+//TODO	Verify whether this scenario is possible -> if so, uncomment the following section
+//#ifdef FILTER_LOCALBROADCAST_LOOPBACK_MSGS
+//			if (was_broadcast == 1 && src_addr == localShortAddr)
+//			{
+//				zb_print ("Incoming: local broadcast message ->  src_addr = %d - localShortAddr = %d \n", src_addr, localShortAddr);
+//				zb_print ("Incoming: local broadcast message -> Discarded! \n");
+//				return;
+//			}
+//#endif
+
+			uchar *asdu;
+			if (asdu_len > 0) {
+				asdu = p;
+				//p += asdu_len;		//Removed
+			} else {
+				asdu = NULL;
+			}
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_APSDE_DATA_indication (
+					dst_addr_mode,
+					dst_addr_p,
+					dst_ep,
+					src_addr_mode,
+					src_addr_p,
+					src_ep,
+					profile_id,
+					cluster_id,
+					asdu_len,
+					asdu,
+					was_broadcast,
+					sec_status
+			);
+#endif
+
+			zbifCbs->APSDE_DATA_indication(zbif_handle, dst_addr_mode,
+					dst_addr_p, dst_ep, src_addr_mode, src_addr_p, src_ep,
+					profile_id, cluster_id, asdu_len, asdu, was_broadcast,
+					sec_status);
+		}
+
+		if (profile_id == EMBER_ZDO_PROFILE_ID) {
+			switch (cluster_id) {
+			case NETWORK_ADDRESS_RESPONSE:
+				break;
+
+			case END_DEVICE_BIND_RESPONSE:
+				if (zbifCbs->ZDO_END_DEVICE_BIND_confirm) {
+					//uchar tr_num = p[0];
+					uchar status = p[1];
+#ifdef DEBUG_ZIGBEE_API
+					ZBPrint_ZDO_END_DEVICE_BIND_confirm(status);
+#endif
+					zbifCbs->ZDO_END_DEVICE_BIND_confirm(zbif_handle, status);
+				}
+				break;
+
+			case PERMIT_JOINING_RESPONSE:
+				if (zbifCbs->MGMT_PERMIT_JOINING_response) {
+					//uchar tr_num = p[0];
+					uchar status = p[1];
+#ifdef DEBUG_ZIGBEE_API
+					ZBPrint_MGMT_PERMIT_JOINING_response(status);
+#endif
+					zbifCbs->MGMT_PERMIT_JOINING_response(zbif_handle, status);
+				}
+				break;
+
+			case LEAVE_RESPONSE:
+				if (zbifCbs->MGMT_LEAVE_response) {
+					uchar status = p[1];
+#ifdef DEBUG_ZIGBEE_API
+					ZBPrint_MGMT_LEAVE_response(status);
+#endif
+					zbifCbs->MGMT_LEAVE_response(zbif_handle, status);
+				}
+				break;
+
+			case BIND_RESPONSE:
+				if (1) {
+					zb_print("BIND_RESPONSE");
+				}
+				break;
+
+			case IEEE_ADDRESS_RESPONSE:
+				if (zbifCbs->ZDO_IEEE_ADDR_confirm) {
+					/// <transaction sequence number: 1>
+					/// <status:1> <EUI64:8> <node ID:2>
+					/// <ID count:1> <start index:1> <child ID:2>*
+					//uchar tr_num = p[0];
+					uchar status = p[1];
+					uchar ieee_addr[IEEE_ADDR_LEN];
+					memcpy(ieee_addr, p + 2, IEEE_ADDR_LEN);
+					swap_bytes(ieee_addr, IEEE_ADDR_LEN);
+					ushort nwk_addr = p[10] | (p[11] << 8);
+					uchar num_assoc_dev = p[12];
+					uchar start_index;
+					ushort *nwk_addr_assoc_dev_list;
+					if (num_assoc_dev > 0) {
+						start_index = p[13];
+						nwk_addr_assoc_dev_list = (ushort*) (p + 14);
+					}
+
+#ifdef DEBUG_ZIGBEE_API
+					ZBPrint_ZDO_IEEE_ADDR_confirm (
+							status,
+							ieee_addr,
+							nwk_addr,
+							num_assoc_dev,
+							start_index,
+							nwk_addr_assoc_dev_list
+					);
+#endif
+
+#ifdef IEEE_ADDR_REQUEST_PATCH
+					if (nwk_addr == 0)
+					{
+						ieeeAddrResponse.status = status;
+
+						memcpy(ieeeAddrResponse.ieee_addr, p+2, IEEE_ADDR_LEN);
+						swap_bytes(ieeeAddrResponse.ieee_addr, IEEE_ADDR_LEN);
+
+						ieeeAddrResponse.nwk_addr = nwk_addr;
+
+						ieeeAddrResponse.endDeviceCount = num_assoc_dev;
+						ieeeAddrResponse.num_assoc_dev = num_assoc_dev;
+
+						ieeeAddrResponse.start_index = start_index;
+
+						if (ieeeAddrResponse.nwk_addr_assoc_dev_list != NULL)
+						{
+							free(ieeeAddrResponse.nwk_addr_assoc_dev_list);
+						}
+
+						ieeeAddrResponse.nwk_addr_assoc_dev_list = (ushort *) malloc ((int)num_assoc_dev * sizeof(ushort));
+						memcpy(ieeeAddrResponse.nwk_addr_assoc_dev_list, p + 14, (int)num_assoc_dev * sizeof(ushort));
+
+						uchar *pOut;
+						EmberStatus reqStatus;
+						pOut = out_buf;
+
+						/* Send EZSP_NEIGHBOR_COUNT message */
+						*pOut++ = ezspSequence++;
+						*pOut++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+						*pOut++ = EZSP_NEIGHBOR_COUNT;
+
+						reqStatus = zb_conn_send(zb_conn_h, out_buf, pOut - out_buf);
+						zb_print("EZSP_ReceiveCb - Send EZSP_NEIGHBOR_COUNT message\n");
+
+					}
+					else {
+
+#endif /* IEEE_ADDR_REQUEST_PATCH */
+
+					zbifCbs->ZDO_IEEE_ADDR_confirm(zbif_handle, status,
+							ieee_addr, nwk_addr, num_assoc_dev, start_index,
+							nwk_addr_assoc_dev_list);
+
+#ifdef IEEE_ADDR_REQUEST_PATCH	
+				}
+#endif	
+				}
+				break;
+
+			case MGMT_LQI_RSP: {
+				uchar src_addr_mode = 0x02; //Note: It is always taken above as a shortAddress...
+				//printf("EZSP_ReceiveCb - Calling ZB_MGMT_LQI_response (srd_addr = 0x%02x%02x)\n",src_addr_p[0],src_addr_p[1]);
+				if (zbifCbs->ZB_MGMT_LQI_response) {
+					zbifCbs->ZB_MGMT_LQI_response(zbif_handle, src_addr_mode,
+							src_addr_p, p);
+				}
+				break;
+			}
+
+			case NODE_DESCRIPTOR_RESPONSE:
+				if (zbifCbs->ZDO_NODE_DESC_confirm) {
+					//Transaction sequence number
+					p++;
+					//Status
+					uchar status = *p++;
+					//NWKAddrOfInterest
+					ushort nwk_addr = *p + (*(p + 1) << 8);
+					p += 2;
+					ZB_NODE_DESC node_desc;
+					//Byte 1
+					node_desc.logical_type = *p & 0x07;
+#ifdef ZIGBEE_2006
+					node_desc.user_desc_avail = *p & 0x08;
+					node_desc.complx_desc_avail = *p & 0x10;
+					node_desc.reserved = *p & 0xE0;
+#endif
+					p++;
+					//Byte 2
+					node_desc.aps_flags = *p & 0x07;
+					node_desc.freq_band = (*p & 0xF8) >> 3;
+					p++;
+					//Byte 3
+					node_desc.mac_cap = *p++;
+					//Byte 4 and 5
+					node_desc.manifact_code = *p + (*(p + 1) << 8);
+					p += 2;
+					//Byte 6
+					node_desc.max_buf_size = *p++;
+					//Byte 7 and 8 (Maximum incoming transfer size)
+					node_desc.max_transf_size = *p + (*(p + 1) << 8);
+					p += 2;
+					//Byte 9 and 10 (Server mask - 16 bits)
+#ifdef ZIGBEE_2006
+					node_desc.server_mask = *p + (*(p + 1) << 8);p += 2;
+#endif
+					//Byte 11 and 12 (Maximum outgoing transfer size - 16 bits)
+					//Byte 13 (Descriptor capability field - 8 bits)
+
+#ifdef DEBUG_ZIGBEE_API
+					ZBPrint_ZDO_NODE_DESC_confirm (
+							status,
+							nwk_addr,
+							&node_desc
+					);
+#endif
+					zbifCbs->ZDO_NODE_DESC_confirm(zbif_handle, status,
+							nwk_addr, &node_desc);
+
+				}
+				break;
+
+			case END_DEVICE_ANNOUNCE:
+				if (zbifCbs->ZDO_DEVICE_ANNCE_indication) {
+					uchar ieee_addr[IEEE_ADDR_LEN];
+					uchar index = *p++;
+					ushort nwk_addr = *p + (*(p + 1) << 8);
+					p += 2;
+
+					memcpy(ieee_addr, p, IEEE_ADDR_LEN);
+					p += IEEE_ADDR_LEN;
+					swap_bytes(ieee_addr, IEEE_ADDR_LEN);
+					uchar child_type = *p++;
+
+#ifdef DEBUG_ZIGBEE_API
+					ZBPrint_ZDO_DEVICE_ANNCE_indication (
+							nwk_addr,
+							ieee_addr,
+							child_type
+					);
+#endif
+					zbifCbs->ZDO_DEVICE_ANNCE_indication(zbif_handle, nwk_addr,
+							ieee_addr, child_type);
+
+				}
+				break;
+
+			case POWER_DESCRIPTOR_RESPONSE:
+				break;
+
+			case ACTIVE_ENDPOINTS_RESPONSE:
+				if (zbifCbs->ZDO_SIMPLE_DESC_confirm) {
+					uchar tr_num = *p++;
+
+					uchar *active_ep_list = NULL;
+					if (p[3] > 0) {
+						/* active ep list is not empty */
+						active_ep_list = p + 4;
+					}
+
+#ifdef DEBUG_ZIGBEE_API
+					ZBPrint_ZDO_ACTIVE_EP_DESC_confirm (
+							p[0], /* status 			*/
+							p[1] | (p[2] << 8), /* nwk_addr			*/
+							p[3], /* active_ep_count	*/
+							active_ep_list /* active_ep_list	*/
+					);
+#endif
+					zbifCbs->ZDO_ACTIVE_EP_DESC_confirm(zbif_handle, p[0], /* status 			*/
+					p[1] | (p[2] << 8), /* nwk_addr			*/
+					p[3], /* active_ep_count	*/
+					active_ep_list /* active_ep_list	*/
+					);
+				}
+				break;
+
+			case SIMPLE_DESCRIPTOR_RESPONSE:
+				if (zbifCbs->ZDO_SIMPLE_DESC_confirm) {
+
+					uchar tr_num = *p++;
+
+					ZB_SIMPLE_DESC simple_desc;
+					int simple_desc_len;
+
+					uchar *q = p;
+
+					simple_desc_len = p[3];
+
+					/* TODO: also cluster must be converted in host byte order */
+
+					if (simple_desc_len > 0) {
+						/* simple descr present */
+
+						simple_desc.ep = p[4];
+						simple_desc.app_profile_id = p[5] | p[6] << 8;
+						simple_desc.app_device_id = p[7] | p[8] << 8;
+						simple_desc.app_device_ver = p[9] & 0x0F;
+						simple_desc.reserved = p[9] >> 4;
+
+						p += 10;
+
+						simple_desc.app_in_cluster_count = *p++;
+
+						if (simple_desc.app_in_cluster_count) {
+							simple_desc.app_in_cluster_list = malloc(
+									simple_desc.app_in_cluster_count
+											* sizeof(ushort));
+							memcpy(simple_desc.app_in_cluster_list, p,
+									simple_desc.app_in_cluster_count
+											* sizeof(ushort));
+							p += simple_desc.app_in_cluster_count
+									* sizeof(ushort);
+
+						} else {
+							simple_desc.app_in_cluster_list = NULL;
+						}
+
+						simple_desc.app_out_cluster_count = *p++;
+
+						if (simple_desc.app_out_cluster_count) {
+							simple_desc.app_out_cluster_list = malloc(
+									simple_desc.app_out_cluster_count
+											* sizeof(ushort));
+							memcpy(simple_desc.app_out_cluster_list, p,
+									simple_desc.app_out_cluster_count
+											* sizeof(ushort));
+						} else {
+							simple_desc.app_out_cluster_list = NULL;
+						}
+					} else {
+						/* simple descr not present */
+						/* TODO: should we return NULL instead of setting all the fields to 0? */
+						memset(&simple_desc, 0, sizeof(simple_desc));
+					}
+
+#ifdef DEBUG_ZIGBEE_API
+					ZBPrint_ZDO_SIMPLE_DESC_confirm (
+							q [0],
+							q [1] | q [2] << 8,
+							&simple_desc
+					);
+#endif
+
+					zbifCbs->ZDO_SIMPLE_DESC_confirm(zbif_handle, q[0],
+							q[1] | q[2] << 8, &simple_desc);
+
+					ZB_Free_SIMPLE_DESC(&simple_desc);
+
+				}
+				break;
+
+			default:
+				break;
+			}
+		}
+
+	}
+		break;
+
+	case EZSP_GET_PARENT_CHILD_PARAMETERS: {
+		zb_print(
+				"EZSP_ReceiveCb - EZSP_GET_PARENT_CHILD_PARAMETERS message: Response received\n");
+		uchar childCount = p[0];
+		zb_print(
+				"EZSP_ReceiveCb - EZSP_GET_PARENT_CHILD_PARAMETERS message - childCount = %d\n", childCount);
+
+	}
+		break;
+
+	case EZSP_GET_CHILD_DATA: {
+		zb_print(
+				"\nEZSP_ReceiveCb - EZSP_GET_CHILD_DATA message: Response received\n");
+	}
+		break;
+
+	case EZSP_NEIGHBOR_COUNT: {
+
+		zb_print(
+				"\nEZSP_ReceiveCb - EZSP_NEIGHBOR_COUNT message: Response received\n");
+
+		// Number of associated devices operating as ZB routers
+		uchar neighborCount = p[0];
+		zb_print(
+				"\nEZSP_ReceiveCb - EZSP_NEIGHBOR_COUNT message: neighborCount = %d", neighborCount);
+
+#ifdef IEEE_ADDR_REQUEST_PATCH
+
+		if (neighborCount == 0)
+		{
+			// The considered node has not any children operating as ZigBee Routers -> Send IEEE ADDR confirm to the higher layer
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_IEEE_ADDR_confirm (
+					ieeeAddrResponse.status,
+					ieeeAddrResponse.ieee_addr,
+					ieeeAddrResponse.nwk_addr,
+					ieeeAddrResponse.num_assoc_dev,
+					ieeeAddrResponse.start_index,
+					ieeeAddrResponse.nwk_addr_assoc_dev_list
+			);
+#endif
+			zbifCbs->ZDO_IEEE_ADDR_confirm (
+					zbif_handle,
+					ieeeAddrResponse.status,
+					ieeeAddrResponse.ieee_addr,
+					ieeeAddrResponse.nwk_addr,
+					ieeeAddrResponse.num_assoc_dev,
+					ieeeAddrResponse.start_index,
+					ieeeAddrResponse.nwk_addr_assoc_dev_list
+			);
+		} else
+		{
+			// Update ieeeAddrResponse data structure
+			ieeeAddrResponse.neighborCount = neighborCount;//
+			ieeeAddrResponse.neighborIndex = 0;// Index of the neighbor ZB router is going to be considered
+
+			// Update the actual number of associated devices
+			ieeeAddrResponse.num_assoc_dev = ieeeAddrResponse.num_assoc_dev + ieeeAddrResponse.neighborCount;
+
+			// Update the list of associated devices
+			ushort * tmp_endDevice_list = (ushort *) malloc ((int)(ieeeAddrResponse.endDeviceCount) * sizeof(ushort));
+			memcpy(tmp_endDevice_list, ieeeAddrResponse.nwk_addr_assoc_dev_list, (int)(ieeeAddrResponse.endDeviceCount) * sizeof(ushort));
+			if (ieeeAddrResponse.nwk_addr_assoc_dev_list != NULL)
+			{
+				free(ieeeAddrResponse.nwk_addr_assoc_dev_list);
+			}
+			ieeeAddrResponse.nwk_addr_assoc_dev_list = (ushort *) malloc ((int)(ieeeAddrResponse.num_assoc_dev) * sizeof(ushort));
+			memcpy(ieeeAddrResponse.nwk_addr_assoc_dev_list, tmp_endDevice_list, (int)(ieeeAddrResponse.endDeviceCount) * sizeof(ushort));
+			free(tmp_endDevice_list); // Free temp variable
+
+			uchar *pOut;
+			EmberStatus reqStatus;
+			pOut = out_buf;
+
+			// Get information concerning the ZB router neighbor identified by the current value of ieeeAddrResponse.neighborIndex
+			// -> Send EZSP_GET_NEIGHBOR message
+			*pOut++ = ezspSequence++;
+			*pOut++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+			*pOut++ = EZSP_GET_NEIGHBOR;
+			*pOut++ = ieeeAddrResponse.neighborIndex;
+			reqStatus = zb_conn_send(zb_conn_h, out_buf, pOut - out_buf);
+
+			zb_print("EZSP_ReceiveCb - Send EZSP_GET_NEIGHBOR message\n");
+
+		}
+#endif		//IEEE_ADDR_REQUEST_PATCH
+
+	}
+		break;
+
+	case EZSP_GET_NEIGHBOR: {
+
+		zb_print(
+				"EZSP_ReceiveCb - EZSP_GET_NEIGHBOR message: response received\n");
+
+#ifdef IEEE_ADDR_REQUEST_PATCH
+
+		// Update nwk_addr_assoc_dev_list
+		int count = (int)(ieeeAddrResponse.endDeviceCount) + ieeeAddrResponse.neighborIndex;
+		ieeeAddrResponse.nwk_addr_assoc_dev_list[count] = p[1] | (p[2] << 8);
+
+		// Update neighborIndex
+		ieeeAddrResponse.neighborIndex++;
+
+		if (ieeeAddrResponse.neighborIndex == ieeeAddrResponse.neighborCount )
+		{
+			// All the required information has been obtained -> Send IEEE ADDR confirm to the higher layer
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_IEEE_ADDR_confirm (
+					ieeeAddrResponse.status,
+					ieeeAddrResponse.ieee_addr,
+					ieeeAddrResponse.nwk_addr,
+					ieeeAddrResponse.num_assoc_dev,
+					ieeeAddrResponse.start_index,
+					ieeeAddrResponse.nwk_addr_assoc_dev_list
+			);
+#endif
+
+			zbifCbs->ZDO_IEEE_ADDR_confirm (
+					zbif_handle,
+					ieeeAddrResponse.status,
+					ieeeAddrResponse.ieee_addr,
+					ieeeAddrResponse.nwk_addr,
+					ieeeAddrResponse.num_assoc_dev,
+					ieeeAddrResponse.start_index,
+					ieeeAddrResponse.nwk_addr_assoc_dev_list
+			);
+		} else
+		{
+			uchar *pOut;
+			EmberStatus reqStatus;
+			pOut = out_buf;
+
+			// Get information concerning the ZB router neighbor identified by the current value of ieeeAddrResponse.neighborIndex			
+			// -> Send EZSP_GET_NEIGHBOR message
+			*pOut++ = ezspSequence++;
+			*pOut++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+			*pOut++ = EZSP_GET_NEIGHBOR;
+			*pOut++ = ieeeAddrResponse.neighborIndex;
+			reqStatus = zb_conn_send(zb_conn_h, out_buf, pOut - out_buf);
+
+			zb_print("EZSP_ReceiveCb - Send EZSP_GET_NEIGHBOR message\n");
+		}
+#endif		//IEEE_ADDR_REQUEST_PATCH
+	}
+		break;
+
+	case EZSP_SET_CONFIGURATION_VALUE: /* 0x53 */
+		zb_print("STATE %d\n", state);
+		switch (state) {
+		case 1: {
+			zb_print("Setting route table size\n");
+#if 0
+			EmberNetworkParameters networkParams;
+			ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+			EmberNodeType nodeType;
+			int8u extendedPanId[EXTENDED_PAN_ID_SIZE] = APP_EXTENDED_PANID;
+			EzspStatus ezspStat;
+#endif
+			EmberStatus status;
+
+			p = out_buf;
+
+			/* Send EZSP ezspSetConfigurationValue command */
+			*p++ = ezspSequence++;
+			*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+			*p++ = EZSP_SET_CONFIGURATION_VALUE;
+			*p++ = EZSP_CONFIG_SOURCE_ROUTE_TABLE_SIZE;
+
+			ushort value = 8;
+			*p++ = LSB_USHORT(value);
+			*p++ = MSB_USHORT(value);
+
+			((zbif_status_t *) zbif_handle)->state++;
+
+			/* sends the command */
+			status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+			break;
+		}
+
+		case 2: {
+			zb_print("setting policy\n");
+			zb_print("\r\nINIT: sink app ");
+			zb_print("\r\n");
+			EmberStatus status;
+
+			p = out_buf;
+
+			/* Send EZSP ezspSetPolicy() command */
+			*p++ = ezspSequence++;
+			*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+			*p++ = EZSP_SET_POLICY;
+			*p++ = EZSP_UNICAST_REPLIES_POLICY;
+			*p++ = EZSP_HOST_WILL_NOT_SUPPLY_REPLY;
+
+			((zbif_status_t *) zbif_handle)->state++;
+
+			/* sends the command */
+			status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+			break;
+		}
+			/*
+			 case ZB_ATTR_CONFIG_SECURITY_LEVEL:
+			 case EZSP_CONFIG_TRUST_CENTER_ADDRESS_CACHE_SIZE:
+			 //Autogenerate a success response!
+			 if (zbifCbs->APSME_SET_confirm) {
+			 zbifCbs->APSME_SET_confirm (zbif_handle, *p++, 0x00);
+			 }
+			 break;
+			 */
+		default: {
+
+			/* 
+			 * This response response is not considered during the 
+			 * startup phase (the loop managed internally in ezsp_if.c
+			 */
+			if (zbifCbs->APSME_SET_confirm) {
+				zbifCbs->APSME_SET_confirm(zbif_handle, *p++, state);
+			}
+		}
+		}
+		break;
+
+	case EZSP_SET_POLICY:
+		zb_print("STATE %d\n", state);
+
+		if (setPolicyActive == TRUE) {
+			setPolicyActive = FALSE;
+
+			if (zbifCbs->APSME_SET_confirm) {
+				zbifCbs->APSME_SET_confirm(zbif_handle, *p++, state);
+			}
+			break;
+		}
+
+		switch (state) {
+		case 3: {
+			zb_print("get network parameters\n");
+			EmberStatus status;
+
+			p = out_buf;
+
+			/* Send EZSP ezspSetConfigurationValue command */
+			*p++ = ezspSequence++;
+			*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+			*p++ = EZSP_GET_NETWORK_PARAMETERS;
+
+			((zbif_status_t *) zbif_handle)->state++;
+
+			/* sends the command */
+			status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+			break;
+		}
+		}
+		break;
+
+	case EZSP_SET_KEY_TABLE_ENTRY: //EZSP setKeyTableEntry - Response
+	{
+		zb_print("STATE %d\n", state);
+
+		if (zbifCbs->APSME_SET_confirm) {
+			zbifCbs->APSME_SET_confirm(zbif_handle, *p++, state);
+		}
+	}
+		break;
+
+	case EZSP_ERASE_KEY_TABLE_ENTRY: //EZSP eraseKeyTableEntry - Response
+	{
+		zb_print("STATE %d\n", state);
+
+		if (zbifCbs->APSME_SET_confirm) {
+			zbifCbs->APSME_SET_confirm(zbif_handle, *p++, state);
+		}
+
+	}
+		break;
+
+	case EZSP_GET_NETWORK_PARAMETERS:
+		switch (state) {
+		case 4: {
+			//EmberNetworkParameters networkParams;
+			ZB_CONN_HANDLE zb_conn_h =
+					((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+			//EmberNodeType nodeType;
+			int8u extendedPanId[EXTENDED_PAN_ID_SIZE];
+			EzspStatus ezspStat;
+			zb_print("received network parameters\n");
+			EmberStatus status;
+
+			status = *p++; // TODO: Check status and use it accordingly
+			uchar node_type = *p++;
+
+			zb_print("status %d\n", status);
+			zb_print("NODE type %d\n", node_type);
+
+			memcpy(extendedPanId, p, EXTENDED_PAN_ID_SIZE);
+			p += EXTENDED_PAN_ID_SIZE;
+
+			ushort pan_id = *p | (*(p + 1) << 8);
+			p += 2;
+			uchar tx_power = *p++;
+			uchar channel = *p++;
+
+			zb_print("Channel %d\n", channel);
+
+			if (securityLevel == 5) {
+				switch (DevType) {
+				case EMBER_COORDINATOR: {
+					zb_print("Setting security for COORDINATOR");
+					zaSecurityTrustCenterInit(zbif_handle);
+				}
+					break;
+
+				default: {
+					zb_print("Setting security for ROUTER/END DEVICE");
+					zaSecurityInit(zbif_handle);
+				}
+				}
+				return;
+			}
+
+			// bring the network up.
+			// use hardcoded settings
+			p = out_buf;
+
+			// Send EZSP formNetwork command
+			*p++ = ezspSequence++;
+			*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+
+			if (DevType == EMBER_COORDINATOR) {
+				*p++ = EZSP_FORM_NETWORK;
+				// marshal g_networkParams
+				memcpy(p, g_networkParams.extendedPanId, EXTENDED_PAN_ID_SIZE);
+				p += EXTENDED_PAN_ID_SIZE;
+				*p++ = LSB_USHORT(g_networkParams.panId);
+				*p++ = MSB_USHORT(g_networkParams.panId);
+				*p++ = g_networkParams.radioTxPower;
+				*p++ = g_networkParams.radioChannel;
+				zb_print(
+						"gal: forming network - channel 0x%x, panid 0x%2x\n", g_networkParams.radioChannel, g_networkParams.panId);
+			} else {
+				*p++ = EZSP_JOIN_NETWORK; // 0x1F
+				*p++ = DevType;
+				// marshal g_networkParams
+				memcpy(p, g_networkParams.extendedPanId, EXTENDED_PAN_ID_SIZE);
+				p += EXTENDED_PAN_ID_SIZE;
+				//With 0xFFFF (default value) it shall joins to any network!
+				*p++ = 0xFF;
+				*p++ = 0xFF;
+				//*p++ = LSB_USHORT(g_networkParams.panId);
+				//*p++ = MSB_USHORT(g_networkParams.panId);
+				*p++ = g_networkParams.radioTxPower;
+				*p++ = g_networkParams.radioChannel;
+				zb_print(
+						"EZSP_GET_NETWORK_PARAMETERS - joining network - channel 0x%x, panid 0x%2x\n", g_networkParams.radioChannel, 0xFFFF);
+			}
+
+			((zbif_status_t *) zbif_handle)->state++;
+
+			// sends the command
+			status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+
+		}
+			break;
+
+		}
+		break;
+
+	case 0x68: //Ember setInitialSecurityState ID - Response
+	{
+		EmberStatus status;
+		p = out_buf;
+
+		// Send EZSP formNetwork command
+		*p++ = ezspSequence++;
+		*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+
+		if (DevType == EMBER_COORDINATOR) {
+			*p++ = EZSP_FORM_NETWORK;
+			// marshal g_networkParams
+			memcpy(p, g_networkParams.extendedPanId, EXTENDED_PAN_ID_SIZE);
+			p += EXTENDED_PAN_ID_SIZE;
+			*p++ = LSB_USHORT(g_networkParams.panId);
+			*p++ = MSB_USHORT(g_networkParams.panId);
+			*p++ = g_networkParams.radioTxPower;
+			*p++ = g_networkParams.radioChannel;
+			zb_print(
+					"gal: forming network - channel 0x%x, panid 0x%2x\n", g_networkParams.radioChannel, g_networkParams.panId);
+		} else {
+			*p++ = EZSP_JOIN_NETWORK; // 0x1F
+			*p++ = DevType;
+			// marshal g_networkParams
+			memcpy(p, g_networkParams.extendedPanId, EXTENDED_PAN_ID_SIZE);
+			p += EXTENDED_PAN_ID_SIZE;
+			//With 0xFFFF (default value) it shall joins to any network!
+			*p++ = 0xFF;
+			*p++ = 0xFF;
+			//*p++ = LSB_USHORT(g_networkParams.panId);
+			//*p++ = MSB_USHORT(g_networkParams.panId);
+			*p++ = g_networkParams.radioTxPower;
+			*p++ = g_networkParams.radioChannel;
+			zb_print(
+					"ezsp_if.c - setInitialSecurityState - joining network with channel 0x%02x, PanId 0x%2x\n", g_networkParams.radioChannel, 0xFFFF);
+		}
+
+		((zbif_status_t *) zbif_handle)->state++;
+
+		// sends the command
+		status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+	}
+		break;
+
+	case EZSP_SCAN_AND_FORM_NETWORK:
+	case EZSP_FORM_NETWORK:
+		switch (state) {
+		case 5: {
+			EmberStatus status;
+			status = *p++;
+
+			zb_print("allow joining\n");
+			// turn allow join on
+
+			p = out_buf;
+
+			/* Send EZSP ezspSetConfigurationValue command */
+			*p++ = ezspSequence++;
+			*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+			*p++ = EZSP_PERMIT_JOINING;
+
+			*p++ = 0xFF; /* duration */
+
+			((zbif_status_t *) zbif_handle)->state++;
+
+			/* sends the command */
+			status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+			break;
+		}
+		}
+		break;
+
+	case EZSP_PERMIT_JOINING:
+		switch (state) {
+		case 6: {
+			EmberStatus status;
+			status = *p++;
+			zb_print("PERMIT JOINING returned\n");
+
+			// TODO: translate status!!!!
+			localShortAddr = 0x0000;
+
+			zbifCbs->ZDO_START_confirm(zbif_handle, status, localShortAddr);
+
+			break;
+		}
+		}
+		break;
+
+	case EZSP_JOIN_NETWORK: /* Join network	(0x1F) */
+	{
+		EmberStatus status;
+		status = *p++;
+
+		zb_print(
+				"EZSP_ReceiveCb - Join Network response received - status = %02x\n", status);
+
+		if (status != EMBER_SUCCESS) {
+			zb_print(
+					"EZSP_ReceiveCb - Join Network - status != EMBER_SUCCESS\n", status);
+
+			// TODO: translate status!!!!
+			localShortAddr = 0xFFFF; // dummy Error Address
+
+			// Call ZDO_START_confirm
+			zbifCbs->ZDO_START_confirm(zbif_handle, status, localShortAddr);
+		} else {
+			zb_print(
+					"EZSP_ReceiveCb - Join Network - status = EMBER_SUCCESS\n", status);
+		}
+
+	}
+		break;
+
+	case EZSP_STACK_STATUS_HANDLER: // stackStatusHandler  (0x19)
+	{
+
+		EmberStatus status;
+		status = *p++;
+
+		zbifCbs->ZIGBEE_STACK_STATUS_indication(zbif_handle, status);
+
+		switch (state) {
+		case 5: {
+			zb_print("EZSP_ReceiveCb - stackStatusHandler called\n");
+
+			if (status != EMBER_NETWORK_UP) {
+				zb_print(
+						"EZSP_ReceiveCb - stackStatusHandler - status != EMBER_NETWORK_UP\n");
+
+				// TODO: translate status!!!!
+				localShortAddr = 0xFFFF; // dummy Error Address
+
+				// Call ZDO_START_confirm
+				zbifCbs->ZDO_START_confirm(zbif_handle, status, localShortAddr);
+			} else {
+				zb_print(
+						"EZSP_ReceiveCb - stackStatusHandler - status = EMBER_NETWORK_UP\n");
+
+				p = out_buf;
+
+				// Send EZSP getNodeid command to obtain the node address
+				*p++ = ezspSequence++;
+				*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+				*p++ = EZSP_GET_NODE_ID;
+
+				((zbif_status_t *) zbif_handle)->state++;
+
+				// sends the command
+				status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+			}
+
+		}
+		}
+
+	}
+		break;
+
+	case EZSP_GET_EUI64: {
+		zb_print("EZSP_ReceiveCb - getEui64 response received\n");
+		localIeeeAddr[0] = *p;
+		localIeeeAddr[1] = (*(p + 1));
+		localIeeeAddr[2] = (*(p + 2));
+		localIeeeAddr[3] = (*(p + 3));
+		localIeeeAddr[4] = (*(p + 4));
+		localIeeeAddr[5] = (*(p + 5));
+		localIeeeAddr[6] = (*(p + 6));
+		localIeeeAddr[7] = (*(p + 7));
+		p += 8;
+
+		zb_print(
+				"EZSP_ReceiveCb - getEui64 response - IEEEAddress = 0x%16X\n", localIeeeAddr);
+
+		// Call APSME_GET_confirm
+		zbifCbs->APSME_GET_confirm(zbif_handle, 0, ZB_ATTR_GET_EUI64, 8,
+				(uchar *) localIeeeAddr);
+	}
+		break;
+
+	case EZSP_GET_NODE_ID: // getNodeid response  (0x17)
+	{
+		switch (state) {
+		case 6: {
+			zb_print("EZSP_ReceiveCb - getNodeid response received\n");
+			//ushort nwk_addr = *p + (*(p + 1) << 8); p += 2;
+			localShortAddr = *p + (*(p + 1) << 8);
+			p += 2;
+
+			zb_print(
+					"EZSP_ReceiveCb - getNodeid response - nwk_addr = 0x%04X\n", localShortAddr);
+
+			// Call ZDO_START_confirm
+			zbifCbs->ZDO_START_confirm(zbif_handle, 0, localShortAddr);
+		}
+		}
+
+	}
+		break;
+
+	case EZSP_SEND_UNICAST: {
+		EmberStatus status;
+		status = *p++;
+		if (status != EZSP_ASH_NO_ERROR) {
+			zb_print("send unicast returned error 0x%02x\n", status);
+		}
+	}
+		break;
+#if 0
+
+		case EZSP_DEBUG_HANDLER: {
+			int8u messageLength;
+			int8u *messageContents;
+			messageLength = fetchInt8u();
+			messageContents = serialInt8uArrayResponse(EZSP_PARAMETERS_INDEX + parameterIndex, messageLength);
+			parameterIndex += messageLength * sizeof(int8u);
+			ezspDebugHandler(messageLength, messageContents);
+			break;
+		}
+
+		case EZSP_STACK_STATUS_HANDLER: {
+			int8u status;
+			status = fetchInt8u();
+			ezspStackStatusHandler(status);
+			break;
+		}
+
+		case EZSP_ENERGY_SCAN_RESULT_HANDLER: {
+			int8u channel;
+			int8u maxRssiValue;
+			channel = fetchInt8u();
+			maxRssiValue = fetchInt8u();
+			ezspEnergyScanResultHandler(channel, maxRssiValue);
+			break;
+		}
+
+		case EZSP_NETWORK_FOUND_HANDLER: {
+			EmberZigbeeNetwork networkFound;
+			int8u lastHopLqi;
+			int8s lastHopRssi;
+			fetchEmberZigbeeNetwork(&networkFound);
+			lastHopLqi = fetchInt8u();
+			lastHopRssi = fetchInt8u();
+			ezspNetworkFoundHandler(&networkFound, lastHopLqi, lastHopRssi);
+			break;
+		}
+
+		case EZSP_SCAN_COMPLETE_HANDLER: {
+			int8u channel;
+			int8u status;
+			channel = fetchInt8u();
+			status = fetchInt8u();
+			ezspScanCompleteHandler(channel, status);
+			break;
+		}
+
+		case EZSP_SCAN_ERROR_HANDLER: {
+			int8u status;
+			status = fetchInt8u();
+			ezspScanErrorHandler(status);
+			break;
+		}
+#endif
+
+#if 0 /* disabled because using actual ANNCE indication from telegesis */
+
+		case EZSP_CHILD_JOIN_HANDLER: {
+			uchar ieee_addr[IEEE_ADDR_LEN];
+
+			uchar index = *p++;
+			uchar joining = *p++;
+			ushort nwk_addr = *p + (*(p + 1) << 8); p += 2;
+
+			memcpy(ieee_addr, p, IEEE_ADDR_LEN); p += IEEE_ADDR_LEN;
+			swap_bytes(ieee_addr, IEEE_ADDR_LEN);
+			uchar child_type = *p++;
+
+			if (zbifCbs->ZDO_DEVICE_ANNCE_indication) {
+#ifdef DEBUG_ZIGBEE_API
+				ZBPrint_ZDO_DEVICE_ANNCE_indication (
+						nwk_addr,
+						ieee_addr,
+						child_type
+				);
+#endif
+				zbifCbs->ZDO_DEVICE_ANNCE_indication (
+						zbif_handle,
+						nwk_addr,
+						ieee_addr,
+						child_type
+				);
+
+			}
+			break;
+		}
+#endif
+
+#if 0
+
+		case EZSP_REMOTE_SET_BINDING_HANDLER: {
+			EmberBindingTableEntry entry;
+			int8u index;
+			int8u policyDecision;
+			fetchEmberBindingTableEntry(&entry);
+			index = fetchInt8u();
+			policyDecision = fetchInt8u();
+			ezspRemoteSetBindingHandler(&entry, index, policyDecision);
+			break;
+		}
+
+		case EZSP_REMOTE_DELETE_BINDING_HANDLER: {
+			int8u index;
+			int8u policyDecision;
+			index = fetchInt8u();
+			policyDecision = fetchInt8u();
+			ezspRemoteDeleteBindingHandler(index, policyDecision);
+			break;
+		}
+#endif
+
+	case EZSP_MESSAGE_SENT_HANDLER: {
+		zb_print("Receive - EZSP message sent handler!\n");
+
+#ifdef ZIGBEE_APS_FRAG_ENABLED
+		uchar type;
+
+		uchar *dst_addr_p = NULL;
+		uchar *src_addr_p = NULL;
+
+		uchar was_broadcast = 0;
+		uchar sec_status = 0;
+
+		type = *p++;
+		zb_print ("type = %d\n", (int) type);
+
+		ushort indexOrDestination = *p | (*(p + 1) << 8); p += 2;
+
+		/* read APS header = EmberApsFrame */
+		ushort profile_id = *p | (*(p + 1) << 8); p += 2;
+		ushort cluster_id = *p | (*(p + 1) << 8); p += 2;
+		uchar src_ep = *p++;
+		uchar dst_ep = *p++;
+		ushort options = *p | (*(p + 1) << 8); p += 2;
+		ushort group_id = *p | (*(p + 1) << 8); p += 2;
+		uchar sequence = *p++;
+
+		zb_print ("options %04x\n", options);
+		zb_print ("group_id %04x\n", group_id);
+		zb_print ("sequence %02x\n", sequence);
+
+		EmberApsFrame apsFrame;
+		apsFrame.profileId = profile_id;
+		apsFrame.clusterId = cluster_id;
+		apsFrame.sourceEndpoint = src_ep;
+		apsFrame.destinationEndpoint = dst_ep;
+		apsFrame.options = options;
+		apsFrame.groupId = group_id;
+		apsFrame.sequence = sequence;
+		/* - EmberApsFrame - ------------------- */
+
+		uchar messageTag = *p++;
+		EmberStatus status = *p++;
+
+		zb_print ("profile_id %04x\n", profile_id);
+		zb_print ("cluster_id %04x\n", cluster_id);
+
+		// Note: uncomment it to emulate Ember Success even if NO APS ACK has been received
+		// status = EMBER_SUCCESS;
+
+		if (ezspIsOutgoingFragment(zbif_handle, &apsFrame, status)) {
+			return;
+		}
+
+#endif /* ZIGBEE_APS_FRAG_ENABLED */
+
+		break;
+	}
+
+	default:
+		return;
+	}
+
+	return;
+}
+
+void EZSP_Autogen(ZBIF_HANDLE zbif_handle, uchar *data, const int size) {
+	int type;
+	uchar *p;
+
+	if (zbif_handle == NULL) {
+		return;
+	}
+
+	ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+	if (zbifCbs == NULL) {
+		/* error! */
+		return;
+	}
+
+	ZB_LOG(zb_print_bytes("EZSP_Autogen ", data, size));
+
+	p = data;
+	type = *p + (*(p + 1) << 8);
+	p += 2;
+
+	switch (type) {
+
+	case 0:
+		if (zbifCbs->ZDO_RESET_confirm) {
+			zbifCbs->ZDO_RESET_confirm(zbif_handle, p[0], restartGW);
+		}
+		break;
+
+	case 1: /* APSME_SET_confirm() */
+		if (zbifCbs->APSME_SET_confirm) {
+			zbifCbs->APSME_SET_confirm(zbif_handle, p[0], p[1]);
+		}
+		break;
+	}
+}
+
+ZBIFFunctions_t zbEzspFunctions = { EZSP_ZDO_RESET_request,
+		EZSP_ZDO_START_request, EZSP_ZDO_NWK_ADDR_request,
+		EZSP_ZDO_IEEE_ADDR_request, EZSP_ZB_MGMT_LQI_request,
+		EZSP_ZDO_NODE_DESC_request, EZSP_ZDO_POWER_DESC_request,
+		EZSP_ZDO_SIMPLE_DESC_request, EZSP_ZDO_ACTIVE_EP_DESC_request,
+		EZSP_ZDO_MATCH_DESC_request, EZSP_ZDO_MATCH_DESC_response,
+		EZSP_ZDO_END_DEVICE_BIND_request, EZSP_APSDE_DATA_request,
+		EZSP_APSME_BIND_request, EZSP_APSME_UNBIND_request,
+		EZSP_APSME_GET_request, EZSP_APSME_SET_request,
+		EZSP_MGMT_PERMIT_JOINING_request,
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+		EZSP_APSME_REMOVE_DEVICE_request,
+		EZSP_APSME_TRANSPORT_KEY_request,
+		EZSP_MGMT_LEAVE_request,
+#endif
+
+		EZSP_ZDO_ERROR_response };
+
+#ifdef ZIGBEE_APS_FRAG_ENABLED
+
+// A message can be broken into at most this many pieces.
+#define MAX_TOTAL_BLOCKS 10
+
+#define ZIGBEE_APSC_MAX_TRANSMIT_RETRIES 3
+
+//------------------------------------------------------------------------------
+// Forward declarations.
+
+static EmberStatus sendNextFragments(ZBIF_HANDLE zbif_handle);
+static void abortTransmission(EmberStatus status);
+static void abortReception(void);
+
+//------------------------------------------------------------------------------
+// Initialization
+
+static int16u receptionTimeout;
+static int8u windowSize;
+static int8u *receiveMessage;
+static int16u receiveMessageMaxLength = 0;
+
+void ezspFragmentInit(int16u receiveBufferLength, int8u *receiveBuffer)
+{
+	//int16u temp;
+	receiveMessageMaxLength = receiveBufferLength;
+	receiveMessage = receiveBuffer;
+	zb_print("\nezspFragmentInit - receiveMessageMaxLength = %d\n",receiveMessageMaxLength);
+
+	memset (receiveMessage, 0, receiveBufferLength);
+
+	//ezspGetConfigurationValue(EZSP_CONFIG_APS_ACK_TIMEOUT, &receptionTimeout);			//TODO	Implement this?
+	//ezspGetConfigurationValue(EZSP_CONFIG_FRAGMENT_WINDOW_SIZE, &temp);				//TODO	Implement this?
+	receptionTimeout = 1600;
+	windowSize = 1;//TODO	This value should be dynamically obtained!!!
+
+	zb_print("ezspFragmentInit - EZSP_CONFIG_APS_ACK_TIMEOUT = %d\n",receptionTimeout);
+	zb_print("ezspFragmentInit - EZSP_CONFIG_FRAGMENT_WINDOW_SIZE = %d\n",windowSize);
+}
+
+EmberStatus ezspFragmentSourceRouteHandler(void)
+{
+	zb_print("ezspFragmentSourceRouteHandler");
+
+//TODO
+	/*
+	 if (globalFragmentSourceRouteInfoValid) { 
+	 return ezspSetSourceRoute(globalFragmentSourceRouteDestination,
+	 globalFragmentSourceRouteRelayCount,
+	 globalFragmentSourceRouteRelayList);
+	 }
+	 // it is ok to not have a source route
+	 */
+
+	return EMBER_SUCCESS;
+}
+
+void ezspFragmentedMessageSentHandler(EmberStatus status)
+{
+	zb_print("\nezspFragmentedMessageSentHandler ------->  status = %d \n", status);
+	// the source route we used is not valid for the next fragmented message
+	globalFragmentSourceRouteInfoValid = FALSE;
+
+	// the fragmented message is no longer in process
+	fragmentedMessageInProcess = FALSE;
+
+}
+
+//------------------------------------------------------------------------------
+// Sending
+
+// Information needed to actually send the messages.
+static EmberOutgoingMessageType fragmentOutgoingType = 0xFF;
+static int16u fragmentIndexOrDestination;
+static EmberApsFrame fragmentApsFrame;
+static int8u totalTxBlocks;
+static int8u txWindowBase;
+static int8u txFragments[MAX_TOTAL_BLOCKS];
+static int8u *sendMessage;
+static int8u blocksInTransit;// How many payloads are in the air.
+
+EmberStatus ezspSendFragmentedMessage(
+		ZBIF_HANDLE zbif_handle,
+		EmberOutgoingMessageType type,
+		int16u indexOrDestination,
+		EmberApsFrame *apsFrame,
+		int8u maxFragmentSize,
+		int8u messageLength,
+		int8u *messageContents
+)
+{
+	EmberStatus status;
+
+	int8u remainingLength = messageLength;
+	if (messageLength == 0 || windowSize == 0) {
+		return EMBER_INVALID_CALL;
+	}
+	abortTransmission(EMBER_ERR_FATAL); // Clear out any existing traffic.
+	fragmentOutgoingType = type;
+	fragmentIndexOrDestination = (ushort) indexOrDestination;
+	MEMCOPY(&fragmentApsFrame, apsFrame, sizeof(EmberApsFrame));
+
+	sendMessage = (int8u *) malloc ((int)messageLength * sizeof(int8u));
+	memcpy(sendMessage, messageContents, (int)messageLength);
+
+	totalTxBlocks = 0;
+	while (remainingLength > 0 && totalTxBlocks < MAX_TOTAL_BLOCKS) {
+		if (remainingLength > maxFragmentSize) {
+			txFragments[totalTxBlocks] = maxFragmentSize;
+		} else {
+			txFragments[totalTxBlocks] = remainingLength;
+		}
+		remainingLength -= txFragments[totalTxBlocks];
+		totalTxBlocks++;
+	}
+	if (remainingLength > 0) {
+		fragmentOutgoingType = 0xFF;
+		return EMBER_MESSAGE_TOO_LONG;
+	}
+	fragmentApsFrame.options |= (EMBER_APS_OPTION_FRAGMENT
+			| EMBER_APS_OPTION_RETRY);
+
+	//TODO: TO BE REMOVED????
+	fragmentApsFrame.options |= (EMBER_APS_OPTION_ENABLE_ROUTE_DISCOVERY |
+			EMBER_APS_OPTION_ENABLE_ADDRESS_DISCOVERY);
+
+	zb_print("ezspSendFragmentedMessage - fragmentApsFrame.sequence  = %d\n", fragmentApsFrame.sequence);
+
+	txWindowBase = 0;
+	blocksInTransit = 0;
+	status = sendNextFragments(zbif_handle);
+	if (status != EMBER_SUCCESS) {
+		zb_print("ezspSendFragmentedMessage - status = %d\n", status);
+		fragmentOutgoingType = 0xFF;
+	}
+	return status;
+}
+
+boolean ezspIsOutgoingFragment(
+		ZBIF_HANDLE zbif_handle,
+		EmberApsFrame *apsFrame,
+		EmberStatus status)
+{
+	if (apsFrame->options & EMBER_APS_OPTION_FRAGMENT) {
+		if (status == EMBER_SUCCESS) {
+
+			fragmentApsFrame.sequence = apsFrame->sequence;
+			zb_print("ezspIsOutgoingFragment - Update fragmentApsFrame.sequence = %02x\n", fragmentApsFrame.sequence);
+
+			blocksInTransit -= 1;
+			if (blocksInTransit == 0) {
+				txWindowBase += windowSize;
+				zb_print("ezspIsOutgoingFragment - status = %d -> call abortTransmission(sendNextFragments)\n",status);
+				abortTransmission(sendNextFragments(zbif_handle));
+			}
+		} else {
+			zb_print("ezspIsOutgoingFragment - status = %d -> call abortTransmission\n",status);
+			abortTransmission(status);
+		}
+		return TRUE;
+	} else
+	return FALSE;
+}
+
+static EmberStatus sendNextFragments(
+		ZBIF_HANDLE zbif_handle
+)
+{
+	int8u i;
+	int8u index = 0;
+	// Move the message index to the start of the first fragment to be sent.
+	for (i = 0; i < txWindowBase; i++) {
+		index += txFragments[i];
+	}
+	// Send fragments until the window is full.
+	for (i = txWindowBase; i - txWindowBase < windowSize && i < totalTxBlocks; i++) {
+		EmberStatus status = ezspFragmentSourceRouteHandler();
+		fragmentApsFrame.groupId = HIGH_LOW_TO_INT(totalTxBlocks, i);
+		if (status == EMBER_SUCCESS) {
+
+			zb_print("\nfragmentIndexOrDestination = %02X ******\n",(ushort)fragmentIndexOrDestination);
+
+			/*
+			 status = ezspSendUnicast(fragmentOutgoingType,
+			 (ushort)fragmentIndexOrDestination,
+			 &fragmentApsFrame,
+			 i,
+			 txFragments[i],
+			 sendMessage + index,
+			 &fragmentApsFrame.sequence);
+			 */
+
+			ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+			uchar *p;
+			p = out_buf;
+
+			*p++ = ezspSequence++;
+			*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+
+			// dst address is a short address	
+			*p++ = EZSP_SEND_UNICAST;
+			*p++ = fragmentOutgoingType;// EmberOutgoingMessageType	
+
+			ushort dst = (ushort)fragmentIndexOrDestination;
+
+			*p++ = LSB_USHORT(dst);
+			*p++ = MSB_USHORT(dst);
+
+			// APS Frame 
+			*p++ = LSB_USHORT(fragmentApsFrame.profileId);
+			*p++ = MSB_USHORT(fragmentApsFrame.profileId);
+
+			*p++ = LSB_USHORT(fragmentApsFrame.clusterId);
+			*p++ = MSB_USHORT(fragmentApsFrame.clusterId);
+
+			*p++ = fragmentApsFrame.sourceEndpoint;
+			*p++ = fragmentApsFrame.destinationEndpoint;
+
+			*p++ = LSB_USHORT(fragmentApsFrame.options);
+			*p++ = MSB_USHORT(fragmentApsFrame.options);
+
+			*p++ = LSB_USHORT(fragmentApsFrame.groupId);
+			*p++ = MSB_USHORT(fragmentApsFrame.groupId);
+			// End of Aps Frame
+
+			*p++ = fragmentApsFrame.sequence;// Sequence 
+			zb_print("EmberStatus sendNextFragments - fragmentApsFrame.sequence = %02x\n", fragmentApsFrame.sequence);
+
+			*p++ = i;// message tag 
+			*p++ = txFragments[i];//  message length
+
+			if (txFragments[i] > 0) {
+				memcpy(p, sendMessage + index, txFragments[i]);
+				p += txFragments[i];
+			}
+
+			status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+		}
+
+		if (status == EMBER_SUCCESS) {
+			blocksInTransit += 1;
+		} else {
+			return status;
+		}
+		index += txFragments[i];
+	}
+	if (blocksInTransit == 0) {
+		zb_print("sendNextFragments - blocksInTransit == 0");
+		fragmentOutgoingType = 0xFF;
+
+		free(sendMessage);
+
+		ezspFragmentedMessageSentHandler(EMBER_SUCCESS);
+	}
+	return EMBER_SUCCESS;
+}
+
+static void abortTransmission(EmberStatus status)
+{
+	if (status != EMBER_SUCCESS
+			&& fragmentOutgoingType != 0xFF) {
+		fragmentOutgoingType = 0xFF;
+
+		free(sendMessage);
+
+		ezspFragmentedMessageSentHandler(status);
+	}
+}
+
+// These two are used to identify incoming blocks.
+static EmberNodeId fragmentSource = EMBER_NULL_NODE_ID;
+static int8u fragmentApsSequenceNumber;
+
+static int8u rxWindowBase;
+static int8u blockMask;// Mask to be sent in the next ACK.
+static int8u expectedRxBlocks;// How many are supposed to arrive.
+static int8u blocksReceived;// How many have arrived.
+static int8u rxFragments[MAX_TOTAL_BLOCKS];
+
+//static boolean runTimer = FALSE;
+static int16u lastRxTime;
+
+// A mask with the low n bits set.
+#define lowBitMask(n) ((1 << (n)) - 1)
+
+static void setBlockMask(void)
+{
+	// Unused bits must be 1.
+	int8u highestZeroBit = windowSize;
+	// If we are in the final window, there may be additional unused bits.
+	if (rxWindowBase + windowSize > expectedRxBlocks) {
+		highestZeroBit = (expectedRxBlocks % windowSize);
+	}
+	blockMask = ~ lowBitMask(highestZeroBit);
+}
+
+static void clearRxFragments(void)
+{
+	int8u i;
+	for (i = 0; i < MAX_TOTAL_BLOCKS; i++) {
+		rxFragments[i] = 0;
+	}
+
+	// Clean buffer
+	memset (receiveMessage, 0, receiveMessageMaxLength);
+}
+
+static void ezspMemCopy(void * destination, const void * source, size_t num )
+{
+	uchar * tmpMem = (uchar *) malloc ( (int)(num) * sizeof(uchar));
+	memcpy(tmpMem, source, num);
+	memcpy(destination, tmpMem, num);
+	free(tmpMem);
+}
+
+static boolean storeRxFragment(
+		int8u blockNumber,
+		int8u messageLength,
+		int8u *messageContents
+) {
+	int8u i;
+	int8u index = 0;
+
+	zb_print("storeRxFragment - ENTERED\n");
+
+	pthread_mutex_lock(&mux);
+	for (i = 0; i < blockNumber; i++) {
+		index += rxFragments[i];
+	}
+	pthread_mutex_unlock(&mux);
+
+	zb_print("storeRxFragment - index = %d - messageLength = %d - receiveMessageMaxLength = %d \n",index,messageLength,receiveMessageMaxLength);
+
+	if (index + messageLength > receiveMessageMaxLength) {
+		zb_print("storeRxFragment - index = %d - messageLength = %d - receiveMessageMaxLength = %d \n",index,messageLength,receiveMessageMaxLength);
+		zb_print("storeRxFragment - whole frag message length > MaxLength !! -> return FALSE\n");
+		return FALSE;
+	}
+
+	MEMCOPY(receiveMessage + index + messageLength,
+			receiveMessage + index,
+			receiveMessageMaxLength - (index + messageLength));
+	MEMCOPY(receiveMessage + index, messageContents, messageLength);
+	/*
+	 ezspMemCopy(receiveMessage + messageLength,
+	 receiveMessage,
+	 index);
+	 ezspMemCopy(receiveMessage + index, messageContents, messageLength);
+	 */
+
+	int count;
+	zb_print("\nstoreRxFragment - Fragment =\n");
+	for (count=0;count < (int) (index + messageLength);count++) {
+		zb_print("%02X",(int)(receiveMessage[count]));
+	}
+
+	zb_print("\nstoreRxFragment - Fragment END\n");
+
+	rxFragments[blockNumber] = messageLength;
+	return TRUE;
+}
+
+boolean ezspIsIncomingFragment(
+		ZBIF_HANDLE zbif_handle,
+		EmberApsFrame *apsFrame,
+		EmberNodeId sender,
+		int16u *messageLength,
+		int8u **messageContents
+)
+{
+	int8u blockNumber;
+	int8u mask;
+	boolean newBlock;
+
+	zb_print("ezspIsIncomingFragment\n");
+
+	// Check whether the received frame is a fragment
+	if (! (apsFrame->options & EMBER_APS_OPTION_FRAGMENT)) {
+		zb_print("ezspIsIncomingFragment - The considered APS FRAME is NOT a fragment! Process as usual!\n");
+		return FALSE; // Not a fragment, process as usual.
+	}
+
+	// Get block number
+	blockNumber = LOW_BYTE(apsFrame->groupId);
+	zb_print("ezspIsIncomingFragment - blockNumber = %04x\n",blockNumber);
+
+	// This section is considered when the first fragment is received
+	pthread_mutex_lock(&mux);
+	if (fragmentSource == EMBER_NULL_NODE_ID && blockNumber < windowSize) {
+		fragmentSource = sender;
+		fragmentApsSequenceNumber = apsFrame->sequence;
+		rxWindowBase = 0;
+		blocksReceived = 0;
+		expectedRxBlocks = 0xFF;
+		setBlockMask();
+		clearRxFragments();
+		//runTimer = TRUE;
+		lastRxTime = halCommonGetInt16uMillisecondTick();
+		zb_print("ezspIsIncomingFragment - First fragment rx - lastRxTime = %d *****************\n",lastRxTime);
+	}
+	pthread_mutex_unlock(&mux);
+
+	// A new fragment has been received -> cheack whether it actually refers to the current ZigBee APS transaction
+	// If not, drop the unexpected fragment !
+	if (! (sender == fragmentSource && apsFrame->sequence == fragmentApsSequenceNumber)) {
+		zb_print("ezspIsIncomingFragment - A - Drop unexpected fragments -> RETURN TRUE\n");
+		zb_print("ezspIsIncomingFragment - sender = %04X | frag source = %04X\n",sender,fragmentSource);
+		zb_print("ezspIsIncomingFragment - apsFrame->sequence = %04X | fragmentApsSequenceNumber = %04X\n",apsFrame->sequence,fragmentApsSequenceNumber);
+		return TRUE; // Drop unexpected fragments.
+	}
+
+	if (blockMask == 0xFF && rxWindowBase + windowSize <= blockNumber) {
+		rxWindowBase += windowSize;
+		setBlockMask();
+		//runTimer = TRUE;
+		lastRxTime = halCommonGetInt16uMillisecondTick();
+		zb_print("ezspIsIncomingFragment - B - lastRxTime = %d *****************\n",lastRxTime);
+	}
+
+	if (rxWindowBase + windowSize <= blockNumber) {
+		zb_print("ezspIsIncomingFragment - B - Drop unexpected fragments -> RETURN TRUE\n");
+		return TRUE; // Drop unexpected fragments.
+	}
+
+	// Remove timer, if any ...
+	if (timerContext.timerData != NULL)
+	{
+		killTimer(timerContext.timerData->timer , timerContext.timerData->eventId);
+
+		// Free memory allocated for timer management
+		free ((TimerThread *) timerContext.timerData->timer);
+		free (timerContext.timerData);
+		timerContext.timerData = NULL;
+	}
+
+	unsigned int *timer;
+	timer = setTimer(0, timerContext.fTimeout, (TIMERPROC) NULL);
+	if (timer == NULL) {
+		zb_print("ezspIsIncomingFragment - ERROR creating timer!\n");
+	}
+//*******************/
+
+	mask = 1 << (blockNumber % windowSize);
+	newBlock = ! (mask & blockMask);
+
+	if (blockNumber == 0) {
+		expectedRxBlocks = HIGH_BYTE(apsFrame->groupId);
+		zb_print("ezspIsIncomingFragment - blockNumber = %04x - expectedRxBlocks = %04x\n",blockNumber, expectedRxBlocks);
+
+		// Need to set unused bits in the window to 1.
+		// Previously a full window was assumed.
+		if ( expectedRxBlocks < windowSize )
+		setBlockMask();
+		if (expectedRxBlocks > MAX_TOTAL_BLOCKS)
+		{
+			// kickout;
+			abortReception();
+			return TRUE;
+		}
+	}
+
+	blockMask |= mask;
+	if (newBlock)
+	{
+		blocksReceived += 1;
+		if (!storeRxFragment(blockNumber, *messageLength, *messageContents))
+		{
+			// kickout;
+			abortReception();
+			return TRUE;
+		}
+	}
+
+	if (blockNumber == expectedRxBlocks - 1 || (blockMask | lowBitMask(blockNumber % windowSize)) == 0xFF)
+	{
+		apsFrame->groupId = HIGH_LOW_TO_INT(blockMask, rxWindowBase);
+
+//		ezspSendReply(sender, apsFrame, 0, NULL);
+		//SEND_REPLY!!!!
+
+		ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+		uchar *p;
+		p = out_buf;
+
+		*p++ = ezspSequence++;
+		*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+
+		*p++ = EZSP_SEND_REPLY;
+
+		ushort dst = (ushort)sender;
+		*p++ = LSB_USHORT(dst);
+		*p++ = MSB_USHORT(dst);
+		zb_print("ezspIsIncomingFragment - dst =%04x\n",dst);
+
+		// APS Frame 
+		*p++ = LSB_USHORT(apsFrame->profileId);
+		*p++ = MSB_USHORT(apsFrame->profileId);
+		zb_print("ezspIsIncomingFragment - apsFrame->profileId =%04x\n",apsFrame->profileId);
+
+		*p++ = LSB_USHORT(apsFrame->clusterId);
+		*p++ = MSB_USHORT(apsFrame->clusterId);
+		zb_print("ezspIsIncomingFragment - apsFrame->clusterId =%04x\n",apsFrame->clusterId);
+
+		*p++ = apsFrame->sourceEndpoint;
+		zb_print("ezspIsIncomingFragment - apsFrame->sourceEndpoint =%02x\n",apsFrame->sourceEndpoint);
+		*p++ = apsFrame->destinationEndpoint;
+		zb_print("ezspIsIncomingFragment - apsFrame->destinationEndpoint =%02x\n",apsFrame->destinationEndpoint);
+
+		apsFrame->options |= EMBER_APS_OPTION_RETRY;
+
+		*p++ = LSB_USHORT(apsFrame->options);
+		*p++ = MSB_USHORT(apsFrame->options);
+		zb_print("ezspIsIncomingFragment - apsFrame->options =%04x\n",apsFrame->options);
+
+		*p++ = LSB_USHORT(apsFrame->groupId);
+		*p++ = MSB_USHORT(apsFrame->groupId);
+		zb_print("ezspIsIncomingFragment - apsFrame->groupId =%02x\n",apsFrame->groupId);
+		// End of Aps Frame
+
+		*p++ = apsFrame->sequence;// Sequence 
+		zb_print("ezspIsIncomingFragment - apsFrame->sequence =%02x\n",apsFrame->sequence);
+
+		*p++ = 0;//  message length
+
+		zb_print("ezspIsIncomingFragmet - Send Reply\n");
+
+		zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+	}
+
+	// Last fragment received
+	if (blocksReceived == expectedRxBlocks)
+	{
+		zb_print("ezspIsIncomingFragment - blocksReceived == expectedRxBlocks -> RETURN FALSE\n");
+		if (timerContext.timerData != NULL)
+		{
+			// Remove timer!
+			killTimer(timerContext.timerData->timer , timerContext.timerData->eventId);
+
+			// Free memory allocated for timer management
+			free ((TimerThread *) timerContext.timerData->timer);
+			free (timerContext.timerData);
+			timerContext.timerData = NULL;
+		}
+
+		int8u i;
+		int16u length = 0;
+		for (i = 0; i < expectedRxBlocks; i++) {
+			length += rxFragments[i];
+		}
+		fragmentSource = EMBER_NULL_NODE_ID;
+		*messageLength = length;
+		*messageContents = receiveMessage;
+		apsFrame->options &= ~ EMBER_APS_OPTION_RETRY;
+		return FALSE;
+	}
+	return TRUE;
+
+}
+
+// Flush the current message if blocks stop arriving.
+static void abortReception(void)
+{
+	zb_print("abortReception\n");
+
+	pthread_mutex_lock(&mux);
+	//runTimer = FALSE;
+	zb_print("abortReception - AND HERE!\n");
+
+	if (fragmentSource != EMBER_NULL_NODE_ID) {
+		clearRxFragments();
+		fragmentSource = EMBER_NULL_NODE_ID;
+	}
+
+	pthread_mutex_unlock(&mux);
+}
+
+/*
+ void ezspFragmentTick(void)
+ {
+ if (runTimer) {
+ int16u now = halCommonGetInt16uMillisecondTick();
+ zb_print("ezspFragmentTick - now = %d *****************\n",now);		
+ if ((int16u)(now - lastRxTime) > receptionTimeout * ZIGBEE_APSC_MAX_TRANSMIT_RETRIES) {
+ abortReception();
+ }
+ }
+ }
+ */
+
+//======================
+
+int initTimers ( void )
+{
+	ThreadPoolAttr attr;
+
+	timerContext.timerData = NULL;
+	timerContext.fTimeout = receptionTimeout * ZIGBEE_APSC_MAX_TRANSMIT_RETRIES / 1000; // Seconds
+	zb_print("initTimers - timerContext.fTimeout = %d \n",timerContext.fTimeout);
+
+	TPAttrInit( &attr );
+	TPAttrSetMaxThreads(&attr, ZBSZSP_MAX_THREADS);
+	TPAttrSetMinThreads(&attr, ZBSZSP_MIN_THREADS);
+	TPAttrSetJobsPerThread(&attr, ZBSZSP_JOBS_PER_THREAD);
+	TPAttrSetIdleTime( &attr, ZBSZSP_THREAD_IDLE_TIME);
+
+#ifdef NEW_VERSION
+	TPAttrSetMaxJobsTotal(&attr, ZBSZSP_MAX_JOBS_TOTAL);
+#endif
+
+	if(ThreadPoolInit( &threadPool, &attr ) != 0) {
+		return -1;
+	}
+	return 0;
+}
+
+unsigned int *setTimer(
+		int timer_id,
+		int time,
+		void *callback
+) {
+	int eventId;
+	int res;
+
+	TimerThread *timer;
+
+	// Only one timer is allowed.
+	if (timerContext.timerData != NULL)
+	{
+		zb_print("setTimer - timer running! -> RETURN NULL\n");
+		return NULL;
+	}
+
+	timer_data_t *data = (timer_data_t *) malloc(sizeof(timer_data_t));
+
+	data->timer_id = timer_id;
+
+	TPJobInit(&job, timer_Cb, (void *) data);
+	TPJobSetFreeFunction(&job, (free_routine) free_upnp_timeout);
+	TPJobSetPriority(&job, MED_PRIORITY);
+
+	timer = (TimerThread *) malloc(sizeof(TimerThread));
+
+	zb_print("setTimer - timer_id = %d\n", timer_id);
+
+	res = TimerThreadInit(timer, &threadPool);
+	if (res != 0) {
+		zb_print("setTimer - TimerThreadInit ERROR\n");
+		return NULL;
+	}
+
+	res = TimerThreadSchedule (
+			timer,
+			time,
+			REL_SEC, &job, SHORT_TERM,
+			&eventId);
+
+	if (res != 0) {
+		return NULL;
+	}
+
+	data->timer = (unsigned int *) timer;
+	data->eventId = eventId;
+
+	timerContext.timerData = data;
+
+	return (unsigned int *) timer;
+}
+
+int killTimer(
+		unsigned int *timer,
+		int eventId
+)
+{
+	ThreadPoolJob tempJob;
+	TimerThread *currentTimer;
+
+	currentTimer = (TimerThread *) timer;
+	if ( TimerThreadRemove(currentTimer, eventId, &tempJob) != 0 )
+	{
+
+		zb_print("killTimer - Error in TimerThreadRemove\n");
+		// Note: this is not an error if the timer has expired -> when a timer expires, it is automatically removed and TimerThreadRemove is not needed;
+		// however, the related thread has to be shut down
+	}
+	if ( TimerThreadShutdown(currentTimer) != 0 )
+	{
+		zb_print("killTimer - Error in TimerThreadShutdown\n");
+	}
+
+	zb_print("killTimer - Timer killed\n");
+
+	return 0;
+}
+
+/**
+ Protected method DiscoveryAgent onTimer
+ Method called on timeout expiration: specific functions context data is updated.
+
+ @param timer_id Timer thread identifier.
+ @return Void.
+ */
+
+void onTimer(unsigned int timer_id)
+{
+	zb_print("\nonTimer - timerId = %d\n",timer_id);
+
+	// Remove timer 
+	killTimer(timerContext.timerData->timer , timerContext.timerData->eventId);
+
+	// Free memory allocated for timer management
+	free ((TimerThread *) timerContext.timerData->timer);
+	free (timerContext.timerData);
+	timerContext.timerData = NULL;
+
+	abortReception();
+}
+
+/**
+ Protected method DiscoveryAgent free_upnp_timeout
+ Implements free function called by upnp library routines.
+
+ @param event Event pointer.
+ @return Void.
+ */
+
+void free_upnp_timeout(void *event)
+{
+	zb_print("\nfree_upnp_timeout\n");
+}
+
+void *timer_Cb(void *input)
+{
+	timer_data_t *data;
+
+	zb_print("\ntimer_Cb\n");
+
+	data = (timer_data_t *) input;
+	onTimer(data->timer_id);
+	//delete data;		However, -data- has to be deleted
+	return NULL;
+}
+
+#endif /* ZIGBEE_APS_FRAG_ENABLED */
+
+void zaSecurityTrustCenterInit(ZBIF_HANDLE zbif_handle) {
+	EmberStatus status;
+	EmberInitialSecurityState state;
+	memset(&state, 0, sizeof(state));
+
+	// set the preconfigured link key
+	MEMCOPY(emberKeyContents(&state.preconfiguredKey), &preconfiguredLinkKey,
+			EMBER_ENCRYPTION_KEY_SIZE);
+
+	// set the preconfigured network key
+	MEMCOPY(emberKeyContents(&state.networkKey), &networkKey,
+			EMBER_ENCRYPTION_KEY_SIZE);
+
+	// set the security state
+	state.bitmask = (EMBER_HAVE_PRECONFIGURED_KEY | EMBER_STANDARD_SECURITY_MODE
+			| EMBER_GLOBAL_LINK_KEY);
+	//              | EMBER_NO_TRUST_CENTER_MODE);
+
+	state.networkKeySequenceNumber = 0;
+
+	if (usePreconfiguredNwkKey)
+		state.bitmask = (state.bitmask | EMBER_HAVE_NETWORK_KEY);
+
+	uchar *p;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	p = out_buf;
+
+	/* Send EZSP ezspSetConfigurationValue command */
+	*p++ = ezspSequence;
+	*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+	*p++ = EZSP_SET_INITIAL_SECURITY_STATE; //Ember setInitialSecurityState ID - Response
+
+	*p++ = LSB_USHORT(state.bitmask);
+	*p++ = MSB_USHORT(state.bitmask);
+
+	memcpy(p, &state.preconfiguredKey, sizeof(EmberKeyData));
+	p += sizeof(EmberKeyData);
+
+	memcpy(p, &state.networkKey, sizeof(EmberKeyData));
+	p += sizeof(EmberKeyData);
+
+	*p++ = state.networkKeySequenceNumber;
+
+	/* sends the command */
+	status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void zaSecurityInit(ZBIF_HANDLE zbif_handle) {
+	EmberInitialSecurityState state;
+	EmberStatus status;
+
+	memset(&state, 0, sizeof(state));
+
+	// set the security state
+	state.bitmask = (EMBER_STANDARD_SECURITY_MODE | EMBER_HAVE_PRECONFIGURED_KEY
+	//        | EMBER_REQUIRE_ENCRYPTED_KEY // good idea to try.
+			);
+	state.networkKeySequenceNumber = 0;
+
+	// set the preconfigured link key
+	MEMCOPY(emberKeyContents(&state.preconfiguredKey), &preconfiguredLinkKey,
+			EMBER_ENCRYPTION_KEY_SIZE);
+
+	zb_print("zaSecurityInit - set state to: 0x%2x\r\n", state.bitmask);
+
+	uchar *p;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	p = out_buf;
+
+	/* Send EZSP ezspSetConfigurationValue command */
+	*p++ = ezspSequence;
+	*p++ = EZSP_FRAME_CONTROL_COMMAND | ezspSleepMode;
+	*p++ = 0x68;
+
+	*p++ = LSB_USHORT(state.bitmask);
+	*p++ = MSB_USHORT(state.bitmask);
+
+	memcpy(p, &state.preconfiguredKey, sizeof(EmberKeyData));
+	p += sizeof(EmberKeyData);
+
+	memcpy(p, &state.networkKey, sizeof(EmberKeyData));
+	p += sizeof(EmberKeyData);
+
+	*p++ = state.networkKeySequenceNumber;
+
+	/* sends the command */
+	status = zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+//#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_if.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_if.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_if.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,8 @@
+#ifndef _EZSP_IF_H_
+#define _EZSP_IF_H_
+
+extern ZBIFFunctions_t zbEzspFunctions;
+
+extern void EZSP_ReceiveCb(ZBIF_HANDLE zbif_handle, uchar *data, const int size);
+
+#endif /* _EZSP_IF_H_ */

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_ser.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_ser.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_ser.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,366 @@
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <pthread.h>
+#include <unistd.h>
+#include "zigbee_log.h"
+
+#include "ezsp_ser.h"
+#include "ezsp_common.h"
+#include "app/util/security/security.h"
+#include "app/ezsp-uart-host/ash-host.h"
+#include "app/ezsp-uart-host/ash-host-ui.h"
+#include "hal/micro/generic/ash-protocol.h"
+#include "app/ezsp-uart-host/ash-host-io.h"
+#include "app/ezsp-uart-host/ash-host-queues.h"
+#include "app/util/ezsp/serial-interface.h"
+
+// TODO: these should by connection!!!
+//
+static pthread_t ezsp_tid;
+static pthread_mutex_t ezsp_mutex;
+
+void *ezspMyTick(void *arg);
+void *ezspMyTick_select(void *arg);
+
+//If emberEndpointCount is nonzero, the application must provide descriptions for each endpoint.
+int8u emberEndpointCount = 0; // By choosing 0 instead of 1, the EndPoints are demanded to be allocated to the upper layer of GAL
+EmberEndpoint emberEndpoints[];
+
+//Notes (all values stored in ezsp_common.h):
+// current wildcard profileId = 0xa1e0
+// clusterId for Common Data Sink Cluster = 0x0300
+/*
+ EmberEndpointDescription PGM endpointDescription = {PROFILE_ID, GW_DEVICE_ID,DEVICE_VERSION,1,1,};
+ int16u PGM inputClusterList[] = {COMMON_DATA_SINK_CLUSTER_ID};
+ int16u PGM outputClusterList[] = {COMMON_DATA_SINK_CLUSTER_ID};
+ EmberEndpoint emberEndpoints[] = { { ENDPOINT, &endpointDescription, inputClusterList, outputClusterList },  };
+ */
+
+// Keep track of the current network state
+static EmberNetworkStatus networkState = EMBER_NO_NETWORK;
+
+void quit(void) {
+	ezspClose();
+	exit(-1);
+}
+
+/**
+ * Opens the serial device and initializes the status
+ * fields related to the framing handling
+ */
+
+int ezsp_open(const char **params) {
+
+	EmberResetType reset = RESET_UNKNOWN;
+	EmberStatus status;
+
+	char *device = get_param(params, "path");
+	if (device == NULL) {
+		return 0;
+	}
+
+	char *speed = get_param(params, "speed");
+	int bitrate = 115200;
+	if (speed != NULL) {
+		bitrate = atoi(speed);
+	}
+
+	// inititialize the serial port
+	// good to do this before ezspUtilInit, that way any errors that occur
+	// can be printed to the serial port.
+
+	//if(emberSerialInit(APP_SERIAL, BAUD_115200, PARITY_NONE, 1)
+	//	!= EMBER_SUCCESS) {
+	//	emberSerialInit(APP_SERIAL, BAUD_19200, PARITY_NONE, 1);
+	//}
+
+	strncpy(ashHostConfig.serialPort, device, ASH_PORT_LEN);
+	ashWriteConfig(baudRate, bitrate);
+
+	char *flowControl = get_param(params, "flowCtrl");
+	//if flowCtrl is present, then disable XON/XOFF, otherwise enables RTS/CTS flow control
+	if (flowControl != NULL) {
+		zb_print("Selected flowControl=false\n");
+		ashWriteConfig(rtsCts, FALSE); //To be used for STM
+	} else {
+		//By default, use the RTS/CTS flow control
+		ashWriteConfig(rtsCts, TRUE); //To be used for EZSP
+	}
+	//reset the EM260 and wait for it to come back
+	//this will guarantee that the two MCUs start in the same state
+	//
+	{
+		/* opens the serial port */
+		EzspStatus stat = ezspInit();
+		if (stat != EZSP_SUCCESS) {
+			// report status here
+			emberSerialGuaranteedPrintf(APP_SERIAL, "ERROR: ezspInit 0x%x\r\n",
+					stat);
+			// the app can choose what to do here, if the app is running
+			// another device then it could stay running and report the
+			// error visually for example. This app asserts.
+			quit();
+		}
+	}
+
+	/* Enable logs */
+#ifdef DEBUG
+	ashWriteConfig(traceFlags, TRACE_FRAMES_BASIC | TRACE_FRAMES_VERBOSE | TRACE_EZSP );
+#else
+	ashWriteConfig(traceFlags, 0);
+#endif
+
+	// ezspUtilInit must be called before other EmberNet stack functions
+	status = ezspUtilInit(APP_SERIAL, reset);
+	if (status != EMBER_SUCCESS) {
+		// report status here
+		//emberSerialGuaranteedPrintf(APP_SERIAL, "ERROR: ezspUtilInit 0x%x\r\n", status);
+		// the app can choose what to do here, if the app is running
+		// another device then it could stay running and report the
+		// error visually for example. This app asserts.
+		quit();
+
+	} else {
+		//emberSerialPrintf(APP_SERIAL, "EVENT: ezspUtilInit passed\r\n");
+		//emberSerialWaitSend(APP_SERIAL);
+	}
+
+	ezsp_status_t *ezsp_status = (ezsp_status_t *) malloc(
+			sizeof(ezsp_status_t));
+	memset(ezsp_status, 0, sizeof(ezsp_status_t));
+
+	int ret;
+
+	/* creates a socketpair */
+	ret = socketpair(AF_LOCAL, SOCK_DGRAM, 0, ezsp_status->pair);
+	if (ret < 0) {
+		zb_print_error("ERROR: unable to create the socketpair");
+		// TODO: close connection to EZSP
+		free(ezsp_status);
+		return 0;
+	}
+
+	ezsp_status->fd = ezsp_status->pair[0];
+
+	pthread_mutex_init(&ezsp_mutex, NULL);
+
+	ret = pthread_create(&ezsp_tid, NULL, ezspMyTick_select, ezsp_status);
+	if (ret < 0) {
+		// TODO: close connection to EZSP
+		free(ezsp_status);
+		return 0;
+	}
+
+	return (int) ezsp_status;
+}
+
+#if 1 
+
+// LE SEGUENTI CALLBACK NON SONO MAI CHIAMATE!!!!
+// MA SONO STATE INCLUSE PERCHE' CHIAMATE 
+// callbackDispatch definita nel file command-functions.h
+// NOI NON USIAMO MAI DIRETTAMENTE QUESTO FILE
+// MA VIENE INCLUSO IN ALTRI FILE CHE DOBBIAMP LIKARE!!!
+
+void ezspMessageSentHandler(EmberOutgoingMessageType type,
+		int16u indexOrDestination, EmberApsFrame *apsFrame, int8u messageTag,
+		EmberStatus status, int8u messageLength, int8u *messageContents) {
+	printf("ezspMessageSentHandler\n");
+}
+
+void ezspIncomingMessageHandler(EmberIncomingMessageType type,
+		EmberApsFrame *apsFrame, int8u lastHopLqi, int8s lastHopRssi,
+		EmberNodeId sender, int8u bindingTableIndex, int8u addressTableIndex,
+		int8u length, int8u *message) {
+	printf("ezspIncomingMessageHandler\n");
+}
+
+// this is called when the stack status changes
+void ezspStackStatusHandler(EmberStatus status) {
+	printf("ezspStackStatusHandler\n");
+}
+
+// this is called when a scan is complete
+void ezspScanCompleteHandler(int8u channel, EmberStatus status) {
+	printf("ezspScanCompleteHandler\n");
+}
+
+// this is called when a network is found when app is performing scan
+void ezspNetworkFoundHandler(EmberZigbeeNetwork *networkFound, int8u lastHopLqi,
+		int8s lastHopRssi) {
+	printf("ezspScanCompleteHandler\n");
+}
+
+// this is called when an error occurs while performing a
+// scanAndFormNetwork or a scanAndJoinNetwork
+void ezspScanErrorHandler(EmberStatus status) {
+	printf("ezspScanErrorHandler\n");
+}
+
+void hal260IsAwakeIsr(boolean isAwake) {
+}
+#endif
+
+void ezspErrorHandler(EzspStatus status) {
+	emberSerialGuaranteedPrintf(APP_SERIAL,
+			"ERROR: ezspErrorHandler %s (0x%x)\r\n", decodeEzspStatus(status),
+			status);
+}
+
+void *ezspMyTick(void *arg) {
+
+	ezsp_status_t *ezsp_status = (ezsp_status_t *) arg;
+
+	while (TRUE) {
+		pthread_mutex_lock(&ezsp_mutex);
+
+		int8u count = ashQueueLength(&rxQueue) + 1;
+		while (count > 0 && responseReceived() == 0) {
+			int response_byte = serialGetResponseByte(EZSP_FRAME_ID_INDEX);
+			if (response_byte != EZSP_NO_CALLBACKS) {
+
+				zb_print("\nezspMyTick");
+				int8u *buf = serialInt8uArrayResponse(0, 127);
+				int size = serialGetResponseByte(EZSP_LENGTH_INDEX);
+				/* Arrived message is sent to the upper layers */
+				write(ezsp_status->pair[1], buf, size);
+			}
+			count--;
+		}
+		pthread_mutex_unlock(&ezsp_mutex);
+	}
+
+	return 0;
+}
+
+void *ezspMyTick_select(void *arg) {
+	fd_set rfds;
+
+	ezsp_status_t *ezsp_status = (ezsp_status_t *) arg;
+
+	int serial_fd = ashSerialFd();
+
+	int max_fd = serial_fd + 1;
+
+	/* This is the main loop of the ASH protocol */
+	while (TRUE) {
+		int sts;
+		struct timeval tv;
+
+		FD_ZERO(&rfds);
+		FD_SET(serial_fd, &rfds);
+
+		/* Wait up to five seconds. */
+		tv.tv_sec = 0;
+		tv.tv_usec = 100000;
+
+		/* wait for any data received from the port */
+		sts = select(max_fd, &rfds, NULL, NULL, NULL);
+		if (sts < 0) {
+			/* error */
+			return NULL;
+		}
+		if (sts == 0) {
+			printf("TIMEOUT!!!\n");
+		}
+
+		/* 
+		 * sts == 0, timeout occourred
+		 * sts > 0, data arrived
+		 */
+
+		pthread_mutex_lock(&ezsp_mutex);
+
+#if 0
+
+		/* received some from the EM260 */
+		size = read(serial_fd, buf, sizeof(buf));
+		if (size < 0) {
+			continue;
+		}
+		zb_print_bytes("Received ", buf, size);
+#endif
+
+		/* Process received data! */
+
+		int8u count = ashQueueLength(&rxQueue) + 1;
+		while (count > 0 && responseReceived() == 0) {
+			int response_byte = serialGetResponseByte(EZSP_FRAME_ID_INDEX);
+			if (response_byte != EZSP_NO_CALLBACKS) {
+				int8u *buf = serialInt8uArrayResponse(0, 127);
+				int size = serialGetResponseByte(EZSP_LENGTH_INDEX);
+				/* Arrived message is sent to the upper layers */
+				write(ezsp_status->pair[1], buf, size);
+			}
+			count--;
+		}
+		pthread_mutex_unlock(&ezsp_mutex);
+
+	}
+	return NULL;
+}
+
+/**
+ * Closes the serial communication
+ */
+
+int ezsp_close(int handle) {
+	pthread_mutex_lock(&ezsp_mutex);
+	ashSerialClose();
+	pthread_mutex_unlock(&ezsp_mutex);
+	return 0;
+}
+
+extern int16u waitStartTime;
+
+static boolean checkConnection(void) {
+	boolean connected = ashIsConnected();
+	if (!connected) {
+		// Attempt to restore the connection. This will reset the EM260.
+		ashSerialClose();
+		ezspInit();
+	}
+	return connected;
+}
+
+int ezsp_transmit(int handle, const unsigned char *data, int size) {
+	EzspStatus status;
+
+	pthread_mutex_lock(&ezsp_mutex);
+
+	zb_print_bytes("ezsp_transmit - Sending ", data, size);
+	//ZB_LOG(zb_print_bytes("Sending ", data, size));
+	if (!checkConnection()) {
+		pthread_mutex_unlock(&ezsp_mutex);
+		return EZSP_ASH_NOT_CONNECTED;
+	}
+
+	status = ashSend(size, data);
+	if (status != EZSP_SUCCESS) {
+		pthread_mutex_unlock(&ezsp_mutex);
+		return status;
+	}
+#if 0
+
+	waitingForResponse = TRUE;
+#endif
+	waitStartTime = halCommonGetInt16uMillisecondTick();
+	pthread_mutex_unlock(&ezsp_mutex);
+	return (int) status;
+}
+
+int ezsp_fd(int handle) {
+	ezsp_status_t *status = (ezsp_status_t *) handle;
+	return status->fd;
+}
+
+int ezsp_receive(int handle, unsigned char *buf, const int size) {
+	return 0;
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_ser.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_ser.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/ezsp_ser.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,16 @@
+#ifndef _EZSP_SER_H_
+#define _EZSP_SER_H_
+
+typedef struct {
+	int fd;
+	int state;
+	int pair[2];
+} ezsp_status_t;
+
+int ezsp_open(const char **params);
+int ezsp_close(int handle);
+int ezsp_transmit(int handle, const unsigned char *data, int size);
+int ezsp_receive(int handle, unsigned char *buf, const int size);
+int ezsp_fd(int handle);
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/fragment.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/fragment.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/fragment.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,75 @@
+#ifndef _ZIGBEE_FRAGMENT_H_
+#define _ZIGBEE_FRAGMENT_H_
+
+#include "upnp/ThreadPool.h"
+#include "upnp/TimerThread.h"
+
+// Previous value = 145
+#define	HOST_FRAGMENT_BUFFER_SIZE			280	
+
+// TODO: such a value should depend on the profileID
+#define ZA_MAX_HOPS 						6
+
+void ezspFragmentInit(int16u receiveBufferLength, int8u *receiveBuffer);
+
+EmberStatus ezspSendFragmentedMessage(ZBIF_HANDLE zbif_handle,
+		EmberOutgoingMessageType type, int16u indexOrDestination,
+		EmberApsFrame *apsFrame, int8u maxFragmentSize, int8u messageLength,
+		int8u *messageContents);
+
+EmberStatus ezspFragmentSourceRouteHandler(void);
+
+boolean ezspIsOutgoingFragment(ZBIF_HANDLE zbif_handle, EmberApsFrame *apsFrame,
+		EmberStatus status);
+
+void ezspFragmentedMessageSentHandler(EmberStatus status);
+
+boolean ezspIsIncomingFragment(ZBIF_HANDLE zbif_handle, EmberApsFrame *apsFrame,
+		EmberNodeId sender, int16u *messageLength, int8u **messageContents);
+
+/**
+ * Set of constants used in thread management.
+ */
+
+#define ZBSZSP_MAX_THREADS					10
+#define ZBSZSP_MIN_THREADS					10
+#define ZBSZSP_JOBS_PER_THREAD				10
+#define ZBSZSP_THREAD_IDLE_TIME 			5000
+#define ZBSZSP_MAX_JOBS_TOTAL 				10
+
+/// Mutex
+pthread_mutex_t mux;
+
+/// Thread management
+ThreadPool threadPool;
+ThreadPoolJob job;
+
+///	Timers management 				
+
+typedef void *TIMERPROC;
+typedef struct {
+	int timer_id;
+	unsigned int *timer;
+	int eventId;
+} timer_data_t;
+
+typedef struct {
+	int fTimeout;
+	timer_data_t *timerData;
+} context_t;
+
+context_t timerContext;
+
+int initTimers(void);
+
+unsigned int *setTimer(int timer_id, int time, void *callback);
+
+int killTimer(unsigned int *timer, int eventID);
+
+void onTimer(unsigned int timer_id);
+
+static void free_upnp_timeout(void *event);
+
+static void *timer_Cb(void *input);
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/freescale_if.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/freescale_if.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/freescale_if.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,2729 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+/**
+ * High level interface to the ZigBee protocol stack
+ * The stack actually runs on the INT or on a external
+ * board connected to the system by means of a serial
+ * connection
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include "zb_conn.h"
+#include <zigbee.h>
+#include "zigbee_local.h"
+#include "zigbee_log.h"
+#include "zigbee_utils.h"
+
+#ifdef DEBUG_ZIGBEE_API
+#include "zigbee_utils.h"
+#endif
+
+#include "freescale_ser.h"
+#include "freescale_if.h"
+
+unsigned char out_buf[300];
+uchar attr_prev = 0x00;
+ushort nwkShortAddress = 0x0000;
+uchar DevType;
+// This variable is used to know if restart the Gateway or just init it
+uchar restartGWafterReset = 0x00; //by default do not restart the network
+uchar useCommissioningMode = 0x00; //by default use the NVM setting
+uchar useSilentStart = 0x00; //by default use the associationMode
+int generateRandomIEEEAddr = 0x00;
+//General variable needed for the MGMT_LQI
+uchar lastSrcAddrMode = 0x02;
+uchar lastSrcAddr[2];
+// Used in FREESCALE_ZDP_MGMT_NWK_UPDATE_request
+int zdp_mgmt_NwkUpdateIdCounter = 0x00;
+int selectedSecLevel = 0;
+int TCLinkKeyTableSize = 0;
+TCLinkKeyTableEntry TCLinkKeyTable[9];
+
+void FREESCALE_ParseNExec(ZBIF_HANDLE zbif_handle, uchar *p, int size);
+
+#ifndef ZIGBEE_USE_DATA_STRUCTURES
+
+void FREESCALE_ZTC_RESET_request(ZBIF_HANDLE zbif_handle);
+
+void FREESCALE_ZDO_RESET_request(ZBIF_HANDLE zbif_handle, uchar options);
+
+void FREESCALE_ZDO_START_request(ZBIF_HANDLE zbif_handle);
+
+void FREESCALE_ZDP_MGMT_NWK_UPDATE_request(ZBIF_HANDLE zbif_handle,
+		unsigned long int scanChannel, ushort scanDuration);
+
+void FREESCALE_ZDO_NWK_ADDR_request(ZBIF_HANDLE zbif_handle, uchar *ieee_addr,
+		uchar request_type, uchar start_index);
+
+void FREESCALE_ZDO_IEEE_ADDR_request(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar request_type, uchar start_index);
+
+void FREESCALE_ZB_MGMT_LQI_request(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar start_index);
+
+void FREESCALE_ZDO_NODE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr);
+
+void FREESCALE_ZDO_POWER_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr);
+
+void FREESCALE_ZDO_SIMPLE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, uchar endpoint);
+
+void FREESCALE_ZDO_ACTIVE_EP_DESC_request(ZBIF_HANDLE zbif_handle,
+		ushort dst_addr, ushort nwk_addr);
+
+void FREESCALE_ZDO_MATCH_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, ushort profile_id, uchar nicl, ushort *icllist,
+		uchar nocl, ushort *ocllist);
+
+void FREESCALE_ZDO_MATCH_DESC_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort dst_addr, uchar match_len, uchar *match_list);
+
+void FREESCALE_ZDO_END_DEVICE_BIND_request(ZBIF_HANDLE zbif_handle,
+		ushort binding_target, uchar *src_ieee_addr, uchar src_ep,
+		ushort profile_id, uchar nicl, ushort *icllist, uchar nocl,
+		ushort *ocllist);
+
+void FREESCALE_APSDE_DATA_request(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, ushort profile_id, ushort cluster_id,
+		uchar src_ep, uchar asdu_len, uchar *asdu, uchar tx_options,
+		uchar radius);
+
+void FREESCALE_ZDP_MGMT_BIND_Request(ZBIF_HANDLE zbif_handle,
+		ushort remote_dest_addr, ushort startIndex);
+
+void FREESCALE_APSME_BIND_request(ZBIF_HANDLE zbif_handle, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep);
+
+void FREESCALE_ZDP_BIND_Request(ZBIF_HANDLE zbif_handle,
+		ushort remote_dest_addr, uchar *src_ieee_addr, uchar src_ep,
+		ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep);
+
+void FREESCALE_ZDP_UNBIND_Request(ZBIF_HANDLE zbif_handle,
+		ushort remote_dest_addr, uchar *src_ieee_addr, uchar src_ep,
+		ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep);
+
+void FREESCALE_APSME_UNBIND_request(ZBIF_HANDLE zbif_handle,
+		uchar *src_ieee_addr, uchar src_ep, ushort cluster_id,
+		uchar *dst_ieee_addr, uchar dst_ep);
+
+void FREESCALE_APSME_GET_request(ZBIF_HANDLE zbif_handle, uchar attr);
+
+void FREESCALE_APSME_SET_request(ZBIF_HANDLE zbif_handle, uchar attr,
+		uchar attr_len, uchar *attr_value);
+
+//
+void FREESCALE_MGMT_PERMIT_JOINING_request(ZBIF_HANDLE zbif_handle,
+		ushort nwk_addr, int permitDuration);
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+
+void FREESCALE_APSME_REMOVE_DEVICE_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *parent_ieee_addr,
+		uchar *child_ieee_addr
+);
+
+void FREESCALE_APSME_TRANSPORT_KEY_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *dst_ieee_addr,
+		uchar key_type,
+		ZB_TRANSPORT_KEY_DATA *transport_key_data
+);
+
+void FREESCALE_NLME_LEAVE_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *dev_ieee_addr,
+		uchar remove_children,
+		uchar rejoin,
+		uchar reuse_address,
+		uchar silent
+);
+
+#endif
+
+void FREESCALE_ZDO_ERROR_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort cluster_id, uchar expected_len);
+#endif /* ZIGBEE_USE_DATA_STRUCTURES */
+
+void printBytes(uchar *p) {
+#ifdef DEBUG_ZIGBEE_API
+	int i;
+	for (i = 0; i < p[2]; i++)
+	{
+		zb_print("%02X ", p[2+i]);
+		//if ((i+1) % 20 == 0)
+		//	zb_print("\n");
+	}
+	zb_print("\n");
+#endif
+}
+
+void FREESCALE_ZDO_RESET_request(ZBIF_HANDLE zbif_handle, uchar options) {
+	int i = 0;
+	uchar callReset;
+
+	ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+
+	// Get all the options values
+	restartGWafterReset = (options & 0x01); // take the first bit of the options byte
+	useCommissioningMode = (options & 0x02); // 2nd bit
+	callReset = (options & 0x04); // 3rd bit
+	generateRandomIEEEAddr = (options & 0x08); // 4th bit
+	useSilentStart = (options & 0x10); // 5th bit
+	/*
+	 printf("restartGWafterReset value: %x\n",restartGWafterReset);
+	 printf("useCommissioningMode value: %x\n",useCommissioningMode);
+	 printf("callReset value: %x\n",callReset);
+	 printf("generateRandomIEEEAddr value: %x\n",generateRandomIEEEAddr);
+	 printf("useSilentStart value: %x\n",useSilentStart);
+	 */
+	// Call the reset of the Freescale dongle
+	if (callReset == 0x04) {
+		FREESCALE_ZTC_RESET_request(zbif_handle); // Call the reset (and only this function, not the sequence!) of the Freescale dongle
+		// Initialize the WriteSAS attributes with all the default values
+		if ((useCommissioningMode == 0x02) && (useSilentStart == 0x10)) {
+			// Only for this scenario (comissioning mode with silent start) the shortAddress shall be set to 0x0000!
+			zb_print(
+					"ZDO_RESET_request - ShortAddress set to 0x0000 due to TC Replacement\n");
+			sasAttr.ShortAddress = 0x0000;
+		} else
+			sasAttr.ShortAddress = 0xFFFF;
+		for (i = 0; i < 8; i++)
+			sasAttr.ExtendedPANId[i] = 0x00;
+		for (i = 0; i < 8; i++)
+			sasAttr.APSUseExtendedPANId[i] = 0x00;
+		sasAttr.PANId = 0xFFFF;
+		for (i = 0; i < 4; i++)
+			sasAttr.ChannelsMask[i] = 0x00; //By default it is 0x07FFF800 (in binary is 111111111111111100000000000)
+		sasAttr.ProtocolVersion = 0x02;
+		sasAttr.StackProfile = 0x02;
+		sasAttr.StartupControl = 0x00; //0x00
+		for (i = 0; i < 8; i++)
+			sasAttr.TrustCenterAddress[i] = 0xAA;
+		for (i = 0; i < 16; i++)
+			sasAttr.TrustCenterMasterKey[i] = 0x00;
+		for (i = 0; i < 16; i++)
+			sasAttr.NetworkKey[i] = 0x00;
+		sasAttr.UseInsecureJoin = 0x01;
+		for (i = 0; i < 16; i++)
+			sasAttr.PreconfiguredTrustCenterLinkKey[i] = 0x00; //was 5A 69 67 42 65 65 41 6C 6C 69 61 6E 63 65 30 39
+		sasAttr.ActiveNwkKeySeqNumber = 0x00;
+		sasAttr.NetworkKeyType = 0x01;
+		sasAttr.NetworkManagerAddress = 0x0000;
+		sasAttr.Scanattempts = 0x03;
+		sasAttr.Timebetweenscans = 0x0064;
+		sasAttr.RejoinInterval = 0x0002;
+		sasAttr.MaximumRejoinInterval = 0x0E10;
+		sasAttr.IndirectPollRate = 0x0BB8;
+		sasAttr.ParentLinkRetryThreshold = 0x02;
+		sasAttr.IsConcentrator = 0x00;
+		sasAttr.ConcentratorRadius = 0x05;
+		sasAttr.ConcentratorDiscoveryTime = 0x00;
+	} else {
+		zb_print("Reset already called, fine!\n");
+		// Fake Reset Confirm
+		zbifCbs->ZDO_RESET_confirm(zbif_handle, 0x00, restartGWafterReset);
+	}
+}
+
+void FREESCALE_ZDO_START_request(ZBIF_HANDLE zbif_handle) {
+	((zbif_status_t *) zbif_handle)->state = 1;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	unsigned char cmd[6] = { 0xA3, 0xE7, 0x03 };
+	if (DevType == 0x01) {
+		//Coordinator
+		cmd[3] = 0xC0;
+	} else if (DevType == 0x02) {
+		// Router
+		cmd[3] = 0x80;
+	} else if (DevType == 0x03) {
+		//EndDevice
+		cmd[3] = 0x20;
+	}
+	//Startup set and StartupControl Mode setting
+	//cmd[4] = 0x18;		// Use commissioning working set - it uses the parameters specified in the WriteSAS command
+	//cmd[4] = 0x00;		// NVM value (this is the latest parameters stored in the dongle before a reset occurs)
+	//cmd[4] = 0x10; 		// Use working set (that's what is written in the RAM)
+	//cmd[4] = 0x08;		// Use rom set (compile time setting)
+	if (useCommissioningMode == 0x02) {
+		// Use commissioning working set (WriteSAS use this feature)
+		cmd[4] = 0x18;
+		zb_print("\n***************************\n");
+		zb_print(
+				"USING COMMISSIONING SETTING\n***************************\n\n");
+	} else {
+		// Use Non Volatile Memory
+		cmd[4] = 0x00;
+		zb_print("\n*****************\n");
+		zb_print("USING NVM SETTING\n*****************\n\n");
+	}
+	//Startup control mode
+	/*
+	 0x00 - Association - Use association (ZR, ZED only), or form (ZC)
+	 0x01 - Orphan Rejoin - FS specific: use orphan rejoin (ZR, ZED only)
+	 0x02 - Network Rejoin - Use NWK rejoin (ZR, ZED only)
+	 0x03 - Find and Rejoin - Valid for ZR, ZED only, search for network on this and other channels, then silent join
+	 0x04 - Silent Start - Already part of the network (no form/join needed)
+	 */
+	if (useSilentStart == 0x10)
+		cmd[5] = 0x04; // Silent mode (NOTE By Mads: the standard firmware does not used it if we're using the StartupAttributeSet)
+	else
+		cmd[5] = 0x00; // Association!
+	zb_print_bytes("ZTC_START_NETWORK->", cmd, cmd[2] + 3);
+	zb_conn_send(zb_conn_h, cmd, cmd[2] + 3);
+}
+
+void FREESCALE_ZTC_RESET_request(ZBIF_HANDLE zbif_handle) {
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	unsigned char cmd[3] = { 0xA3, 0x08, 0x00 };
+	zb_print_bytes("\nZTC_RESET->", cmd, cmd[2] + 3);
+	zb_conn_send(zb_conn_h, cmd, cmd[2] + 3);
+	zb_print("FREESCALE_ZTC_RESET_request called!\n");
+	/*
+	 // We shall force the stack to use the "MC13226_receive" function to read anything just after the reset!
+	 usleep(200000);
+	 unsigned char cmdFake[3] = { 0xA3, 0x14, 0x00 };		//This is a "ZTC-GetPanID.Request
+	 zb_conn_send(zb_conn_h, cmdFake, cmdFake[2] + 3);
+	 */
+}
+
+void FREESCALE_ZDP_MGMT_NWK_UPDATE_request(ZBIF_HANDLE zbif_handle,
+		unsigned long int scanChannel, ushort scanDuration) {
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	unsigned char cmd[13] = { 0xA2, 0x38, 0x08 };
+	// Broadcast destionation address
+	cmd[3] = 0xFD;
+	cmd[4] = 0xFF;
+	// scanChannel
+	memcpy(&cmd[5], &scanChannel, 4);
+	//scanDuration (valid range 0x00-0x05 or 0xfe-0xff)
+	cmd[9] = scanDuration;
+	if (scanDuration == 0xfe) {
+		//NwkUpdateId
+		cmd[10] = zdp_mgmt_NwkUpdateIdCounter++;
+	} else if (scanDuration >= 0x00 && scanDuration <= 0x05) {
+		//ScanCount
+		cmd[10] = 0x01; //max value =0x05!
+	} else {
+		zb_print(
+				"ZDP_MGMT_NWK_UPDATE_request - ERROR: not supported for scanDuration != 0xfe or > 0x05!\n");
+		//For 0xff we shall include an extra 2 bytes for the 'nwkManagerAddress'
+		return;
+	}
+	zb_print_bytes("ZDP_MGMT_NWK_UPDATE_request->", cmd, cmd[2] + 3);
+	zb_conn_send(zb_conn_h, cmd, cmd[2] + 3);
+	zb_print("ZDP_MGMT_NWK_UPDATE_request called!\n");
+}
+
+void FREESCALE_ZDO_NWK_ADDR_request(ZBIF_HANDLE zbif_handle, uchar *ieee_addr,
+		uchar request_type, uchar start_index) {
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	unsigned char cmd[15] = { 0xA2, 0x00, 0x0C };
+	ushort dest = 0xFFFF; //Send it in broadcast since we cannot poll direct the IEEEAddr
+	// Destination address (where this packet message will be sent!)
+	cmd[3] = LSB_USHORT(dest);
+	cmd[4] = MSB_USHORT(dest);
+	//IEEE ADDR
+	cmd[5] = ieee_addr[7];
+	cmd[6] = ieee_addr[6];
+	cmd[7] = ieee_addr[5];
+	cmd[8] = ieee_addr[4];
+	cmd[9] = ieee_addr[3];
+	cmd[10] = ieee_addr[2];
+	cmd[11] = ieee_addr[1];
+	cmd[12] = ieee_addr[0];
+
+	cmd[13] = request_type;
+	cmd[14] = start_index;
+
+	zb_print_bytes("ZDO_NWK_ADDR->", cmd, cmd[2] + 3);
+	zb_conn_send(zb_conn_h, cmd, cmd[2] + 3);
+
+}
+
+void FREESCALE_ZDO_IEEE_ADDR_request(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar request_type, uchar start_index) {
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	unsigned char cmd[9] = { 0xA2, 0x01, 0x06 };
+	//ushort dest = 0xFFFF;
+	// Send this IEEE_Addr_Req in broadcast (to everybody)!
+	//cmd[3] = LSB_USHORT(dest);
+	//cmd[4] = MSB_USHORT(dest);
+	// Send this IEEE_Addr_Req only to the selected node
+	cmd[3] = LSB_USHORT(nwk_addr);
+	cmd[4] = MSB_USHORT(nwk_addr);
+	// ShortAddress that we're looking for!
+	cmd[5] = LSB_USHORT(nwk_addr);
+	cmd[6] = MSB_USHORT(nwk_addr);
+	cmd[7] = request_type;
+	cmd[8] = start_index;
+
+	zb_print_bytes("ZDO_IEEE_ADDR->", cmd, cmd[2] + 3);
+	zb_conn_send(zb_conn_h, cmd, cmd[2] + 3);
+}
+
+void FREESCALE_ZB_MGMT_LQI_request(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar start_index) {
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	unsigned char cmd[6] = { 0xA2, 0x31, 0x03 };
+	//DestAddress
+	cmd[3] = LSB_USHORT(nwk_addr);
+	cmd[4] = MSB_USHORT(nwk_addr);
+	//StartIndex
+	cmd[5] = LSB_USHORT(start_index);
+
+	zb_print_bytes("MGMT_LQI_request->", cmd, cmd[2] + 3);
+	zb_conn_send(zb_conn_h, cmd, cmd[2] + 3);
+}
+
+void FREESCALE_ZDO_NODE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr) {
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	unsigned char cmd[7] = { 0xA2, 0x02, 0x04 };
+
+	cmd[3] = LSB_USHORT(dst_addr);
+	cmd[4] = MSB_USHORT(dst_addr);
+
+	cmd[5] = LSB_USHORT(nwk_addr);
+	cmd[6] = MSB_USHORT(nwk_addr);
+
+	zb_print_bytes("ZDO_NODE_DESC->", cmd, cmd[2] + 3);
+	zb_conn_send(zb_conn_h, cmd, cmd[2] + 3);
+}
+
+void FREESCALE_ZDO_POWER_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr) {
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	unsigned char cmd[7] = { 0xA2, 0x03, 0x04 };
+
+	cmd[3] = LSB_USHORT(dst_addr);
+	cmd[4] = MSB_USHORT(dst_addr);
+
+	cmd[5] = LSB_USHORT(nwk_addr);
+	cmd[6] = MSB_USHORT(nwk_addr);
+
+	zb_print_bytes("ZDO_POWER_DESC->", cmd, cmd[2] + 3);
+	zb_conn_send(zb_conn_h, cmd, cmd[2] + 3);
+}
+
+void FREESCALE_ZDO_SIMPLE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, uchar endpoint) {
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	unsigned char cmd[8] = { 0xA2, 0x04, 0x05 };
+
+	cmd[3] = LSB_USHORT(dst_addr);
+	cmd[4] = MSB_USHORT(dst_addr);
+
+	cmd[5] = LSB_USHORT(nwk_addr);
+	cmd[6] = MSB_USHORT(nwk_addr);
+
+	cmd[7] = endpoint;
+
+	zb_print_bytes("ZDO_SIMPLE_DESC->", cmd, cmd[2] + 3);
+	zb_conn_send(zb_conn_h, cmd, cmd[2] + 3);
+}
+
+void FREESCALE_ZDO_ACTIVE_EP_DESC_request(ZBIF_HANDLE zbif_handle,
+		ushort dst_addr, ushort nwk_addr) {
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	//ZB_CONN_HANDLE zb_conn_h = NULL;
+
+	unsigned char cmd[7] = { 0xA2, 0x05, 0x04 };
+
+	cmd[3] = LSB_USHORT(dst_addr);
+	cmd[4] = MSB_USHORT(dst_addr);
+
+	cmd[5] = LSB_USHORT(nwk_addr);
+	cmd[6] = MSB_USHORT(nwk_addr);
+
+	zb_print_bytes("ZDO_ACTIVE_EP_DESC_request->", cmd, cmd[2] + 3);
+	zb_conn_send(zb_conn_h, cmd, cmd[2] + 3);
+}
+
+void FREESCALE_ZDO_MATCH_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, ushort profile_id, uchar nicl, ushort *icllist,
+		uchar nocl, ushort *ocllist) {
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	int i = 0, p = 0;
+	unsigned char cmd[255] = { 0xA2, 0x06 };
+
+	cmd[2] = 6 + nicl * 2 + nocl * 2 + 2;
+
+	cmd[3] = LSB_USHORT(dst_addr);
+	cmd[4] = MSB_USHORT(dst_addr);
+
+	cmd[5] = LSB_USHORT(nwk_addr);
+	cmd[6] = MSB_USHORT(nwk_addr);
+
+	cmd[7] = LSB_USHORT(profile_id);
+	cmd[8] = MSB_USHORT(profile_id);
+
+	cmd[9] = nicl;
+
+	for (i = 0; i < nicl; i++) {
+		cmd[10 + (i * 2)] = LSB_USHORT(icllist[i]);
+		cmd[10 + (i * 2) + 1] = MSB_USHORT(icllist[i]);
+	}
+
+	p = 10 + (i * 2);
+
+	cmd[p] = nocl;
+
+	for (i = 0; i < nocl; i++) {
+		cmd[p + (i * 2)] = LSB_USHORT(ocllist[i]);
+		cmd[p + (i * 2) + 1] = MSB_USHORT(ocllist[i]);
+	}
+
+	zb_print_bytes("ZDO_MATCH_DESC->", cmd, cmd[2] + 3);
+	zb_conn_send(zb_conn_h, cmd, cmd[2] + 3);
+}
+
+void FREESCALE_ZDO_MATCH_DESC_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, uchar match_len, uchar *match_list) {
+	zb_not_yet_implemented()
+}
+
+void FREESCALE_ZDO_END_DEVICE_BIND_request(ZBIF_HANDLE zbif_handle,
+		ushort binding_target, uchar *src_ieee_addr, uchar src_ep,
+		ushort profile_id, uchar nicl, ushort *icllist, uchar nocl,
+		ushort *ocllist) {
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	int i = 0, p = 0;
+	unsigned char cmd[255] = { 0xA2, 0x20 };
+
+	cmd[2] = 13 + 2 + nicl * 2 + nocl * 2;
+
+	cmd[3] = LSB_USHORT(binding_target);
+	cmd[4] = MSB_USHORT(binding_target);
+
+	cmd[5] = src_ieee_addr[7];
+	cmd[6] = src_ieee_addr[6];
+	cmd[7] = src_ieee_addr[5];
+	cmd[8] = src_ieee_addr[4];
+	cmd[9] = src_ieee_addr[3];
+	cmd[10] = src_ieee_addr[2];
+	cmd[11] = src_ieee_addr[1];
+	cmd[12] = src_ieee_addr[0];
+
+	cmd[13] = src_ep;
+	cmd[14] = LSB_USHORT(profile_id);
+	cmd[15] = MSB_USHORT(profile_id);
+
+	cmd[16] = nicl;
+
+	for (i = 0; i < nicl; i++) {
+		cmd[16 + (i * 2)] = LSB_USHORT(icllist[i]);
+		cmd[16 + (i * 2) + 1] = MSB_USHORT(icllist[i]);
+	}
+
+	p = 16 + (i * 2);
+
+	cmd[p] = nocl;
+
+	for (i = 0; i < nocl; i++) {
+		cmd[p + (i * 2)] = LSB_USHORT(ocllist[i]);
+		cmd[p + (i * 2) + 1] = MSB_USHORT(ocllist[i]);
+	}
+
+	zb_print_bytes("ZDO_END_DEVICE_BIND->", cmd, cmd[2] + 3);
+	zb_conn_send(zb_conn_h, cmd, cmd[2] + 3);
+}
+
+void FREESCALE_APSDE_DATA_request(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, ushort profile_id, ushort cluster_id,
+		uchar src_ep, uchar asdu_len, uchar *asdu, uchar tx_options,
+		uchar radius) {
+	int i = 0;
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	unsigned char cmd[255] = { 0x9C, 0x00 };
+
+#ifdef DEBUG_ZIGBEE_API
+	ZBPrint_APSDE_DATA_request (
+			dst_addr_mode,
+			dst_addr,
+			dst_ep,
+			profile_id,
+			cluster_id,
+			src_ep,
+			asdu_len,
+			asdu,
+			tx_options,
+			radius);
+#endif
+	ushort dst = *((ushort *) dst_addr);
+	// PATCH: If we're sending out a MGMT-PERMIT-JOINING.Request we convert it to a ZDP-Mgmt_Permit_Join.Request
+	if (cluster_id == 0x0036 && profile_id == 0x0000 && dst_ep == 0x00
+			&& src_ep == 0x00) {
+		unsigned char cmdPermitJoin[7] = { 0xA2, 0x36, 0x04 };
+		if (dst == 0xFFFF)
+			dst = 0xFFFC;
+		cmdPermitJoin[3] = LSB_USHORT(dst);
+		cmdPermitJoin[4] = MSB_USHORT(dst);
+		cmdPermitJoin[5] = asdu[1];
+		cmdPermitJoin[6] = asdu[2];
+		zb_print(
+				"ZDP-Mgmt_Permit_Join.Request to %04x, timer value %02x, TCSignificance %02x\n", dst, cmdPermitJoin[5], cmdPermitJoin[6]);
+		zb_print_bytes("ZDP-Mgmt_Permit_Join.Request->", cmdPermitJoin,
+				cmdPermitJoin[2] + 3);
+		zb_conn_send(zb_conn_h, cmdPermitJoin, cmdPermitJoin[2] + 3);
+		return;
+	}
+	// Normal scenario: prepare and send the message!
+	cmd[2] = 15 + 1 + asdu_len + 2; //Double checked, this is the correct length!
+	cmd[3] = dst_addr_mode;
+	if (dst_addr_mode == 0x02) {
+		// Direct 16 bit : 0x02 - Short address and ep used
+		// Since DstAddrMode specifies short addresses, ignore last 6 bytes!!!
+		cmd[4] = LSB_USHORT(dst);
+		cmd[5] = MSB_USHORT(dst);
+		cmd[6] = 0x00;
+		cmd[7] = 0x00;
+		cmd[8] = 0x00;
+		cmd[9] = 0x00;
+		cmd[10] = 0x00;
+		cmd[11] = 0x00;
+	} else if (dst_addr_mode == 0x03) {
+		// Direct 64 bit : 0x03 - Extended address and ep
+		cmd[4] = dst_addr[0];
+		cmd[5] = dst_addr[1];
+		cmd[6] = dst_addr[2];
+		cmd[7] = dst_addr[3];
+		cmd[8] = dst_addr[4];
+		cmd[9] = dst_addr[5];
+		cmd[10] = dst_addr[6];
+		cmd[11] = dst_addr[7];
+	} else {
+		//Indirect (binding table) 0x00
+		//Group 0x01
+		// Not supported!
+		zb_print("ERROR: unsupported dst_addr_mode: %d", (int) dst_addr_mode);
+		return;
+	}
+	cmd[12] = dst_ep;
+	cmd[13] = LSB_USHORT(profile_id);
+	cmd[14] = MSB_USHORT(profile_id);
+	cmd[15] = LSB_USHORT(cluster_id);
+	cmd[16] = MSB_USHORT(cluster_id);
+	cmd[17] = src_ep;
+	cmd[18] = MSB_USHORT(asdu_len);
+	// Note: We could verify if this packet is a leave command, and in case substitute this command with a ZDO primitive
+	// but then we shall do this operation for any ZDO messages we would like to send!
+	for (i = 0; i < asdu_len; i++) {
+		cmd[19 + i] = asdu[i];
+	}
+	cmd[19 + i] = tx_options;
+	// To send a message without security (even with a firmware flashed to work only with it) use:
+	//tx_options = tx_options | (1 << 5);  //(0x20 hex)
+	if (radius == 0xFF)
+		cmd[19 + i + 1] = 0x00; //Default value: this is 2*max depth (30)
+	else
+		cmd[19 + i + 1] = LSB_USHORT(radius);
+	// Print and send the message!
+	zb_print_bytes("APSME_DATA->", cmd, cmd[2] + 3);
+	zb_conn_send(zb_conn_h, cmd, cmd[2] + 3);
+	// If we're sending out a LeaveRequest command send also a ZTC-ClearApsDeviceKeyPairSet.Request
+	if (cluster_id == 0x0034 && profile_id == 0x0000 && dst_ep == 0x00
+			&& src_ep == 0x00) {
+		// In this case we shall ask the Freescale stack to clean all the entry related to this node!
+		unsigned char cmdClearDevice[12] = { 0xA3, 0x3F, 0x08 };
+		cmdClearDevice[3] = asdu[1];
+		cmdClearDevice[4] = asdu[2];
+		cmdClearDevice[5] = asdu[3];
+		cmdClearDevice[6] = asdu[4];
+		cmdClearDevice[7] = asdu[5];
+		cmdClearDevice[8] = asdu[6];
+		cmdClearDevice[9] = asdu[7];
+		cmdClearDevice[10] = asdu[8];
+		zb_print_bytes("ZTC-ClearApsDeviceKeyPairSet.Request ", cmdClearDevice,
+				cmdClearDevice[2] + 3);
+		zb_conn_send(zb_conn_h, cmdClearDevice, cmdClearDevice[2] + 3);
+	}
+}
+
+void FREESCALE_ZDP_MGMT_BIND_Request(ZBIF_HANDLE zbif_handle,
+		ushort remote_dest_addr, ushort startIndex) {
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	unsigned char cmd[255] = { 0xA2, 0x33 };
+	cmd[2] = 4;
+	cmd[3] = LSB_USHORT(remote_dest_addr);
+	cmd[4] = MSB_USHORT(remote_dest_addr);
+	cmd[5] = LSB_USHORT(startIndex);
+	cmd[6] = MSB_USHORT(startIndex);
+	zb_print_bytes("ZDP-MGMT_BIND.Request->", cmd, cmd[2] + 3);
+	zb_conn_send(zb_conn_h, cmd, cmd[2] + 3);
+}
+
+void FREESCALE_APSME_BIND_request(ZBIF_HANDLE zbif_handle, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep) {
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	unsigned char cmd[255] = { 0x99, 0x00 };
+
+	unsigned char dest_addr_mode = 0x03;
+
+	cmd[2] = 21;
+
+	cmd[3] = src_ieee_addr[7];
+	cmd[4] = src_ieee_addr[6];
+	cmd[5] = src_ieee_addr[5];
+	cmd[6] = src_ieee_addr[4];
+	cmd[7] = src_ieee_addr[3];
+	cmd[8] = src_ieee_addr[2];
+	cmd[9] = src_ieee_addr[1];
+	cmd[10] = src_ieee_addr[0];
+
+	cmd[11] = src_ep;
+
+	cmd[12] = LSB_USHORT(cluster_id);
+	cmd[13] = MSB_USHORT(cluster_id);
+
+	cmd[14] = dest_addr_mode;
+	cmd[15] = dst_ieee_addr[7];
+	cmd[16] = dst_ieee_addr[6];
+	cmd[17] = dst_ieee_addr[5];
+	cmd[18] = dst_ieee_addr[4];
+	cmd[19] = dst_ieee_addr[3];
+	cmd[20] = dst_ieee_addr[2];
+	cmd[21] = dst_ieee_addr[1];
+	cmd[22] = dst_ieee_addr[0];
+	cmd[23] = dst_ep;
+
+	zb_print_bytes("APSME_BIND->", cmd, cmd[2] + 3);
+	zb_conn_send(zb_conn_h, cmd, cmd[2] + 3);
+}
+
+void FREESCALE_ZDP_BIND_Request(ZBIF_HANDLE zbif_handle,
+		ushort remote_dest_addr, uchar *src_ieee_addr, uchar src_ep,
+		ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep) {
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	unsigned char cmd[255] = { 0xA2, 0x21 };
+
+	unsigned char dest_addr_mode = 0x03;
+
+	cmd[2] = 23;
+
+	cmd[3] = LSB_USHORT(remote_dest_addr);
+	cmd[4] = MSB_USHORT(remote_dest_addr);
+
+	cmd[5] = src_ieee_addr[7];
+	cmd[6] = src_ieee_addr[6];
+	cmd[7] = src_ieee_addr[5];
+	cmd[8] = src_ieee_addr[4];
+	cmd[9] = src_ieee_addr[3];
+	cmd[10] = src_ieee_addr[2];
+	cmd[11] = src_ieee_addr[1];
+	cmd[12] = src_ieee_addr[0];
+
+	cmd[13] = src_ep;
+
+	cmd[14] = LSB_USHORT(cluster_id);
+	cmd[15] = MSB_USHORT(cluster_id);
+
+	cmd[16] = dest_addr_mode;
+
+	cmd[17] = dst_ieee_addr[7];
+	cmd[18] = dst_ieee_addr[6];
+	cmd[19] = dst_ieee_addr[5];
+	cmd[20] = dst_ieee_addr[4];
+	cmd[21] = dst_ieee_addr[3];
+	cmd[22] = dst_ieee_addr[2];
+	cmd[23] = dst_ieee_addr[1];
+	cmd[24] = dst_ieee_addr[0];
+
+	cmd[25] = dst_ep;
+
+	zb_print_bytes("ZDP_BIND_Request->", cmd, cmd[2] + 3);
+	zb_conn_send(zb_conn_h, cmd, cmd[2] + 3);
+}
+
+void FREESCALE_ZDP_UNBIND_Request(ZBIF_HANDLE zbif_handle,
+		ushort remote_dest_addr, uchar *src_ieee_addr, uchar src_ep,
+		ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep) {
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	unsigned char cmd[255] = { 0xA2, 0x22 };
+
+	unsigned char dest_addr_mode = 0x03;
+
+	cmd[2] = 23;
+
+	cmd[3] = LSB_USHORT(remote_dest_addr);
+	cmd[4] = MSB_USHORT(remote_dest_addr);
+
+	cmd[5] = src_ieee_addr[7];
+	cmd[6] = src_ieee_addr[6];
+	cmd[7] = src_ieee_addr[5];
+	cmd[8] = src_ieee_addr[4];
+	cmd[9] = src_ieee_addr[3];
+	cmd[10] = src_ieee_addr[2];
+	cmd[11] = src_ieee_addr[1];
+	cmd[12] = src_ieee_addr[0];
+
+	cmd[13] = src_ep;
+
+	cmd[14] = LSB_USHORT(cluster_id);
+	cmd[15] = MSB_USHORT(cluster_id);
+
+	cmd[16] = dest_addr_mode;
+
+	cmd[17] = dst_ieee_addr[7];
+	cmd[18] = dst_ieee_addr[6];
+	cmd[19] = dst_ieee_addr[5];
+	cmd[20] = dst_ieee_addr[4];
+	cmd[21] = dst_ieee_addr[3];
+	cmd[22] = dst_ieee_addr[2];
+	cmd[23] = dst_ieee_addr[1];
+	cmd[24] = dst_ieee_addr[0];
+
+	cmd[25] = dst_ep;
+
+	zb_print_bytes("ZDP_UNBIND->", cmd, cmd[2] + 3);
+	zb_conn_send(zb_conn_h, cmd, cmd[2] + 3);
+}
+
+void FREESCALE_APSME_UNBIND_request(ZBIF_HANDLE zbif_handle,
+		uchar *src_ieee_addr, uchar src_ep, ushort cluster_id,
+		uchar *dst_ieee_addr, uchar dst_ep) {
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	unsigned char cmd[255] = { 0x99, 0x09 };
+
+	unsigned char dest_addr_mode = 0x00;
+
+	cmd[2] = 21;
+
+	cmd[3] = src_ieee_addr[7];
+	cmd[4] = src_ieee_addr[6];
+	cmd[5] = src_ieee_addr[5];
+	cmd[6] = src_ieee_addr[4];
+	cmd[7] = src_ieee_addr[3];
+	cmd[8] = src_ieee_addr[2];
+	cmd[9] = src_ieee_addr[1];
+	cmd[10] = src_ieee_addr[0];
+
+	cmd[11] = src_ep;
+
+	cmd[12] = LSB_USHORT(cluster_id);
+	cmd[13] = MSB_USHORT(cluster_id);
+
+	cmd[14] = dest_addr_mode;
+
+	cmd[15] = dst_ieee_addr[7];
+	cmd[16] = dst_ieee_addr[6];
+	cmd[17] = dst_ieee_addr[5];
+	cmd[18] = dst_ieee_addr[4];
+	cmd[19] = dst_ieee_addr[3];
+	cmd[20] = dst_ieee_addr[2];
+	cmd[21] = dst_ieee_addr[1];
+	cmd[22] = dst_ieee_addr[0];
+
+	cmd[23] = dst_ep;
+
+	zb_print_bytes("APSME_UNBIND->", cmd, cmd[2] + 3);
+	zb_conn_send(zb_conn_h, cmd, cmd[2] + 3);
+}
+
+void FREESCALE_APSME_GET_request(ZBIF_HANDLE zbif_handle, uchar attr) {
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	// Store the current attribute that will be used for the response
+	attr_prev = attr;
+
+	if (attr == ZB_ATTR_GET_EUI64) {
+		unsigned char cmdEui[3] = { 0xA3, 0xD2, 0x00 };
+		zb_print_bytes("APSME_GET->", cmdEui, cmdEui[2] + 3);
+		zb_conn_send(zb_conn_h, cmdEui, cmdEui[2] + 3);
+	} else if (attr == ZB_ATTR_GET_CHANNEL_MASK) {
+		unsigned char cmdEui[3] = { 0xA3, 0x12, 0x00 };
+		zb_print_bytes("APSME_GET->", cmdEui, cmdEui[2] + 3);
+		zb_conn_send(zb_conn_h, cmdEui, cmdEui[2] + 3);
+	} else {
+		//use the default mode...
+		unsigned char cmd[7] = { 0xA3, 0x20, 0x04 };
+		cmd[3] = attr;
+		cmd[4] = 0x00;
+		cmd[5] = 0x00;
+		cmd[6] = 0x00;
+		zb_print_bytes("APSME_GET->", cmd, cmd[2] + 3);
+		zb_conn_send(zb_conn_h, cmd, cmd[2] + 3);
+	}
+}
+
+void sendWriteSAScommand(ZBIF_HANDLE zbif_handle) {
+	unsigned char cmd[255] = { 0x50, 0x01, 0x65 };
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	//Short Address                       [2 bytes]
+	cmd[3] = LSB_USHORT(sasAttr.ShortAddress);
+	cmd[4] = MSB_USHORT(sasAttr.ShortAddress);
+	//Extended PAN Id                     [8 bytes]
+	cmd[5] = sasAttr.ExtendedPANId[7];
+	cmd[6] = sasAttr.ExtendedPANId[6];
+	cmd[7] = sasAttr.ExtendedPANId[5];
+	cmd[8] = sasAttr.ExtendedPANId[4];
+	cmd[9] = sasAttr.ExtendedPANId[3];
+	cmd[10] = sasAttr.ExtendedPANId[2];
+	cmd[11] = sasAttr.ExtendedPANId[1];
+	cmd[12] = sasAttr.ExtendedPANId[0];
+	//APS Use Extended PAN Id             [8 bytes]
+	cmd[13] = sasAttr.APSUseExtendedPANId[7];
+	cmd[14] = sasAttr.APSUseExtendedPANId[6];
+	cmd[15] = sasAttr.APSUseExtendedPANId[5];
+	cmd[16] = sasAttr.APSUseExtendedPANId[4];
+	cmd[17] = sasAttr.APSUseExtendedPANId[3];
+	cmd[18] = sasAttr.APSUseExtendedPANId[2];
+	cmd[19] = sasAttr.APSUseExtendedPANId[1];
+	cmd[20] = sasAttr.APSUseExtendedPANId[0];
+	//PAN Id                              [2 bytes]
+	cmd[21] = LSB_USHORT(sasAttr.PANId);
+	cmd[22] = MSB_USHORT(sasAttr.PANId);
+	//Channels Mask                       [4 bytes]
+	cmd[23] = sasAttr.ChannelsMask[3];
+	cmd[24] = sasAttr.ChannelsMask[2];
+	cmd[25] = sasAttr.ChannelsMask[1];
+	cmd[26] = sasAttr.ChannelsMask[0];
+	//Protocol Version                    [1 byte ]
+	cmd[27] = sasAttr.ProtocolVersion;
+	//Stack Profile                       [1 byte ]
+	cmd[28] = sasAttr.StackProfile;
+	//Startup Control                     [1 byte ]
+	cmd[29] = sasAttr.StartupControl;
+	//Trust Center Address                [8 bytes]
+	cmd[30] = sasAttr.TrustCenterAddress[7];
+	cmd[31] = sasAttr.TrustCenterAddress[6];
+	cmd[32] = sasAttr.TrustCenterAddress[5];
+	cmd[33] = sasAttr.TrustCenterAddress[4];
+	cmd[34] = sasAttr.TrustCenterAddress[3];
+	cmd[35] = sasAttr.TrustCenterAddress[2];
+	cmd[36] = sasAttr.TrustCenterAddress[1];
+	cmd[37] = sasAttr.TrustCenterAddress[0];
+	//Trust Center Master Key             [16 bytes]
+	cmd[38] = sasAttr.TrustCenterMasterKey[15];
+	cmd[39] = sasAttr.TrustCenterMasterKey[14];
+	cmd[40] = sasAttr.TrustCenterMasterKey[13];
+	cmd[41] = sasAttr.TrustCenterMasterKey[12];
+	cmd[42] = sasAttr.TrustCenterMasterKey[11];
+	cmd[43] = sasAttr.TrustCenterMasterKey[10];
+	cmd[44] = sasAttr.TrustCenterMasterKey[9];
+	cmd[45] = sasAttr.TrustCenterMasterKey[8];
+	cmd[46] = sasAttr.TrustCenterMasterKey[7];
+	cmd[47] = sasAttr.TrustCenterMasterKey[6];
+	cmd[48] = sasAttr.TrustCenterMasterKey[5];
+	cmd[49] = sasAttr.TrustCenterMasterKey[4];
+	cmd[50] = sasAttr.TrustCenterMasterKey[3];
+	cmd[51] = sasAttr.TrustCenterMasterKey[2];
+	cmd[52] = sasAttr.TrustCenterMasterKey[1];
+	cmd[53] = sasAttr.TrustCenterMasterKey[0];
+	//Network Key                         [16 bytes]
+	cmd[54] = sasAttr.NetworkKey[15];
+	cmd[55] = sasAttr.NetworkKey[14];
+	cmd[56] = sasAttr.NetworkKey[13];
+	cmd[57] = sasAttr.NetworkKey[12];
+	cmd[58] = sasAttr.NetworkKey[11];
+	cmd[59] = sasAttr.NetworkKey[10];
+	cmd[60] = sasAttr.NetworkKey[9];
+	cmd[61] = sasAttr.NetworkKey[8];
+	cmd[62] = sasAttr.NetworkKey[7];
+	cmd[63] = sasAttr.NetworkKey[6];
+	cmd[64] = sasAttr.NetworkKey[5];
+	cmd[65] = sasAttr.NetworkKey[4];
+	cmd[66] = sasAttr.NetworkKey[3];
+	cmd[67] = sasAttr.NetworkKey[2];
+	cmd[68] = sasAttr.NetworkKey[1];
+	cmd[69] = sasAttr.NetworkKey[0];
+	//Use Insecure Join                   [1 byte ]
+	cmd[70] = sasAttr.UseInsecureJoin;
+	//Preconfigured Trust Center Link Key [16 bytes]
+	cmd[71] = sasAttr.PreconfiguredTrustCenterLinkKey[15];
+	cmd[72] = sasAttr.PreconfiguredTrustCenterLinkKey[14];
+	cmd[73] = sasAttr.PreconfiguredTrustCenterLinkKey[13];
+	cmd[74] = sasAttr.PreconfiguredTrustCenterLinkKey[12];
+	cmd[75] = sasAttr.PreconfiguredTrustCenterLinkKey[11];
+	cmd[76] = sasAttr.PreconfiguredTrustCenterLinkKey[10];
+	cmd[77] = sasAttr.PreconfiguredTrustCenterLinkKey[9];
+	cmd[78] = sasAttr.PreconfiguredTrustCenterLinkKey[8];
+	cmd[79] = sasAttr.PreconfiguredTrustCenterLinkKey[7];
+	cmd[80] = sasAttr.PreconfiguredTrustCenterLinkKey[6];
+	cmd[81] = sasAttr.PreconfiguredTrustCenterLinkKey[5];
+	cmd[82] = sasAttr.PreconfiguredTrustCenterLinkKey[4];
+	cmd[83] = sasAttr.PreconfiguredTrustCenterLinkKey[3];
+	cmd[84] = sasAttr.PreconfiguredTrustCenterLinkKey[2];
+	cmd[85] = sasAttr.PreconfiguredTrustCenterLinkKey[1];
+	cmd[86] = sasAttr.PreconfiguredTrustCenterLinkKey[0];
+	//Active Nwk Key Seq Number           [1 byte ]
+	cmd[87] = sasAttr.ActiveNwkKeySeqNumber;
+	////Network Key Type                    [1 byte ]
+	cmd[88] = sasAttr.NetworkKeyType;
+	//Network Manager Address             [2 bytes]
+	cmd[89] = LSB_USHORT(sasAttr.NetworkManagerAddress);
+	cmd[90] = MSB_USHORT(sasAttr.NetworkManagerAddress);
+	//Scan attempts                       [1 byte ]
+	cmd[91] = sasAttr.Scanattempts;
+	//Time between scans                  [2 bytes]
+	cmd[92] = LSB_USHORT(sasAttr.Timebetweenscans);
+	cmd[93] = MSB_USHORT(sasAttr.Timebetweenscans);
+	//Rejoin Interval                     [2 bytes]
+	cmd[94] = LSB_USHORT(sasAttr.RejoinInterval);
+	cmd[95] = MSB_USHORT(sasAttr.RejoinInterval);
+	//Maximum Rejoin Interval             [2 bytes]
+	cmd[96] = LSB_USHORT(sasAttr.MaximumRejoinInterval);
+	cmd[97] = MSB_USHORT(sasAttr.MaximumRejoinInterval);
+	//Indirect Poll Rate                  [2 bytes]
+	cmd[98] = LSB_USHORT(sasAttr.IndirectPollRate);
+	cmd[99] = MSB_USHORT(sasAttr.IndirectPollRate);
+	//Parent Link Retry Threshold         [1 byte ]
+	cmd[100] = sasAttr.ParentLinkRetryThreshold;
+	//Is Concentrator                     [1 byte ]
+	cmd[101] = sasAttr.IsConcentrator;
+	//Concentrator Radius                 [1 byte ]
+	cmd[102] = sasAttr.ConcentratorRadius;
+	//Concentrator Discovery Time         [1 byte ]
+	cmd[103] = sasAttr.ConcentratorDiscoveryTime;
+
+	zb_print_bytes("BlackBox.WriteSAS->", cmd, cmd[2] + 3);
+	zb_conn_send(zb_conn_h, cmd, cmd[2] + 3);
+}
+
+void FREESCALE_APSME_SET_request(ZBIF_HANDLE zbif_handle, uchar attr,
+		uchar attr_len, uchar *attr_value) {
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	unsigned char cmd[255]; // = { 0xA3, 0x21, 0x00, 0x00, 0x00, 0x00 };
+	memset(cmd, 0, sizeof(unsigned char) * 255);
+	cmd[0] = 0xA3;
+	cmd[1] = 0x21;
+	uchar *p = cmd + 3; // skip length
+
+	// Store the current attribute that will be used for the response
+	attr_prev = attr;
+
+#ifdef DEBUG_ZIGBEE_API
+	ZBPrint_APSME_SET_request (
+			attr,
+			attr_len,
+			attr_value
+	);
+#endif
+
+	switch (attr) {
+	case ZB_ATTR_CONFIG_NODE_DESCRIPTOR: {
+		// Store the logical_type (it will we used when calling the start network...)
+		ZB_NODE_DESC *g_node_desc = (ZB_NODE_DESC *) attr_value;
+		DevType = g_node_desc->logical_type;
+		zb_print(
+				"FREESCALE_APSME_SET_request::ZB_ATTR_CONFIG_NODE_DESCRIPTOR - DevType %02x\n", DevType);
+		// Autogen a return!
+		ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+		if (zbifCbs->APSME_SET_confirm) {
+			zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+		}
+		return;
+	}
+
+	case ZB_ATTR_CONFIG_PANID:
+		if (attr_len == 2) {
+			zb_print("FREESCALE_APSME_SET_request - ZB_ATTR_CONFIG_PANID\n");
+			// Get the PanId
+			sasAttr.PANId = *attr_value | (*(attr_value + 1) << 8);
+			// Autogen a return!
+			ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+			if (zbifCbs->APSME_SET_confirm) {
+				zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+			}
+		}
+		return;
+
+	case ZB_ATTR_CONFIG_STARTUPCONTROL:
+		zb_print(
+				"FREESCALE_APSME_SET_request - ZB_ATTR_CONFIG_STARTUPCONTROL\n");
+		// Get the PanId
+		sasAttr.StartupControl = *attr_value;
+		// Autogen a return!
+		ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+		if (zbifCbs->APSME_SET_confirm) {
+			zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+		}
+		return;
+
+	case ZB_ATTR_CONFIG_SIMPLE_DESCRIPTOR: {
+		int i, c;
+		zb_print(
+				"FREESCALE_APSME_SET_request - ZB_ATTR_CONFIG_SIMPLE_DESCRIPTOR\n");
+		// Reset the cmd buffer
+		memset(cmd, 0, sizeof(unsigned char) * 255);
+		cmd[0] = 0xa3;
+		cmd[1] = 0x0b;
+		//cmd[2] will be set at the end
+		i = 3;
+		memcpy(&cmd[3], attr_value, attr_len);
+		i += attr_len;
+		cmd[i++] = 0x01; //Maximum Window Size (Default value)
+		//Set the length
+		cmd[2] = i - 3;
+		// Message ready but the only difference with Ember is that the ApplicationNumberOutClusters must be moved just before its list
+		// where instead now it is next to the ApplicationNumberInClusters and before the ClusterLists!!
+		int numInCluster = cmd[9];
+		int numOutCluster = cmd[10];
+		for (c = 10; c < 10 + (numInCluster * 2); c++)
+			cmd[c] = cmd[c + 1];
+		cmd[10 + (numInCluster * 2)] = numOutCluster;
+		//Done, send the message
+		zb_conn_send(zb_conn_h, cmd, i);
+		return;
+	}
+
+	case ZB_ATTR_CONFIG_EXTENDEDPANID:
+		if (attr_len == 8) {
+			uchar v[8];
+			int c;
+
+			zb_print(
+					"FREESCALE_APSME_SET_request - ZB_ATTR_CONFIG_EXTENDEDPANID\n");
+			for (c = 0; c < 8; c++)
+				v[c] = attr_value[c];
+			// Store the ExtendedPanId
+			memcpy(sasAttr.ExtendedPANId, v, attr_len);
+			zb_print(
+					"ExtendedPANId: %02x %02x %02x %02x %02x %02x %02x %02x\n", sasAttr.ExtendedPANId[7], sasAttr.ExtendedPANId[6], sasAttr.ExtendedPANId[5], sasAttr.ExtendedPANId[4], sasAttr.ExtendedPANId[3], sasAttr.ExtendedPANId[2], sasAttr.ExtendedPANId[1], sasAttr.ExtendedPANId[0]);
+			// Autogen a return!
+			ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+			if (zbifCbs->APSME_SET_confirm) {
+				zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+			}
+		}
+		return;
+
+	case ZB_ATTR_CONFIG_FRAGMENT_WINDOW_SIZE:
+		if (attr_len == 2) {
+			*p++ = 0xCD;
+			p += 3;
+			*p++ = attr_value[0];
+			/*
+			 // Autogen a response since the fragmentation is not currently implemented in Freescale
+			 ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+			 if (zbifCbs->APSME_SET_confirm) {
+			 zbifCbs->APSME_SET_confirm (zbif_handle, 0x00, attr);
+			 }
+			 */
+		}
+		break;
+		//return;
+
+	case ZB_ATTR_CONFIG_FRAGMENT_DELAY_MS:
+		if (attr_len == 2) {
+			*p++ = 0xC9;
+			p += 3;
+			*p++ = attr_value[0];
+			/*
+			 // Autogen a response since the fragmentation is not currently implemented in Freescale
+			 ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+			 if (zbifCbs->APSME_SET_confirm) {
+			 zbifCbs->APSME_SET_confirm (zbif_handle, 0x00, attr);
+			 }
+			 */
+		}
+		break;
+		//return;
+
+	case ZB_ATTR_CONFIG_SECURITY:
+		if (attr_len == 1) {
+			selectedSecLevel = (int) attr_value[0];
+			// For Freescale this is not a run time option (you need to download a image without security if you want)
+			// Autogen a return!
+			ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+			if (zbifCbs->APSME_SET_confirm) {
+				zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+			}
+		}
+		return;
+
+	case ZB_TC_KEY_REQUEST_POLICY:
+	case ZB_APP_KEY_REQUEST_POLICY:
+	case 0x00: //EZSP_TRUST_CENTER_POLICY
+	{
+		//Those two values are just some policy setting valid for EZSP but not for Freescale!
+		ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+		if (zbifCbs->APSME_SET_confirm) {
+			zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+		}
+		return;
+	}
+
+	case ZB_ATTR_PRECONF_TC_LINK_KEY:
+		if (attr_len == 16) {
+			uchar v[16];
+			int c;
+
+			// Here it is passed the preconfiguredTCLinkKey!
+			zb_print(
+					"FREESCALE_APSME_SET_request - ZB_ATTR_PRECONF_TC_LINK_KEY\n");
+			for (c = 0; c < 16; c++)
+				v[c] = attr_value[15 - c];
+			// Store the PreconfiguredTrustCenterLinkKey
+			memcpy(sasAttr.PreconfiguredTrustCenterLinkKey, v, attr_len);
+			zb_print(
+					"preconfiguredTCLinkKey: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", sasAttr.PreconfiguredTrustCenterLinkKey[15], sasAttr.PreconfiguredTrustCenterLinkKey[14], sasAttr.PreconfiguredTrustCenterLinkKey[13], sasAttr.PreconfiguredTrustCenterLinkKey[12], sasAttr.PreconfiguredTrustCenterLinkKey[11], sasAttr.PreconfiguredTrustCenterLinkKey[10], sasAttr.PreconfiguredTrustCenterLinkKey[9], sasAttr.PreconfiguredTrustCenterLinkKey[8], sasAttr.PreconfiguredTrustCenterLinkKey[7], sasAttr.PreconfiguredTrustCenterLinkKey[6], sasAttr.PreconfiguredTrustCenterLinkKey[5], sasAttr.PreconfiguredTrustCenterLinkKey[4], sasAttr.PreconfiguredTrustCenterLinkKey[3], sasAttr.PreconfiguredTrustCenterLinkKey[2], sasAttr.PreconfiguredTrustCenterLinkKey[1], sasAttr.PreconfiguredTrustCenterLinkKey[0]);
+			// Autogen a return!
+			ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+			if (zbifCbs->APSME_SET_confirm) {
+				zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+			}
+		}
+		return;
+
+	case ZB_ATTR_NWK_KEY:
+		if (attr_len == 16) {
+			uchar v[16];
+			int c;
+			// Here it is passed the networkKey!
+			zb_print("FREESCALE_APSME_SET_request - ZB_ATTR_NWK_KEY\n");
+			for (c = 0; c < 16; c++)
+				v[c] = attr_value[15 - c];
+			// Store the NetworkKey
+			memcpy(sasAttr.NetworkKey, v, attr_len);
+			zb_print(
+					"NETWORK KEY STORED: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", sasAttr.NetworkKey[15], sasAttr.NetworkKey[14], sasAttr.NetworkKey[13], sasAttr.NetworkKey[12], sasAttr.NetworkKey[11], sasAttr.NetworkKey[10], sasAttr.NetworkKey[9], sasAttr.NetworkKey[8], sasAttr.NetworkKey[7], sasAttr.NetworkKey[6], sasAttr.NetworkKey[5], sasAttr.NetworkKey[4], sasAttr.NetworkKey[3], sasAttr.NetworkKey[2], sasAttr.NetworkKey[1], sasAttr.NetworkKey[0]);
+			// Autogen a return!
+			ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+			if (zbifCbs->APSME_SET_confirm) {
+				zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+			}
+		}
+		return;
+
+	case ZB_ATTR_KEY_TABLE_SIZE: {
+		TCLinkKeyTableSize = attr_value[0];
+		zb_print("ZB_ATTR_KEY_TABLE_SIZE value = %02x", TCLinkKeyTableSize);
+		// Autogen a return!
+		ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+		if (zbifCbs->APSME_SET_confirm) {
+			zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+		}
+		return;
+	}
+
+	case ZB_ATTR_KEY_TABLE_ENTRY: {
+		// Use a ZTC-SetApsDeviceKeyPairSet.Request (A3 3E)
+		cmd[0] = 0xA3;
+		cmd[1] = 0x3E;
+		cmd[2] = 25;
+		// Insert in order: IEEEAddr, KeyType and Aps_Key
+		memcpy(&cmd[3], &attr_value[1], 25); //They're coming in the correct order from GalZbIf, just ignore the first byte, the index!
+		// Modify the KeyType to ApplicationLinkKey (0x00 for Ember, 0x03 here for Freescale)
+		cmd[11] = 0x03;
+		//Store the whole message (it will be send once the network is up!)
+		memcpy(TCLinkKeyTable[attr_value[0]], cmd, 28);
+		// Autogen a return!
+		ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+		zbifCbs->APSME_SET_confirm(zbif_handle, 0x00, attr);
+		return;
+	}
+
+	case ZB_ATTR_CONFIG_CHANNEL_MASK:
+		if (attr_len == 4) {
+			// Store the channel mask!
+			sasAttr.ChannelsMask[3] = attr_value[0];
+			sasAttr.ChannelsMask[2] = attr_value[1];
+			sasAttr.ChannelsMask[1] = attr_value[2];
+			sasAttr.ChannelsMask[0] = attr_value[3];
+			zb_print(
+					"Selected radio channel = %02x%02x%02x%02x\n", sasAttr.ChannelsMask[3], sasAttr.ChannelsMask[2], sasAttr.ChannelsMask[1], sasAttr.ChannelsMask[0]);
+			// We concluded the setting of all the possible parameters, so now call the WriteSAS command!
+			sendWriteSAScommand(zbif_handle);
+			// We shall wait a confirm (BlackBoxWriteSAS.Confirm)
+			return;
+		}
+		break;
+
+	default:
+		*p++ = attr;
+		p += 3;
+		memcpy(p, attr_value, attr_len);
+		p += attr_len;
+		break;
+	}
+
+	// If we arrive it is because we have to send the above prepared command!
+	cmd[2] = p - cmd - 3;
+	zb_conn_send(zb_conn_h, cmd, p - cmd);
+}
+
+void FREESCALE_APSME_SET_confirm(uchar status, uchar attr) {
+	zb_print("APSME_SET_confirm: status = 0x%02x\n", status);
+	return;
+}
+
+void FREESCALE_MGMT_PERMIT_JOINING_request(ZBIF_HANDLE zbif_handle,
+		ushort nwk_addr, int permitDuration) {
+	zb_print("FREESCALE_MGMT_PERMIT_JOINING_request - NOT implemented");
+
+}
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+
+void FREESCALE_APSME_REMOVE_DEVICE_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *parent_ieee_addr,
+		uchar *child_ieee_addr
+) {
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+
+	unsigned char cmd[255] = {0x99, 0xF4};
+
+	cmd[2] = 16;
+	cmd[3] = parent_ieee_addr[7];
+	cmd[4] = parent_ieee_addr[6];
+	cmd[5] = parent_ieee_addr[5];
+	cmd[6] = parent_ieee_addr[4];
+	cmd[7] = parent_ieee_addr[3];
+	cmd[8] = parent_ieee_addr[2];
+	cmd[9] = parent_ieee_addr[1];
+	cmd[10] = parent_ieee_addr[0];
+
+	cmd[11] = child_ieee_addr[7];
+	cmd[12] = child_ieee_addr[6];
+	cmd[13] = child_ieee_addr[5];
+	cmd[14] = child_ieee_addr[4];
+	cmd[15] = child_ieee_addr[3];
+	cmd[16] = child_ieee_addr[2];
+	cmd[17] = child_ieee_addr[1];
+	cmd[18] = child_ieee_addr[0];
+
+	zb_print_bytes("APSME_SET->", cmd, cmd[2]+3);
+	zb_conn_send(zb_conn_h, cmd , cmd[2]+3);
+
+}
+void FREESCALE_APSME_TRANSPORT_KEY_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *dst_ieee_addr,
+		uchar key_type,
+		ZB_TRANSPORT_KEY_DATA *transport_key_data
+) {
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	unsigned char cmd[255] = {0x99, 0xd1};
+
+	switch(key_type) {
+		case 0x00:
+		cmd[2] = 0x21;
+		cmd[3] = key_type;
+		cmd[4] = dst_ieee_addr[7];
+		cmd[5] = dst_ieee_addr[6];
+		cmd[6] = dst_ieee_addr[5];
+		cmd[7] = dst_ieee_addr[4];
+		cmd[8] = dst_ieee_addr[3];
+		cmd[9] = dst_ieee_addr[2];
+		cmd[10] = dst_ieee_addr[1];
+		cmd[11] = dst_ieee_addr[0];
+
+		cmd[12] = transport_key_data->tcmk.parent_ieee_addr[7];
+		cmd[13] = transport_key_data->tcmk.parent_ieee_addr[6];
+		cmd[14] = transport_key_data->tcmk.parent_ieee_addr[5];
+		cmd[15] = transport_key_data->tcmk.parent_ieee_addr[4];
+		cmd[16] = transport_key_data->tcmk.parent_ieee_addr[3];
+		cmd[17] = transport_key_data->tcmk.parent_ieee_addr[2];
+		cmd[18] = transport_key_data->tcmk.parent_ieee_addr[1];
+		cmd[19] = transport_key_data->tcmk.parent_ieee_addr[0];
+
+		cmd[20] = transport_key_data->tcmk.tc_master_key[15];
+		cmd[21] = transport_key_data->tcmk.tc_master_key[14];
+		cmd[22] = transport_key_data->tcmk.tc_master_key[13];
+		cmd[23] = transport_key_data->tcmk.tc_master_key[12];
+		cmd[24] = transport_key_data->tcmk.tc_master_key[11];
+		cmd[25] = transport_key_data->tcmk.tc_master_key[10];
+		cmd[26] = transport_key_data->tcmk.tc_master_key[9];
+		cmd[27] = transport_key_data->tcmk.tc_master_key[8];
+		cmd[28] = transport_key_data->tcmk.tc_master_key[7];
+		cmd[29] = transport_key_data->tcmk.tc_master_key[6];
+		cmd[30] = transport_key_data->tcmk.tc_master_key[5];
+		cmd[31] = transport_key_data->tcmk.tc_master_key[4];
+		cmd[32] = transport_key_data->tcmk.tc_master_key[3];
+		cmd[33] = transport_key_data->tcmk.tc_master_key[2];
+		cmd[34] = transport_key_data->tcmk.tc_master_key[1];
+		cmd[35] = transport_key_data->tcmk.tc_master_key[0];
+
+		break;
+		case 0x01:
+
+		cmd[2] = 0x23;
+		cmd[3] = key_type;
+		cmd[4] = dst_ieee_addr[7];
+		cmd[5] = dst_ieee_addr[6];
+		cmd[6] = dst_ieee_addr[5];
+		cmd[7] = dst_ieee_addr[4];
+		cmd[8] = dst_ieee_addr[3];
+		cmd[9] = dst_ieee_addr[2];
+		cmd[10] = dst_ieee_addr[1];
+		cmd[11] = dst_ieee_addr[0];
+
+		cmd[12] = transport_key_data->nwk_key.key_seq_num;
+
+		cmd[13] = transport_key_data->nwk_key.nwk_key[15];
+		cmd[14] = transport_key_data->nwk_key.nwk_key[14];
+		cmd[15] = transport_key_data->nwk_key.nwk_key[13];
+		cmd[16] = transport_key_data->nwk_key.nwk_key[12];
+		cmd[17] = transport_key_data->nwk_key.nwk_key[11];
+		cmd[18] = transport_key_data->nwk_key.nwk_key[10];
+		cmd[19] = transport_key_data->nwk_key.nwk_key[9];
+		cmd[20] = transport_key_data->nwk_key.nwk_key[8];
+		cmd[21] = transport_key_data->nwk_key.nwk_key[7];
+		cmd[22] = transport_key_data->nwk_key.nwk_key[6];
+		cmd[23] = transport_key_data->nwk_key.nwk_key[5];
+		cmd[24] = transport_key_data->nwk_key.nwk_key[4];
+		cmd[25] = transport_key_data->nwk_key.nwk_key[3];
+		cmd[26] = transport_key_data->nwk_key.nwk_key[2];
+		cmd[27] = transport_key_data->nwk_key.nwk_key[1];
+		cmd[28] = transport_key_data->nwk_key.nwk_key[0];
+
+		cmd[29] = transport_key_data->nwk_key.use_parent;
+
+		cmd[30] = transport_key_data->nwk_key.parent_ieee_addr[7];
+		cmd[31] = transport_key_data->nwk_key.parent_ieee_addr[6];
+		cmd[32] = transport_key_data->nwk_key.parent_ieee_addr[5];
+		cmd[33] = transport_key_data->nwk_key.parent_ieee_addr[4];
+		cmd[34] = transport_key_data->nwk_key.parent_ieee_addr[3];
+		cmd[35] = transport_key_data->nwk_key.parent_ieee_addr[2];
+		cmd[36] = transport_key_data->nwk_key.parent_ieee_addr[1];
+		cmd[37] = transport_key_data->nwk_key.parent_ieee_addr[0];
+
+		break;
+
+		case 0x02:
+		cmd[2] = 0x22;
+		cmd[3] = key_type;
+		cmd[4] = dst_ieee_addr[7];
+		cmd[5] = dst_ieee_addr[6];
+		cmd[6] = dst_ieee_addr[5];
+		cmd[7] = dst_ieee_addr[4];
+		cmd[8] = dst_ieee_addr[3];
+		cmd[9] = dst_ieee_addr[2];
+		cmd[10] = dst_ieee_addr[1];
+		cmd[11] = dst_ieee_addr[0];
+
+		cmd[12] = transport_key_data->link_key.partner_ieee_addr[7];
+		cmd[13] = transport_key_data->link_key.partner_ieee_addr[6];
+		cmd[14] = transport_key_data->link_key.partner_ieee_addr[5];
+		cmd[15] = transport_key_data->link_key.partner_ieee_addr[4];
+		cmd[16] = transport_key_data->link_key.partner_ieee_addr[3];
+		cmd[17] = transport_key_data->link_key.partner_ieee_addr[2];
+		cmd[18] = transport_key_data->link_key.partner_ieee_addr[1];
+		cmd[19] = transport_key_data->link_key.partner_ieee_addr[0];
+
+		cmd[20] = transport_key_data->link_key.initiator;
+
+		cmd[21] = transport_key_data->link_key.key[15];
+		cmd[22] = transport_key_data->link_key.key[14];
+		cmd[23] = transport_key_data->link_key.key[13];
+		cmd[24] = transport_key_data->link_key.key[12];
+		cmd[25] = transport_key_data->link_key.key[11];
+		cmd[26] = transport_key_data->link_key.key[10];
+		cmd[27] = transport_key_data->link_key.key[9];
+		cmd[28] = transport_key_data->link_key.key[8];
+		cmd[29] = transport_key_data->link_key.key[7];
+		cmd[30] = transport_key_data->link_key.key[6];
+		cmd[31] = transport_key_data->link_key.key[5];
+		cmd[32] = transport_key_data->link_key.key[4];
+		cmd[33] = transport_key_data->link_key.key[3];
+		cmd[34] = transport_key_data->link_key.key[2];
+		cmd[35] = transport_key_data->link_key.key[1];
+		cmd[36] = transport_key_data->link_key.key[0];
+		break;
+		default:
+		break;
+	}
+
+	zb_print_bytes("APSME_TRANSPORT_KEY->", cmd, cmd[2]+3);
+	zb_conn_send(zb_conn_h, cmd , cmd[2]+3);
+}
+
+void FREESCALE_NLME_LEAVE_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *dev_ieee_addr,
+		uchar remove_children,
+		uchar rejoin,
+		uchar reuse_address,
+		uchar silent
+) {
+}
+
+#endif /* INCLUDE_ZIGBEE_SECURITY */
+
+void FREESCALE_ZDO_ERROR_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort cluster_id, uchar expected_len) {
+	zb_not_yet_implemented()
+}
+
+/**
+ * This function provides decoding functionalities.
+ * The passed data should not be freed!
+ */
+
+ushort g_data_short_1[128];
+uchar g_data_uchar_1[256];
+
+#define set_zero_uchar(a)  memset(a,0,256*sizeof(uchar))
+#define set_zero_ushort(a) memset(a,0,128*sizeof(ushort))
+
+int indexTCLinkKey = 0;
+void initializeTCLinkKeyTable(ZBIF_HANDLE zbif_handle) {
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	if (indexTCLinkKey < TCLinkKeyTableSize) {
+		zb_print(
+				"initializeTCLinkKeyTable - Configuring index %02x\n", indexTCLinkKey);
+		zb_conn_send(zb_conn_h, TCLinkKeyTable[indexTCLinkKey], 28);
+		indexTCLinkKey++;
+	} else {
+		zb_print("initializeTCLinkKeyTable - Completed!\n");
+		// Request for the networkMaterialKey (in case a random security key is generated)
+		ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+		unsigned char cmd[7] = { 0xA3, 0x22, 0x04, 0xA1, 0x00, 0x01, 0x00 };
+		zb_print_bytes("APSME_GET->", cmd, cmd[2] + 3);
+		zb_conn_send(zb_conn_h, cmd, cmd[2] + 3);
+	}
+}
+
+void FREESCALE_ParseNExec(ZBIF_HANDLE zbif_handle, uchar *p, int size) {
+	int i;
+
+	//uchar out_data[256 * 256];
+	uchar dst_addr_2[2];
+	uchar src_addr_2[2];
+	uchar dst_addr_8[8];
+	uchar src_addr_8[8];
+
+	ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+
+	if (zbifCbs == NULL) {
+		zb_print_bytes(
+				"Received those bytes but without callback, ignoring them >>>> ",
+				p, size);
+		/* error! */
+		return;
+	}
+
+	/* retrieve the state */
+	//int state = ((zbif_status_t *) zbif_handle)->state;
+	//zb_print_bytes("FREESCALE_ParseNExec - Parsing >>>> ", p, size);
+	switch (p[0]) {
+	//**** p[0] ****
+	case 0x50:
+		if (p[1] == 0x04) {
+			zb_print("ZTC-BlackBoxWriteSAS.Confirm\n");
+			// Act as the Set.Confirm command was doing before...
+			zbifCbs->APSME_SET_confirm(zbif_handle, p[3], attr_prev);
+		}
+		break;
+
+		//**** p[0] ****
+	case 0x84: {
+		switch (p[1]) {
+
+		case 0x05:
+			zb_print("MacGetPIBAttribute.Confirm: ");
+			printBytes(p);
+			break;
+
+		case 0x14:
+			zb_print("MacPollNotify.Indication: ");
+			printBytes(p);
+			break;
+
+			//MacStart.Confirm
+		case 0x0E:
+			if (p[3] == 0x00) {
+				//Success, we can request the short address assigned using NLME-GET
+				unsigned char cmd[7] = { 0xa3, 0x22, 0x04, 0x96, 0x00, 0x00,
+						0x00 };
+				zb_print_bytes("NLME-GET.Request: ", cmd, cmd[2] + 3);
+				zb_conn_send(((zbif_status_t *) zbif_handle)->zb_conn_h, cmd,
+						cmd[2] + 3);
+			} else {
+				zb_print("ERROR: MacStart.Request failed!\n");
+			}
+			break;
+
+		default:
+			break;
+		}
+		break;
+	}
+
+		//**** p[0] ****
+	case 0x96: {
+		switch (p[1]) {
+		case 0x54:
+			zb_print("NLME-ENERGY-SCAN.Request: ");
+			printBytes(p);
+			break;
+		case 0x34:
+			zb_print("NLME-NETWORK-DISCOVERY.Request: ");
+			printBytes(p);
+			break;
+		case 0x35:
+			zb_print("NLME-NETWORK-FORMATION.Request: ");
+			printBytes(p);
+			break;
+		case 0x37:
+			zb_print("NLME-START-ROUTER.Request: ");
+			printBytes(p);
+			break;
+		default:
+			/*
+			 #ifdef DEBUG_ZIGBEE_API
+			 zb_print("NLME Req Unhandled OP %02x\n",p[1]);
+			 #endif
+			 */
+			break;
+		}
+		break;
+	}
+
+		//**** p[0] ****
+	case 0x97:
+		switch (p[1]) {
+		case 0x55:
+			zb_print("NLME-ENERGY-SCAN.Confirm: ");
+			printBytes(p);
+			break;
+		case 0x41:
+			zb_print("NLME-NETWORK-DISCOVERY.Confirm: ");
+			printBytes(p);
+			break;
+
+		case 0x42:
+			zb_print("NLME-NETWORK-FORMATION.Confirm: ");
+			printBytes(p);
+			if (p[3] != 0x00) {
+				/*
+				 <ParmValue>0xC2</ParmValue>
+				 <ParmText>INVALID_REQUEST</ParmText>
+				 <ParmHint>Not Valid Request</ParmHint>
+
+				 <ParmValue>0xC4</ParmValue>
+				 <ParmText>STARTUP_FAILURE</ParmText>
+				 <ParmHint>Cannot initiate as Zigbee Coordinator</ParmHint>
+
+				 <ParmValue>0xEC</ParmValue>
+				 <ParmText>NO_SHORT_ADDRESS</ParmText>
+				 <ParmHint>Doesn't have short address</ParmHint>
+
+				 <ParmValue>0xF3</ParmValue>
+				 <ParmText>UNAVIALBLE_KEY</ParmText>
+				 <ParmHint>Key not present</ParmHint>
+
+				 <ParmValue>0xE5</ParmValue>
+				 <ParmText>FRAME_TOO_LONG</ParmText>
+				 <ParmHint>Frame too long</ParmHint>
+
+				 <ParmValue>0xE4</ParmValue>
+				 <ParmText>FAILED_SECURITY_CHECK</ParmText>
+				 <ParmHint>Failed security check</ParmHint>
+
+				 <ParmValue>0xE8</ParmValue>
+				 <ParmText>INVALID_PARAMETER</ParmText>
+				 <ParmHint>Not Valid Parameter</ParmHint>
+				 */
+				printf("\n************************\n");
+				printf(
+						"NETWORK FORMATION FAILED - Reason: 0x%02x\n************************\n\n",
+						p[3]);
+				//Network creation failed, report the error!
+				if (zbifCbs->ZDO_START_confirm)
+					zbifCbs->ZDO_START_confirm(zbif_handle, p[3],
+							nwkShortAddress);
+			}
+			break;
+
+		case 0x43:
+			zb_print("NLME-PERMIT-JOINING.Confirm - status %02x\n", p[3]);
+			//Since the current GAL send a MGMT_Permit_Join through an APSDE_Data, we won't get the response so we intercept this callback here!
+			uchar statusValue = 0x00;
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_MGMT_PERMIT_JOINING_response(statusValue);
+#endif
+			//zb_print("Entering here, calling the permitJoinResponse handler\r\n");
+			zbifCbs->MGMT_PERMIT_JOINING_response(zbif_handle, statusValue);
+			break;
+
+		case 0x44:
+			zb_print("NLME-START-ROUTER.Confirm: ");
+			printBytes(p);
+			break;
+
+		case 0x45: {
+			zb_print("NLME-JOIN.Indication: ");
+			printBytes(p);
+		}
+			break;
+
+		case 0x46:
+			zb_print("NLME-JOIN.Confirm: status %02x\n", p[3]);
+			//printBytes(p);
+			if (p[8] != 0x00) {
+				//Join failed, report the error!
+				if (zbifCbs->ZDO_START_confirm)
+					zbifCbs->ZDO_START_confirm(zbif_handle, p[8],
+							nwkShortAddress);
+			}
+			break;
+
+		case 0x49:
+			zb_print("NLME-LEAVE.Indication: ");
+			printBytes(p);
+			// Send a ClearApsDeviceKeyPairSet to remove any entries!
+			ZB_CONN_HANDLE zb_conn_h =
+					((zbif_status_t *) zbif_handle)->zb_conn_h;
+			unsigned char cmdClearDevice[12] = { 0xA3, 0x3F, 0x08 };
+			memcpy(&cmdClearDevice[3], &p[3], IEEE_ADDR_LEN);
+			zb_print_bytes("ZTC-ClearApsDeviceKeyPairSet.Request ",
+					cmdClearDevice, cmdClearDevice[2] + 3);
+			zb_conn_send(zb_conn_h, cmdClearDevice, cmdClearDevice[2] + 3);
+			// Since we sent a LeaveRequest trough an APSDE-Data, we would never receive a MGMT_Leave_Response, so we intercept it here!
+			zb_print(
+					"NLME-LEAVE.Indication: Convert it to a MGMT_LEAVE_response\n");
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_MGMT_LEAVE_response(0x00);
+#endif
+			zbifCbs->MGMT_LEAVE_response(zbif_handle, 0x00);
+			// Check if there is also a callback registered for the confirm callback!
+			if (zbifCbs->MGMT_LEAVE_confirm) {
+				uchar ieee_addr[IEEE_ADDR_LEN];
+				memcpy(ieee_addr, &p[3], IEEE_ADDR_LEN);
+				swap_bytes(ieee_addr, IEEE_ADDR_LEN);
+#ifdef DEBUG_ZIGBEE_API
+				//zb_print("NLME-LEAVE.Indication - Node %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x left the network\n",
+				//	ieee_addr[0],ieee_addr[1],ieee_addr[2],ieee_addr[3],ieee_addr[4],ieee_addr[5],ieee_addr[6],ieee_addr[7]);
+				ZBPrint_MGMT_LEAVE_confirm(ieee_addr,p[11]);
+#endif
+				zbifCbs->MGMT_LEAVE_confirm(zbif_handle, ieee_addr, p[11]);
+			}
+			break;
+
+		case 0x70:
+			if (p[3] == 0xA2) {
+				printf(
+						"NLME-ProcessSecureFrame.Confirm - ERROR: 0x%02x - Unable to encrypt/decrypt the packet\n",
+						p[3]);
+			}
+			/*
+			 else if (p[3] == 0x06){
+			 zb_print("NLME-ProcessSecureFrame.Confirm: status 0x%02x",p[3]);
+			 zb_print(" (security was not applied or removed to/from the packet)\n");
+			 }
+			 */
+			else {
+				//printBytes(p);
+			}
+			break;
+
+		default:
+			break;
+		}
+		break;
+
+		//**** p[0] ****1
+	case 0x98:
+		switch (p[1]) {
+		case 0x07:
+			for (i = 0; i < 8; i++) {
+				src_addr_8[i] = p[4 + i];
+				dst_addr_8[i] = p[16 + i];
+			}
+			zbifCbs->APSME_BIND_confirm(zbif_handle, p[3], //Status
+					src_addr_8, //Src ieee Addr
+					p[12], //Src End point
+					p[14] | p[13] << 8, //Cluster Id
+					dst_addr_8, //Dst ieee addr
+					p[24]); //Dst End point
+			break;
+/*
+		case 0x08:
+			for (i= 0; i < 8; i++)
+			{
+				src_addr_8[i] = p[ 4 + i];
+				dst_addr_8[i] = p[16 + i];
+			}
+			zbifCbs->APSME_UNBIND_confirm(zbif_handle,
+					p[3], //Status
+					src_addr_8,//Src ieee Addr
+					p[12],//Src End point
+					p[14] | p[13] << 8,//Cluster Id
+					dst_addr_8,//Dst ieee addr
+					p[24]);//Dst End point
+			break;
+*/
+		case 0xC0:
+			zb_print("APSME-TRANSPORT-KEY.Confirm: ");
+			printBytes(p);
+			break;
+
+		case 0xCC:
+			if (p[3] == 0xA2) {
+				zb_print(
+						"APSME-ProcessSecureFrame.Confirm - ERROR: 0x%02x - Unable to encrypt or decrypt the packet", p[3]);
+			}
+			/*
+			 else if (p[3] == 0x06){
+			 zb_print("APSME-ProcessSecureFrame.Confirm: status 0x%02x",p[3]);
+			 zb_print(" (security was not applied or removed to/from the packet)\n");
+			 }
+			 */
+			/*
+			 else{
+			 printBytes(p);
+			 }
+			 */
+			break;
+
+		default:
+			break;
+		}
+		break;
+
+		//**** p[0] ****
+	case 0x99:
+		if (p[1] == 0xD1) {
+			zb_print("APSME-TRANSPORT-KEY.Request: ");
+			printBytes(p);
+		}
+		break;
+
+		//**** p[0] ****
+	case 0x9A:
+		if (p[1] == 0x33) {
+			zb_print("NLDE-DATA.Request: ");
+			printBytes(p);
+		}
+		break;
+
+		//**** p[0] ****
+	case 0x9B:
+		if (p[1] == 0x3F) {
+			zb_print("NLDE-DATA.Confirm: ");
+			printBytes(p);
+		} else if (p[1] == 0x40) {
+			zb_print("NLDE-DATA.Indication: ");
+			printBytes(p);
+		}
+		break;
+
+	case 0xA2:
+		switch (p[1]) {
+		case 0x13:
+			zb_print("ZDP-EndDeviceAnnounce.Request: ");
+			printBytes(p);
+			// Here we have also to callback the announcement of this new device!
+			if (zbifCbs->ZDO_DEVICE_ANNCE_indication) {
+				uchar ieee_addr[IEEE_ADDR_LEN];
+				ushort nwk_addr = p[5] + (p[6] << 8);
+				memcpy(ieee_addr, &p[7], IEEE_ADDR_LEN);
+				swap_bytes(ieee_addr, IEEE_ADDR_LEN);
+				uchar capability = p[15];
+#ifdef DEBUG_ZIGBEE_API
+				ZBPrint_ZDO_DEVICE_ANNCE_indication (nwk_addr,ieee_addr,capability);
+#endif
+				zbifCbs->ZDO_DEVICE_ANNCE_indication(zbif_handle, nwk_addr,
+						ieee_addr, capability);
+			}
+			break;
+		default:
+			break;
+		}
+		break;
+
+		//**** p[0] ****
+	case 0x9D:
+		switch (p[1]) {
+		case 0x00:
+			zb_print("APSDE-DATA.Confirm:\n");
+			printBytes(p);
+			for (i = 0; i < 8; i++)
+				dst_addr_8[i] = p[4 + i];
+			zbifCbs->APSDE_DATA_confirm(zbif_handle, p[3], dst_addr_8, p[12],
+					p[13], p[14]);
+			break;
+
+		case 0x01:
+			set_zero_uchar(g_data_uchar_1);
+			//DestAddr_mode p[3]
+			dst_addr_2[0] = p[4];
+			dst_addr_2[1] = p[5];
+			//DestEndPoint p[6]
+			//SrcAddrMode p[7]
+			src_addr_2[0] = p[8];
+			src_addr_2[1] = p[9];
+			//Store the latest scrAddr and scrAddrMode for the MGMT_LQI
+			lastSrcAddrMode = 0x02; //It doesn't change for the APSDE-DATA.Indication
+			lastSrcAddr[0] = p[8];
+			lastSrcAddr[1] = p[9];
+			//SrcEndpoint p[10]
+			//ProfileId p[11] & p[12]
+			//ClusterId p[13] & p[14]
+			//asduLength[15]
+			//asdu from p[16]
+			for (i = 0; i < p[15]; i++)
+				g_data_uchar_1[i] = p[16 + i];
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_APSDE_DATA_indication(
+					p[3],
+					dst_addr_2,
+					p[6],
+					p[7],
+					src_addr_2,
+					p[10],
+					p[11] | p[12] << 8,
+					p[13] | p[14] << 8,
+					p[15],
+					g_data_uchar_1,
+					p[15+p[15] + 2],
+					p[15+p[15] + 3]);
+#endif
+			zbifCbs->APSDE_DATA_indication(zbif_handle, p[3], //Dest Addr Mode
+					dst_addr_2, //Dest Addr
+					p[6], //Dest Endpoint
+					p[7], //Src Addr Mode
+					src_addr_2, //Src Addr
+					p[10], //Src Endpoint
+					p[11] | p[12] << 8, //Profile Id
+					p[13] | p[14] << 8, //Cluster Id
+					p[15], //Asdu Len
+					g_data_uchar_1, //Asdu
+					p[15 + p[15] + 2], //Web Broadcast,
+					p[15 + p[15] + 3] //Security Status,
+					);
+			// Send a DeviceAnnouncement indication when we recognize this specific message!
+			if (p[6] == 0x00 && p[14] == 0x00 && p[13] == 0x13) { //0x0013 is the DeviceAnnounce clusterId!
+				zb_print(
+						"APSDE-DATA.Indication - (Freescale_if.c) - DeviceAnnounce message\n");
+				if (zbifCbs->ZDO_DEVICE_ANNCE_indication) {
+					uchar ieee_addr[IEEE_ADDR_LEN];
+					ushort nwk_addr = g_data_uchar_1[1]
+							+ (g_data_uchar_1[2] << 8);
+					memcpy(ieee_addr, &g_data_uchar_1[3], IEEE_ADDR_LEN);
+					swap_bytes(ieee_addr, IEEE_ADDR_LEN);
+					uchar capability = g_data_uchar_1[11];
+#ifdef DEBUG_ZIGBEE_API
+					ZBPrint_ZDO_DEVICE_ANNCE_indication (nwk_addr,ieee_addr,capability);
+#endif
+					zbifCbs->ZDO_DEVICE_ANNCE_indication(zbif_handle, nwk_addr,
+							ieee_addr, capability);
+				}
+			}
+			break;
+
+		case 0x03:
+			zb_print("APS-ConfirmID.Report\n");
+			break;
+
+		default:
+			break;
+		}
+		break;
+
+		//**** p[0] ****
+	case 0xA0:
+		switch (p[1]) {
+		case 0x70:
+			if (p[3] == 0xA2) {
+				zb_print(
+						"ZDP-Nwk-ProcessSecureFrame.Confirm - ERROR: 0x%02x - Unable to encrypt or decrypt the packet\n", p[3]);
+			}
+			/*
+			 else if (p[3] == 0x06){
+			 zb_print("ZDP-Nwk-ProcessSecureFrame.Confirm: status 0x%02x",p[3]);
+			 zb_print(" (security was not applied or removed to/from the packet)\n");
+			 }
+			 */
+			else {
+				//printBytes(p);
+			}
+			break;
+
+		case 0x80:
+			zb_print("ZDP-NWK_addr.response: ");
+			printBytes(p);
+			break;
+
+		case 0x81:
+			zb_print("ZDP-IEEE_addr.response: ");
+			printBytes(p);
+			//p[4] IEEEAddrRemoteDev
+			//p[12] NWKAddrRemoteDev
+			//p[14] NumOfAssociatedDevice
+			//p[15] StartIndex
+			//p[16-17] * 2 ListOfShortAddress
+			uchar status = p[3];
+			uchar ieee_addr[IEEE_ADDR_LEN];
+			memcpy(ieee_addr, &p[4], IEEE_ADDR_LEN);
+			swap_bytes(ieee_addr, IEEE_ADDR_LEN);
+			ushort nwk_addr = p[12] + (p[13] << 8);
+			uchar num_assoc_dev = p[14];
+			uchar start_index;
+			ushort *nwk_addr_assoc_dev_list;
+			if (num_assoc_dev > 0) {
+				start_index = p[15];
+				nwk_addr_assoc_dev_list = (ushort*) &p[16];
+			} else {
+				start_index = 0;
+				nwk_addr_assoc_dev_list = NULL;
+			}
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_IEEE_ADDR_confirm (
+					status,
+					ieee_addr,
+					nwk_addr,
+					num_assoc_dev,
+					start_index,
+					nwk_addr_assoc_dev_list
+			);
+#endif
+			zbifCbs->ZDO_IEEE_ADDR_confirm(zbif_handle, status, ieee_addr,
+					nwk_addr, num_assoc_dev, start_index,
+					nwk_addr_assoc_dev_list);
+			break;
+
+		case 0x82: {
+			zb_print("ZDP-NodeDescriptor.Response: ");
+			printBytes(p);
+
+			//Length
+			p += 3;
+			//Status
+			uchar status = *p++;
+			//NWKAddrOfInterest
+			ushort nwk_addr = *p + (*(p + 1) << 8);
+			p += 2;
+			ZB_NODE_DESC node_desc;
+			//Byte 1
+			node_desc.logical_type = *p & 0x07;
+#ifdef ZIGBEE_2006
+			node_desc.user_desc_avail = *p & 0x08;
+			node_desc.complx_desc_avail = *p & 0x10;
+			node_desc.reserved = *p & 0xE0;
+#endif
+			p++;
+			//Byte 2
+			node_desc.aps_flags = *p & 0x07;
+			node_desc.freq_band = (*p & 0xF8) >> 3;
+			p++;
+			//Byte 3
+			node_desc.mac_cap = *p++;
+			//Byte 4 and 5
+			node_desc.manifact_code = *p + (*(p + 1) << 8);
+			p += 2;
+			//Byte 6
+			node_desc.max_buf_size = *p++;
+			//Byte 7 and 8 (Maximum incoming transfer size)
+			node_desc.max_transf_size = *p + (*(p + 1) << 8);
+			p += 2;
+			//Byte 9 and 10 (Server mask - 16 bits)
+#ifdef ZIGBEE_2006
+			node_desc.server_mask = *p + (*(p + 1) << 8);p += 2;
+#endif
+			//Byte 11 and 12 (Maximum outgoing transfer size - 16 bits)
+			//Byte 13 (Descriptor capability field - 8 bits)
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_NODE_DESC_confirm (
+					status,
+					nwk_addr,
+					&node_desc
+			);
+#endif
+			zbifCbs->ZDO_NODE_DESC_confirm(zbif_handle, status, nwk_addr,
+					&node_desc);
+		}
+			break;
+
+		case 0x83:
+			zb_print("ZDO_POWER_DESC_confirm: ");
+			printBytes(p);
+			break;
+
+		case 0x84: {
+			//Example: A0 84 1A 00 32 94 16 08 3C C2 01 05 00 05 00 00 00 08 02 07 06 0A 03 00 02 00 08 0A 00
+			ZB_SIMPLE_DESC simple_desc;
+
+			uchar *q = p;
+
+			int simple_desc_len = p[6];
+			zb_print("ZDO_SIMPLE_DESC_confirm: ");
+			printBytes(p);
+
+			if (p[3] == 0x00) {
+				// p[3] status
+				// p[4], p[5] address of interest
+				if (simple_desc_len > 0) {
+					simple_desc.ep = p[7];
+					simple_desc.app_profile_id = p[8] | p[9] << 8;
+					simple_desc.app_device_id = p[10] | p[11] << 8;
+					simple_desc.app_device_ver = p[12] & 0x0F;
+
+					simple_desc.reserved = p[12] >> 4;
+
+					p += 13;
+
+					simple_desc.app_in_cluster_count = *p++;
+
+					if (simple_desc.app_in_cluster_count) {
+						simple_desc.app_in_cluster_list = malloc(
+								simple_desc.app_in_cluster_count
+										* sizeof(ushort));
+						memcpy(simple_desc.app_in_cluster_list, p,
+								simple_desc.app_in_cluster_count
+										* sizeof(ushort));
+						p += 2 * simple_desc.app_in_cluster_count;
+					} else {
+						simple_desc.app_in_cluster_list = NULL;
+					}
+
+					simple_desc.app_out_cluster_count = *p++;
+
+					if (simple_desc.app_out_cluster_count) {
+						simple_desc.app_out_cluster_list = malloc(
+								simple_desc.app_out_cluster_count
+										* sizeof(ushort));
+						memcpy(simple_desc.app_out_cluster_list, p,
+								simple_desc.app_out_cluster_count
+										* sizeof(ushort));
+						p += 2 * simple_desc.app_out_cluster_count;
+					} else {
+						simple_desc.app_out_cluster_list = NULL;
+					}
+				} else {
+					/* simple descr not present */
+					zb_print("SimpleDescriptor not present\n");
+					memset(&simple_desc, 0, sizeof(simple_desc));
+				}
+
+				zbifCbs->ZDO_SIMPLE_DESC_confirm(zbif_handle, q[3],
+						q[4] | q[5] << 8, &simple_desc);
+
+				// Free all the resources
+				if (simple_desc.app_in_cluster_count != 0)
+					free(simple_desc.app_in_cluster_list);
+				if (simple_desc.app_out_cluster_count != 0)
+					free(simple_desc.app_out_cluster_list);
+			} else {
+				zb_print(
+						"ZDO_SIMPLE_DESC_confirm - status failed %02x %02x %02x %02x", p[0], p[1], p[2], p[3]);
+			}
+		}
+			break;
+
+		case 0x85:
+			set_zero_uchar(g_data_uchar_1);
+
+			for (i = 0; i < p[6]; i++)
+				g_data_uchar_1[i] = p[7 + i];
+
+			zbifCbs->ZDO_ACTIVE_EP_DESC_confirm(zbif_handle, p[3],
+					p[4] | p[5] << 8, p[6], g_data_uchar_1);
+			break;
+		case 0x86:
+			set_zero_uchar(g_data_uchar_1);
+
+			for (i = 0; i < p[6]; i++)
+				g_data_uchar_1[i] = p[7 + i];
+
+			zbifCbs->ZDO_MATCH_DESC_confirm(zbif_handle, p[3], p[5] | p[4] << 8,
+					p[6], g_data_uchar_1);
+			break;
+
+		case 0xA0:
+			zbifCbs->ZDO_END_DEVICE_BIND_confirm(zbif_handle, p[3]);
+			break;
+
+		case 0xA1:
+			zbifCbs->ZDP_BIND_response(zbif_handle, p[3]);
+			break;
+
+		case 0xA2:
+			zbifCbs->ZDP_UNBIND_response(zbif_handle, p[3]);
+			break;
+			/*
+			 case 0xA8:
+			 {
+			 int i=0;
+			 int pos=10;
+			 //p[3] 				- status
+			 //p[4] | p[5] << 8	- bindingTableEntries
+			 //p[6] | p[7] << 8	- StartIndex
+			 //p[8] | p[9] << 8	- BindingTableListCount
+			 //&p[10]			- BindingTableList
+			 ZB_BIND_STRUCT bindingTableList[5];
+			 for (i=0; i < p[9]; i++){		//p[9] is the LSB of BindingTableListCount
+			 memcpy(bindingTableList[i].src_addr, &p[pos] ,8);
+			 pos+=8;
+			 bindingTableList[i].src_ep = p[pos++];
+			 bindingTableList[i].cluster_id = p[pos] | p[pos] << 8;
+			 bindingTableList[i].groupDestination = 0x0000;	//Not specified!
+			 //p[21] is the destAddrMode = 0x03!
+			 pos+=3;
+			 memcpy(bindingTableList[i].dst_addr, &p[pos] ,8);
+			 pos+=8;
+			 bindingTableList[i].dst_ep = p[pos++];
+			 }
+			 zbifCbs->ZDP_MGMT_BIND_response(zbif_handle, p[3], p[4]|p[5]<<8,
+			 p[6]|p[7]<<8, p[8]|p[9]<<8,bindingTableList);
+			 }
+			 break;
+			 */
+		case 0xB1:
+			zb_print("ZDP-Mgmt_Lqi.Response: ");
+			printBytes(p);
+			zbifCbs->ZB_MGMT_LQI_response(zbif_handle, lastSrcAddrMode,
+					lastSrcAddr, &p[2]); //Return a pointer starting from PayloadLength (which will be ignored and considered as tsNum)
+			break;
+
+		case 0xB3: {
+			int i = 0, j;
+			int pos = 7;
+			ZB_BIND_STRUCT bindingTableList[6]; //It is impossible to have more than 6 entries into a unique ZigBee message!
+
+			zb_print("ZDP-Mgmt_Bind.Response: ");
+			printBytes(p);
+			/*
+			 p[3] 	- status
+			 p[4]	- bindingTableEntries
+			 p[5]	- StartIndex
+			 p[6]	- BindingTableListCount
+			 &p[7]	- BindingTableList
+			 */
+			for (i = 0; i < p[6]; i++) {
+				//Store the source address
+				for (j = 0; j < 8; j++)
+					bindingTableList[i].src_addr[7 - j] = p[pos++];
+				//memcpy(bindingTableList[i].src_addr, &p[pos] ,8);
+				//pos+=8;
+				bindingTableList[i].src_ep = p[pos++];
+				bindingTableList[i].cluster_id = p[pos] | p[pos + 1] << 8;
+				//p[pos] is the destAddrMode = 0x03!
+				pos += 3;
+				//Store the destination address
+				for (j = 0; j < 8; j++)
+					bindingTableList[i].dst_addr[7 - j] = p[pos++];
+				//memcpy(bindingTableList[i].dst_addr, &p[pos] ,8);
+				//pos+=8;
+				bindingTableList[i].dst_ep = p[pos++];
+			}
+			zbifCbs->ZDP_MGMT_BIND_response(zbif_handle, p[3], p[4], p[5], p[6],
+					bindingTableList);
+		}
+			break;
+
+		case 0xB6: {
+			uchar statusValue = p[3];
+			zb_print(
+					"ZDP-Mgmt_Permit_Join.response - status %02x\n", statusValue);
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_MGMT_PERMIT_JOINING_response(statusValue);
+#endif
+			//zb_print("Entering here, calling the permitJoinResponse handler\r\n");
+			zbifCbs->MGMT_PERMIT_JOINING_response(zbif_handle, statusValue);
+			break;
+		}
+
+		case 0xCC:
+			if (p[3] == 0xA2) {
+				zb_print(
+						"ZDP-APSME-ProcessSecureFrame.Confirm - ERROR: 0x%02x - Unable to encrypt or decrypt the packet", p[3]);
+			}
+			/*
+			 else if (p[3] == 0x06){
+			 zb_print("ZDP-APSME-ProcessSecureFrame.Confirm: status 0x%02x",p[3]);
+			 zb_print(" (security was not applied or removed to/from the packet)\n");
+			 }
+			 */
+			/*
+			 else{
+			 printBytes(p);
+			 }
+			 */
+			break;
+
+		case 0xE6:
+			switch (p[3]) {
+			case 0x00:
+				zb_print("ZDO-NetworkState.Event - Device initialized\n");
+				break;
+			case 0x01:
+				zb_print(
+						"ZDO-NetworkState.Event - Device in Network Discovery State\n");
+				break;
+			case 0x03:
+				zb_print(
+						"ZDO-NetworkState.Event - Device in Coordinator starting state\n");
+				break;
+			case 0x04:
+				zb_print(
+						"ZDO-NetworkState.Event - Device in Router Running state\n");
+				// Send a ZDO_START_confirm since concluded the startup procedure!
+				if (zbifCbs->ZDO_START_confirm)
+					zbifCbs->ZDO_START_confirm(zbif_handle, 0x00,
+							nwkShortAddress);
+				break;
+			case 0x05:
+				zb_print(
+						"ZDO-NetworkState.Event - Device in End Device Running state\n");
+				// Send a ZDO_START_confirm since concluded the startup procedure!
+				if (zbifCbs->ZDO_START_confirm)
+					zbifCbs->ZDO_START_confirm(zbif_handle, 0x00,
+							nwkShortAddress);
+				break;
+
+			case 0x09:
+				zb_print(
+						"ZDO-NetworkState.Event - Device in leave network state\n");
+				break;
+
+			case 0x0b:
+				zb_print(
+						"ZDO-NetworkState.Event - Device is in state 'Deviceinstoppedstate'\n");
+				// Send a ZDO_START_confirm reporting the error
+				if (zbifCbs->ZDO_START_confirm)
+					zbifCbs->ZDO_START_confirm(zbif_handle, p[3],
+							nwkShortAddress);
+				break;
+
+			case 0x10:
+				zb_print(
+						"ZDO-NetworkState.Event - Device is Coordinator Running state\n");
+				//Send a permit join to zero so that no device will be allowed to join the network!
+				ZB_CONN_HANDLE zb_conn_h =
+						((zbif_status_t *) zbif_handle)->zb_conn_h;
+				unsigned char cmdPermitJoin[4] = { 0x96, 0x36, 0x01, 0x00 };
+				zb_print_bytes("NLME-PERMIT-JOINING.Request->", cmdPermitJoin,
+						cmdPermitJoin[2] + 3);
+				zb_conn_send(zb_conn_h, cmdPermitJoin, cmdPermitJoin[2] + 3);
+				if (selectedSecLevel == 5) {
+					if (TCLinkKeyTableSize != 0) {
+						zb_print(
+								"ZDO-NetworkState.Event - Initialize the TCLinkKeytable\n");
+						indexTCLinkKey = 0;
+						initializeTCLinkKeyTable(zbif_handle);
+					} else {
+						// Request for the networkMaterialKey (in case a random security key is generated)
+						ZB_CONN_HANDLE zb_conn_h =
+								((zbif_status_t *) zbif_handle)->zb_conn_h;
+						unsigned char cmd[7] = { 0xA3, 0x22, 0x04, 0xA1, 0x00,
+								0x01, 0x00 };
+						zb_print_bytes("APSME_GET->", cmd, cmd[2] + 3);
+						zb_conn_send(zb_conn_h, cmd, cmd[2] + 3);
+					}
+				}
+				// Send a ZDO_START_confirm since concluded the startup procedure!
+				if (zbifCbs->ZDO_START_confirm)
+					zbifCbs->ZDO_START_confirm(zbif_handle, 0x00,
+							nwkShortAddress);
+				break;
+
+			case 0x13:
+				zb_print(
+						"ZDO-NetworkState.Event - Device is in state 'DeviceOfftheNetwork'\n");
+				//0x91 is a value used by Ember to indicate EMBER_NETWORK_DOWN
+				zbifCbs->ZIGBEE_STACK_STATUS_indication(zbif_handle, 0x91);
+				break;
+
+			default:
+				zb_print(
+						"ZDO-NetworkState.Event - State %02x (see Table 6-127, page 139)\n", p[3]);
+				//TODO: By default we could imagine to manage all those status unrecognized as a network down state!
+				//zbifCbs->ZIGBEE_STACK_STATUS_indication (zbif_handle, 0x91);
+				break;
+			}
+
+			break;
+
+		default:
+			break;
+
+		}
+		break;
+
+		//**** p[0] ****
+	case 0xA3: {
+		// Fake ZTC-CPU_Reset.Confirm (it doesn't exist)
+		switch (p[1]) {
+		case 0x08: {
+			// Fake Reset Confirm, so move on by setting ZTC_SET_MODE_request
+			if (p[4] == 0x02) {
+				// This call is coming from freescal_ser.c (it is a fake confirm)
+				unsigned char cmdMode[14] = { 0xA3, 0x00, 0x0B, 0x01, 0x02,
+						0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 };
+				zb_print_bytes("\nZTC_SET_MODE->", cmdMode, cmdMode[2] + 3);
+				zb_conn_send(((zbif_status_t *) zbif_handle)->zb_conn_h,
+						cmdMode, cmdMode[2] + 3);
+			} else {
+				// End of the whole reset procedure, just return a confirm
+				zbifCbs->ZDO_RESET_confirm(zbif_handle, p[3],
+						restartGWafterReset);
+			}
+			break;
+		}
+
+		case 0x21: {
+			zb_print("APSME-SET.Request: ");
+			// Find the APS Information Base ID (just for useful printing info...)
+			switch (p[3]) {
+			case 0xC0:
+				zb_print("Extended Address Map - ");
+				break;
+
+			default:
+				zb_print("iId %02x (Table 6-98, pag 120) - ", p[3]);
+				break;
+			}
+			printBytes(p);
+			break;
+		}
+
+		case 0x23:
+			zb_print("NLME-SET.Request - ");
+			printBytes(p);
+			switch (p[3]) {
+			case 0x9a:
+				zb_print("NIB Attribute nwkExtendedPANID - ");
+				break;
+			case 0x96:
+				//Store also the shortAddress that will be sent back to galZbIf
+				nwkShortAddress = p[7] + (p[8] << 8);
+				zb_print(
+						"NIB Attribute nwkShortAddress %04x - ", nwkShortAddress);
+				break;
+			case 0x80:
+				zb_print("NIB Attribute nwkPanId - ");
+				break;
+			case 0xd3:
+				zb_print("NIB Attribute nwkChannel %02x - ", p[7]);
+				break;
+			default:
+				zb_print("NIB ID %2x (unknown or not managed yet) - ", p[3]);
+				break;
+			}
+			break;
+
+		default:
+#ifdef DEBUG_ZIGBEE_API
+			zb_print("Req Unhandled OP 0xA3 %02x\n",p[1]);
+#endif
+			break;
+		}
+		break;
+	}
+
+		//**** p[0] ****
+	case 0xA4:
+
+		switch (p[1]) {
+
+		// ZTC-ModeSelect.Confirm
+		case 0x00: {
+			int y = 0;
+			if (p[3] == 0x00) {
+				// Success
+				((zbif_status_t *) zbif_handle)->state = 2;
+				// Insert all 0xFF to randomly generate a MAC Address
+				unsigned char cmd[11] = { 0xA3, 0xDB, 0x08 };
+
+				if (generateRandomIEEEAddr != 0x00) {
+					// Use a random IEEE Address (but with a common initial value)
+					for (y = 3; y <= 10; y++)
+						cmd[y] = rand() % 0xFF;
+					cmd[9] = 0xCD;
+					cmd[10] = 0xAB;
+					// use fixed value
+					/*
+					 cmd[3] = 0x00;
+					 cmd[4] = 0x01;
+					 cmd[5] = 0x02;
+					 cmd[6] = 0x03;
+					 cmd[7] = 0x04;
+					 cmd[8] = 0x05;
+					 cmd[9] = 0x06;
+					 cmd[10] = 0x07;
+					 */
+					/*
+					 zb_print("USING THE FOLLOWING RANDOM IEEEADDRESS:");
+					 for (y=3; y <= 10 ; y++ )
+					 printf("%02x ",cmd[y]);
+					 printf("\n");
+					 */
+
+					//Send the command
+					zb_print_bytes("ZTC_WRITE_EXT_ADDR->", cmd, cmd[2] + 3);
+					zb_conn_send(((zbif_status_t *) zbif_handle)->zb_conn_h,
+							cmd, cmd[2] + 3);
+				} else {
+					// Maintain the manufacture IEEE Address, just return to galzbif!
+					ZBIFCbs_t *zbifCbs =
+							((zbif_status_t *) zbif_handle)->zbifCbs;
+					if (zbifCbs->ZDO_RESET_confirm) {
+						zb_print("ZTC-ModeSelect.Confirm\n");
+						zbifCbs->ZDO_RESET_confirm(zbif_handle, 0x00,
+								restartGWafterReset);
+					}
+				}
+			} else {
+				zb_print("ZTC-ModeSelect.Request failed!\n");
+			}
+			break;
+		}
+
+			// APS-RegisterEndPoint.Confirm
+		case 0x0b: {
+			if (p[3] == 0x00) {
+				zb_print("APS-RegisterEndPoint.Confirm\n");
+			} else {
+				zb_print(
+						"ERROR: APS-RegisterEndPoint.Confirm FAILED (status %02x)\n", p[3]);
+			}
+			if (zbifCbs->APSME_SET_confirm)
+				zbifCbs->APSME_SET_confirm(zbif_handle, p[3], attr_prev);
+			break;
+		}
+			/*
+			 // ZTC-GetPanID.Confirm
+			 case 0x14:{
+			 //We should never enter here, this is just a recovery function!
+			 p[1] = 0x00;
+			 p[3] = 0x00;
+			 // This editing correspond to a ZTC-ModeSelect.Confirm!
+			 FREESCALE_ParseNExec(zbif_handle,p,size);
+			 break;
+			 }
+			 */
+
+			// ZTC-GetChannel.Confirm
+		case 0x12: {
+			if (p[3] == 0x00) {
+				//SUCCESS, so we can conclude by returning to the GalZbIf the Channel Mask...
+				ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+				zbifCbs->APSME_GET_confirm(zbif_handle, p[3], attr_prev, 1,
+						&p[4]);
+			} else {
+				// The request failed, report an error!
+				zb_print("ZTC-GetChannel.Confirm failed!\n");
+			}
+			break;
+		}
+
+			// ZTC-WriteExtAddr.Confirm
+		case 0xDB: {
+			if (p[3] == 0x00) {
+				//SUCCESS, so we can conclude by returning to the GalZbIf the ResetConfirm
+				ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+				if (zbifCbs->ZDO_RESET_confirm) {
+					zb_print("ZTC-WriteExtAddr.Confirm\n");
+					zbifCbs->ZDO_RESET_confirm(zbif_handle, 0x00,
+							restartGWafterReset);
+				}
+			} else {
+				zb_print("ERROR: ZTC-WriteExtAddr.Request failed!\n");
+			}
+			break;
+		}
+
+			// ZTC-ReadExtAddr.Confirm
+		case 0xD2: {
+			if (p[3] == 0x00) {
+				//SUCCESS, so we can conclude by returning to the GalZbIf the IEEEAddress...
+				ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+				zbifCbs->APSME_GET_confirm(zbif_handle, p[3], attr_prev, 8,
+						&p[4]);
+			} else {
+				// The request failed, report an error!
+				zb_print("ZTC-ReadExtAddr.Confirm failed!\n");
+			}
+			break;
+		}
+
+		case 0x3E:
+			if (p[3] == 0x00) {
+				initializeTCLinkKeyTable(zbif_handle);
+			} else {
+				zb_print(
+						"ERROR with ZTC-SetApsDeviceKeyPairSet: 0x%02x\n", p[3]);
+			}
+			break;
+
+		case 0xE4:
+			if (p[3] == 0x00) {
+				// This is the function called after a BlackBox.WriteSAS
+				zb_print("ZTC-BeeStackSave.Confirm\n");
+				zbifCbs->APSME_SET_confirm(zbif_handle, p[3], attr_prev);
+			}
+			break;
+
+			// ZTC-StartNwkEx.Confirm
+		case 0xE7: {
+			zb_print("ZDP-StartNwkEx.Confirm\n");
+			printBytes(p);
+			//This is just a confirm that the StartNwkEx.Request was processed!
+			// Do nothing, other messages will arrive
+			break;
+		}
+
+		case 0x21:
+			if (p[3] == 0) {
+				zb_print("APSME-SET.Confirm\n");
+				/*
+				 if (setApsDeviceKeyPairEnable == 0x01){
+				 setApsDeviceKeyPairSetSecondPart();
+				 } else
+				 // just send a confirm to GalZbIf
+				 *
+				 */
+				zbifCbs->APSME_SET_confirm(zbif_handle, p[3], attr_prev);
+			} else {
+				zb_print(
+						"ERROR: APSME-SET.Confirm with error status code %x!\n", p[3]);
+			}
+			break;
+
+		case 0x20:
+			// FIX: currently here we don't know the attribute that has been set
+			//zbifCbs->APSME_GET_confirm(zbif_handle, p[3], 0x00);
+			break;
+
+		case 0xFE:
+			// ZTC is reporting an error condition!
+			if (p[3] != 0) {
+				zb_print(
+						"WARNING: ZTC-Error.event (status code %02x)\n"
+						"Please verify that 'SecurityLevel' in config.ini is zero (security not supported for this firmware)!\n", p[3]);
+			}
+			break;
+
+			//NLME-GET.Confirm
+		case 0x22:
+			if (p[3] == 0x00 && p[4] == 0x96) { //0x96 is the nwkShortAddress
+				zb_print("NLME-GET.Confirm: ");
+				ushort nwk_addr = (p[10] << 8) + p[11];
+				if (nwk_addr == 0xFFFF)
+					zb_print("The shortAddress is not yet assigned!\n");
+				else
+					zb_print("shortAddress 0x%04x\n", nwk_addr);
+			} else if (p[3] == 0x00 && p[4] == 0xA1) {
+				//nwkSecurityMaterial
+				zb_print("NLME-GET.Confirm - nwkSecurityMaterial\n");
+				//08 and 09 is the length
+				//0A - keySeqNum
+				//B - E - outgoingFrameCounter
+				// 0F - 1E network Key
+				printf("\n************\nNETWORK KEY:\n");
+				printf(
+						"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+						p[0x0F], p[0x10], p[0x11], p[0x12], p[0x13], p[0x14],
+						p[0x15], p[0x16], p[0x17], p[0x18], p[0x19], p[0x1A],
+						p[0x1B], p[0x1C], p[0x1D], p[0x1E]);
+				printf(
+						"0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
+						p[0x0F], p[0x10], p[0x11], p[0x12], p[0x13], p[0x14],
+						p[0x15], p[0x16], p[0x17], p[0x18], p[0x19], p[0x1A],
+						p[0x1B], p[0x1C], p[0x1D], p[0x1E]);
+				printf(
+						"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+						p[0x1E], p[0x1D], p[0x1C], p[0x1B], p[0x1A], p[0x19],
+						p[0x18], p[0x17], p[0x16], p[0x15], p[0x14], p[0x13],
+						p[0x12], p[0x11], p[0x10], p[0x0F]);
+				printf(
+						"0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
+						p[0x1E], p[0x1D], p[0x1C], p[0x1B], p[0x1A], p[0x19],
+						p[0x18], p[0x17], p[0x16], p[0x15], p[0x14], p[0x13],
+						p[0x12], p[0x11], p[0x10], p[0x0F]);
+				printf("\n************\n\n");
+			} else {
+				zb_print(
+						"NLME-GET.Confirm - Status %2x, Attribute %2x\n", p[3], p[4]);
+			}
+			break;
+
+			//ZTC-ClearApsDeviceKeyPairSet.Confirm
+		case 0x3F:
+			zb_print(
+					"ZTC-ClearApsDeviceKeyPairSet.Confirm - Status 0x%02x\n", p[3]);
+			break;
+
+		default:
+			break;
+		}
+		break;
+
+		//**** p[0] ****
+	default:
+		break;
+	}
+}
+
+void FREESCALE_ReceiveCb(ZBIF_HANDLE zbif_handle, uchar *data, const int size) {
+
+	if (zbif_handle == NULL) {
+		return;
+	}
+
+	FREESCALE_ParseNExec(zbif_handle, data, size);
+}
+
+ZBIFFunctions_t zbFreescaleFunctions = { FREESCALE_ZDO_RESET_request,
+		FREESCALE_ZDO_START_request, FREESCALE_ZDP_MGMT_NWK_UPDATE_request,
+		FREESCALE_ZDO_NWK_ADDR_request, FREESCALE_ZDO_IEEE_ADDR_request,
+		FREESCALE_ZB_MGMT_LQI_request, FREESCALE_ZDO_NODE_DESC_request,
+		FREESCALE_ZDO_POWER_DESC_request, FREESCALE_ZDO_SIMPLE_DESC_request,
+		FREESCALE_ZDO_ACTIVE_EP_DESC_request, FREESCALE_ZDO_MATCH_DESC_request,
+		FREESCALE_ZDO_MATCH_DESC_response,
+		FREESCALE_ZDO_END_DEVICE_BIND_request, FREESCALE_APSDE_DATA_request,
+		FREESCALE_ZDP_MGMT_BIND_Request, FREESCALE_APSME_BIND_request,
+		FREESCALE_ZDP_BIND_Request, FREESCALE_ZDP_UNBIND_Request,
+		FREESCALE_APSME_UNBIND_request, FREESCALE_APSME_GET_request,
+		FREESCALE_APSME_SET_request, FREESCALE_MGMT_PERMIT_JOINING_request,
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+		FREESCALE_APSME_REMOVE_DEVICE_request,
+		FREESCALE_APSME_TRANSPORT_KEY_request,
+		FREESCALE_NLME_LEAVE_request,
+#endif
+
+		FREESCALE_ZDO_ERROR_response };

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/freescale_if.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/freescale_if.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/freescale_if.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,53 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef _FREESCALE_IF_H_
+#define _FREESCALE_IF_H_
+
+extern ZBIFFunctions_t zbFreescaleFunctions;
+
+extern void FREESCALE_ReceiveCb(ZBIF_HANDLE zbif_handle, uchar *data,
+		const int size);
+
+extern void ZBPrint_APSME_SET_request(uchar attr, uchar attr_len,
+		uchar *attr_value);
+
+typedef uchar TCLinkKeyTableEntry[30];
+
+typedef struct {
+	ushort ShortAddress;
+	uchar ExtendedPANId[8];
+	uchar APSUseExtendedPANId[8];
+	ushort PANId;
+	uchar ChannelsMask[4];
+	uchar ProtocolVersion;
+	uchar StackProfile;
+	uchar StartupControl;
+	uchar TrustCenterAddress[8];
+	uchar TrustCenterMasterKey[16];
+	uchar NetworkKey[16];
+	int UseInsecureJoin;
+	uchar PreconfiguredTrustCenterLinkKey[16];
+	int ActiveNwkKeySeqNumber;
+	int NetworkKeyType;
+	ushort NetworkManagerAddress;
+	int Scanattempts;
+	ushort Timebetweenscans;
+	ushort RejoinInterval;
+	ushort MaximumRejoinInterval;
+	ushort IndirectPollRate;
+	int ParentLinkRetryThreshold;
+	int IsConcentrator;
+	int ConcentratorRadius;
+	int ConcentratorDiscoveryTime;
+} WriteSASAttribute;
+
+WriteSASAttribute sasAttr;
+
+#endif /* _FREESCALE_IF_H_ */

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/freescale_ser.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/freescale_ser.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/freescale_ser.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,564 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <zigbee_log.h>
+
+#include "freescale_ser.h"
+
+#define DEFAULT_BAUDRATE 115200
+#define DEFAULT_ZIGBEEDEVICE "/dev/ttyUSB0"
+
+static const struct {
+	int bps;
+	speed_t posixBaud;
+} baudTable[] = { { 600, B600 }, { 1200, B1200 }, { 2400, B2400 },
+		{ 4800, B4800 }, { 9600, B9600 }, { 19200, B19200 }, { 38400, B38400 },
+		{ 57600, B57600 }, { 115200, B115200 }, { 230400, B230400 }, { 921600,
+				B921600 } };
+
+#define BAUD_TABLE_SIZE ( sizeof(baudTable) / sizeof(baudTable[0]) )
+
+#if defined(DEBUG)
+#define pr_debug(fmt, ...) \
+        printf(fmt, ##__VA_ARGS__)
+#else
+#define pr_debug(fmt, ...) \
+        ({ if (0) printf(fmt, ##__VA_ARGS__); 0; })
+#endif
+
+typedef enum {
+
+	MC13226_TX,
+	MC13226_RECV,
+	MC13226_IDLE,
+	MC13226_CLOSE,
+	MC13226_RESETTING_MODE
+} MC13226_dongle_state_t;
+
+//	Mutex
+pthread_mutex_t mux;
+//extern char restartGWafterReset;
+
+#ifdef MC13226_ASYNC_READ
+static inline void wait_for_usec(int n)
+{
+	struct timeval tv_start, tv_stop;
+	int left_to_sleep = n;
+	int slept = 0;
+
+	while (left_to_sleep > 0 )
+	{
+		gettimeofday(&tv_start,NULL);
+		usleep(left_to_sleep);
+		gettimeofday(&tv_stop,NULL);
+		slept = (((tv_stop.tv_sec % 10)*1000000) + tv_stop.tv_usec) -
+		(((tv_start.tv_sec % 10)*1000000) + tv_start.tv_usec);
+		left_to_sleep -= slept;
+	}
+
+}
+#else
+#define wait_for_usec(n) usleep(n)
+#endif
+
+int freescale_zigbb_make_frame(const unsigned char *cmd, unsigned char *frm) {
+
+	int i = 0;
+	unsigned char fcs = 0x00;
+
+	//pr_debug("MC13226 :%s: Calculating FCS\n",__func__);
+
+	frm[0] = 0x02;
+
+	for (i = 0; i < 3 + cmd[2]; i++) {
+		frm[i + 1] = cmd[i];
+		fcs ^= cmd[i];
+
+	}
+	frm[i + 1] = fcs;
+
+	/*
+	 #ifdef DEBUG
+	 pr_debug("MC13226 :%s: ZIGBEE BB Frame : Size %d\n", __func__, 5 + frm[3] );
+	 for (i = 0; i < 5 + frm[3]; i++)
+	 {
+	 pr_debug("%02x ",frm[i]);
+	 
+	 if(((i+1) % 20) == 0)
+	 pr_debug(" \n");
+	 }
+	 pr_debug(" \n");
+	 
+	 #endif 
+	 */
+	return 5 + frm[3];
+}
+
+// This function verify the correctness of the message received and it extract the 0x02 header byte and the checksum, not needed anymore!
+int freescale_zigbb_parse_frame(unsigned char *buf, unsigned char *frm,
+		int size) {
+
+	int i;
+	unsigned char fcs;
+
+	fcs = 0x00;
+
+	if (size < (frm[3] + 5)) {
+		pr_debug(
+				"MC13226 Waiting for more data in the buffer (current %02x, expected %02x)\n",
+				size, frm[3] + 5);
+		return -2;
+	}
+#ifdef DEBUG
+	pr_debug("MC13226 - Buffer received (size %d):\n",5 + frm[3]);
+	for (i = 0; i < 5 + frm[3]; i++)
+	{
+		pr_debug("%02x ",frm[i]);
+		if(((i+1) % 20) == 0)
+		pr_debug(" \n");
+	}
+#endif 
+	pr_debug(" \n");
+
+	if (frm[0] != 0x02) {
+		printf("MC13226 : ERROR at FirstByte - Expected 0x02, received %02X \n",
+				frm[0]);
+		return -1;
+	} else {
+		//pr_debug("MC13226 :%s: Calculating CHKSUM: \n",__func__);
+
+		for (i = 1; i <= frm[3] + 3; i++) {
+#ifdef MC13226_SUPPRESS_OPCODE_OUTPUT_FRM
+			if(i > 3)
+#endif
+			buf[i - 1] = frm[i];
+			fcs ^= frm[i]; // ^ is the Bitwise XOR (exclusive or)
+		}
+
+		if (fcs != frm[i]) {
+			printf("MC13226 : ERROR at Checksum : calc %02x recv %02x\n", fcs,
+					frm[i + 1]);
+			for (i = 0; i < frm[3]; i++)
+				buf[i] = 0x00;
+			return -1;
+		}
+	}
+	return 0;
+}
+
+/**
+ * Opens the serial device and initializes the status
+ * fields related to the framing handling
+ */
+
+static freescale_status_t *MC13226_dongle = NULL;
+//struct sigaction *MC13226_saio;  //Fixed a bug noted by valgrind
+int MC13226_wait_flag;
+
+void signal_handler_zigbb_io(int status) {
+	MC13226_wait_flag = 0;
+}
+
+int MC13226_open(const char **params) {
+	FILE *test;
+
+	const char *speed = get_param(params, "speed");
+	int bps = DEFAULT_BAUDRATE;
+	int i;
+	int baud; // posix baud
+
+	if (speed != NULL) {
+		bps = atoi(speed);
+	}
+
+	for (i = 0; i < BAUD_TABLE_SIZE; i++) {
+		if (baudTable[i].bps == bps)
+			break;
+	}
+	if (i < BAUD_TABLE_SIZE) {
+		baud = baudTable[i].posixBaud;
+	} else {
+		fprintf(stderr, "Invalid baud rate %d bps\n", bps);
+		return errno;
+	}
+
+	pr_debug("BAUDRATE SELECTED: %d\n", bps);
+
+	const char *device = get_param(params, "path"); // {DEFAULT_ZIGBEEDEVICE};
+	if (device == NULL) {
+		device = 0;
+	}
+
+	struct termios oldtio, newtio;
+
+	int fd = 0;
+
+	if (MC13226_dongle != NULL) {
+		pr_debug("MC13226 :%s: Device Already opened\n", __func__);
+		return -ENOMEM;
+	}
+
+	MC13226_dongle = (freescale_status_t *) malloc(sizeof(freescale_status_t));
+
+	if (MC13226_dongle == NULL) {
+		pr_debug("MC13226 :%s: Can'allocate Memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	//Verify if we're using a CEDAC board or a Freescale USB dongle
+	int zigbee_usb_dongle = 1;
+	test = fopen("/sys/devices/platform/zigbee-gpio.0/cmd", "r");
+	if (test != NULL) {
+		zb_print("**** This is a CEDAC BOARD ****\n");
+		fclose(test);
+		// Execute the hard reset!
+		system("echo reset > /sys/devices/platform/zigbee-gpio.0/cmd");
+		usleep(2000000);
+		zigbee_usb_dongle = 0;
+	}
+	// Now open the connection
+	fd = open(device, O_RDWR | O_NOCTTY);
+
+	if (fd < 0) {
+		pr_debug("MC13226 :%s: Failing open the device\n", __func__);
+		perror(device);
+		return -ENODEV;
+	}
+	memset(&newtio, 0, sizeof(struct termios));
+	tcgetattr(fd, &oldtio); /* save current serial port settings */
+
+	newtio.c_cflag &= ~PARENB; /* Disable parity checking */
+	newtio.c_cflag &= ~CSTOPB; /* 1 stop bit */
+	newtio.c_cflag &= ~CSIZE; /* Clear data sice field */
+	newtio.c_cflag |= CS8; /* 8 data bits */
+	newtio.c_cflag &= ~CRTSCTS; /* Disable HW flow control */
+	newtio.c_cflag |= (CLOCAL | CREAD); /* Enable receiver */
+	newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* Raw mode */
+	newtio.c_iflag &= ~(IXON | IXOFF | IXANY | ICRNL); /* No SW flow control */
+	newtio.c_oflag &= ~OPOST; /* No post-processing */
+
+	//NEW SETTING - 01/09/2011
+	newtio.c_cc[VTIME] = 1; /* No inter-character timer */
+	newtio.c_cc[VMIN] = 0; /* Block until 8 characters are available */
+
+	cfmakeraw(&newtio); // This command say to the port that we will send binary data
+	cfsetospeed(&newtio, baud);
+	cfsetispeed(&newtio, baud);
+
+	tcflush(fd, TCIOFLUSH); //discards any data written to the specified file descriptor but that has not been transmitted (TCIFLUSH), or data that has been received but not read (TCOFLUSH). TCIOFLUSH for both!
+
+	if ((tcsetattr(fd, TCSANOW, &newtio)) != 0) {
+		perror(device);
+		return -ENODEV;
+	}
+
+	MC13226_dongle->fd = fd;
+	MC13226_dongle->state = MC13226_IDLE;
+
+	//Initialize the mux
+	pthread_mutex_init(&mux, NULL);
+	return 0;
+}
+
+/**
+ * Closes the serial communication
+ */
+
+int MC13226_close(void) {
+
+	pr_debug("MC13226: %s: Closing the device connection \n", __func__);
+	if (MC13226_dongle != NULL && MC13226_dongle->fd >= 0) {
+		//pr_debug("MC13226: TEMP - fd value %x \n",MC13226_dongle->fd);
+		close(MC13226_dongle->fd);
+		//pr_debug("MC13226: TEMP - Close connection done, now free MC13226_dongle\n");
+		free(MC13226_dongle);
+	} else
+		pr_debug("MC13226: DONE!\n");
+	return 0;
+}
+
+int MC13226_transmit(const unsigned char *data) {
+	unsigned char frm[255];
+	int size, sent_size, i;
+
+	pthread_mutex_lock(&mux);
+
+	if (MC13226_dongle == NULL) {
+		pr_debug("MC13226 :%s: No Device\n", __func__);
+		pthread_mutex_unlock(&mux);
+		return -ENODEV;
+	} else if ((MC13226_dongle->state != MC13226_IDLE) && (0)) {
+		pr_debug("MC13226 :%s: ERROR - Device busy %d\n",
+				__func__, MC13226_dongle->state);
+		pthread_mutex_unlock(&mux);
+		return -EBUSY;
+	} else {
+		MC13226_dongle->state = MC13226_TX;
+		//pr_debug("MC13226 :%s: Starting TX state %d\n", __func__, MC13226_dongle->state);
+		size = freescale_zigbb_make_frame(data, frm);
+		//pr_debug("MC13226 :%s: TX %d bytes\n",__func__,size);
+		sent_size = write(MC13226_dongle->fd, frm, size);
+		//printf("Bytes frm[1]=%02x,frm[2]=%02x,frm[3]=%02x\n",frm[1],frm[2],frm[3]);
+		// Check if we shall enter in a resetting mode state
+		if ((frm[1] == 0xa3) && (frm[2] == 0x08) && (frm[3] == 0x00)) {
+			MC13226_dongle->state = MC13226_RESETTING_MODE;
+		} else {
+			MC13226_dongle->state = MC13226_IDLE;
+		}
+#ifdef DEBUG
+		pr_debug("MC13226 - Transmitting buffer (size %d):\n",sent_size);
+		for (i = 0; i < 5 + frm[3]; i++)
+		{
+			pr_debug("%02x ",frm[i]);
+
+			if(((i+1) % 20) == 0)
+			pr_debug(" \n");
+		}
+		pr_debug(" \n");
+#endif
+	}
+	pthread_mutex_unlock(&mux);
+	return 0;
+}
+
+int MC13226_fd(void) {
+	return MC13226_dongle->fd;
+}
+
+#define MC13226_RECV_TIMEOUT 4 * 1000000
+// Boolean used to fix the missing "checksum-byte" error!
+int messageRecovered = 0x00;
+
+int MC13226_receive(int handle, unsigned char *buf, int buffer_size) {
+	int size = 0, frm_size = 0;
+	int msg_complete = 0;
+	int reads = 0;
+	int ret = 0;
+	int i = 0;
+	int b = 0;
+	int payload_size = 0;
+	unsigned char frm[4096];
+	unsigned char recv_buf[255];
+	unsigned char hdr[4] = { 0, 0, 0, 0 };
+	unsigned int bytes_dropped = 0;
+
+	memset(frm, 0, sizeof(char) * 4096);
+	memset(recv_buf, 0, sizeof(char) * 255);
+
+	if (MC13226_dongle->fd == 0) {
+		pr_debug("MC13226 :%s: No Device\n", __func__);
+		return -ENODEV;
+	}
+
+	if (MC13226_dongle->state == MC13226_RESETTING_MODE) {
+		usleep(1000000);
+		size = read(MC13226_dongle->fd, recv_buf, sizeof(recv_buf));
+		bytes_dropped = size;
+		pr_debug("Dropped %d bytes\n", bytes_dropped);
+		// Send a fake Reset...
+		buf[0] = 0xA3;
+		buf[1] = 0x08;
+		buf[2] = 0x02;
+		buf[3] = 0x00;
+		buf[4] = 0x02; // This value is used in freescale_if.c to understand that it is a fake confirm!
+		msg_complete = 1;
+		MC13226_dongle->state = MC13226_IDLE;
+#if DEBUG
+		pr_debug("Sending a fake ZTC-CPU_Reset.Confirm\r\n");
+		for (i = 0; i < 5; i++) {
+			printf("%02x ",buf[i]);
+		}
+		printf(" \n");
+#endif
+		return 5; // The size of the packet just created!
+	}
+
+	// In case a previous message was correctly received apart from the last byte (checksum byte), recovery the first token byte already received (0x02)
+	if (messageRecovered == 0x01) {
+		messageRecovered = 0x00;
+		hdr[0] = 0x02;
+		i = 1;
+		b = 1;
+	}
+	for (; i < 4; b++, i++) {
+		//pr_debug("MC13226: Waiting input from serial port (count %d)\n", b);
+
+		read(MC13226_dongle->fd, hdr + i, 1);
+
+		if (hdr[0] != 0x02) {
+			printf("DROP %2x ", hdr[0]);
+			bytes_dropped++;
+			i--;
+		}
+	}
+	if (bytes_dropped != 0)
+		printf("\nMC13226 : Bytes Dropped : %d\n", bytes_dropped);
+
+	// And now we can get the rest of the message/buffer
+	memcpy(frm, hdr, 4);
+	frm_size = 4;
+	payload_size = hdr[3] + 1;
+
+	while (!msg_complete) {
+		size = read(MC13226_dongle->fd, recv_buf, payload_size + 4 - frm_size);
+
+		reads++;
+
+		if (size > 0) {
+			memcpy(frm + frm_size, recv_buf, size);
+			/*
+			 #ifdef DEBUG
+			 pr_debug("MC13226 - Received %d Bytes: ", size);
+			 for (i = 0; i < size; i++){
+			 pr_debug("%02x ",recv_buf[i]);
+			 if(((i+1) % 20) == 0)
+			 pr_debug(" \n");
+			 }
+			 pr_debug(" \n");
+			 #endif
+			 */
+			frm_size += size;
+			ret = freescale_zigbb_parse_frame(buf, frm, frm_size);
+			if (ret == -2) {
+				// Case the whole message is not completed yet!
+				pr_debug(
+						"MC13226 :%s: Frame Not Completed...Looping : Reads %d\n",
+						__func__, reads);
+			} else if (ret == -1) {
+				printf(
+						"MC13226 : WARNING @ THIS MESSAGE (wholeBufferSize 0x%02x)\n",
+						frm_size);
+				for (i = 0; i < frm_size; i++) {
+					printf("%02x ", frm[i]);
+					if (((i + 1) % 20) == 0)
+						printf(" \n");
+				}
+				printf(" \n");
+				// We have a corrupter message but there are some know bugs that could be fixed!
+				if ((frm[frm_size - 1] == 0x02) && (frm[3] == frm_size - 5)) //5 is equals to the two border (checksum and 0x02) + the three header info (OPcode and length)
+						{
+					// A) Sometimes only the last byte, the checksum byte, is missing! Try to verify the integrity of the whole message knowing that the last byte is 0x02
+					printf(
+							"MC13226 : FRAMES RECOVERED BY SKIPPING CHECKSUM BYTE\n");
+					// This is a case of the know bug of the missing checksum byte so process the message as valid!
+					for (i = 1; i <= frm[3] + 3; i++) {
+#ifdef MC13226_SUPPRESS_OPCODE_OUTPUT_FRM
+						if(i > 3)
+#endif
+						buf[i - 1] = frm[i];
+					}
+					msg_complete = 1;
+					MC13226_dongle->state = MC13226_IDLE;
+					//pr_debug("MC13226 - Frame Complete : Reads %d \n", reads);
+					//Finally, we have to recovery the next message by setting the first byte to 0x02 (already readed!)
+					messageRecovered = 0x01;
+					return frm_size - 2;
+				} else if ((frm[0] == 0x02) && (frm[3] == frm_size - 5)) { //5 is equals to the two border (checksum and 0x02) + the three header info (OPcode and length)
+					// B) Check if it is only the checksum byte wrong!
+					printf(
+							"MC13226 : FRAMES RECOVERED BUT CHECKSUM BYTE WRONG!!!\n");
+					// This is a case of the know bug of the missing checksum byte so process the message as valid!
+					for (i = 1; i < frm[3] + 3; i++) {
+#ifdef MC13226_SUPPRESS_OPCODE_OUTPUT_FRM
+						if(i > 3)
+#endif
+						buf[i - 1] = frm[i];
+					}
+					msg_complete = 1;
+					MC13226_dongle->state = MC13226_IDLE;
+					//pr_debug("MC13226 - Frame Complete : Reads %d \n", reads);
+					return frm_size - 2;
+				} else {
+					// C) This is a very corrupted message (No reasons why it shall enter here!)
+					pr_debug(
+							"MC13226 : FRAME COMPLETELY WRONG (wholeBufferSize 0x%02x)\n",
+							frm_size);
+					for (i = 0; i < frm_size; i++) {
+						pr_debug("%02x ", frm[i]);
+						if (((i + 1) % 20) == 0)
+							pr_debug(" \n");
+					}
+					pr_debug(" \n");
+					// Drop bytes until we find the next 0x02 byte!
+					//NB: i= 1 originally!!!
+					for (i = 0; i < frm_size; i++) //recv_buf[0] = 0x02!
+						if (frm[i] == 0x02) {
+							frm_size -= i;
+							memcpy(frm, &frm[i], frm_size);
+						}
+					pr_debug(
+							"MC13226 : DROPPED SOME BYTES, THE NEW BUFFER REMAINED IS\n");
+					for (i = 0; i < frm_size; i++) {
+						pr_debug("%02x ", frm[i]);
+						if (((i + 1) % 20) == 0)
+							pr_debug(" \n");
+					}
+					pr_debug(" \n");
+				}
+			} else {
+				// A whole message is now completed!
+				msg_complete = 1;
+				MC13226_dongle->state = MC13226_IDLE;
+				/*
+				 #if defined(DEBUG)
+				 pr_debug("MC13226 - Frame Complete : Reads %d \n", reads);
+				 for (i = 0; i < frm_size; i++){
+				 printf("%02x ",frm[i]);
+				 if(((i+1) % 20) == 0)
+				 printf(" \n");
+				 }
+				 printf(" \n");
+				 #endif
+				 */
+			}
+		}
+	}
+	return frm_size - 2;
+}
+
+int freescale_open(const char **params) {
+
+	if (MC13226_open(params) == 0)
+		return (int) MC13226_dongle;
+	else
+		return 0;
+}
+
+int freescale_close(int handle) {
+	return MC13226_close();
+}
+
+int freescale_transmit(int handle, const unsigned char *data, int size) {
+	return MC13226_transmit(data);
+}
+
+int freescale_receive(int handle, unsigned char *buf, const int size) {
+	return MC13226_receive(handle, buf, size);
+}
+
+int freescale_fd(int handle) {
+	return MC13226_fd();
+}
+
+#ifdef MC13226_TEST_BENCH
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/freescale_ser.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/freescale_ser.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/freescale_ser.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,24 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef _FREESCALE_SER_H_
+#define _FREESCALE_SER_H_
+
+typedef struct {
+	int fd;
+	int state;
+} freescale_status_t;
+
+int freescale_open(const char **params);
+int freescale_close(int handle);
+int freescale_transmit(int handle, const unsigned char *data, int size);
+int freescale_receive(int handle, unsigned char *buf, const int size);
+int freescale_fd(int handle);
+
+#endif

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/hdlc_net.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/hdlc_net.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/hdlc_net.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,300 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#ifdef WIN32
+# include <windows.h>
+# include <winsock.h>
+# include <io.h>
+#else
+# include <stdlib.h>
+# include <time.h>
+# include <sys/socket.h>
+# include <sys/select.h>
+# include <sys/time.h>
+# include <sys/types.h>
+# include <unistd.h>
+# include <stddef.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# include <errno.h>
+# include <sys/un.h>
+#endif
+
+#include "hdlc_dl.h"
+#include "hdlc_proto.h"
+#include "zigbee_log.h"
+
+#ifndef HDLC_REMOTE_PORT
+#define HDLC_REMOTE_PORT	30001
+#endif
+
+#ifndef HDLC_LOCAL_PORT
+#define HDLC_LOCAL_PORT		30000
+#endif
+
+static int hdlc_net_rx_loop(int fd);
+static int hdlc_net_tx(int fd, int control, const unsigned char *data, int size);
+static int hdlc_net_close(int fd);
+
+/**
+ * Opens the HDLC serial device and initializes the status
+ * fields related to the framing handling
+ *
+ * @param remote_url 
+ * 	Socket info. Should be in the form "hdlc://<remote IP address>[:<remote port>],<local port>"
+ * 	If <remote port> is omitted, HDLC_REMOTE_PORT define is used instead
+ * 	If <local port> is omitted, HDLC_LOCAL_PORT define is used instead
+ */
+
+int hdlc_net_open(const char *remote_url) {
+	int ret;
+	int sock;
+	int proto_family;
+	char *p, *q;
+
+	char url_proto[10];
+	char url_host[100];
+	int url_port;
+	int local_port = HDLC_LOCAL_PORT;
+
+	assert(remote_url != NULL);
+
+	hdlc_status_t *status = (hdlc_status_t *) malloc(sizeof(hdlc_status_t));
+
+#ifdef HDLC_USE_INET_SOCKET
+	proto_family = PF_INET;
+#else
+	struct sockaddr_un saddr;
+	struct sockaddr_un caddr;
+	proto_family = PF_LOCAL;
+#endif
+
+	/* parses remote_url */
+	p = strstr(remote_url, "://");
+	if (p == NULL) {
+		fprintf(stderr, "ERROR: parsing remote url '%s'\n", remote_url);
+		return -1;
+	}
+
+	memcpy(url_proto, remote_url, p - remote_url);
+	url_proto[p - remote_url] = 0;
+
+	p += strlen("://");
+
+	if (strcmp(url_proto, "hdlc")) {
+		fprintf(stderr, "ERROR: only hdlc proto is supported in the url\n");
+		return -1;
+	}
+
+	q = strstr(p, ":");
+	if (q != NULL) {
+		if (sscanf(q + 1, "%d", &url_port) != 1) {
+			fprintf(stderr, "ERROR: parsing remote url '%s'\n", remote_url);
+			return -1;
+		}
+
+		memcpy(url_host, p, q - p);
+		url_host[q - p] = 0;
+		p = q + 1;
+	} else {
+		url_port = HDLC_REMOTE_PORT;
+		memcpy(url_host, p, strlen(p));
+		url_host[strlen(p)] = 0;
+	}
+
+	q = strstr(p, ",");
+	if (q != NULL) {
+		if (sscanf(q + 1, "%d", &local_port) != 1) {
+			fprintf(stderr, "ERROR: parsing url '%s': wrong local port\n",
+					remote_url);
+			return -1;
+		}
+	}
+
+	DEBUG_HDLC_DL_LOG(printf("remote url %s://%s:%d,%d\n", url_proto, url_host, url_port, local_port));
+
+	/* create a socket */
+	sock = socket(proto_family, SOCK_DGRAM, 0);
+	if (sock < 0) {
+		perror("ERROR: socket creation failed!\n");
+		return -1;
+	}
+
+	memset(&status->saddr, 0, sizeof(status->saddr));
+
+#ifdef HDLC_USE_INET_SOCKET
+	status->saddr.sin_family = AF_INET;
+	status->saddr.sin_port = htons(url_port);
+	ret = inet_aton(url_host, &status->saddr.sin_addr);
+	if (ret < 0) {
+		perror("inet_aton");
+		return -1;
+	}
+
+	/* configures the local socket */
+	status->laddr.sin_family = AF_INET;
+	status->laddr.sin_port = htons(local_port);
+	status->laddr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+	/* we need to bind the local socket address */
+	if (bind(sock, (struct sockaddr *) &status->laddr, sizeof(status->laddr)) < 0) {
+		perror("socket binding failed for client");
+		close (sock);
+		return -1;
+	}
+
+	DEBUG_HDLC_DL_LOG(printf("local port = %d\n", local_port));
+
+#else
+	strcpy(saddr.sun_path, socket_path);
+	saddr.sun_family = AF_LOCAL;
+
+	/* creates a client socket name */
+	strcpy(caddr.sun_path, tempnam("/tmp", "zbsock"));
+	caddr.sun_family = AF_LOCAL;
+
+	/* we need to bind the local socket address */
+	if (bind(sock, (struct sockaddr *) &caddr, SUN_LEN(&caddr)) < 0) {
+		perror("socket binding failed for client\n");
+		close(sock);
+		return -1;
+	}
+#endif
+
+	status->rcv_loop = hdlc_net_rx_loop;
+	status->send = hdlc_net_tx;
+	status->close = hdlc_net_close;
+
+	DEBUG_HDLC_DL_LOG(printf ("socket %d\n", sock));
+
+	status->fd_dl = sock;
+	return (int) status;
+}
+
+/**
+ * Closes the serial communication
+ */
+
+int hdlc_net_close(int fd) {
+	hdlc_status_t *status = (hdlc_status_t *) fd;
+	return close(status->fd_dl);
+}
+
+/**
+ * Receive data from the serial port. It blocks till a message 
+ * has been completely received.
+ *
+ * @return 0 
+ * 	if the message has been received without errors
+ */
+
+int hdlc_net_rx_loop(int fd) {
+	fd_set rfds;
+	int completed = FALSE;
+
+	hdlc_status_t *status = (hdlc_status_t *) fd;
+
+	FD_ZERO(&rfds);
+	FD_SET(status->fd_dl, &rfds);
+
+	completed = FALSE;
+
+	unsigned char buf[300];
+
+	while (!completed) {
+		int sts;
+		struct sockaddr_in from;
+		socklen_t fromlen;
+
+		/* wait for any data received from the port */
+		sts = select(status->fd_dl + 1, &rfds, NULL, NULL, NULL);
+		if (sts == 0) {
+			/* timeout has occurred: this should never happen, since we don't have a timeout */
+			return -1;
+		} else if (sts < 0) {
+			/* error */
+			return -1;
+		}
+
+		int size;
+		fromlen = sizeof(from); /* NEEDED to make recvfrom work! */
+
+		size = recvfrom(status->fd_dl, buf, sizeof(buf), 0,
+				(struct sockaddr *) &from, &fromlen);
+		if (size < 0) {
+			/* error reading data! */
+			fprintf(stderr, "ERROR: reading data from network\n");
+			return size;
+		}
+
+		/* The following lines stores the from address for future use */
+
+		if (status->saddr.sin_addr.s_addr == htonl(INADDR_ANY)) {
+			/* we use the first packet arrived to setup the saddr */
+			fprintf(stderr,
+					"Set peer address accoring the first packet arrived\n");
+			memcpy(&status->saddr, &from, sizeof(status->saddr));
+		} else if (status->saddr.sin_addr.s_addr != from.sin_addr.s_addr) {
+			/* discard the packet! */
+			fprintf(stderr,
+					"WARNING: packet discarded because arrived from a wrong source\n");
+			continue;
+		}
+
+		DEBUG_HDLC_DL_LOG(zb_print_bytes("hdlc_net_rx_loop ", buf, size));
+		hdlc_input(fd, buf, size);
+	}
+	return 0;
+}
+
+/**
+ * Transmit the information field passed as parameter 
+ */
+
+int hdlc_net_tx(int fd, int control, const unsigned char *data, int size) {
+	int res;
+	unsigned char *out_frame;
+	const unsigned char *p;
+	unsigned char *q;
+
+	assert(data != NULL);
+
+	hdlc_status_t *status = (hdlc_status_t *) fd;
+
+	out_frame = (unsigned char *) malloc(2 * size + 5);
+	q = out_frame;
+
+	*q++ = control;
+
+	/* append the information field */
+	for (p = data; p < (data + size); p++) {
+		*q++ = *p;
+	}
+
+	/* append the calculated FCS */
+	int crc = crc16(out_frame + 1, q - out_frame - 1);
+	*q++ = crc & 0xFF;
+	*q++ = (crc >> 8) & 0xFF;
+
+	DEBUG_HDLC_DL_LOG(zb_print_bytes("hdlc_net_tx ", out_frame, q - out_frame));
+
+	/* write out the resulting frame */
+	res = sendto(status->fd_dl, out_frame, q - out_frame, 0,
+			(struct sockaddr *) &status->saddr, sizeof(status->saddr));
+	if (res < 0) {
+		fprintf(stderr, "ERROR: sending message\n");
+	}
+
+	free(out_frame);
+	return res;
+}

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/hdlc_proto.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/hdlc_proto.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/hdlc_proto.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,366 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+
+#ifdef WIN32
+# include <windows.h>
+# include <winsock.h>
+#else
+# include <time.h>
+# include <stdlib.h>
+# include <fcntl.h>
+# include <string.h>
+# include <sys/select.h>
+# include <sys/time.h>
+# include <sys/types.h>
+# include <unistd.h>
+# include <pthread.h>
+#endif
+
+#include "hdlc_dl.h"
+#include "hdlc_proto.h"
+#include "zigbee_log.h"
+
+int hdlc_output(int fd);
+static void *input_thread(void *);
+void *output_thread(void *arg);
+static int hdlc_to_upper(int fd, const unsigned char *frame, const int size);
+
+static pthread_t tid;
+
+/**
+ * Open the device device passed as parameter
+ * according its type
+ *
+ * @returns 
+ * 	0 if successful, < 0 in case of error.
+ */
+
+int hdlc_open(const char **params) {
+	int handle, ret;
+
+	if (params == NULL) {
+		return 0;
+	}
+
+	hdlc_status_t *hdlc_status;
+
+	const char *hostname = get_param(params, "hostname");
+	const char *port = get_param(params, "port");
+	const char *path = get_param(params, "path");
+
+#ifdef INCLUDE_HDLC_NET
+
+	if ((hostname != NULL) && (port != NULL)) {
+		if (path == NULL) {
+			char url[100];
+			strcpy(url, "hdlc://");
+			strcat(url, hostname);
+			strcat(url, ":");
+			strcat(url, port);
+			strcat(url, ",");
+			strcat(url, port + 1);
+
+			handle = hdlc_net_open(url);
+			if (handle == -1) {
+				return 0;
+			}
+			goto opened;
+		}
+		else {
+			return 0;
+		}
+	}
+#endif
+
+#ifdef INCLUDE_HDLC_SERIAL
+	if ((path != NULL) && (hostname == NULL) && (port == NULL)) {
+
+		handle = hdlc_ser_open(path);
+		if (handle == -1) {
+			return 0;
+		}
+	}
+	else {
+		return 0;
+	}
+#endif
+
+	opened:
+
+	/* fd is actually an hdlc_status_t *  */
+	hdlc_status = (hdlc_status_t *) handle;
+
+	/* creates a socketpair */
+	ret = socketpair(AF_LOCAL, SOCK_DGRAM, 0, hdlc_status->pair);
+	if (ret < 0) {
+		fprintf(stderr, "ERROR: unable to create the socketpair");
+		// TODO: close descriptor
+		free(hdlc_status);
+		return 0;
+	}
+
+	hdlc_status->fd = hdlc_status->pair[0];
+
+	ret = pthread_create(&tid, NULL, input_thread, hdlc_status);
+	if (ret < 0) {
+		// TODO: close descriptor
+		free(hdlc_status);
+		return 0;
+	}
+
+	ret = pthread_create(&tid, NULL, output_thread, hdlc_status);
+	if (ret < 0) {
+		// TODO: close descriptor
+		free(hdlc_status);
+		return 0;
+	}
+
+	return (int) hdlc_status;
+}
+
+void *input_thread(void *arg) {
+	assert(arg != NULL);
+	hdlc_status_t *hdlc_status = arg;
+	(hdlc_status->rcv_loop)((int) hdlc_status);
+	return NULL;
+}
+
+void *output_thread(void *arg) {
+	assert(arg != NULL);
+	hdlc_status_t *hdlc_status = arg;
+
+	hdlc_output((int) hdlc_status);
+	return NULL;
+}
+
+/**
+ * Closes the HDLC connection
+ */
+
+int hdlc_close(int handle) {
+	int sts;
+
+	/* the pointer to the close function is in the status */
+	hdlc_status_t *hdlc_status = (hdlc_status_t *) handle;
+
+	sts = (hdlc_status->close)(handle);
+	return sts;
+}
+
+/**
+ * Read 'count' number of bytes
+ */
+
+int hdlc_recv(int fd, void *buf, size_t count) {
+	/* get the received bytes from the message queue */
+	return 0;
+}
+
+/**
+ * Transmit the passed data trough the serial connection
+ * by using the HDLC protocol
+ *
+ * data is the payload that have to be embedded in an HDLC I-frame
+ */
+
+int hdlc_send(int handle, const unsigned char *data, int size) {
+	int sts;
+
+	hdlc_status_t *hdlc_status = (hdlc_status_t *) handle;
+
+	DEBUG_HDLC_PROTO_LOG(zb_print_bytes("APP frame ", data, size);)
+
+	/* write the passed frame to the socketpair */
+	sts = write(hdlc_status->pair[0], data, size);
+
+	return sts;
+}
+
+int hdlc_fd(int handle) {
+	hdlc_status_t *hdlc_status = (hdlc_status_t *) handle;
+	return hdlc_status->fd;
+}
+
+#ifdef HDLC_RELIABLE
+/**
+ * Manages the HDLC state machine
+ */
+
+int hdlc_output (int fd) {
+	return sts;
+}
+#else
+int hdlc_output(int handle) {
+	fd_set rfds;
+	unsigned char control;
+
+	control = 0x00;
+	hdlc_status_t *hdlc_status = (hdlc_status_t *) handle;
+
+	unsigned char buf[100];
+
+	while (1) {
+		int size, sts;
+
+		FD_ZERO(&rfds);
+		FD_SET(hdlc_status->pair[1], &rfds);
+
+		/* wait for any data received from the port */
+		sts = select(hdlc_status->pair[1] + 1, &rfds, NULL, NULL, NULL);
+		if (sts == 0) {
+			/* timeout has occurred: this should never happen, since we don't have a timeout */
+			return -1;
+		} else if (sts < 0) {
+			/* error */
+			return -1;
+		}
+
+		/* received some data */
+		size = read(hdlc_status->pair[1], buf, sizeof(buf));
+		if (size < 0) {
+			/* error reading data! */
+			return size;
+		}
+
+		/* send the packet to the other end */
+		sts = (hdlc_status->send)(handle, control, buf, size);
+	}
+	return 0;
+}
+#endif
+
+#ifdef HDLC_RELIABLE
+
+/**
+ * Called each time a frame has been decoded.
+ * This function in conjuction with the hdlc_output() function
+ * manages the HDLC protocol and thus retrasmission of trasmitted frames
+ * It uses the hdlccb (HDLC control block) structure in the status struct
+ * to mantain the local status
+ */
+
+int hdlc_input (int fd, const unsigned char *frame, const int size) {
+	unsigned short fcs;
+	unsigned char control, mask;
+
+	hdlc_status *status = (hdlc_status *) fd;
+
+	/* first of all checks if the received frame is valid */
+	if (size < 3) {
+		/* length MUST be at least 3 bytes. If not discard the frame */
+		status->hdlc_stats_len_errors++;
+		return -1;
+	}
+
+	fcs = frame[size - 2] | frame[size -1] << 8;
+
+	if (fcs != crc16(frame, size - 2)) {
+		status->hdlc_stats_fcs_errors++;
+		return -1;
+	}
+
+	/* the frame is OK. Now has to handle it according its type */
+	control = frame[0];
+	mask = control & 0x11;
+
+	if (mask == 0x00) {
+		/* this is an I-frame: handle it */
+		if (NR(control) != status->hdlccb_vr) {
+			/* the received I-frame is out-of-order and must be discarded */
+			status->hdlc_stats_ooo++;
+			return -1;
+		}
+
+		/* the received frame is in-order, pass the information field to the upper layers */
+		hdlc_to_upper(fd, frame + 1, size - 3);
+
+		/* increment V(R) */
+		status->hdlccb_vr++;
+	}
+	else if (mask == 0x01) {
+		/* this is an S-frame: handle it */
+		if (SS(control) == S_FRAME_RR) {
+			/* this is an RR frame */
+		}
+		else if (SS(control) == S_FRAME_RNR) {
+			/* this is a RNR frame. Force trasmitter to stop transmission */
+		}
+
+		if (NR(control) != status->hdlccb_vr) {
+			/* the received S-frame is out of order. Discard it! */
+			status->hdlc_stats_ooo++;
+			return -1;
+		}
+	}
+	else {
+		/* unexpected frame type */
+		status->hdlc_stats_unknown_type++;
+		return -1;
+	}
+
+	return 0; /* frame successfully processed */
+}
+
+#else
+
+/**
+ * This is a light implementation. No retrasmissions
+ */
+
+int hdlc_input(int handle, const unsigned char *frame, int size) {
+
+	unsigned short fcs;
+	unsigned char control, mask;
+
+	hdlc_status_t *hdlc_status = (hdlc_status_t *) handle;
+
+	DEBUG_HDLC_PROTO_LOG(zb_print_bytes("hdlc_input ", frame, size));
+
+	/* first of all checks if the received frame is valid */
+	if (size < 3) {
+		/* length MUST be at least 3 bytes. If not discard the frame */
+		hdlc_status->hdlc_stats_len_errors++;
+		return -1;
+	}
+
+	fcs = frame[size - 2] | frame[size - 1] << 8;
+
+	if (fcs != crc16(frame, size - 2)) {
+		hdlc_status->hdlc_stats_fcs_errors++;
+		return -1;
+	}
+
+	/* the frame is OK. Now has to handle it according its type */
+	control = frame[0];
+	mask = control & 0x11;
+
+	if (mask == 0x00) {
+		/* pass the information field to the upper layers */
+		hdlc_to_upper(handle, frame + 1, size - 3);
+	} else {
+		/* unknown frame type */
+		fprintf(stderr, "ERROR: unknown frame type\n");
+	}
+	return 0; /* frame successfully processed */
+}
+#endif
+
+int hdlc_to_upper(int handle, const unsigned char *frame, int size) {
+	int res;
+	hdlc_status_t *hdlc_status = (hdlc_status_t *) handle;
+
+	res = write(hdlc_status->pair[1], frame, size);
+
+	DEBUG_HDLC_PROTO_LOG(zb_print_bytes("hdlc_to_upper ", frame, size));
+	return res;
+}

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/hdlc_ser.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/hdlc_ser.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/hdlc_ser.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,338 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#ifndef _VXWORKS
+# include <time.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <fcntl.h>
+# include <termios.h>
+# include <string.h>
+# include <errno.h>
+# include <sys/select.h>
+# include <sys/time.h>
+# include <sys/types.h>
+# include <unistd.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#ifndef PCSC_TARGET_VXWORKS
+# include <sys/un.h>
+#endif
+
+#include <stddef.h>
+
+#include "hdlc_dl.h"
+#include "hdlc_proto.h"
+#include "zigbee_log.h"
+
+#define HDLC_FRAME_IDLE			0
+#define HDLC_FRAME_FLAG			1
+#define HDLC_FRAME_DECODE		2
+#define HDLC_FRAME_ESC			3
+
+static int hdlc_ser_rx_loop(int fd);
+static int hdlc_ser_tx(int fd, int control, const unsigned char *data, int size);
+static int hdlc_ser_close(int fd);
+
+/**
+ * Opens the HDLC serial device and initializes the status
+ * fields related to the framing handling
+ */
+
+int hdlc_ser_open(const char *dev_name) {
+	int fd;
+
+	assert(dev_name != NULL);
+
+	hdlc_status_t *status = (hdlc_status_t *) malloc(sizeof(hdlc_status_t));
+
+#ifndef _VXWORKS
+	struct termios current_termios;
+	int ospeed;
+
+	fd = open(dev_name, O_RDWR | O_NOCTTY);
+
+	if (fd == -1) {
+		return -1;
+	}
+
+	/* empty in and out serial buffers */
+	if (tcflush(fd, TCIOFLUSH)) {
+		close(fd);
+		return -1;
+	}
+	/* get config attributes */
+	if (tcgetattr(fd, &current_termios) == -1) {
+		close(fd);
+		return -1;
+	}
+
+	/* actual serial port baud rate */
+	ospeed = cfgetospeed(&current_termios);
+
+	current_termios.c_iflag = 0;
+	current_termios.c_oflag = 0; /* Raw output modes */
+	current_termios.c_cflag = 0; /* Raw output modes */
+
+	/* 
+	 * Do not echo characters because if you connect
+	 * to a host it or your
+	 * modem will echo characters for you.
+	 * Don't generate signals.
+	 */
+
+	current_termios.c_lflag = 0;
+
+	/* 
+	 * control flow - enable receiver - ignore modem
+	 * control lines
+	 */
+
+	current_termios.c_cflag = CREAD | CLOCAL;
+
+	current_termios.c_cflag |= CS8;
+
+	/*
+	 * This is Non Canonical mode set.
+	 * by setting c_cc[VMIN]=0 and c_cc[VTIME] = 10
+	 * each read operation will wait for 10*1/10 = 1 sec
+	 * If single byte is received, read function returns.
+	 * if timer expires, read() returns 0.
+	 * Minimum bytes to read
+	 */
+
+	current_termios.c_cc[VMIN] = 0;
+
+	/*
+	 * Time between two bytes read (VTIME x 0.10 s)
+	 * 10 seconds may not be the correct maximum value
+	 * If the card becomes mute the reader will tell us
+	 * If the reader becomes mute (crash or serial comm pb.) we won't know
+	 */
+
+	cfsetospeed(&current_termios, B9600);
+	cfsetispeed(&current_termios, 0); /* 0 corresponds to output speed */
+
+	if (tcsetattr(fd, TCSANOW, &current_termios) == -1) {
+		perror("tcsetattr():");
+		close(fd);
+		return -1;
+	}
+#else
+	fd = open(dev_name, O_RDWR, 0644);
+	if (fd == -1) {
+		zb_print_error (__FILE__, __LINE__, "ERROR: While opening device %s", dev_name);
+		return -1;
+	}
+#endif
+
+	status->rcv_loop = hdlc_ser_rx_loop;
+	status->send = hdlc_ser_tx;
+	status->close = hdlc_ser_close;
+
+	status->fd_dl = fd;
+	status->rx_state = HDLC_FRAME_IDLE;
+	status->tx_state = HDLC_FRAME_IDLE;
+	status->rx_offs = 0;
+
+	return (int) status;
+}
+
+/**
+ * Closes the serial communication
+ */
+
+int hdlc_ser_close(int fd) {
+	hdlc_status_t *status = (hdlc_status_t *) fd;
+
+	return close(status->fd_dl);
+}
+
+/**
+ * Receive data from the serial port. It blocks till a message 
+ * has been completely received.
+ *
+ * @return 0 
+ * 	if the message has been received without errors
+ */
+
+int hdlc_ser_rx_loop(int fd) {
+
+	int i;
+	fd_set rfds;
+	int completed = FALSE;
+
+	hdlc_status_t *status = (hdlc_status_t *) fd;
+
+	assert(status != NULL);
+
+	completed = FALSE;
+
+	unsigned char buf[300];
+	unsigned char out[300];
+
+	while (!completed) {
+		int sts;
+
+		FD_ZERO(&rfds);
+		FD_SET(status->fd_dl, &rfds);
+
+		/* wait for any data received from the port */
+		sts = select(status->fd_dl + 1, &rfds, NULL, NULL, NULL);
+		if (sts == 0) {
+			/* timeout has occurred: this should never happen, since we don't have a timeout */
+			return -1;
+		} else if (sts < 0) {
+			/* error */
+			return -1;
+		}
+
+		int no_more = FALSE;
+		int ch;
+		int size;
+
+		while (!no_more) {
+
+			/* received some data */
+			size = read(status->fd_dl, buf, sizeof(buf));
+			if (sts < 0) {
+				/* error reading data! */
+				return -1;
+			}
+
+			/* decodes received data */
+			for (i = 0; i < size; i++) {
+				ch = buf[i];
+				switch (status->rx_state) {
+				case HDLC_FRAME_IDLE:
+					/* we are waiting for the start frame flag */
+					if (ch == 0x7E) {
+						status->rx_state = HDLC_FRAME_FLAG; /* this is the state we received a start flag! */
+					}
+
+					/* skip the received char */
+					break;
+
+				case HDLC_FRAME_FLAG:
+					if (ch == 0x7E) {
+						/* FLAG might be followed by other flags */
+						break;
+					} else {
+						status->rx_state = HDLC_FRAME_DECODE; /* OK the frame started */
+						status->rx_offs = 0; /* offset of the next received out char */
+					}
+
+					/* ATTENTION! no break statement here */
+
+				case HDLC_FRAME_DECODE:
+				case HDLC_FRAME_ESC:
+					if (ch == 0x7E) {
+						/* 
+						 * this is the flag that terminates the frame
+						 * and might indicate the starting point of the
+						 * next one
+						 */
+
+						status->rx_state = HDLC_FRAME_IDLE;
+						/* status->rx_offs = 0; fix: this line has been removed by Garino. */
+						/* frame decoded, pass it to upper level */
+						DEBUG_HDLC_DL_LOG(zb_print_bytes("hdlc_ser_rx_loop ", out, status->rx_offs));
+						hdlc_input(fd, out, status->rx_offs); /* status, buff, size */
+					} else if (ch == 0x7F) {
+						/* abort the current frame */
+						status->rx_state = HDLC_FRAME_IDLE;
+						status->rx_offs = 0;
+					} else if (ch == 0x7D) {
+						/* this is the escape char we need to decode the next one */
+						status->rx_state = HDLC_FRAME_ESC;
+					} else {
+						assert(status->rx_offs < sizeof(out));
+						if (status->rx_state == HDLC_FRAME_ESC) {
+							out[status->rx_offs] = ch | 0x20;
+							status->rx_state = HDLC_FRAME_DECODE;
+						} else {
+							out[status->rx_offs] = ch;
+						}
+
+						status->rx_offs++;
+					}
+					break;
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+/**
+ * Transmit the infomration field passed as parameter 
+ */
+
+int hdlc_ser_tx(int fd, int control, const unsigned char *data, int size) {
+	int res;
+	unsigned char *out_frame;
+	const unsigned char *p;
+	unsigned char *q;
+
+	assert(data != NULL);
+
+	hdlc_status_t *status = (hdlc_status_t *) fd;
+
+	out_frame = (unsigned char *) malloc(2 * size + 5);
+	q = out_frame;
+
+	*q++ = 0x7E;
+
+	/* generate the control field */
+	if ((control == 0x7E) || (control == 0x7D) || (control == 0x7F)) {
+		*q++ = 0x7D;
+		*q++ = control & 0xDF; /* reset bit */
+	} else {
+		*q++ = control;
+	}
+
+	/* append the information field */
+	for (p = data; p < (data + size); p++) {
+		if ((*p == 0x7E) || (*p == 0x7D) || (*p == 0x7F)) {
+			*q++ = 0x7D;
+			*q++ = *p & 0xDF; /* reset bit */
+		} else {
+			*q++ = *p;
+		}
+	}
+
+	/* append the calculated FCS */
+	int crc = crc16(out_frame + 1, q - out_frame - 1);
+
+	*q++ = crc & 0xFF;
+	*q++ = (crc >> 8) & 0xFF;
+
+	/* append the termination flag */
+	*q++ = 0x7E;
+
+	DEBUG_HDLC_DL_LOG (zb_print_bytes("hdlc_ser_tx ", out_frame, q - out_frame));
+
+	/* write out the resulting frame */
+	res = write(status->fd_dl, out_frame, q - out_frame);
+	free(out_frame);
+	return res;
+}

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/integration_if.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/integration_if.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/integration_if.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,1372 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+/**
+ * High level interface to the ZigBee protocol stack
+ * The stack actually runs on the INT or on a external
+ * board connected to the system by means of a serial 
+ * connection
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include "zb_conn.h"
+#include "zigbee.h"
+#include "zigbee_local.h"
+#include "integration_if.h"
+#include "zigbee_log.h"
+
+#include "bisync.h"
+#include "bisync_tokens.h"
+
+#ifdef DEBUG_ZIGBEE_API
+#include "zigbee_utils.h"
+#endif
+
+unsigned char out_buf[200];
+
+#ifndef ZIGBEE_USE_DATA_STRUCTURES
+
+void INT_ZDO_RESET_request(ZBIF_HANDLE zbif_handle, ushort options);
+
+void INT_ZDO_START_request(ZBIF_HANDLE zbif_handle);
+
+void INT_ZDO_NWK_ADDR_request(ZBIF_HANDLE zbif_handle, uchar *ieee_addr,
+		uchar request_type, uchar start_index);
+
+void INT_ZDO_IEEE_ADDR_request(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar request_type, uchar start_index);
+
+void INT_ZDO_NODE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr);
+
+void INT_ZDO_POWER_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr);
+
+void INT_ZDO_SIMPLE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, uchar endpoint);
+
+void INT_ZDO_ACTIVE_EP_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr);
+
+void INT_ZDO_MATCH_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, ushort profile_id, uchar nicl, ushort *icllist,
+		uchar nocl, ushort *ocllist);
+
+void INT_ZDO_MATCH_DESC_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort dst_addr, uchar match_len, uchar *match_list);
+
+void INT_ZDO_END_DEVICE_BIND_request(ZBIF_HANDLE zbif_handle,
+		ushort binding_target, uchar *src_ieee_addr, uchar src_ep,
+		ushort profile_id, uchar nicl, ushort *icllist, uchar nocl,
+		ushort *ocllist);
+
+void INT_APSDE_DATA_request(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, ushort profile_id, ushort cluster_id,
+		uchar src_ep, uchar asdu_len, uchar *asdu, uchar tx_options,
+		uchar radius);
+
+void INT_APSME_BIND_request(ZBIF_HANDLE zbif_handle, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep);
+
+void INT_APSME_UNBIND_request(ZBIF_HANDLE zbif_handle, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep);
+
+void INT_APSME_GET_request(ZBIF_HANDLE zbif_handle, uchar attr);
+
+void INT_APSME_SET_request(ZBIF_HANDLE zbif_handle, uchar attr, uchar attr_len,
+		uchar *attr_value);
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+
+void INT_APSME_REMOVE_DEVICE_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *parent_ieee_addr,
+		uchar *child_ieee_addr
+);
+
+void INT_APSME_TRANSPORT_KEY_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *dst_ieee_addr,
+		uchar key_type,
+		ZB_TRANSPORT_KEY_DATA *transport_key_data
+);
+
+void INT_NLME_LEAVE_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *dev_ieee_addr,
+		uchar remove_children,
+		uchar rejoin,
+		uchar reuse_address,
+		uchar silent
+);
+
+#endif
+
+void INT_ZDO_ERROR_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort cluster_id, uchar expected_len);
+
+#endif /* ZIGBEE_USE_DATA_STRUCTURES */
+
+void INT_ZDO_RESET_request(ZBIF_HANDLE zbif_handle, ushort options) {
+	uchar *p;
+	p = out_buf + 1;
+
+	*p++ = ZDO_RESET_REQUEST;
+	*p++ = type;
+
+	*out_buf = p - out_buf - 1;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+	return;
+}
+
+void INT_ZDO_START_request(ZBIF_HANDLE zbif_handle) {
+	uchar *p;
+	p = out_buf + 1;
+
+	*p++ = ZDO_START_REQUEST;
+
+	*out_buf = p - out_buf - 1;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+	return;
+}
+
+void INT_ZDO_NWK_ADDR_request(ZBIF_HANDLE zbif_handle, uchar *ieee_addr,
+		uchar request_type, uchar start_index) {
+	uchar *p;
+
+	assert(ieee_addr != NULL);
+
+	p = out_buf + 1;
+
+	*p++ = ZDO_NWK_ADDR_REQUEST;
+
+	memcpy(p, ieee_addr, IEEE_ADDR_LEN);
+	swap_bytes(p, IEEE_ADDR_LEN);
+
+	p += IEEE_ADDR_LEN;
+	*p++ = request_type;
+	*p++ = start_index;
+
+	*out_buf = p - out_buf - 1;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void INT_ZDO_IEEE_ADDR_request(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar request_type, uchar start_index) {
+	uchar *p;
+	p = out_buf + 1;
+
+	*p++ = ZDO_IEEE_ADDR_REQUEST;
+
+	*p++ = LSB_USHORT(nwk_addr);
+	*p++ = MSB_USHORT(nwk_addr);
+	*p++ = request_type;
+	*p++ = start_index;
+	*out_buf = p - out_buf - 1;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void INT_ZDO_NODE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr) {
+	uchar *p;
+	p = out_buf + 1;
+
+	*p++ = ZDO_NODE_DESC_REQUEST;
+
+	*p++ = LSB_USHORT(dst_addr);
+	*p++ = MSB_USHORT(dst_addr);
+
+	*p++ = LSB_USHORT(nwk_addr);
+	*p++ = MSB_USHORT(nwk_addr);
+	*out_buf = p - out_buf - 1;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void INT_ZDO_POWER_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr) {
+	uchar *p;
+	p = out_buf + 1;
+
+	*p++ = ZDO_POWER_DESC_REQUEST;
+
+	*p++ = LSB_USHORT(dst_addr);
+	*p++ = MSB_USHORT(dst_addr);
+
+	*p++ = LSB_USHORT(nwk_addr);
+	*p++ = MSB_USHORT(nwk_addr);
+	*out_buf = p - out_buf - 1;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void INT_ZDO_SIMPLE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, uchar endpoint) {
+	uchar *p;
+	p = out_buf + 1;
+
+	*p++ = ZDO_SIMPLE_DESC_REQUEST;
+
+	*p++ = LSB_USHORT(dst_addr);
+	*p++ = MSB_USHORT(dst_addr);
+
+	*p++ = LSB_USHORT(nwk_addr);
+	*p++ = MSB_USHORT(nwk_addr);
+	*p++ = endpoint;
+
+	*out_buf = p - out_buf - 1;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void INT_ZDO_ACTIVE_EP_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr) {
+	uchar *p;
+	p = out_buf + 1;
+
+	*p++ = ZDO_ACTIVE_EP_DESC_REQUEST;
+
+	*p++ = LSB_USHORT(dst_addr);
+	*p++ = MSB_USHORT(dst_addr);
+
+	*p++ = LSB_USHORT(nwk_addr);
+	*p++ = MSB_USHORT(nwk_addr);
+	*out_buf = p - out_buf - 1;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void INT_ZDO_MATCH_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, ushort profile_id, uchar nicl, ushort *icllist,
+		uchar nocl, ushort *ocllist) {
+	uchar *p;
+	int i;
+
+	p = out_buf + 1;
+
+	assert(icllist != NULL);
+	assert(ocllist != NULL);
+
+	*p++ = ZDO_MATCH_DESC_REQUEST;
+
+	*p++ = LSB_USHORT(dst_addr);
+	*p++ = MSB_USHORT(dst_addr);
+	*p++ = LSB_USHORT(nwk_addr);
+	*p++ = MSB_USHORT(nwk_addr);
+	*p++ = LSB_USHORT(profile_id);
+	*p++ = MSB_USHORT(profile_id);
+
+	*p++ = nicl;
+
+	for (i = 0; i < nicl; i++) {
+		*p++ = LSB_USHORT(icllist[i]);
+		*p++ = MSB_USHORT(icllist[i]);
+	}
+
+	*p++ = nocl;
+
+	for (i = 0; i < nicl; i++) {
+		*p++ = LSB_USHORT(ocllist[i]);
+		*p++ = MSB_USHORT(ocllist[i]);
+	}
+
+	*out_buf = p - out_buf - 1;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void INT_ZDO_MATCH_DESC_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, uchar match_len, uchar *match_list) {
+#if 0
+	uchar *p;
+	int i;
+
+	p = out_buf + 1;
+
+	PUT_USHORT(p, ZB_ZDO_MATCH_DESC_RESPONSE);
+
+	*p++ = status;
+
+	*p++ = LSB_USHORT(nwk_addr);
+	*p++ = MSB_USHORT(nwk_addr);
+
+	*p++ = match_len;
+
+	for (i = 0; i < match_len; i++) {
+		*p++ = match_list[i];
+	}
+
+	*out_buf = p - out_buf;
+	zb_conn_send(zbif_handle, out_buf, p - out_buf);
+#endif
+}
+
+void INT_ZDO_END_DEVICE_BIND_request(ZBIF_HANDLE zbif_handle,
+		ushort binding_target, uchar *src_ieee_addr, uchar src_ep,
+		ushort profile_id, uchar nicl, ushort *icllist, uchar nocl,
+		ushort *ocllist) {
+	uchar *p;
+	int i;
+
+	p = out_buf + 1;
+
+	*p++ = ZDO_END_DEVICE_BIND_REQUEST;
+
+	*p++ = LSB_USHORT(binding_target);
+	*p++ = MSB_USHORT(binding_target);
+
+	memcpy(p, src_ieee_addr, IEEE_ADDR_LEN);
+	p += IEEE_ADDR_LEN;
+	*p++ = src_ep;
+
+	*p++ = LSB_USHORT(profile_id);
+	*p++ = MSB_USHORT(profile_id);
+
+	*p++ = nicl;
+
+	for (i = 0; i < nicl; i++) {
+		*p++ = LSB_USHORT(icllist[i]);
+		*p++ = MSB_USHORT(icllist[i]);
+	}
+
+	*p++ = nocl;
+
+	for (i = 0; i < nocl; i++) {
+		*p++ = LSB_USHORT(ocllist[i]);
+		*p++ = MSB_USHORT(ocllist[i]);
+	}
+
+	*out_buf = p - out_buf - 1;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void INT_APSDE_DATA_request(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, ushort profile_id, ushort cluster_id,
+		uchar src_ep, uchar asdu_len, uchar *asdu, uchar tx_options,
+		uchar radius) {
+	uchar *p;
+	p = out_buf + 1;
+
+#if 0
+	*p++ = APSDE_DATA_REQUEST);
+
+	*p++ = dst_addr_mode;
+	if (dst_addr_mode == ZB_AM_INDIRECT) {
+		/* Indirect address mode. dst_addr and dst_ep not used */
+	}
+	else if (dst_addr_mode == ZB_AM_DIRECT_GROUP) {
+		/* Direct address mode with short grp_addr */
+		if (dst_addr == NULL) {
+			return;
+		}
+
+		ushort dst = *((ushort *) dst_addr);
+
+		*p++ = LSB_USHORT(dst);
+		*p++ = MSB_USHORT(dst);
+
+		*p++ = dst_ep; /* not used! */
+	}
+	else if (dst_addr_mode == ZB_AM_DIRECT) {
+		/* Direct address mode with short dst_addr */
+		if (dst_addr == NULL) {
+			return;
+		}
+
+		ushort dst = *((ushort *) dst_addr);
+
+		*p++ = LSB_USHORT(dst);
+		*p++ = MSB_USHORT(dst);
+
+		*p++ = dst_ep;
+	}
+	else if (dst_addr_mode == ZB_AM_DIRECT_EX) {
+		/* Direct address mode with long (ieee) dst_addr */
+		if (dst_addr == NULL) {
+			zb_print_error("ERROR: passed NULL pointer instead of an IEEE address");
+			return;
+		}
+
+		memcpy(p, dst_addr, IEEE_ADDR_LEN); p += IEEE_ADDR_LEN;
+
+		*p++ = dst_ep;
+	}
+	else {
+		/* error! */
+		zb_print_error("ERROR: unsupported dst_addr_mode: %d", (int) dst_addr_mode);
+		return;
+	}
+
+	*p++ = LSB_USHORT(profile_id);
+	*p++ = MSB_USHORT(profile_id);
+	*p++ = LSB_USHORT(cluster_id);
+	*p++ = MSB_USHORT(cluster_id);
+
+	*p++ = src_ep;
+	*p++ = asdu_len;
+
+	if (asdu_len > 0) {
+		memcpy(p, asdu, asdu_len);
+		p += asdu_len;
+	}
+	*p++ = tx_options;
+	*p++ = radius;
+#endif
+
+	*out_buf = p - out_buf;
+	zb_conn_send(zbif_handle, out_buf, p - out_buf);
+}
+
+void INT_APSME_BIND_request(ZBIF_HANDLE zbif_handle, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep) {
+	uchar *p;
+	p = out_buf + 1;
+
+#if 0
+
+	assert (src_ieee_addr != NULL);
+
+	PUT_USHORT(p, ZB_APSME_BIND_REQUEST);
+
+	memcpy(p, src_ieee_addr, IEEE_ADDR_LEN);
+	p += IEEE_ADDR_LEN;
+	*p++ = src_ep;
+
+	*p++ = LSB_USHORT(cluster_id);
+	*p++ = MSB_USHORT(cluster_id);
+
+	memcpy(p, dst_ieee_addr, IEEE_ADDR_LEN);
+	p += IEEE_ADDR_LEN;
+	*p++ = dst_ep;
+#endif
+
+	*out_buf = p - out_buf;
+	zb_conn_send(zbif_handle, out_buf, p - out_buf);
+}
+
+void INT_APSME_UNBIND_request(ZBIF_HANDLE zbif_handle, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep) {
+	uchar *p;
+
+	p = out_buf + 1;
+
+#if 0
+	assert (src_ieee_addr != NULL);
+
+	PUT_USHORT(p, ZB_APSME_UNBIND_REQUEST);
+
+	memcpy(p, src_ieee_addr, IEEE_ADDR_LEN);
+	p += IEEE_ADDR_LEN;
+	*p++ = src_ep;
+
+	*p++ = LSB_USHORT(cluster_id);
+	*p++ = MSB_USHORT(cluster_id);
+
+	memcpy(p, dst_ieee_addr, IEEE_ADDR_LEN);
+	p += IEEE_ADDR_LEN;
+	*p++ = dst_ep;
+#endif
+
+	*out_buf = p - out_buf;
+	zb_conn_send(zbif_handle, out_buf, p - out_buf);
+}
+
+void INT_APSME_GET_request(ZBIF_HANDLE zbif_handle, uchar attr) {
+#if 0
+	uchar *p;
+
+	p = out_buf + 1;
+
+	PUT_USHORT(p, ZB_APSME_GET_REQUEST);
+
+	*p++ = attr;
+
+	*out_buf = p - out_buf;
+	zb_conn_send(zbif_handle, out_buf, p - out_buf);
+#endif
+}
+
+void INT_APSME_SET_request(ZBIF_HANDLE zbif_handle, uchar attr, uchar attr_len,
+		uchar *attr_value) {
+	/* PATCHED */
+	uchar *p;
+
+	p = out_buf + 1;
+
+	*p++ = ZDO_SET_REQUEST;
+
+	*p++ = attr;
+	*p++ = attr_len;
+
+	if (attr_len > 0) {
+		memcpy(p, attr_value, attr_len);
+		p += attr_len;
+	}
+
+	*out_buf = p - out_buf - 1;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void INT_APSME_SET_confirm(uchar status, uchar attr) {
+	zb_print("APSME_SET_confirm: status = 0x%02x\n", status);
+	return;
+}
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+
+void INT_APSME_UPDATE_DEVICE_indication (
+		uchar *src_ieee_addr,
+		uchar *dev_ieee_addr,
+		uchar status,
+		ushort dev_nwk_addr
+) {
+	return;
+}
+
+/**
+ * TODO: document it!
+ */
+
+void INT_APSME_REMOVE_DEVICE_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *parent_ieee_addr,
+		uchar *child_ieee_addr
+) {
+#if 0
+	uchar *p;
+
+	assert (parent_ieee_addr != NULL);
+	assert (child_ieee_addr != NULL);
+
+	p = out_buf + 1;
+
+	*p = APSME_REMOVE_DEVICE_REQUEST;
+
+	memcpy(p, parent_ieee_addr, IEEE_ADDR_LEN); swap_bytes(p, IEEE_ADDR_LEN); p += IEEE_ADDR_LEN;
+	memcpy(p, child_ieee_addr, IEEE_ADDR_LEN); swap_bytes(p, IEEE_ADDR_LEN); p += IEEE_ADDR_LEN;
+
+	*out_buf = p - out_buf;
+	zb_conn_send(zbif_handle, out_buf, p - out_buf);
+#endif
+}
+
+void INT_APSME_TRANSPORT_KEY_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *dst_ieee_addr,
+		uchar key_type,
+		ZB_TRANSPORT_KEY_DATA *transport_key_data
+) {
+	/* PORTED */
+	uchar *p;
+
+	assert (dst_ieee_addr != NULL);
+
+	p = out_buf + 1;
+
+	*p++ = APSME_TRANSPORT_KEY_REQUEST;
+
+	memcpy(p, dst_ieee_addr, IEEE_ADDR_LEN); swap_bytes(p, IEEE_ADDR_LEN); p += IEEE_ADDR_LEN;
+	*p++ = key_type;
+
+	switch (key_type) {
+		case ZB_TC_MASTER_KEY:
+		memcpy(p, transport_key_data->tcmk.parent_ieee_addr, IEEE_ADDR_LEN);
+		swap_bytes(p, IEEE_ADDR_LEN); p += IEEE_ADDR_LEN;
+
+		memcpy(p, transport_key_data->tcmk.tc_master_key, ZB_TRANSPORT_KEY_LEN);
+		swap_bytes(p, ZB_TRANSPORT_KEY_LEN); p += ZB_TRANSPORT_KEY_LEN;
+
+		break;
+
+		case ZB_NWK_KEY:
+		*p++ = transport_key_data->nwk_key.key_seq_num;
+		memcpy(p, transport_key_data->nwk_key.nwk_key, ZB_TRANSPORT_KEY_LEN);
+		swap_bytes(p, ZB_TRANSPORT_KEY_LEN); p += ZB_TRANSPORT_KEY_LEN;
+
+		*p++ = transport_key_data->nwk_key.use_parent;
+
+		memcpy (p, transport_key_data->nwk_key.parent_ieee_addr, IEEE_ADDR_LEN);
+		swap_bytes(p, IEEE_ADDR_LEN); p += IEEE_ADDR_LEN;
+		break;
+
+		case ZB_APP_MASTER_KEY:
+		case ZB_APP_LINK_KEY:
+		memcpy (p, transport_key_data->link_key.partner_ieee_addr, IEEE_ADDR_LEN);
+		swap_bytes(p, IEEE_ADDR_LEN); p += IEEE_ADDR_LEN;
+
+		*p++ = transport_key_data->link_key.initiator;
+
+		memcpy (p, transport_key_data->link_key.key, ZB_TRANSPORT_KEY_LEN);
+		swap_bytes(p, ZB_TRANSPORT_KEY_LEN); p += ZB_TRANSPORT_KEY_LEN;
+		break;
+
+	}
+
+	*out_buf = p - out_buf - 1;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void INT_NLME_LEAVE_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *dev_ieee_addr,
+		uchar remove_children,
+		uchar rejoin,
+		uchar reuse_address,
+		uchar silent
+) {
+	/* PATCHED */
+	uchar *p;
+
+	assert (dev_ieee_addr != NULL);
+
+	p = out_buf + 1;
+
+	*p++ = ZDO_NLME_LEAVE_REQUEST;
+
+	memcpy(p, dev_ieee_addr, IEEE_ADDR_LEN);
+	p += IEEE_ADDR_LEN;
+
+	*p++ = remove_children;
+	*p++ = rejoin;
+
+	*out_buf = p - out_buf - 1;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+#endif /* INCLUDE_ZIGBEE_SECURITY */
+
+void INT_ZDO_ERROR_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort cluster_id, uchar expected_len) {
+#if 0
+	uchar *p;
+	p = out_buf + 1;
+
+	PUT_USHORT(p, ZB_ERROR_RESPONSE);
+
+	*p++ = status;
+
+	*p++ = LSB_USHORT(cluster_id);
+	*p++ = MSB_USHORT(cluster_id);
+
+	*p++ = expected_len;
+
+	*out_buf = p - out_buf;
+	zb_conn_send(zbif_handle, out_buf, p - out_buf);
+#endif
+}
+
+/**
+ * This function provides decoding functionalities.
+ * The passed data should not be freed!
+ */
+
+void INT_ReceiveCb(ZBIF_HANDLE zbif_handle, uchar *data, const int size) {
+	int exp_size;
+	uchar *p;
+
+	if (!zbif_handle) {
+		return;
+	}
+
+	ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+	if (!zbifCbs) {
+		/* error! */
+		return;
+	}
+
+	p = data + 1;
+
+	switch (*p) {
+
+	case ZDO_RESET_CONFIRM:
+		if (zbifCbs->ZDO_RESET_confirm) {
+			zbifCbs->ZDO_RESET_confirm(zbif_handle, p[0]);
+		}
+		break;
+
+	case ZDO_START_CONFIRM:
+		if (zbifCbs->ZDO_START_confirm) {
+			ushort nwk_addr = p[1] | (p[2] << 8);
+			zbifCbs->ZDO_START_confirm(zbif_handle, p[0], nwk_addr);
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_START_confirm (p[0], nwk_addr);
+#endif
+		}
+		break;
+
+	case ZDO_NWK_ADDR_CONFIRM:
+		if (zbifCbs->ZDO_NWK_ADDR_confirm) {
+			/* invoke the callback */
+			ushort *nwk_addr_assoc_dev = NULL;
+			uchar start_index = 0;
+			uchar num_assoc_dev = 0;
+
+			/* 
+			 * the actual packet format depends on the request_mode
+			 * of the previous request sent. Unfortunately this
+			 * field is not present in the confirm and we need to
+			 * rely on the message size
+			 */
+
+			int len = 14; /* minimum message len (std response) */
+
+			if (size >= (len + 1)) {
+				/* Extended response. Field num_assoc_dev present */
+				num_assoc_dev = p[3 + IEEE_ADDR_LEN];
+				if (num_assoc_dev > 0) {
+					nwk_addr_assoc_dev = (unsigned short *) (p + 5
+							+ IEEE_ADDR_LEN);
+
+					start_index = p[4 + IEEE_ADDR_LEN];
+
+				}
+
+				exp_size = len + 1 + (num_assoc_dev << 1);
+			} else {
+				exp_size = len;
+			}
+
+			if (exp_size != size) {
+				zb_print_error(
+						"WARNING: expected size (%d) different from actual size (%d) "
+						"for ZB_ZDO_NWK_ADDR_CONFIRM\n", exp_size, size);
+			}
+
+			swap_bytes(p + 1, IEEE_ADDR_LEN);
+
+			zbifCbs->ZDO_NWK_ADDR_confirm(zbif_handle, p[0], /* status 	*/
+			p + 1, /* ieee_addr 	*/
+			p[1 + IEEE_ADDR_LEN] | (p[2 + IEEE_ADDR_LEN] << 8), num_assoc_dev, /* num_assoc_dev	*/
+			start_index, /* start_index 		*/
+			nwk_addr_assoc_dev);
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_NWK_ADDR_confirm (
+					p [0], /* status 	*/
+					p + 1, /* ieee_addr 	*/
+					p [1 + IEEE_ADDR_LEN] | (p [2 + IEEE_ADDR_LEN] << 8),
+					num_assoc_dev, /* num_assoc_dev	*/
+					start_index, /* start_index 		*/
+					nwk_addr_assoc_dev
+			);
+#endif
+		}
+		break;
+
+	case ZDO_IEEE_ADDR_CONFIRM:
+		if (zbifCbs->ZDO_IEEE_ADDR_confirm) {
+			/* invoke the callback */
+			ushort *nwk_addr_assoc_dev = NULL;
+			uchar start_index = 0;
+			uchar num_assoc_dev = 0;
+
+			/* 
+			 * the actual packet format depends on the request_mode
+			 * of the previous request sent. Unfortunately this
+			 * field is not present in the confirm and we need to
+			 * rely on the message size
+			 */
+
+			int len = 14; /* minimum message len (std response) */
+
+			if (size >= (len + 1)) {
+				/* Extended response. Field num_assoc_dev present */
+				num_assoc_dev = p[3 + IEEE_ADDR_LEN];
+				if (num_assoc_dev > 0) {
+					nwk_addr_assoc_dev = (unsigned short *) (p + 5
+							+ IEEE_ADDR_LEN);
+
+					start_index = p[4 + IEEE_ADDR_LEN];
+
+				}
+
+				exp_size = len + 1 + (num_assoc_dev << 1);
+			} else {
+				exp_size = len;
+			}
+
+			if (exp_size != size) {
+				zb_print_error(
+						"WARNING: expected size (%d) different from actual size (%d) "
+						"for ZDO_IEEE_ADDR_CONFIRM\n", exp_size, size);
+			}
+
+			swap_bytes(p + 1, IEEE_ADDR_LEN);
+
+			zbifCbs->ZDO_IEEE_ADDR_confirm(zbif_handle, p[0], /* status 	*/
+			p + 1, /* ieee_addr 	*/
+			p[1 + IEEE_ADDR_LEN] | (p[2 + IEEE_ADDR_LEN] << 8), num_assoc_dev, /* num_assoc_dev	*/
+			start_index, /* start_index 		*/
+			nwk_addr_assoc_dev);
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_IEEE_ADDR_confirm (
+					p [0], /* status 	*/
+					p + 1, /* ieee_addr 	*/
+					p [1 + IEEE_ADDR_LEN] | (p [2 + IEEE_ADDR_LEN] << 8),
+					num_assoc_dev, /* num_assoc_dev	*/
+					start_index, /* start_index 		*/
+					nwk_addr_assoc_dev
+			);
+#endif
+		}
+		break;
+
+	case ZDO_NODE_DESC_CONFIRM:
+		if (zbifCbs->ZDO_NODE_DESC_confirm) {
+			ZB_NODE_DESC node_desc;
+
+			memcpy(&node_desc, p + 3, sizeof(ZB_NODE_DESC));
+
+			node_desc.manifact_code = ntohs(node_desc.manifact_code);
+			node_desc.max_transf_size = ntohs(node_desc.max_transf_size);
+
+#ifdef ZIGBEE_2006
+			node_desc.server_mask = ntohs(node_desc.server_mask);
+#endif
+			zbifCbs->ZDO_NODE_DESC_confirm(zbif_handle, p[0], p[1] | p[2] << 8,
+					&node_desc);
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_NODE_DESC_confirm (
+					p [0],
+					p [1] | p [2] << 8,
+					&node_desc
+			);
+#endif
+		}
+		break;
+
+	case ZDO_POWER_DESC_CONFIRM:
+		if (zbifCbs->ZDO_POWER_DESC_confirm) {
+			ZB_POWER_DESC power_desc;
+
+			memcpy(&power_desc, p + 3, sizeof(ZB_POWER_DESC));
+
+			zbifCbs->ZDO_POWER_DESC_confirm(zbif_handle, p[0], p[1] | p[2] << 8,
+					&power_desc);
+		}
+		break;
+
+	case ZDO_SIMPLE_DESC_CONFIRM:
+		if (zbifCbs->ZDO_SIMPLE_DESC_confirm) {
+			ZB_SIMPLE_DESC simple_desc;
+			int simple_desc_len;
+
+			simple_desc_len = p[3];
+
+			int additional = sizeof(simple_desc.app_in_cluster_list)
+					+ sizeof(simple_desc.app_out_cluster_count)
+					+ sizeof(simple_desc.app_out_cluster_list);
+
+			memcpy(&simple_desc, p + 4, sizeof(ZB_SIMPLE_DESC) - additional);
+
+			if (simple_desc_len > 0) {
+				/* simple descr present */
+				if (simple_desc.app_in_cluster_count) {
+					simple_desc.app_in_cluster_list = (ushort *) (p + 11);
+				} else {
+					simple_desc.app_in_cluster_list = NULL;
+				}
+
+				simple_desc.app_out_cluster_count = p[11
+						+ simple_desc.app_in_cluster_count * 2];
+				if (simple_desc.app_out_cluster_count) {
+					simple_desc.app_out_cluster_list = (ushort *) (p + 12
+							+ simple_desc.app_in_cluster_count * 2);
+				} else {
+					simple_desc.app_out_cluster_list = NULL;
+				}
+			} else {
+				/* simple descr not present */
+				simple_desc.app_in_cluster_list = NULL;
+				simple_desc.app_out_cluster_count = 0;
+				simple_desc.app_out_cluster_list = NULL;
+			}
+
+			zbifCbs->ZDO_SIMPLE_DESC_confirm(zbif_handle, p[0],
+					p[1] | p[2] << 8, &simple_desc);
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_SIMPLE_DESC_confirm (
+					p [0],
+					p [1] | p [2] << 8,
+					&simple_desc
+			);
+#endif
+		}
+		break;
+
+	case ZDO_ACTIVE_EP_DESC_CONFIRM:
+		if (zbifCbs->ZDO_ACTIVE_EP_DESC_confirm) {
+			uchar *active_ep_list = NULL;
+			if (p[3] > 0) {
+				/* active ep list is not empty */
+				active_ep_list = p + 4;
+			}
+
+			zbifCbs->ZDO_ACTIVE_EP_DESC_confirm(zbif_handle, p[0], /* status 			*/
+			p[1] | (p[2] << 8), /* nwk_addr			*/
+			p[3], /* active_ep_count	*/
+			active_ep_list /* active_ep_list	*/
+			);
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_ACTIVE_EP_DESC_confirm (
+					p[0], /* status 			*/
+					p[1] | (p[2] << 8), /* nwk_addr			*/
+					p[3], /* active_ep_count	*/
+					active_ep_list /* active_ep_list	*/
+			);
+#endif
+		}
+		break;
+
+	case ZDO_MATCH_DESC_CONFIRM:
+		if (zbifCbs->ZDO_MATCH_DESC_confirm) {
+			uchar *match_list = NULL;
+			if (p[3] > 0) {
+				/* match list list is not empty */
+				match_list = p + 4;
+			}
+
+			zbifCbs->ZDO_MATCH_DESC_confirm(zbif_handle, p[0], /* status 			*/
+			p[1] | (p[2] << 8), /* nwk_addr			*/
+			p[3], /* match_len		*/
+			match_list /* match_list		*/
+			);
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_MATCH_DESC_confirm (
+					p[0], /* status 			*/
+					p[1] | (p[2] << 8), /* nwk_addr			*/
+					p[3], /* match_len		*/
+					match_list /* match_list		*/
+			);
+#endif
+		}
+		break;
+
+#if 0
+
+		case ZDO_MATCH_DESC_INDICATION:
+		if (zbifCbs->ZDO_MATCH_DESC_indication) {
+			ushort *icllist = NULL;
+			ushort *ocllist = NULL;
+			int nicl = p[4];
+			int nocl = 0;
+
+			if (nicl > 0) {
+				icllist = (ushort *) (p + 5);
+			}
+			nocl = p[4 + (nicl << 1)];
+			if (nocl > 0) {
+				ocllist = (ushort *) (p + 6 + (nicl << 1));
+			}
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_MATCH_DESC_indication (
+					p[0] | (p[1] << 8), /* nwk_addr			*/
+					p[2] | (p[3] << 8), /* profile_id		*/
+					nicl, /* nicl				*/
+					icllist, /* input clusters	*/
+					nocl, /* nicl				*/
+					ocllist /* output clusters	*/
+			);
+#endif
+
+			zbifCbs->ZDO_MATCH_DESC_indication (
+					p[0] | (p[1] << 8), /* nwk_addr			*/
+					p[2] | (p[3] << 8), /* profile_id		*/
+					nicl, /* nicl				*/
+					icllist, /* input clusters	*/
+					nocl, /* nicl				*/
+					ocllist /* output clusters	*/
+			);
+		}
+		break;
+
+		case ZDO_END_DEVICE_BIND_CONFIRM:
+		if (zbifCbs->ZDO_END_DEVICE_BIND_confirm) {
+			exp_size = 4;
+
+			if (exp_size != size) {
+				zb_print_error("WARNING: expected size (%d) different from actual size (%d) "
+						"for ZDO_END_DEVICE_BIND_confirm\n", exp_size, size);
+			}
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_END_DEVICE_BIND_confirm (
+					p[0] /* status 			*/
+			);
+#endif
+			zbifCbs->ZDO_END_DEVICE_BIND_confirm (
+					p[0] /* status 			*/
+			);
+		}
+		break;
+#endif
+
+	case AF_DATA_INDICATION:
+		if (zbifCbs->APSDE_DATA_indication) {
+			/* decode according the dst address mode */
+
+			uchar dst_ep;
+			ushort dst_addr;
+			uchar *dst_addr_p = NULL;
+
+			uchar src_ep;
+			ushort src_addr;
+			uchar *src_addr_p = NULL;
+
+			uchar dst_addr_mode = *p++;
+			uchar src_addr_mode;
+
+			uchar flags = *p++;
+			dst_addr = *p | (*(p + 1) << 8);
+			p += 2;
+			dst_ep = *p++;
+			src_addr = *p | (*(p + 1) << 8);
+			p += 2;
+			src_ep = *p++;
+
+			if ((flags & 0x03) == 0x00) {
+				dst_addr_mode = ZB_AM_DIRECT;
+			} else if ((flags & 0x03) == 0x02) {
+				dst_addr_mode = ZB_AM_DIRECT_GROUP;
+			}
+
+			if (flags & 0x04) {
+				/* src IEEE address present */
+				src_addr_p = p;
+				src_addr_mode = ZB_AM_DIRECT_EX;
+				swap_bytes(src_addr_p, IEEE_ADDR_LEN);
+			} else {
+				src_addr_mode = ZB_AM_DIRECT;
+			}
+
+			ushort cluster_id = *p | (*(p + 1) << 8);
+			p += 2;
+			ushort profile_id = 0x0000;
+
+			zb_print("cluster ID %04X\n", cluster_id);
+
+			uchar asdu_len = *p++;
+			uchar *asdu;
+
+			if (asdu_len > 0) {
+				asdu = p;
+				p += asdu_len;
+			} else {
+				asdu = NULL;
+			}
+
+			uchar was_broadcast = (flags & 0x03) == 0x02;
+			uchar sec_status = (flags & 0x18) >> 3;
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_APSDE_DATA_indication (
+					dst_addr_mode,
+					dst_addr_p,
+					dst_ep,
+					src_addr_mode,
+					src_addr_p,
+					src_ep,
+					profile_id,
+					cluster_id,
+					asdu_len,
+					asdu,
+					was_broadcast,
+					sec_status
+			);
+#endif
+
+			zbifCbs->APSDE_DATA_indication(zbif_handle, dst_addr_mode,
+					dst_addr_p, dst_ep, src_addr_mode, src_addr_p, src_ep,
+					profile_id, cluster_id, asdu_len, asdu, was_broadcast,
+					sec_status);
+
+		}
+		break;
+
+#if 0
+
+		case ZB_APSDE_DATA_CONFIRM:
+		if (zbifCbs->APSDE_DATA_confirm) {
+			/* decode according the address mode */
+			if (p[0] == ZB_AM_INDIRECT) {
+				zbifCbs->APSDE_DATA_confirm (
+						p[0], /* dst_addr_mode	*/
+						NULL, /* dst_addr 		*/
+						p[1], /* dst_ep 			*/
+						p[2], /* src_ep			*/
+						p[3] /* status 			*/
+				);
+#ifdef DEBUG_ZIGBEE_API
+				ZBPrint_APSDE_DATA_confirm (
+						p[0], /* dst_addr_mode	*/
+						NULL, /* dst_addr 		*/
+						p[1], /* dst_ep 			*/
+						p[2], /* src_ep			*/
+						p[3] /* status 			*/
+				);
+#endif
+			}
+			else if ((p[0] == ZB_AM_DIRECT) || (p[0] == ZB_AM_DIRECT_GROUP)) {
+				/* direct mode, short address */
+				ushort addr = p[1] | (p[2] << 8);
+
+#ifdef DEBUG_ZIGBEE_API
+				ZBPrint_APSDE_DATA_confirm (
+						p[0], /* dst_addr_mode	*/
+						(uchar *) &addr, /* dst_addr 		*/
+						p[3], /* dst_ep 			*/
+						p[4], /* src_ep			*/
+						p[5] /* status 			*/
+				);
+#endif
+				zbifCbs->APSDE_DATA_confirm (
+						p[0], /* dst_addr_mode	*/
+						(uchar *) &addr, /* dst_addr 		*/
+						p[3], /* dst_ep 			*/
+						p[4], /* src_ep			*/
+						p[5] /* status 			*/
+				);
+			}
+			else if (p[0] == ZB_AM_DIRECT_EX) {
+				/* direct mode, short address */
+#ifdef DEBUG_ZIGBEE_API
+				ZBPrint_APSDE_DATA_confirm (
+						p[0], /* dst_addr_mode	*/
+						p + 1, /* dst_addr 		*/
+						p[1 + IEEE_ADDR_LEN], /* dst_ep 			*/
+						p[2 + IEEE_ADDR_LEN], /* src_ep			*/
+						p[3 + IEEE_ADDR_LEN] /* status			*/
+				);
+#endif
+				zbifCbs->APSDE_DATA_confirm (
+						p[0], /* dst_addr_mode	*/
+						p + 1, /* dst_addr 		*/
+						p[1 + IEEE_ADDR_LEN], /* dst_ep 			*/
+						p[2 + IEEE_ADDR_LEN], /* src_ep			*/
+						p[3 + IEEE_ADDR_LEN] /* status			*/
+				);
+			}
+			else {
+				/* unknown address mode */
+				zb_print_error("ERROR: unknown address mode 0x%02x\n", p[0]);
+				return;
+			}
+		}
+		break;
+
+		case ZB_APSME_BIND_CONFIRM:
+		if (zbifCbs->APSME_BIND_confirm) {
+			ushort cluster_id;
+
+			cluster_id = p[1 + IEEE_ADDR_LEN] | (p[1 + IEEE_ADDR_LEN + 1] << 8);
+
+			zbifCbs->APSME_BIND_confirm (
+					p [0], /* status			*/
+					p + 1, /* src_ieee_addr 	*/
+					p[1 + IEEE_ADDR_LEN], /* src_ep			*/
+					cluster_id, /* cluster_id 		*/
+					p + 1 + IEEE_ADDR_LEN + 2, /* dst_ieee_addr	*/
+					p [1 + IEEE_ADDR_LEN + 3] /* dst_ep 			*/
+			);
+		}
+		break;
+
+		case ZB_APSME_UNBIND_CONFIRM:
+		zb_print_error("ERROR: unhandled message type 0x%02x\n", type);
+
+		case ZB_APSME_GET_CONFIRM:
+		if (zbifCbs->APSME_GET_confirm) {
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_APSME_GET_confirm (
+					p [0], /* status			*/
+					p [1], /* attr				*/
+					p [2], /* attr_len			*/
+					p + 3 /* attr				*/
+			);
+#endif
+			zbifCbs->APSME_GET_confirm (
+					p [0], /* status			*/
+					p [1], /* attr				*/
+					p [2], /* attr_len			*/
+					p + 3 /* attr				*/
+			);
+		}
+		break;
+#endif
+
+	case ZDO_SET_CONFIRM:
+		if (zbifCbs->APSME_SET_confirm) {
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_APSME_SET_confirm (
+					p [0], /* status			*/
+					p [1] /* attr				*/
+			);
+#endif
+			zbifCbs->APSME_SET_confirm(zbif_handle, p[0], /* status			*/
+			p[1] /* attr				*/
+			);
+		}
+		break;
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+#if 0
+		case ZB_APSME_UPDATE_DEVICE_INDICATION:
+		if (zbifCbs->APSME_UPDATE_DEVICE_indication) {
+			swap_bytes(p, IEEE_ADDR_LEN);
+			swap_bytes(p + IEEE_ADDR_LEN, IEEE_ADDR_LEN);
+
+			zbifCbs->APSME_UPDATE_DEVICE_indication (
+					p, /* src_ieee_addr	*/
+					p + IEEE_ADDR_LEN, /* dev_ieee_addr	*/
+					p[2 * IEEE_ADDR_LEN], /* status */
+					p[2 * IEEE_ADDR_LEN + 1] | (p[2 * IEEE_ADDR_LEN + 2] << 8)
+			);
+		}
+		break;
+
+		case ZB_APSME_REMOVE_DEVICE_CONFIRM:
+		if (zbifCbs->APSME_REMOVE_DEVICE_confirm) {
+			zbifCbs->APSME_REMOVE_DEVICE_confirm (
+					*p /* status	*/
+			);
+		}
+		break;
+
+		case ZB_APSME_TRANSPORT_KEY_CONFIRM:
+		if (zbifCbs->APSME_TRANSPORT_KEY_confirm) {
+			zbifCbs->APSME_TRANSPORT_KEY_confirm (
+					*p /* status	*/
+			);
+		}
+		break;
+
+		case ZB_APSME_TRANSPORT_KEY_INDICATION:
+		if (zbifCbs->APSME_TRANSPORT_KEY_indication) {
+			swap_bytes(p, IEEE_ADDR_LEN);
+
+			zbifCbs->APSME_TRANSPORT_KEY_indication (
+					p, /* dst_ieee_addr	*/
+					p[IEEE_ADDR_LEN], /* key_type	*/
+					(ZB_TRANSPORT_KEY_DATA *) (p + IEEE_ADDR_LEN + 1) /* transport key data */
+			);
+		}
+		break;
+
+		case ZB_NLME_JOIN_INDICATION:
+		if (zbifCbs->NLME_JOIN_indication) {
+			swap_bytes(p + 2, IEEE_ADDR_LEN);
+
+			zbifCbs->NLME_JOIN_indication (
+					p[0] | (p[1] << 8), /* nwk_addr			*/
+					p + 2, /* ieee_addr		*/
+					p[IEEE_ADDR_LEN + 3], /* capability info	*/
+					p[IEEE_ADDR_LEN + 4] /* secure_join 		*/
+			);
+		}
+		break;
+#endif
+
+		case ZDO_NLME_LEAVE_CONFIRM:
+		if (zbifCbs->NLME_LEAVE_confirm) {
+			swap_bytes(p, IEEE_ADDR_LEN);
+			zbifCbs->NLME_LEAVE_confirm (
+					zbif_handle,
+					p, /* dev_ieee_addr	*/
+					p[IEEE_ADDR_LEN] /* status			*/
+			);
+		}
+		break;
+#endif
+
+#if 0
+
+		case ZB_ERROR_CONFIRM:
+		if (zbifCbs->ZDO_ERROR_confirm) {
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_ERROR_confirm (
+					p [0], /* status 			*/
+					p[1] | (p[2] << 8), /* cluster_id		*/
+					p[3] /* expected_len		*/
+			);
+#endif
+			zbifCbs->ZDO_ERROR_confirm (
+					p [0], /* status 			*/
+					p[1] | (p[2] << 8), /* cluster_id		*/
+					p[3] /* expected_len		*/
+			);
+
+		}
+		break;
+
+		default:
+		if (zbifCbs->ZDO_ERROR_confirm) {
+			zbifCbs->ZDO_ERROR_confirm (
+					ZB_ZDO_UNKNOWN_CLUSTER_ID,
+					type, /* cluster_id		*/
+					0 /* expected_len		*/
+			);
+		}
+		else {
+			zb_print_error("ERROR: unknown message type 0x%02x\n", type);
+		}
+		break;
+#endif
+	}
+}
+
+ZBIFFunctions_t zbIntegrationFunctions = { INT_ZDO_RESET_request,
+		INT_ZDO_START_request, INT_ZDO_NWK_ADDR_request,
+		INT_ZDO_IEEE_ADDR_request, INT_ZDO_NODE_DESC_request,
+		INT_ZDO_POWER_DESC_request, INT_ZDO_SIMPLE_DESC_request,
+		INT_ZDO_ACTIVE_EP_DESC_request, INT_ZDO_MATCH_DESC_request,
+		INT_ZDO_MATCH_DESC_response, INT_ZDO_END_DEVICE_BIND_request,
+		INT_APSDE_DATA_request, INT_APSME_BIND_request,
+		INT_APSME_UNBIND_request, INT_APSME_GET_request, INT_APSME_SET_request,
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+		INT_APSME_REMOVE_DEVICE_request,
+		INT_APSME_TRANSPORT_KEY_request,
+		INT_NLME_LEAVE_request,
+#endif
+
+		INT_ZDO_ERROR_response };

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/integration_if.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/integration_if.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/integration_if.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,17 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef _INTEGRATION_IF_H_
+#define _INTEGRATION_IF_H_
+
+extern ZBIFFunctions_t zbIntegrationFunctions;
+
+extern void INT_ReceiveCb(ZBIF_HANDLE zbif_handle, uchar *data, const int size);
+
+#endif /* _INTEGRATION_IF_H_ */

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/stdafx.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/stdafx.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/stdafx.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,10 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#define LINUX

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/time_CE.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/time_CE.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/time_CE.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,20 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+
+typedef time_t time_t_ce;
+
+time_t_ce time_ce(long *par);
+
+double difftime_ce(time_t_ce timer2, time_t_ce timer1);
+
+struct tm * localtime_ce(const time_t_ce *t);

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/time_ce.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/time_ce.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/time_ce.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,27 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "time_CE.h"
+
+time_t_ce time_ce(long *par) {
+	return time(NULL);
+}
+
+double difftime_ce(time_t_ce timer2, time_t_ce timer1) {
+	return difftime(timer2, timer1);
+}
+
+struct tm * localtime_ce(const time_t_ce *t) {
+	return localtime(t);
+}

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zb_conn.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zb_conn.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zb_conn.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,246 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+
+#ifdef WIN32
+# include <windows.h>
+# include <winsock.h>
+#else
+# include <time.h>
+# include <stdlib.h>
+# include <fcntl.h>
+# include <string.h>
+# include <sys/select.h>
+# include <sys/time.h>
+# include <sys/types.h>
+# include <unistd.h>
+# include <pthread.h>
+#endif
+
+#ifdef BUILD_ZSDIO
+#include "hdlc_proto.h"
+#endif
+
+#ifdef BUILD_INTEGRATION
+#include "bisync.h"
+#endif
+
+#ifdef BUILD_EZSP
+#include "ezsp_ser.h"
+#endif
+
+#ifdef BUILD_FREESCALE
+#include "freescale_ser.h"
+#endif
+
+#ifdef BUILD_MICRO_SD
+#include "MicroSD_ser.h"
+#endif
+
+#include "zb_conn.h"
+#include "zigbee_log.h"
+
+void *rcv_thread(void *arg);
+
+int usingMicroSD = 0;
+
+ZB_CONN_HANDLE zb_conn_open(const char **params, void *hh,
+		ZBIFReceiveCb_t zbifCb) {
+	int ret;
+
+	if (params == NULL) {
+		zb_print_error("ERROR: params is NULL");
+		return NULL;
+	}
+
+	const char *dongle = get_param(params, "dongle");
+	if (dongle == NULL) {
+		return NULL;
+	}
+
+	zb_conn_status_t *status = malloc(sizeof(zb_conn_status_t));
+	memset(status, 0, sizeof(zb_conn_status_t));
+
+#ifdef BUILD_ZSDIO
+	if (strcmp(dongle, "zsdio") == 0) {
+		status->open = hdlc_open;
+		status->close = hdlc_close;
+		status->write = hdlc_send;
+		status->read = NULL;
+		status->fd = hdlc_fd;
+	}
+#endif
+
+#ifdef BUILD_INTEGRATION
+	if (strcmp(dongle, "integration") == 0) {
+		status->open = bisync_open;
+		status->close = bisync_close;
+		status->write = bisync_transmit;
+		status->read = bisync_receive;
+		status->fd = bisync_fd;
+	}
+#endif
+
+#ifdef BUILD_EZSP
+	if (strcmp(dongle, "ezsp") == 0) {
+		status->open = ezsp_open;
+		status->close = ezsp_close;
+		status->write = ezsp_transmit;
+		status->read = NULL;
+		status->fd = ezsp_fd;
+	}
+#endif
+
+#ifdef BUILD_FREESCALE
+
+	if (strcmp(dongle, "freescale") == 0) {
+		status->open = freescale_open;
+		status->close = freescale_close;
+		status->write = freescale_transmit;
+		status->read = freescale_receive;
+		status->fd = freescale_fd;
+	}
+#endif
+
+#ifdef BUILD_MICRO_SD
+	if (strcmp(dongle, "microSD") == 0) {
+		status->open = microSD_open;
+		status->close = microSD_close;
+		status->write = microSD_transmit;
+		status->read = microSD_receive;
+		status->fd = microSD_fd;
+		usingMicroSD = 1; //TRUE
+	}
+#endif
+
+	status->zbifCb = zbifCb;
+	status->hh = hh;
+	status->handle = (status->open)(params);
+
+	if (status->handle == 0) {
+		free(status);
+		return NULL;
+	}
+
+	/* 
+	 * now creates a thread that waits for messages coming from the 
+	 * newly opened device 
+	 */
+
+	ret = pthread_create(&status->tid, NULL, rcv_thread, status);
+	if (ret < 0) {
+		(status->close)(status->handle);
+		free(status);
+		// TODO: close the socketpair
+		return NULL;
+	}
+	return (ZB_CONN_HANDLE) status;
+}
+
+/**
+ * Closes the ZB descriptor 
+ */
+
+int zb_conn_close(ZB_CONN_HANDLE zb_conn_h) {
+	int sts;
+
+	/* the pointer to the close function is in the status */
+	zb_conn_status_t *status = (zb_conn_status_t *) zb_conn_h;
+	pthread_cancel(rcv_thread);
+	sts = (status->close)(status->handle);
+	free(status);
+	return sts;
+}
+
+/**
+ * Transmit the passed data
+ */
+
+int zb_conn_send(ZB_CONN_HANDLE zb_conn_h, const unsigned char *data,
+		const int size) {
+	int sts;
+	time_t raw_time;
+	struct tm *ptr_ts;
+
+	zb_conn_status_t *status = (zb_conn_status_t *) zb_conn_h;
+	sts = (status->write)(status->handle, data, size);
+#ifdef DEBUG_ZIGBEE_API
+	time ( &raw_time );
+	ptr_ts = gmtime ( &raw_time );
+	zb_print("[%2d:%02d:%02d]",ptr_ts->tm_hour, ptr_ts->tm_min, ptr_ts->tm_sec);
+#endif
+ZB_LOG(zb_print_bytes("[zb_conn write]", data, size);)
+return sts;
+}
+
+void *rcv_thread(void *arg) {
+	time_t raw_time;
+	struct tm *ptr_ts;
+	zb_conn_status_t *status = (zb_conn_status_t *) arg;
+
+	fd_set rfds;
+	unsigned char buf[300];
+
+	int fd = status->fd(status->handle);
+
+	while (1) {
+
+		int size, sts;
+
+		FD_ZERO(&rfds);
+		FD_SET(fd, &rfds);
+
+		/* wait for any data received from the port */
+		if (usingMicroSD == 0)
+			sts = select(fd + 1, &rfds, NULL, NULL, NULL); //MicroSD needs an extra read!
+		else
+			sts = 1; //We suppose the read was fine, just move on
+
+		if (sts <= 0) {
+			// timeout or an error has occurred
+			return NULL;
+		}
+
+		if (status->read) {
+			size = status->read(status->handle, buf, sizeof(buf));
+#ifdef DEBUG_ZIGBEE_API
+			time ( &raw_time );
+			ptr_ts = gmtime ( &raw_time );
+			zb_print("[%2d:%02d:%02d]",ptr_ts->tm_hour, ptr_ts->tm_min, ptr_ts->tm_sec);
+#endif
+ZB_LOG		(zb_print_bytes("[zb_conn read]", buf, size);)
+	}
+	else {
+		zb_print("Using Default Read\n");
+
+		size = read (fd, buf, sizeof(buf));
+		if (size < 0) {
+			/* error reading data! */
+			continue;
+		}
+	}
+		if (size < 0) {
+			perror("Error reading ");
+			continue;
+		}
+
+		/* check if the message is consistent */
+		if (size < 2) {
+			zb_print_error("ERROR: message too short (%d)!\n", size);
+			continue;
+		}
+
+		if (status->zbifCb)
+			status->zbifCb(status->hh, buf, size);
+	}
+	return 0;
+}

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zigbee.cpp
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zigbee.cpp (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zigbee.cpp Fri Oct 19 18:37:43 2012
@@ -1,0 +1,732 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+/**
+ * High level interface to the ZigBee protocol stack
+ * The stack actually runs on the ZSDIO or on a external
+ * board connected to the system by means of a serial 
+ * connection
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/select.h>
+
+#include "zigbee.h"
+#include "zigbee_local.h"
+#include "zb_conn.h"
+#include "zigbee_log.h"
+#include "zigbee_utils.h"
+
+#ifdef BUILD_ZSDIO
+#include "zsdio_if.h"
+#endif
+
+#ifdef BUILD_INTEGRATION
+#include "integration.h"
+#endif
+
+#ifdef BUILD_XBEE2
+#include "xbee2.h"
+#endif
+
+#ifdef BUILD_TELEGESIS
+#include "telegesis.h"
+#endif
+
+#ifdef BUILD_EZSP
+#include "ezsp_if.h"
+#endif
+
+//#define pthread_mutex_lock(a)  
+//#define pthread_mutex_unlock(a)  
+
+CZbIf::CZbIf() {
+	zbif_handle = NULL;
+	zbif_funcs = NULL;
+	pthread_mutex_init(&zb_mutex, NULL);
+}
+
+CZbIf::~CZbIf() {
+	this->ZBIFDisconnect();
+}
+
+#ifdef __cplusplus__
+extern "C" {
+#endif
+
+void CPP_ZDO_RESET_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		uchar restartGW //true=Restart, false=just init
+		) {
+	assert(zbif_handle != NULL);
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->ZDO_RESET_confirm(status, restartGW);
+}
+
+void CPP_ZDO_START_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr) {
+	assert(zbif_handle != NULL);
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->ZDO_START_confirm(status, nwk_addr);
+}
+
+void CPP_ZDO_NWK_ADDR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		uchar *ieee_addr, ushort nwk_addr, uchar num_assoc_dev,
+		uchar start_index, ushort *nwk_addr_assoc_dev_list) {
+	assert(zbif_handle != NULL);
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->ZDO_NWK_ADDR_confirm(status, ieee_addr, nwk_addr, num_assoc_dev,
+			start_index, nwk_addr_assoc_dev_list);
+}
+void CPP_ZDO_IEEE_ADDR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		uchar *ieee_addr, ushort nwk_addr, uchar num_assoc_dev,
+		uchar start_index, ushort *nwk_addr_assoc_dev_list) {
+	assert(zbif_handle != NULL);
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->ZDO_IEEE_ADDR_confirm(status, ieee_addr, nwk_addr, num_assoc_dev,
+			start_index, nwk_addr_assoc_dev_list);
+}
+
+void CPP_ZB_MGMT_LQI_response(ZBIF_HANDLE zbif_handle, uchar srcAddrMode,
+		uchar* src_addr, uchar * asdu) {
+	assert(zbif_handle != NULL);
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->ZB_MGMT_LQI_response(srcAddrMode, src_addr, asdu);
+}
+
+void CPP_ZDO_NODE_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, ZB_NODE_DESC *node_descr) {
+	assert(zbif_handle != NULL);
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->ZDO_NODE_DESC_confirm(status, nwk_addr, node_descr);
+}
+
+void CPP_ZDO_SIMPLE_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, ZB_SIMPLE_DESC *simple_desc) {
+	assert(zbif_handle != NULL);
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->ZDO_SIMPLE_DESC_confirm(status, nwk_addr, simple_desc);
+}
+
+void CPP_ZDO_POWER_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, ZB_POWER_DESC *power_desc) {
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->ZDO_POWER_DESC_confirm(status, nwk_addr, power_desc);
+}
+
+void CPP_ZDO_ACTIVE_EP_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, uchar active_ep_count, uchar *active_ep_list) {
+	assert(zbif_handle != NULL);
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->ZDO_ACTIVE_EP_DESC_confirm(status, nwk_addr, active_ep_count,
+			active_ep_list);
+}
+
+void CPP_ZDO_MATCH_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, uchar match_len, uchar *match_list) {
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->ZDO_MATCH_DESC_confirm(status, nwk_addr, match_len, match_list);
+}
+
+void CPP_ZDO_MATCH_DESC_indication(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		ushort profile_id, uchar nicl, ushort *icllist, uchar nocl,
+		ushort *ocllist) {
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->ZDO_MATCH_DESC_indication(nwk_addr, profile_id, nicl, icllist, nocl,
+			ocllist);
+}
+
+void CPP_ZDO_MATCH_DESC_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, uchar match_len, uchar *match_list) {
+	printf("%s:%d: NYI!!!!!\n", __FILE__, __LINE__);
+}
+
+void CPP_ZDO_END_DEVICE_BIND_confirm(ZBIF_HANDLE zbif_handle, uchar status) {
+	zb_print("WARNING: CZbIf::ZDO_END_DEVICE_BIND_confirm not overrided\n");
+}
+
+void CPP_ZDP_MGMT_BIND_Response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort bindingTableEntries, ushort StartIndex,
+		ushort BindingTableListCount, ZB_BIND_STRUCT * BindingTableList) {
+	assert(zbif_handle != NULL);
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->ZDP_MGMT_BIND_Response(status, bindingTableEntries, StartIndex,
+			BindingTableListCount, BindingTableList);
+}
+
+void CPP_APSME_BIND_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		uchar *src_ieee_addr, uchar src_ep, ushort cluster_id,
+		uchar *dst_ieee_addr, uchar dst_ep) {
+	assert(zbif_handle != NULL);
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->APSME_BIND_confirm(status, src_ieee_addr, src_ep, cluster_id,
+			dst_ieee_addr, dst_ep);
+}
+
+void CPP_ZDP_BIND_response(ZBIF_HANDLE zbif_handle, uchar status) {
+	assert(zbif_handle != NULL);
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->ZDP_BIND_response(status);
+}
+
+void CPP_ZDP_UNBIND_response(ZBIF_HANDLE zbif_handle, uchar status) {
+	assert(zbif_handle != NULL);
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->ZDP_UNBIND_response(status);
+}
+
+void CPP_MGMT_PERMIT_JOINING_response(ZBIF_HANDLE zbif_handle, uchar status) {
+	assert(zbif_handle != NULL);
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->MGMT_PERMIT_JOINING_response(status);
+}
+
+void CPP_APSDE_DATA_confirm(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, uchar src_ep, uchar status) {
+	return;
+}
+
+void CPP_APSDE_DATA_indication(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, uchar src_addr_mode, uchar *src_addr,
+		uchar src_ep, ushort profile_id, ushort cluster_id, ushort asdu_len,
+		uchar *asdu, uchar was_broadcast, uchar sec_status) {
+	assert(zbif_handle != NULL);
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->APSDE_DATA_indication(dst_addr_mode, dst_addr, dst_ep, src_addr_mode,
+			src_addr, src_ep, profile_id, cluster_id, asdu_len, asdu,
+			was_broadcast, sec_status);
+}
+
+void CPP_ZDO_DEVICE_ANNCE_indication(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar *ieee_addr, uchar capability) {
+	assert(zbif_handle != NULL);
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->ZDO_DEVICE_ANNCE_indication(nwk_addr, ieee_addr, capability);
+}
+
+void CPP_ZIGBEE_STACK_STATUS_indication(ZBIF_HANDLE zbif_handle, uchar status) {
+	assert(zbif_handle != NULL);
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->ZIGBEE_STACK_STATUS_indication(status);
+}
+
+void CPP_APSME_GET_confirm(ZBIF_HANDLE zbif_handle, uchar status, uchar attr,
+		uchar attr_len, uchar *attr_value) {
+	assert(zbif_handle != NULL);
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->APSME_GET_confirm(status, attr, attr_len, attr_value);
+}
+
+void CPP_APSME_SET_confirm(ZBIF_HANDLE zbif_handle, uchar status, uchar attr) {
+	assert(zbif_handle != NULL);
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->APSME_SET_confirm(status, attr);
+}
+
+void CPP_MGMT_LEAVE_response(ZBIF_HANDLE zbif_handle, uchar status) {
+	assert(zbif_handle != NULL);
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->MGMT_LEAVE_response(status);
+}
+
+void CPP_MGMT_LEAVE_confirm(ZBIF_HANDLE zbif_handle, uchar *dev_ieee_addr,
+		uchar status //This byte is the "rejoin" byte!
+		) {
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->MGMT_LEAVE_confirm(dev_ieee_addr, status);
+}
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+
+void CPP_APSME_UPDATE_DEVICE_indication (
+		ZBIF_HANDLE zbif_handle,
+		uchar *src_ieee_addr,
+		uchar *dev_ieee_addr,
+		uchar status,
+		ushort dev_nwk_addr
+) {
+	assert (zbif_handle != NULL);
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->APSME_UPDATE_DEVICE_indication (
+			src_ieee_addr,
+			dev_ieee_addr,
+			status,
+			dev_nwk_addr
+	);
+}
+
+void CPP_APSME_REMOVE_DEVICE_confirm (
+		ZBIF_HANDLE zbif_handle,
+		uchar status
+) {
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->APSME_REMOVE_DEVICE_confirm (
+			status
+	);
+}
+
+void CPP_APSME_TRANSPORT_KEY_confirm (
+		ZBIF_HANDLE zbif_handle,
+		uchar status
+) {
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->APSME_TRANSPORT_KEY_confirm (
+			status
+	);
+}
+
+void CPP_APSME_TRANSPORT_KEY_indication (
+		ZBIF_HANDLE zbif_handle,
+		uchar *dst_ieee_addr,
+		uchar key_type,
+		ZB_TRANSPORT_KEY_DATA *transport_key_data
+) {
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->APSME_TRANSPORT_KEY_indication (
+			dst_ieee_addr,
+			key_type,
+			transport_key_data
+	);
+}
+
+void CPP_NLME_JOIN_indication (
+		ZBIF_HANDLE zbif_handle,
+		ushort nwk_addr,
+		uchar *ieee_addr,
+		uchar capability_info,
+		uchar secure_join
+) {
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->NLME_JOIN_indication (
+			nwk_addr,
+			ieee_addr,
+			capability_info,
+			secure_join
+	);
+}
+#endif /* INCLUDE_ZIGBEE_SECURITY */
+
+void CPP_ZDO_ERROR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort cluster_id, uchar expected_len) {
+	CZbIf *cZbIf = (CZbIf *) (((zbif_status_t *) zbif_handle)->hh);
+	cZbIf->ZDO_ERROR_confirm(status, cluster_id, expected_len);
+}
+
+void CPP_ZDO_ERROR_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort cluster_id, uchar expected_len) {
+	printf("%s:%d: NYI!!!!!\n", __FILE__, __LINE__);
+}
+
+static ZBIFCbs_t cbs = { CPP_ZDO_RESET_confirm, CPP_ZDO_START_confirm,
+		CPP_ZDO_NWK_ADDR_confirm, CPP_ZDO_IEEE_ADDR_confirm,
+		CPP_ZB_MGMT_LQI_response, CPP_ZDO_NODE_DESC_confirm,
+		CPP_ZDO_POWER_DESC_confirm, CPP_ZDO_SIMPLE_DESC_confirm,
+		CPP_ZDO_ACTIVE_EP_DESC_confirm, CPP_ZDO_MATCH_DESC_confirm,
+		CPP_ZDO_MATCH_DESC_indication, CPP_ZDO_END_DEVICE_BIND_confirm,
+		CPP_ZDO_DEVICE_ANNCE_indication, CPP_ZIGBEE_STACK_STATUS_indication,
+		CPP_APSDE_DATA_confirm, CPP_APSDE_DATA_indication,
+		CPP_ZDP_MGMT_BIND_Response, CPP_APSME_BIND_confirm,
+		CPP_ZDP_BIND_response, CPP_ZDP_UNBIND_response, CPP_APSME_GET_confirm,
+		CPP_APSME_SET_confirm, CPP_MGMT_PERMIT_JOINING_response,
+		CPP_MGMT_LEAVE_response, CPP_MGMT_LEAVE_confirm,
+#ifdef INCLUDE_ZIGBEE_SECURITY
+		CPP_APSME_UPDATE_DEVICE_indication,
+		CPP_APSME_REMOVE_DEVICE_confirm,
+		CPP_APSME_TRANSPORT_KEY_confirm,
+		CPP_APSME_TRANSPORT_KEY_indication,
+		CPP_NLME_JOIN_indication,
+#endif
+		CPP_ZDO_ERROR_confirm, };
+
+#ifdef __cplusplus__
+}
+#endif
+
+int CZbIf::ZBIFConnect(const char *uri) {
+	zbif_status_t * zbif_status;
+
+	zbif_handle = ::ZBIFConnect(uri, &cbs, this);
+	if (zbif_handle == NULL) {
+		return -1;
+	}
+	zbif_status = (zbif_status_t *) zbif_handle;
+
+	/* we save locally just for efficiency! */
+	this->zbif_funcs = zbif_status->zbifFuncs;
+
+	return 0;
+}
+
+int CZbIf::ZBIFDisconnect(void) {
+	if (zbif_handle != NULL) {
+// Original line
+//		return ::ZBIFDisconnect(zbif_handle);
+// Modifications inserted ...
+		int result = ::ZBIFDisconnect(zbif_handle);
+		zbif_handle = NULL;
+		return result;
+	}
+	return 0;
+}
+
+void CZbIf::ZDO_RESET_request(uchar options) {
+	if (zbif_funcs != NULL)
+		zbif_funcs->ZDO_RESET_request(zbif_handle, options);
+}
+
+void CZbIf::ZDO_RESET_confirm(uchar status, uchar restartGW //true=Restart, false=just init
+		) {
+	zb_print("WARNING: CZbIf::ZDO_RESET_confirm not overrided\n");
+	return;
+}
+
+void CZbIf::ZDO_START_request(void) {
+	zbif_funcs->ZDO_START_request(zbif_handle);
+}
+
+void CZbIf::ZDO_START_confirm(uchar status, ushort nwk_addr) {
+	zb_print("WARNING: CZbIf::ZDO_START_confirm not overrided\n");
+	return;
+}
+
+void CZbIf::ZDP_MGMT_NWK_UPDATE_request(unsigned long int scanChannel,
+		ushort scanDuration) {
+	if (zbif_funcs != NULL)
+		zbif_funcs->ZDP_MGMT_NWK_UPDATE_request(zbif_handle, scanChannel,
+				scanDuration);
+}
+
+void CZbIf::ZDO_NWK_ADDR_request(uchar *ieee_addr, uchar request_type,
+		uchar start_index) {
+	zbif_funcs->ZDO_NWK_ADDR_request(zbif_handle, ieee_addr, request_type,
+			start_index);
+}
+
+void CZbIf::ZDO_NWK_ADDR_confirm(uchar status, uchar *ieee_addr,
+		ushort nwk_addr, uchar num_assoc_dev, uchar start_index,
+		ushort *nwk_addr_assoc_dev_list) {
+	zb_print("WARNING: CZbIf::ZDO_NWK_ADDR_confirm not overrided\n");
+	return;
+}
+
+void CZbIf::ZDO_IEEE_ADDR_request(ushort nwk_addr, uchar request_type,
+		uchar start_index) {
+	zbif_funcs->ZDO_IEEE_ADDR_request(zbif_handle, nwk_addr, request_type,
+			start_index);
+}
+
+void CZbIf::ZDO_IEEE_ADDR_confirm(uchar status, uchar *ieee_addr,
+		ushort nwk_addr, uchar num_assoc_dev, uchar start_index,
+		ushort *nwk_addr_assoc_dev_list) {
+	zb_print("WARNING: CZbIf::ZDO_IEEE_ADDR_confirm not overrided\n");
+}
+
+void CZbIf::ZB_MGMT_LQI_request(ushort nwk_addr, uchar start_index) {
+	zbif_funcs->ZB_MGMT_LQI_request(zbif_handle, nwk_addr, start_index);
+}
+
+void CZbIf::ZB_MGMT_LQI_response(uchar srcAddrMode, uchar* src_addr,
+		uchar * asdu) {
+	zb_print("WARNING: CZbIf::ZB_MGMT_LQI_response not overrided\n");
+}
+
+void CZbIf::ZDO_NODE_DESC_request(ushort dst_addr, ushort nwk_addr) {
+	zbif_funcs->ZDO_NODE_DESC_request(zbif_handle, dst_addr, nwk_addr);
+}
+
+void CZbIf::ZDO_NODE_DESC_confirm(uchar status, ushort nwk_addr,
+		ZB_NODE_DESC *node_descr) {
+	zb_print("WARNING: CZbIf::ZDO_NODE_DESC_confirm not overrided\n");
+}
+
+void CZbIf::ZDO_POWER_DESC_request(ushort dst_addr, ushort nwk_addr) {
+	zbif_funcs->ZDO_POWER_DESC_request(zbif_handle, dst_addr, nwk_addr);
+}
+
+void CZbIf::ZDO_POWER_DESC_confirm(uchar status, ushort nwk_addr,
+		ZB_POWER_DESC *power_descr) {
+	zb_print("WARNING: CZbIf::ZDO_POWER_DESC_confirm not overrided\n");
+}
+
+void CZbIf::ZDO_SIMPLE_DESC_request(ushort dst_addr, ushort nwk_addr,
+		uchar endpoint) {
+	zbif_funcs->ZDO_SIMPLE_DESC_request(zbif_handle, dst_addr, nwk_addr,
+			endpoint);
+}
+
+void CZbIf::ZDO_ACTIVE_EP_DESC_request(ushort dst_addr, ushort nwk_addr) {
+	zbif_funcs->ZDO_ACTIVE_EP_DESC_request(zbif_handle, dst_addr, nwk_addr);
+}
+
+void CZbIf::ZDO_SIMPLE_DESC_confirm(uchar status, ushort nwk_addr,
+		ZB_SIMPLE_DESC *simple_descr) {
+	zb_print("WARNING: CZbIf::ZDO_SIMPLE_DESC_confirm not overrided\n");
+}
+
+void CZbIf::ZDO_ACTIVE_EP_DESC_confirm(uchar status, ushort nwk_addr,
+		uchar active_ep_count, uchar *active_ep_list) {
+	zb_print("WARNING: CZbIf::ZDO_ACTIVE_EP_DESC_confirm not overrided\n");
+}
+
+void CZbIf::ZDO_MATCH_DESC_request(ushort dst_addr, ushort nwk_addr,
+		ushort profile_id, uchar nicl, ushort *icllist, uchar nocl,
+		ushort *ocllist) {
+	zbif_funcs->ZDO_MATCH_DESC_request(zbif_handle, dst_addr, nwk_addr,
+			profile_id, nicl, icllist, nocl, ocllist);
+}
+
+void CZbIf::ZDO_MATCH_DESC_confirm(uchar status, ushort nwk_addr,
+		uchar match_len, uchar *match_list) {
+	zb_print("WARNING: CZbIf::ZDO_MATCH_DESC_confirm not overrided\n");
+}
+
+void CZbIf::ZDO_MATCH_DESC_response(uchar status, ushort nwk_addr,
+		uchar match_len, uchar *match_list) {
+	zbif_funcs->ZDO_MATCH_DESC_response(zbif_handle, status, nwk_addr,
+			match_len, match_list);
+}
+
+void CZbIf::ZDO_MATCH_DESC_indication(ushort nwk_addr, ushort profile_id,
+		uchar nicl, ushort *icllist, uchar nocl, ushort *ocllist) {
+	zb_print("WARNING: CZbIf::ZDO_MATCH_DESC_indication not overrided\n");
+}
+
+void CZbIf::ZDO_END_DEVICE_BIND_request(ushort binding_target,
+		uchar *src_ieee_addr, uchar src_ep, ushort profile_id, uchar nicl,
+		ushort *icllist, uchar nocl, ushort *ocllist) {
+	zbif_funcs->ZDO_END_DEVICE_BIND_request(zbif_handle, binding_target,
+			src_ieee_addr, src_ep, profile_id, nicl, icllist, nocl, ocllist);
+}
+
+void CZbIf::ZDO_END_DEVICE_BIND_confirm(uchar status) {
+	zb_print("WARNING: CZbIf::ZDO_END_DEVICE_BIND_confirm not overrided\n");
+}
+
+void CZbIf::MGMT_PERMIT_JOINING_response(uchar status) {
+	zb_print("WARNING: CZbIf::MGMT_PERMIT_JOINING_response not overrided\n");
+}
+
+void CZbIf::ZDO_DEVICE_ANNCE_indication(ushort nwk_addr, uchar *ieee_addr,
+		uchar capability) {
+}
+
+void CZbIf::ZIGBEE_STACK_STATUS_indication(uchar status) {
+}
+
+void CZbIf::NLME_SYNC_request(uchar track) {
+}
+
+void CZbIf::NLME_SYNC_confirm(uchar status) {
+	zb_print("WARNING: CZbIf::NLME_SYNC_confirm not overrided\n");
+}
+
+void CZbIf::NLME_SYNC_indication(void) {
+	zb_print("WARNING: CZbIf::NLME_SYNC_indication not overrided\n");
+}
+
+void CZbIf::APSDE_DATA_request(uchar dst_addr_mode, uchar *dst_addr,
+		uchar dst_ep, ushort profile_id, ushort cluster_id, uchar src_ep,
+		uchar asdu_len, uchar *asdu, uchar tx_options, uchar radius) {
+	zbif_funcs->APSDE_DATA_request(zbif_handle, dst_addr_mode, dst_addr, dst_ep,
+			profile_id, cluster_id, src_ep, asdu_len, asdu, tx_options, radius);
+}
+
+void CZbIf::APSDE_DATA_confirm(uchar dst_addr_mode, uchar *dst_addr,
+		uchar dst_ep, uchar src_ep, uchar status) {
+	zb_print("WARNING: CZbIf::APSME_DATA_confirm not overrided\n");
+	return;
+}
+
+void CZbIf::APSDE_DATA_indication(uchar dst_addr_mode, uchar *dst_addr,
+		uchar dst_ep, uchar src_addr_mode, uchar *src_addr, uchar src_ep,
+		ushort profile_id, ushort cluster_id, ushort asdu_len, uchar *asdu,
+		uchar was_broadcast, uchar sec_status) {
+	zb_print("WARNING: CZbIf::APSME_DATA_indication not overrided\n");
+	return;
+}
+
+void CZbIf::ZDP_MGMT_BIND_Request(ushort remote_dest_addr, ushort startIndex) {
+	zbif_funcs->ZDP_MGMT_BIND_Request(zbif_handle, remote_dest_addr,
+			startIndex);
+}
+
+void CZbIf::APSME_BIND_request(uchar *src_ieee_addr, uchar src_ep,
+		ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep) {
+	zbif_funcs->APSME_BIND_request(zbif_handle, src_ieee_addr, src_ep,
+			cluster_id, dst_ieee_addr, dst_ep);
+}
+
+void CZbIf::ZDP_BIND_request(ushort remote_dest_addr, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep) {
+	zbif_funcs->ZDP_BIND_request(zbif_handle, remote_dest_addr, src_ieee_addr,
+			src_ep, cluster_id, dst_ieee_addr, dst_ep);
+}
+
+void CZbIf::ZDP_UNBIND_request(ushort remote_dest_addr, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep) {
+	zbif_funcs->ZDP_UNBIND_request(zbif_handle, remote_dest_addr, src_ieee_addr,
+			src_ep, cluster_id, dst_ieee_addr, dst_ep);
+}
+
+void CZbIf::ZDP_MGMT_BIND_Response(uchar status, ushort bindingTableEntries,
+		ushort StartIndex, ushort BindingTableListCount,
+		ZB_BIND_STRUCT * BindingTableList) {
+	zb_print("WARNING: CZbIf::ZDP_MGMT_BIND_Response not overrided\n");
+	return;
+}
+
+void CZbIf::APSME_BIND_confirm(uchar status, uchar *src_ieee_addr, uchar src_ep,
+		ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep) {
+	zb_print("WARNING: CZbIf::APSME_BIND_confirm not overrided\n");
+	return;
+}
+
+void CZbIf::ZDP_BIND_response(uchar status) {
+	zb_print("WARNING: CZbIf::ZDP_BIND_response not overrided\n");
+	return;
+}
+
+void CZbIf::ZDP_UNBIND_response(uchar status) {
+	zb_print("WARNING: CZbIf::ZDP_UNBIND_response not overrided\n");
+	return;
+}
+
+void CZbIf::APSME_UNBIND_request(uchar *src_ieee_addr, uchar src_ep,
+		ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep) {
+	zbif_funcs->APSME_UNBIND_request(zbif_handle, src_ieee_addr, src_ep,
+			cluster_id, dst_ieee_addr, dst_ep);
+}
+
+void CZbIf::APSME_UNBIND_confirm(uchar status, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep) {
+	zb_print("WARNING: CZbIf::APSME_UNBIND_confirm not overrided\n");
+}
+
+void CZbIf::APSME_GET_request(uchar attr) {
+	zbif_funcs->APSME_GET_request(zbif_handle, attr);
+}
+
+void CZbIf::APSME_GET_confirm(uchar status, uchar attr, uchar attr_len,
+		uchar *attr_value) {
+	zb_print("WARNING: CZbIf::APSME_GET_confirm not overrided\n");
+}
+
+void CZbIf::APSME_SET_request(uchar attr, uchar attr_len, uchar *attr_value) {
+	zbif_funcs->APSME_SET_request(zbif_handle, attr, attr_len, attr_value);
+}
+
+void CZbIf::APSME_SET_confirm(uchar status, uchar attr) {
+	zb_print("WARNING: CZbIf::APSME_SET_confirm not overrided\n");
+	return;
+}
+
+void CZbIf::MGMT_PERMIT_JOINING_request(ushort nwk_addr, int permitDuration) {
+	zb_print("zigbee.cpp: calling MGMT_PERMIT_JOINING_request\n");
+	zbif_funcs->MGMT_PERMIT_JOINING_request(zbif_handle, nwk_addr,
+			permitDuration);
+}
+
+void CZbIf::MGMT_LEAVE_response(uchar status) {
+	zb_print("WARNING: CZbIf::MGMT_LEAVE_response not overrided\n");
+}
+
+void CZbIf::MGMT_LEAVE_confirm(uchar *dev_ieee_addr, uchar status) {
+	zb_print("WARNING: CZbIf::MGMT_LEAVE_confirm not overrided\n");
+	return;
+}
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+
+void CZbIf::APSME_UPDATE_DEVICE_indication (
+		uchar *src_ieee_addr,
+		uchar *dev_ieee_addr,
+		uchar status,
+		ushort dev_nwk_addr
+) {
+	zb_print("WARNING: CZbIf::APSME_UPDATE_DEVICE_indication not overrided\n");
+	return;
+}
+
+void CZbIf::APSME_REMOVE_DEVICE_request (
+		uchar *parent_ieee_addr,
+		uchar *child_ieee_addr
+) {
+	zbif_funcs->APSME_REMOVE_DEVICE_request (zbif_handle, parent_ieee_addr, child_ieee_addr);
+}
+
+void CZbIf::APSME_REMOVE_DEVICE_confirm (
+		uchar status
+) {
+	zb_print("WARNING: CZbIf::APSME_REMOVE_DEVICE_confirm not overrided\n");
+	return;
+}
+
+void CZbIf::APSME_TRANSPORT_KEY_request (
+		uchar *dst_ieee_addr,
+		uchar key_type,
+		ZB_TRANSPORT_KEY_DATA *transport_key_data
+) {
+	zbif_funcs->APSME_TRANSPORT_KEY_request (zbif_handle, dst_ieee_addr, key_type, transport_key_data);
+}
+
+void CZbIf::APSME_TRANSPORT_KEY_confirm (
+		uchar status
+) {
+	zb_print("WARNING: CZbIf::APSME_TRANSPORT_KEY_confirm not overrided\n");
+	return;
+}
+
+void CZbIf::APSME_TRANSPORT_KEY_indication (
+		uchar *dst_ieee_addr,
+		uchar key_type,
+		ZB_TRANSPORT_KEY_DATA *transport_key_data
+) {
+	zb_print("WARNING: CZbIf::APSME_TRANSPORT_KEY_indication not overrided\n");
+	return;
+}
+
+void CZbIf::NLME_JOIN_indication (
+		ushort nwk_addr,
+		uchar *ieee_addr,
+		uchar capability_info,
+		uchar secure_join
+) {
+	zb_print("WARNING: CZbIf::NLME_JOIN_indication not overrided\n");
+	return;
+}
+
+void CZbIf::MGMT_LEAVE_request (
+		uchar *dev_ieee_addr,
+		uchar remove_children,
+		uchar rejoin,
+		uchar reuse_address,
+		uchar silent
+) {
+	zbif_funcs->MGMT_LEAVE_request(zbif_handle, dev_ieee_addr, remove_children, rejoin, reuse_address, silent);
+}
+#endif
+
+void CZbIf::ZDO_ERROR_confirm(uchar status, ushort cluster_id,
+		uchar expected_len) {
+	zb_print("WARNING: CZbIf::ZDO_ERROR_confirm not overrided\n");
+	return;
+}
+
+/**
+ * TODO: document it!
+ */
+
+void CZbIf::ZDO_ERROR_response(uchar status, ushort cluster_id,
+		uchar expected_len) {
+	zbif_funcs->ZDO_ERROR_response(zbif_handle, status, cluster_id,
+			expected_len);
+}

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zigbee_c.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zigbee_c.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zigbee_c.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,703 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+/**
+ * High level interface to the ZigBee protocol stack
+ * The stack actually runs on the ZSDIO or on a external
+ * board connected to the system by means of a serial 
+ * connection
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "zigbee.h"
+#include "zigbee_local.h"
+#include "zigbee_log.h"
+
+#ifdef BUILD_ZSDIO
+#include "zsdio_if.h"
+#define HAS_DONGLE
+#endif
+
+#ifdef BUILD_INTEGRATION
+#include "integration_if.h"
+#define HAS_DONGLE
+#endif
+
+#ifdef BUILD_EZSP 
+#include "ezsp_if.h"
+#define HAS_DONGLE
+#endif
+
+#ifdef BUILD_FREESCALE
+#include "freescale_if.h"
+#define HAS_DONGLE
+#endif
+
+#ifdef BUILD_MICRO_SD
+#include "MicroSD_if.h"
+#define HAS_DONGLE
+#endif
+
+#ifndef HAS_DONGLE
+#error "ATTENTION: enable at least a dongle!"
+#endif
+
+#ifdef DEBUG_ZIGBEE_API
+#include "zigbee_utils.h"
+#endif
+
+static void ZBIFReceiveCb(void *handle, uchar *data, const int size);
+
+/**
+ * Connect to the selected ZigBee adapter
+ *
+ * @param adapter
+ * 		The adapter type (i.e. zsdio or telegesis)
+ * 	
+ * @param uri
+ * 		Represents the URI describing the device and its location
+ * 		Examples:
+ *			zigbee://<hostname>?dongle=ezsp&type=serial&speed=9600
+ * 			zigbee://<hostname>/dev/ttyUSB0?dongle=zsdio&speed=19400
+ *
+ * 		If <hostname> is missing the resource device is used
+ *
+ * @param zbCbs
+ * 		Callbacks to be called
+ */
+
+ZBIF_HANDLE ZBIFConnect(const char *uri, ZBIFCbs_t *zbifCbs, void *hh) {
+	zbif_status_t *zbif_status;
+	ZB_CONN_HANDLE zb_conn_h;
+
+	const char *p = uri;
+	const char *head, *tail, *t, *v;
+	const char *q;
+	int j = 0;
+
+	q = strstr(p, "://");
+	if (q == NULL) {
+		return NULL;
+	}
+
+	tail = p + strlen(uri);
+
+	char *proto;
+
+	proto = (char *) malloc(q - p + 1);
+	memcpy(proto, p, q - p);
+	proto[q - p] = 0;
+
+	p = q + strlen("://");
+
+	t = strchr(p, '?');
+	if (t == NULL) {
+		return NULL;
+	}
+
+	if (strcmp(proto, "zigbee") != 0) {
+		free(proto);
+		return NULL;
+	}
+	free(proto);
+
+	head = p;
+
+	char *hostname = NULL;
+
+	/* stops if it gets a '/' or a ':' */
+	while (p < t) {
+		if ((*p == ':') || (*p == '/')) {
+			break;
+		}
+		p++;
+	}
+
+	v = head;
+
+	if (p > head) {
+		/* build hostname */
+		char *s = "hostname=";
+		hostname = (char *) malloc(p - head + strlen(s) + 1);
+		strcpy(hostname, s);
+		strncat(hostname, v, p - head);
+		hostname[p - head + strlen(s)] = 0;
+	}
+
+	char *port = NULL;
+
+	/* we stopped at : */
+	if (*p == ':') {
+		head = ++p;
+
+		v = head;
+
+		while (p < t) {
+			if (*p == '/') {
+				break;
+			}
+			p++;
+		}
+
+		if (p > v) {
+
+			/* build port */
+			char *s = "port=";
+			port = (char *) malloc(p - v + strlen(s) + 1);
+			strcpy(port, s);
+			strncat(port, v, p - v);
+			port[p - v + strlen(s)] = 0;
+		}
+	}
+	v = p;
+
+	char *path = NULL;
+	if (t > v) {
+		/* the rest is the path */
+		char *s_path = "path=";
+		path = (char *) malloc(t - v + strlen(s_path) + 1);
+		strcpy(path, s_path);
+		strncat(path, v, t - v);
+		path[t - v + strlen(s_path)] = 0;
+	}
+
+	/* extract parameters */
+	head = t + 1;
+
+	/* first pass, checks the num of parameters */
+	int count = 0;
+
+	/* alloc space for 10 params */
+	int params_size = 10;
+
+	char **params;
+
+	params = (char **) malloc(params_size * sizeof(char *));
+
+	if (hostname != NULL) {
+		params[count++] = hostname;
+	}
+
+	if (port != NULL) {
+		params[count++] = port;
+	}
+
+	if (path != NULL) {
+		params[count++] = path;
+	}
+
+	const char *next = t + 1;
+
+	while (next < tail) {
+		head = next;
+		p = strchr(head, '&');
+		if (p != NULL) {
+			next = p;
+		} else {
+			next = tail;
+		}
+
+		p = strchr(head, '=');
+		if (p == NULL) {
+			zb_print_error("ERROR: in param=value pairs\n");
+			return NULL;
+		}
+
+		/* realloc params if necessary */
+		if (count > params_size) {
+			params_size += 5;
+			params = (char **) realloc(params, params_size);
+		}
+
+		/* store the param,value into the array */
+		params[count] = (char *) malloc(next - head + 1);
+		memcpy(params[count], head, next - head);
+		params[count][next - head] = 0;
+
+		if ((next < tail) && (*next == '&')) {
+			next++;
+		}
+		count++;
+	}
+
+	params[count] = NULL;
+
+	const char *dongle;
+
+	dongle = get_param(params, "dongle");
+	if (dongle == NULL) {
+		zb_print_error("ERROR: no dongle specified\n");
+		return NULL;
+	}
+
+	zbif_status = (zbif_status_t *) malloc(sizeof(zbif_status_t));
+	memset(zbif_status, 0, sizeof(zbif_status_t));
+
+#ifdef BUILD_ZSDIO
+	if (strcmp(dongle, "zsdio") == 0) {
+		zbif_status->zbifFuncs = &zbZsdioFunctions;
+		zbif_status->zbifReceiveCb = ZSDIO_ReceiveCb;
+	}
+#endif
+
+#ifdef BUILD_INTEGRATION
+	if (strcmp(dongle, "integration") == 0) {
+		zbif_status->zbifFuncs = &zbIntegrationFunctions;
+		zbif_status->zbifReceiveCb = INT_ReceiveCb;
+	}
+#endif
+
+#ifdef BUILD_XBEE2
+	if (strcmp(dongle, "xbee2") == 0) {
+		zbif_status->zbifFuncs = &zbXbee2Functions;
+		zbif_status->zbifReceiveCb = XBEE_ReceiveCb;
+	}
+#endif
+
+#ifdef BUILD_TELEGESIS
+	if (strcmp(dongle, "telegesis") == 0) {
+		zbif_status->zbifFuncs = &zbTelegesisFunctions;
+		zbif_status->zbifReceiveCb = TELEGESIS_ReceiveCb;
+	}
+#endif
+
+#ifdef BUILD_EZSP
+	if (strcmp(dongle, "ezsp") == 0) {
+		zbif_status->zbifFuncs = &zbEzspFunctions;
+		zbif_status->zbifReceiveCb = EZSP_ReceiveCb;
+	}
+#endif
+
+#ifdef BUILD_FREESCALE
+	if (strcmp(dongle, "freescale") == 0) {
+		zbif_status->zbifFuncs = &zbFreescaleFunctions;
+		zbif_status->zbifReceiveCb = FREESCALE_ReceiveCb;
+	}
+#endif
+
+#ifdef BUILD_MICRO_SD
+	if (strcmp(dongle, "microSD") == 0) {
+		zbif_status->zbifFuncs = &zbMicroSDFunctions;
+		zbif_status->zbifReceiveCb = MicroSD_ReceiveCb;
+	}
+#endif
+
+	if (zbif_status->zbifFuncs == NULL) {
+		/* sorry! adapter not supported */
+		zb_print_error("ERROR: dongle %s not supported\n", dongle);
+		free(zbif_status);
+		for (j = 0; j < count; j++)
+			free(params[j]);
+		free(params);
+		return NULL;
+	}
+
+	zbif_status->hh = hh;
+	zbif_status->zbifCbs = zbifCbs;
+
+	zb_conn_h = zb_conn_open(params, zbif_status, ZBIFReceiveCb);
+	if (zb_conn_h == NULL) {
+		free(zbif_status);
+		for (j = 0; j < count; j++)
+			free(params[j]);
+		free(params);
+		return NULL;
+	}
+
+	zbif_status->zb_conn_h = zb_conn_h; /* handle to the low level connection */
+	for (j = 0; j < count; j++)
+		free(params[j]);
+	free(params);
+	return (ZBIF_HANDLE) zbif_status;
+}
+
+int ZBIFDisconnect(ZBIF_HANDLE zbif_handle) {
+	zbif_status_t *zbif_status;
+	int res;
+
+	assert(zbif_handle != NULL);
+
+	if (zbif_handle == NULL) {
+		return -1;
+	}
+
+	zbif_status = (zbif_status_t *) zbif_handle;
+
+	//Another check added to fix an issue detected by using "valgrind"
+	if (zbif_status->zb_conn_h == NULL)
+		return -1;
+
+	res = zb_conn_close(zbif_status->zb_conn_h);
+
+	free(zbif_status);
+
+	return res;
+}
+
+void ZBIFReceiveCb(void *handle, uchar *data, const int size) {
+	zbif_status_t *zbif_status;
+	zbif_status = (zbif_status_t *) handle;
+
+	/* Dispatch the received data to the right handler */
+	if (zbif_status->zbifReceiveCb) {
+		(zbif_status->zbifReceiveCb)(zbif_status, data, size);
+	}
+}
+
+void ZDO_RESET_request(ZBIF_HANDLE zbif_handle, uchar options) {
+	if (zbif_handle == NULL) {
+		return;
+	}
+	((zbif_status_t *) zbif_handle)->zbifFuncs->ZDO_RESET_request(zbif_handle,
+			options);
+}
+
+void ZDO_RESET_confirm(ZBIF_HANDLE zbif_handle, uchar status, uchar restartGW //true=Restart, false=just init
+		) {
+	zb_print("ZDO_RESET_confirm -> status = 0x%02x\n", status);
+	return;
+}
+
+void ZDO_START_request(ZBIF_HANDLE zbif_handle) {
+	((zbif_status_t *) zbif_handle)->zbifFuncs->ZDO_START_request(zbif_handle);
+}
+
+void ZDO_START_confirm(ZBIF_HANDLE zbif_handle, uchar status, ushort nwk_addr) {
+	zb_print("ZDO_START_confirm -> status = 0x%02x\n", status);
+	return;
+}
+
+void ZDP_MGMT_NWK_UPDATE_request(ZBIF_HANDLE zbif_handle,
+		unsigned long int scanChannel, ushort scanDuration) {
+	((zbif_status_t *) zbif_handle)->zbifFuncs->ZDP_MGMT_NWK_UPDATE_request(
+			zbif_handle, scanChannel, scanDuration);
+}
+
+void ZDO_NWK_ADDR_request(ZBIF_HANDLE zbif_handle, uchar *ieee_addr,
+		uchar request_type, uchar start_index) {
+	((zbif_status_t *) zbif_handle)->zbifFuncs->ZDO_NWK_ADDR_request(
+			zbif_handle, ieee_addr, request_type, start_index);
+}
+
+void ZDO_NWK_ADDR_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		uchar *ieee_addr, ushort nwk_addr, uchar num_assoc_dev,
+		uchar start_index, ushort *nwk_addr_assoc_dev_list) {
+	zb_print("ZDO_NWK_ADDR_confirm -> status = 0x%02x\n", status);
+	return;
+}
+
+void ZDO_IEEE_ADDR_request(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar request_type, uchar start_index) {
+}
+
+void ZB_MGMT_LQI_request(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar start_index) {
+}
+
+void ZDO_NODE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr) {
+}
+
+void ZDO_NODE_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, ZB_NODE_DESC *node_descr) {
+	zb_print("ZDO_NODE_DESC_confirm -> %d\n", status);
+}
+
+void ZDO_POWER_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr) {
+	zb_not_yet_implemented()
+}
+
+void ZDO_SIMPLE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, uchar endpoint) {
+	((zbif_status_t *) zbif_handle)->zbifFuncs->ZDO_SIMPLE_DESC_request(
+			zbif_handle, dst_addr, nwk_addr, endpoint);
+}
+
+void ZDO_ACTIVE_EP_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr) {
+	((zbif_status_t *) zbif_handle)->zbifFuncs->ZDO_ACTIVE_EP_DESC_request(
+			zbif_handle, dst_addr, nwk_addr);
+}
+
+void ZDO_ACTIVE_EP_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, uchar active_ep_count, uchar *active_ep_list) {
+	zb_print("ZDO_ACTIVE_EP_DESC_confirm -> %d\n", status);
+}
+
+void ZDO_MATCH_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, ushort profile_id, uchar nicl, ushort *icllist,
+		uchar nocl, ushort *ocllist) {
+}
+
+void ZDO_MATCH_DESC_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, uchar match_len, uchar *match_list) {
+	zb_print("ZDO_MATCH_DESC_confirm -> %d\n", status);
+}
+
+void ZDO_MATCH_DESC_indication(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		ushort profile_id, uchar nicl, ushort *icllist, uchar nocl,
+		ushort *ocllist) {
+	zb_print("ZDO_MATCH_DESC_indication\n");
+}
+
+void ZDO_MATCH_DESC_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, uchar match_len, uchar *match_list) {
+	zb_not_yet_implemented()
+}
+
+void ZDO_END_DEVICE_BIND_request(ZBIF_HANDLE zbif_handle, ushort binding_target,
+		uchar *src_ieee_addr, uchar src_ep, ushort profile_id, uchar nicl,
+		ushort *icllist, uchar nocl, ushort *ocllist) {
+	((zbif_status_t *) zbif_handle)->zbifFuncs->ZDO_END_DEVICE_BIND_request(
+			zbif_handle, binding_target, src_ieee_addr, src_ep, profile_id,
+			nicl, icllist, nocl, ocllist);
+}
+
+void ZDO_END_DEVICE_BIND_confirm(ZBIF_HANDLE zbif_handle, uchar status) {
+	zb_print("ZDO_END_DEVICE_BIND_confirm -> 0x%02X\n", status);
+	return;
+}
+
+void MGMT_PERMIT_JOINING_response(ZBIF_HANDLE zbif_handle, uchar status) {
+	zb_print("MGMT_PERMIT_JOINING_response -> 0x%02X\n", status);
+	return;
+}
+
+void MGMT_LEAVE_response(ZBIF_HANDLE zbif_handle, uchar status) {
+	//zb_print("MGMT_LEAVE_response -> 0x%02X\n", status);
+	ZBPrint_MGMT_LEAVE_response(status);
+	return;
+}
+
+void MGMT_LEAVE_confirm(ZBIF_HANDLE zbif_handle, uchar *ieee_addr, uchar rejoin) {
+	ZBPrint_MGMT_LEAVE_confirm(ieee_addr, rejoin);
+	return;
+}
+
+void ZDO_DEVICE_ANNCE_indication(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar *ieee_addr, uchar capability) {
+	zb_print("WARNING: ZDO_DEVICE_ANNCE_indication not overrided\n");
+}
+
+void ZIGBEE_STACK_STATUS_indication(ZBIF_HANDLE zbif_handle, uchar status) {
+	zb_print("WARNING: ZIGBEE_STACK_STATUS_indication not overrided\n");
+}
+
+void APSDE_DATA_request(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, ushort profile_id, ushort cluster_id,
+		uchar src_ep, uchar asdu_len, uchar *asdu, uchar tx_options,
+		uchar radius) {
+	((zbif_status_t *) zbif_handle)->zbifFuncs->APSDE_DATA_request(zbif_handle,
+			dst_addr_mode, dst_addr, dst_ep, profile_id, cluster_id, src_ep,
+			asdu_len, asdu, tx_options, radius);
+}
+
+void APSDE_DATA_confirm(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, uchar src_ep, uchar status) {
+	zb_print("APSDE_DATA_confirm -> %d\n", status);
+	return;
+}
+
+void APSDE_DATA_indication(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, uchar src_addr_mode, uchar *src_addr,
+		uchar src_ep, ushort profile_id, ushort cluster_id, ushort asdu_len,
+		uchar *asdu, uchar was_broadcast, uchar sec_status) {
+	zb_print("APSDE_DATA_indication\n");
+	return;
+}
+
+void ZDP_MGMT_BIND_Request(ZBIF_HANDLE zbif_handle, ushort remote_dest_addr,
+		ushort startIndex) {
+	((zbif_status_t *) zbif_handle)->zbifFuncs->ZDP_MGMT_BIND_Request(
+			zbif_handle, remote_dest_addr, startIndex);
+}
+
+void APSME_BIND_request(ZBIF_HANDLE zbif_handle, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep) {
+	((zbif_status_t *) zbif_handle)->zbifFuncs->APSME_BIND_request(zbif_handle,
+			src_ieee_addr, src_ep, cluster_id, dst_ieee_addr, dst_ep);
+}
+
+void ZDP_BIND_request(ZBIF_HANDLE zbif_handle, ushort remote_dest_addr,
+		uchar *src_ieee_addr, uchar src_ep, ushort cluster_id,
+		uchar *dst_ieee_addr, uchar dst_ep) {
+	((zbif_status_t *) zbif_handle)->zbifFuncs->ZDP_BIND_request(zbif_handle,
+			remote_dest_addr, src_ieee_addr, src_ep, cluster_id, dst_ieee_addr,
+			dst_ep);
+}
+
+void ZDP_UNBIND_request(ZBIF_HANDLE zbif_handle, ushort remote_dest_addr,
+		uchar *src_ieee_addr, uchar src_ep, ushort cluster_id,
+		uchar *dst_ieee_addr, uchar dst_ep) {
+	((zbif_status_t *) zbif_handle)->zbifFuncs->ZDP_UNBIND_request(zbif_handle,
+			remote_dest_addr, src_ieee_addr, src_ep, cluster_id, dst_ieee_addr,
+			dst_ep);
+}
+
+void ZDP_MGMT_BIND_Response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort bindingTableEntries, ushort StartIndex,
+		ushort BindingTableListCount, ZB_BIND_STRUCT * BindingTableList) {
+	zb_print(
+			"ZDP_MGMT_BIND_Response -> status %d, bindingTableEntries %04x, StartIndex %04x, BindingTableListCount %04x\n", status, bindingTableEntries, StartIndex, BindingTableListCount);
+	return;
+}
+
+void APSME_BIND_confirm(ZBIF_HANDLE zbif_handle, uchar status,
+		uchar *src_ieee_addr, uchar src_ep, ushort cluster_id,
+		uchar *dst_ieee_addr, uchar dst_ep) {
+	zb_print("APSME_BIND_confirm -> %d\n", status);
+	return;
+}
+
+void ZDP_BIND_response(ZBIF_HANDLE zbif_handle, uchar status) {
+	zb_print("ZDP_BIND_response -> %d\n", status);
+	return;
+}
+
+void ZDP_UNBIND_response(ZBIF_HANDLE zbif_handle, uchar status) {
+	zb_print("ZDP_UNBIND_response -> %d\n", status);
+	return;
+}
+
+void APSME_UNBIND_request(ZBIF_HANDLE zbif_handle, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep) {
+	zb_not_yet_implemented()
+}
+
+void APSME_GET_request(ZBIF_HANDLE zbif_handle, uchar attr) {
+}
+
+void APSME_GET_confirm(ZBIF_HANDLE zbif_handle, uchar status, uchar attr,
+		uchar attr_len, uchar *attr_value) {
+	zb_print_bytes("ATTRIBUTE -> ", attr_value, attr_len);
+}
+
+void APSME_SET_request(ZBIF_HANDLE zbif_handle, uchar attr, uchar attr_len,
+		uchar *attr_value) {
+	((zbif_status_t *) zbif_handle)->zbifFuncs->APSME_SET_request(zbif_handle,
+			attr, attr_len, attr_value);
+}
+
+void APSME_SET_confirm(ZBIF_HANDLE zbif_handle, uchar status, uchar attr) {
+	zb_print("APSME_SET_confirm: status = 0x%02x\n", status);
+	return;
+}
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+
+void APSME_UPDATE_DEVICE_indication (
+		ZBIF_HANDLE zbif_handle,
+		uchar *src_ieee_addr,
+		uchar *dev_ieee_addr,
+		uchar status,
+		ushort dev_nwk_addr
+) {
+	zb_not_yet_implemented()
+	return;
+}
+
+/**
+ * TODO: document it!
+ */
+
+void APSME_REMOVE_DEVICE_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *parent_ieee_addr,
+		uchar *child_ieee_addr
+) {
+	zb_not_yet_implemented()
+}
+
+void APSME_REMOVE_DEVICE_confirm (
+		ZBIF_HANDLE zbif_handle,
+		uchar status
+) {
+	return;
+}
+
+void APSME_TRANSPORT_KEY_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *dst_ieee_addr,
+		uchar key_type,
+		ZB_TRANSPORT_KEY_DATA *transport_key_data
+) {
+}
+
+void APSME_TRANSPORT_KEY_confirm (
+		ZBIF_HANDLE zbif_handle,
+		uchar status
+) {
+	return;
+}
+
+void APSME_TRANSPORT_KEY_indication (
+		ZBIF_HANDLE zbif_handle,
+		uchar *dst_ieee_addr,
+		uchar key_type,
+		ZB_TRANSPORT_KEY_DATA *transport_key_data
+) {
+	return;
+}
+
+void NLME_JOIN_indication (
+		ZBIF_HANDLE zbif_handle,
+		ushort nwk_addr,
+		uchar *ieee_addr,
+		uchar capability_info,
+		uchar secure_join
+) {
+	return;
+}
+
+/*
+ void EZSP_MGMT_LEAVE_request (
+ ZBIF_HANDLE zbif_handle,
+ uchar *dev_ieee_addr,
+ uchar remove_children,
+ uchar rejoin,
+ uchar reuse_address,
+ uchar silent
+ ) {
+ zb_not_yet_implemented()
+ }
+ */
+
+void NLME_LEAVE_confirm (
+		ZBIF_HANDLE zbif_handle,
+		uchar *dev_ieee_addr,
+		uchar status
+) {
+	return;
+}
+
+#endif /* INCLUDE_ZIGBEE_SECURITY */
+
+void ZDO_ERROR_confirm(ZBIF_HANDLE zbif_handle, uchar status, ushort cluster_id,
+		uchar expected_len) {
+	return;
+}
+
+void ZDO_ERROR_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort cluster_id, uchar expected_len) {
+	zb_not_yet_implemented()
+}
+
+void ZIGBEE_request(ZBIF_HANDLE zbif_handle, int request_type,
+		void *request_data) {
+	((zbif_status_t *) zbif_handle)->zbifFuncs->ZIGBEE_request(zbif_handle,
+			request_type, request_data);
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zigbee_local.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zigbee_local.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zigbee_local.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,27 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef _ZIGBEE_LOCAL_H_
+#define _ZIGBEE_LOCAL_H_
+
+#include "zb_conn.h"
+
+typedef struct {
+	ZBIFCbs_t *zbifCbs;
+	ZBIFFunctions_t *zbifFuncs;
+	ZB_CONN_HANDLE zb_conn_h;
+	int state;
+	void *hh;
+
+	void (*zbifReceiveCb)(void *zbif_handle, unsigned char *data,
+			const int size);
+} zbif_status_t;
+
+#endif
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zigbee_log.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zigbee_log.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zigbee_log.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,56 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "zigbee_log.h"
+
+#ifdef DEBUG_ZIGBEE_API
+void zb_print_bytes (const char *str, const unsigned char *data, const int size) {
+	int i;
+	printf("%s > ", str);
+	for (i = 0; i < size; i++) {
+		printf("%02X ", data[i]);
+	}
+	printf ("\n");
+}
+#else
+void zb_print_bytes(const char *str, const unsigned char *data, const int size) {
+	// Do nothing
+}
+#endif
+
+/**
+ * Computes the CRC
+ */
+
+int crc16(const unsigned char *data, const int size) {
+	return 0xADDE;
+}
+
+const char *get_param(const char *params[], char *name) {
+	const char **param = params;
+	char _name[41];
+	char _value[41];
+	char ch;
+
+	while (*param) {
+		if (sscanf(*param, "%40[^=]%c%40s", _name, &ch, _value) != 3) {
+			return NULL;
+		}
+
+		if (strcmp(name, _name) == 0) {
+			return *param + strlen(name) + 1;
+		}
+		param++;
+	}
+
+	return NULL;
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zigbee_utils.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zigbee_utils.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zigbee_utils.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,614 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+/*
+ * This file contains utility functions for debugging this implementation
+ */
+
+#include "zigbee.h"
+#include <string.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+
+int ZB_Init_SIMPLE_DESC(ZB_SIMPLE_DESC *simple_desc) {
+	memset(simple_desc, 0, sizeof(ZB_SIMPLE_DESC));
+	return 0;
+}
+
+int ZB_Free_SIMPLE_DESC(ZB_SIMPLE_DESC *simple_desc) {
+	free(simple_desc->app_out_cluster_list);
+	free(simple_desc->app_in_cluster_list);
+	return 0;
+}
+
+int ZB_Init_NODE_DESC(ZB_NODE_DESC *node_desc) {
+	memset(node_desc, 0, sizeof(ZB_NODE_DESC));
+	return 0;
+}
+
+int ZB_Copy_SIMPLE_DESC(ZB_SIMPLE_DESC *simple_desc_dst,
+		ZB_SIMPLE_DESC *simple_desc_src) {
+
+	if (simple_desc_dst->app_in_cluster_list != NULL) {
+		free(simple_desc_dst->app_in_cluster_list);
+	}
+	if (simple_desc_dst->app_out_cluster_list != NULL) {
+		free(simple_desc_dst->app_out_cluster_list);
+	}
+
+	*simple_desc_dst = *simple_desc_src;
+
+	if (simple_desc_dst->app_in_cluster_list) {
+		simple_desc_dst->app_in_cluster_list = (ushort *) malloc(
+				simple_desc_dst->app_in_cluster_count * 2);
+		memcpy(simple_desc_dst->app_in_cluster_list,
+				simple_desc_src->app_in_cluster_list,
+				simple_desc_dst->app_in_cluster_count * 2);
+	}
+	if (simple_desc_dst->app_out_cluster_list) {
+		simple_desc_dst->app_out_cluster_list = malloc(
+				simple_desc_dst->app_out_cluster_count * 2);
+		memcpy(simple_desc_dst->app_out_cluster_list,
+				simple_desc_src->app_out_cluster_list,
+				simple_desc_dst->app_out_cluster_count * 2);
+	}
+	return 0;
+}
+
+void ZBPrint_ZDO_NWK_ADDR_confirm(uchar status, uchar *ieee_addr,
+		ushort nwk_addr, uchar num_assoc_dev, uchar start_index,
+		ushort *nwk_addr_assoc_dev_list);
+
+void ZBPrint_ZDO_IEEE_ADDR_confirm(uchar status, uchar *ieee_addr,
+		ushort nwk_addr, uchar num_assoc_dev, uchar start_index,
+		ushort *nwk_addr_assoc_dev_list);
+
+void ZBPrint_ZDO_NODE_DESC_confirm(uchar status, ushort nwk_addr,
+		ZB_NODE_DESC *node_desc);
+
+char *ieee_addr2a(uchar *ieee_addr) {
+	static char buf[IEEE_ADDR_LEN * 4];
+	sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", ieee_addr[0],
+			ieee_addr[1], ieee_addr[2], ieee_addr[3], ieee_addr[4],
+			ieee_addr[5], ieee_addr[6], ieee_addr[7]);
+	return buf;
+}
+
+char *bool2a(uchar b) {
+	static char buf[6];
+	if (b) {
+		sprintf(buf, "true");
+	} else {
+		sprintf(buf, "false");
+	}
+	return buf;
+}
+
+char *status2a(uchar status) {
+	static char buf[50];
+
+	switch (status) {
+
+	case ZB_SUCCESS:
+		strcpy(buf, "ZB_SUCCESS");
+		break;
+
+	case ZB_NWK_INVALID_PARAMETER:
+		strcpy(buf, "ZB_NWK_INVALID_PARAMETER");
+		break;
+
+	case ZB_NWK_INVALID_REQUEST:
+		strcpy(buf, "ZB_NWK_INVALID_REQUEST");
+		break;
+
+	case ZB_NWK_NOT_PERMITTED:
+		strcpy(buf, "ZB_NWK_NOT_PERMITTED");
+		break;
+
+	case ZB_NWK_STARTUP_FAILURE:
+		strcpy(buf, "ZB_NWK_STARTUP_FAILURE");
+		break;
+
+	case ZB_NWK_ALREADY_PRESENT:
+		strcpy(buf, "ZB_NWK_ALREADY_PRESENT");
+		break;
+
+	case ZB_NWK_SYNC_FAILURE:
+		strcpy(buf, "ZB_NWK_SYNC_FAILURE");
+		break;
+
+	case ZB_NWK_NEIGHBOR_TABLE_FULL:
+		strcpy(buf, "ZB_NWK_NEIGHBOR_TABLE_FULL");
+		break;
+	case ZB_NWK_UNKNOWN_DEVICE:
+		strcpy(buf, "ZB_NWK_UNKNOWN_DEVICE");
+		break;
+	case ZB_NWK_UNSUPPORTED_ATTRIBUTE:
+		strcpy(buf, "ZB_NWK_UNSUPPORTED_ATTRIBUTE");
+		break;
+	case ZB_NWK_NO_NETWORKS:
+		strcpy(buf, "ZB_NWK_NO_NETWORKS");
+		break;
+	case ZB_NWK_LEAVE_UNCONFIRMED:
+		strcpy(buf, "ZB_NWK_LEAVE_UNCONFIRMED");
+		break;
+	case ZB_NWK_MAX_FRM_CNTR:
+		strcpy(buf, "ZB_NWK_MAX_FRM_CNTR");
+		break;
+	case ZB_NWK_NO_KEY:
+		strcpy(buf, "ZB_NWK_NO_KEY");
+		break;
+	case ZB_NWK_BAD_CCM_OUTPUT:
+		strcpy(buf, "ZB_NWK_BAD_CCM_OUTPUT");
+		break;
+	case ZB_NWK_NO_ROUTING_CAPACITY:
+		strcpy(buf, "ZB_NWK_NO_ROUTING_CAPACITY");
+		break;
+	case ZB_NWK_ROUTE_DISCOVERY_FAILED:
+		strcpy(buf, "ZB_SUCCESS");
+		break;
+	case ZB_NWK_ROUTE_ERROR:
+		strcpy(buf, "ZB_NWK_ROUTE_ERROR");
+		break;
+	case ZB_NWK_BT_TABLE_FULL:
+		strcpy(buf, "ZB_NWK_BT_TABLE_FULL");
+		break;
+	case ZB_NWK_FRAME_NOT_BUFFERED:
+		strcpy(buf, "ZB_NWK_FRAME_NOT_BUFFERED");
+		break;
+	case ZB_ZDO_INV_REQUESTTYPE:
+		strcpy(buf, "ZB_ZDO_INV_REQUESTTYPE");
+		break;
+	case ZB_ZDO_DEVICE_NOT_FOUND:
+		strcpy(buf, "ZB_ZDO_DEVICE_NOT_FOUND");
+		break;
+	case ZB_ZDO_INVALID_EP:
+		strcpy(buf, "ZB_ZDO_INVALID_EP");
+		break;
+	case ZB_ZDO_NOT_ACTIVE:
+		strcpy(buf, "ZB_ZDO_NOT_ACTIVE");
+		break;
+	case ZB_ZDO_NOT_SUPPORTE:
+		strcpy(buf, "ZB_ZDO_NOT_SUPPORTE");
+		break;
+	case ZB_ZDO_TIMEOUT:
+		strcpy(buf, "ZB_ZDO_TIMEOUT");
+		break;
+	case ZB_ZDO_NO_MATCH:
+		strcpy(buf, "ZB_ZDO_NO_MATCH");
+		break;
+	case ZB_ZDO_TABLE_FULL:
+		strcpy(buf, "ZB_ZDO_TABLE_FULL");
+		break;
+	case ZB_ZDO_NO_ENTRY:
+		strcpy(buf, "ZB_ZDO_NO_ENTRY");
+		break;
+	case ZB_ZDO_NO_REPLY:
+		strcpy(buf, "ZB_ZDO_NO_REPLY");
+		break;
+	default:
+		strcpy(buf, "Unknown error code");
+		break;
+	}
+	return buf;
+}
+
+void swap_bytes(uchar *buf, int len) {
+	uchar *p = buf, *q = buf + len - 1;
+	uchar tmp;
+	int i;
+	for (i = 0; i < len / 2; i++) {
+		tmp = *p;
+		*p++ = *q;
+		*q-- = tmp;
+	}
+}
+
+void ZBPrint_ZDO_START_confirm(uchar status, ushort nwk_addr) {
+	printf("\tstatus: %s (0x%02X)\n", status2a(status), status);
+	printf("\tnwk_addr: %04x\n", nwk_addr);
+}
+
+void ZBPrint_ZDO_NWK_ADDR_confirm(uchar status, uchar *ieee_addr,
+		ushort nwk_addr, uchar num_assoc_dev, uchar start_index,
+		ushort *nwk_addr_assoc_dev_list) {
+	int i;
+
+	printf("ZDO_NWK_ADDR_confirm:\n");
+	printf("\tstatus: %s (0x%02X)\n", status2a(status), status);
+	printf("\tieee_addr: %s\n", ieee_addr2a(ieee_addr));
+	printf("\tnwk_addr: %04x\n", nwk_addr);
+	printf("\tnum_assoc_dev: %d\n", num_assoc_dev);
+	printf("\tstart_index: %d\n", start_index);
+	printf("\tnwk_addr_assoc_dev_list: ");
+
+	if (num_assoc_dev > 0) {
+		for (i = 0; i < num_assoc_dev; i++) {
+			printf("%04X ", nwk_addr_assoc_dev_list[i]);
+		}
+		printf("\n");
+	} else {
+		printf("empty\n");
+	}
+}
+
+void ZBPrint_ZDO_IEEE_ADDR_confirm(uchar status, uchar *ieee_addr,
+		ushort nwk_addr, uchar num_assoc_dev, uchar start_index,
+		ushort *nwk_addr_assoc_dev_list) {
+	int i;
+
+	printf("ZDO_IEEE_ADDR_confirm (status: %s - 0x%02X)\n", status2a(status),
+			status);
+	printf("\tieee_addr: %s - nwk_addr: %04x\n", ieee_addr2a(ieee_addr),
+			nwk_addr);
+	printf("\tnum_assoc_dev: %d - start_index: %d - nwk_addr_assoc_dev_list: ",
+			num_assoc_dev, start_index);
+	if (num_assoc_dev > 0) {
+		for (i = 0; i < num_assoc_dev; i++) {
+			printf("%04X ", nwk_addr_assoc_dev_list[i]);
+		}
+		printf("\n");
+	} else {
+		printf("empty\n");
+	}
+}
+
+void ZBPrint_ZDO_NODE_DESC_confirm(uchar status, ushort nwk_addr,
+		ZB_NODE_DESC *node_desc) {
+	printf(
+			"ZDO_NODE_DESC_confirm - nwk_addr: %04x - status %s (0x%02X). Node_desc:\n",
+			nwk_addr, status2a(status), status);
+	printf("\tlogical_type: %02X,", node_desc->logical_type);
+#ifdef ZIGBEE_2006
+	printf (" complx_desc_avail: %02X,", node_desc->complx_desc_avail);
+	printf (" user_desc_avail: %02X,", node_desc->user_desc_avail);
+#endif
+	printf(" taps_flags: %02X,", node_desc->aps_flags);
+	printf(" freq_band: %02X,", node_desc->freq_band);
+	printf(" mac_cap: %02X,", node_desc->mac_cap);
+	printf(" manifact_code: %04x,", node_desc->manifact_code);
+	printf(" max_buf_size: %02x,", node_desc->max_buf_size);
+	printf(" max_transf_size: %04x,", node_desc->max_transf_size);
+#ifdef ZIGBEE_2006
+	printf (" server_mask: %04x", node_desc->server_mask);
+#endif
+	printf("\n");
+
+}
+
+void ZBPrint_ZDO_POWER_DESC_confirm(uchar status, ushort nwk_addr,
+		ZB_POWER_DESC *power_desc) {
+	printf("ZDO_POWER_DESC_confirm:\n");
+	printf("\tstatus: %s (0x%02X)\n", status2a(status), status);
+	printf("\tnwk_addr: %04x\n", nwk_addr);
+}
+
+void ZBPrint_ZDO_SIMPLE_DESC_confirm(uchar status, ushort nwk_addr,
+		ZB_SIMPLE_DESC *simple_desc) {
+	int i;
+	printf("ZDO_SIMPLE_DESC_confirm:\n");
+	printf("\tstatus: %s (0x%02X)\n", status2a(status), status);
+	printf("\tnwk_addr: %04x\n", nwk_addr);
+	if (simple_desc != NULL) {
+		printf("\tsimple_desc {\n");
+		printf("\t\tep: %02X\n", simple_desc->ep);
+		printf("\t\tapp_profile_id: %04X\n", simple_desc->app_profile_id);
+		printf("\t\tapp_device_id: %04X\n", simple_desc->app_device_id);
+		printf("\t\tapp_device_ver: %01X\n", simple_desc->app_device_ver);
+		printf("\t\treserved: %01X\n", simple_desc->reserved);
+		printf("\t\tapp_in_cluster_count: %02X\n",
+				simple_desc->app_in_cluster_count);
+		printf("\t\tapp_in_cluster_list: ");
+		if (simple_desc->app_in_cluster_count > 0) {
+			for (i = 0; i < simple_desc->app_in_cluster_count; i++) {
+				printf("%04X ", simple_desc->app_in_cluster_list[i]);
+			}
+			printf("\n");
+		} else {
+			printf("none\n");
+		}
+
+		printf("\t\tapp_out_cluster_count: %02X\n",
+				simple_desc->app_out_cluster_count);
+		printf("\t\tapp_out_cluster_list: ");
+		if (simple_desc->app_out_cluster_count > 0) {
+			for (i = 0; i < simple_desc->app_out_cluster_count; i++) {
+				printf("%04X ", simple_desc->app_out_cluster_list[i]);
+			}
+			printf("\n");
+		} else {
+			printf("none\n");
+		}
+		printf("\t}\n");
+	} else {
+		printf("\tsimple_desc { not present! }\n");
+	}
+}
+
+void ZBPrint_ZDO_ACTIVE_EP_DESC_confirm(uchar status, ushort nwk_addr,
+		uchar active_ep_count, uchar *active_ep_list) {
+	int i;
+	printf("ZDO_ACTIVE_EP_DESC_confirm:\n");
+	printf("\tstatus: %s (0x%02X)\n", status2a(status), status);
+	printf("\tnwk_addr: %04x\n", nwk_addr);
+	printf("\tactive_ep_count: %d\n", active_ep_count);
+	printf("\tactive_ep_list: ");
+	if (active_ep_count > 0) {
+		for (i = 0; i < active_ep_count; i++) {
+			printf("%02X ", active_ep_list[i]);
+		}
+		printf("\n");
+	} else {
+		printf("none\n");
+	}
+}
+
+void ZBPrint_ZDO_MATCH_DESC_confirm(uchar status, ushort nwk_addr,
+		uchar match_len, uchar *match_list) {
+	int i;
+	printf("ZDO_MATCH_DESC_confirm:\n");
+	printf("\tstatus: %s (0x%02X)\n", status2a(status), status);
+	printf("\tnwk_addr: %04x\n", nwk_addr);
+	printf("\tmatch_len: %d\n", match_len);
+	printf("\tmatch_list: ");
+	if (match_len > 0) {
+		for (i = 0; i < match_len; i++) {
+			printf("%02X ", match_list[i]);
+		}
+		printf("\n");
+	} else {
+		printf("none\n");
+	}
+}
+
+void ZBPrint_ZDO_MATCH_DESC_indication(ushort nwk_addr, ushort profile_id,
+		uchar nicl, ushort *icllist, uchar nocl, ushort *ocllist) {
+	int i;
+
+	printf("ZDO_MATCH_DESC_indication:\n");
+	printf("\tnwk_addr: %04x\n", nwk_addr);
+	printf("\tnicl: %d\n", nicl);
+
+	printf("\ticllist: ");
+	if (nicl > 0) {
+		for (i = 0; i < nicl; i++) {
+			printf("%02X ", icllist[i]);
+		}
+		printf("\n");
+	} else {
+		printf("none\n");
+	}
+	printf("\tnocl: %d\n", nocl);
+
+	printf("\tocllist: ");
+	if (nocl > 0) {
+		for (i = 0; i < nocl; i++) {
+			printf("%02X ", ocllist[i]);
+		}
+		printf("\n");
+	} else {
+		printf("none\n");
+	}
+}
+
+void ZBPrint_ZDO_END_DEVICE_BIND_confirm(uchar status) {
+	printf("ZDO_END_DEVICE_BIND_confirm:\n");
+	printf("\tstatus: %s (0x%02X)\n", status2a(status), status);
+}
+
+void ZBPrint_MGMT_PERMIT_JOINING_response(uchar status) {
+	printf("MGMT_PERMIT_JOINING_response:\n");
+	printf("\tstatus: %s (0x%02X)\n", status2a(status), status);
+}
+
+void ZBPrint_MGMT_LEAVE_response(uchar status) {
+	printf("MGMT_LEAVE_response:\n");
+	printf("\tstatus: %s (0x%02X)\n", status2a(status), status);
+}
+
+void ZBPrint_MGMT_LEAVE_confirm(uchar *ieee_addr, uchar rejoin) {
+	printf("MGMT_LEAVE_confirm:\n");
+	printf("\tieee_addr: %s\n", ieee_addr2a(ieee_addr));
+	printf("\trejoin: %02X\n", rejoin);
+}
+
+void ZBPrint_ZDO_DEVICE_ANNCE_indication(ushort nwk_addr, uchar *ieee_addr,
+		uchar capability) {
+	printf("ZDO_DEVICE_ANNCE_indication:\n");
+	printf("\tnwk_addr: %04x\n", nwk_addr);
+	printf("\tieee_addr: %s\n", ieee_addr2a(ieee_addr));
+	printf("\tcapability: %02X\n", capability);
+}
+
+void ZBPrint_APSME_GET_confirm(uchar status, uchar attr, uchar attr_len,
+		uchar *attr_value) {
+	int i;
+
+	printf("APSME_GET_confirm:\n");
+	printf("\tstatus: %s (0x%02X)\n", status2a(status), status);
+	printf("\tattr: %02x\n", attr);
+	printf("\tattr_len: %02x\n", attr_len);
+
+	if (attr_len > 0) {
+		switch (attr) {
+		case ZB_ATTR_CONFIG_PANID:
+			printf("\tPANID: %04X\n", ztohs(*((ushort *) attr_value)));
+			break;
+
+		case ZB_ATTR_CONFIG_CHANNEL_MASK:
+			printf("\tChannel Mask: %08X\n",
+					(unsigned int) ztohl(*((unsigned long *) attr_value)));
+			break;
+
+		case ZB_ATTR_GET_EUI64:
+			printf("\tEUI64: %02x %02x %02x %02x %02x %02x %02x %02x\n",
+					attr_value[0], attr_value[1], attr_value[2], attr_value[3],
+					attr_value[4], attr_value[5], attr_value[6], attr_value[7]);
+			break;
+
+		default:
+			printf("\tattr_value: ");
+
+			if (attr_len > 0) {
+				for (i = 0; i < attr_len; i++) {
+					printf("%02X ", attr_value[i]);
+				}
+				printf("\n");
+			} else {
+				printf("none\n");
+			}
+			break;
+		}
+	}
+}
+
+void ZBPrint_APSME_SET_confirm(uchar status, uchar attr) {
+	printf("APSME_SET_confirm:\n");
+	printf("\tstatus: %s (0x%02X)\n", status2a(status), status);
+	printf("\tattr: %02x\n", attr);
+}
+
+void ZBPrint_APSME_SET_request(uchar attr, uchar attr_len, uchar *attr_value) {
+	printf("APSME_SET_request - attr:0x%02x, attr_len:0x%02x\n", attr,
+			attr_len);
+}
+
+void ZBPrint_APSDE_DATA_confirm(uchar dst_addr_mode, uchar *dst_addr,
+		uchar dst_ep, uchar src_ep, uchar status) {
+	printf("APSDE_DATA_confirm:\n");
+	printf("\tdst_addr_mode: %02x\n", dst_addr_mode);
+	if (dst_addr_mode == ZB_AM_INDIRECT) {
+	} else if (dst_addr_mode == ZB_AM_DIRECT) {
+		printf("\tdst_addr: %04x\n", *((ushort *) dst_addr));
+		printf("\tdst_ep: %02x\n", dst_ep);
+	} else if (dst_addr_mode == ZB_AM_DIRECT_EX) {
+		printf("\tdst_addr: %s\n", ieee_addr2a(dst_addr));
+		printf("\tdst_ep: %02x\n", dst_ep);
+	}
+#ifdef ZIGBEE_2006
+	else if (dst_addr_mode == ZB_AM_DIRECT_GROUP) {
+		printf ("\tgrp_addr: %04x\n", *((ushort *) dst_addr));
+	}
+#endif
+	else {
+		/* unknown address mode */
+	}
+
+	printf("\tsrc_ep: %02x\n", src_ep);
+	printf("\tstatus: %s (0x%02X)\n", status2a(status), status);
+}
+
+void ZBPrint_APSDE_DATA_request(uchar dst_addr_mode, uchar *dst_addr,
+		uchar dst_ep, ushort profile_id, ushort cluster_id, uchar src_ep,
+		uchar asdu_len, uchar *asdu, uchar tx_options, uchar radius) {
+
+	printf("APSDE_DATA_request: DestDddrMode %02x, ", dst_addr_mode);
+	if (dst_addr_mode == ZB_AM_DIRECT) {
+		printf("destAddr %04x, destEndPoint %02x, ", *((ushort *) dst_addr),
+				dst_ep);
+	} else if (dst_addr_mode == ZB_AM_DIRECT_EX) {
+		printf(
+				"destAddr 0x%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, destEndPoint %02x, ",
+				dst_addr[7], dst_addr[6], dst_addr[5], dst_addr[4], dst_addr[3],
+				dst_addr[2], dst_addr[1], dst_addr[0], dst_ep);
+	}
+#ifdef ZIGBEE_2006
+	else if (dst_addr_mode == ZB_AM_DIRECT_GROUP) {
+		printf ("grp_addr %04x ", *((ushort *) dst_addr));
+	}
+#endif
+	else {
+		/* unknown address mode */
+	}
+	printf("profile_id %04X, cluster_id: %04X, src_ep: %02x, payload: ",
+			profile_id, cluster_id, src_ep);
+	int i;
+	for (i = 0; i < asdu_len; i++) {
+		printf("%02X ", asdu[i]);
+	}
+	printf("\n");
+	//printf ("\ttx_options: %02X\n", tx_options);
+	//printf ("\tradius: %02X\n", radius);
+}
+
+void ZBPrint_APSDE_DATA_indication(uchar dst_addr_mode, uchar *dst_addr,
+		uchar dst_ep, uchar src_addr_mode, uchar *src_addr_p, uchar src_ep,
+		ushort profile_id, ushort cluster_id, ushort asdu_len, uchar *asdu,
+		uchar was_broadcast, uchar sec_status) {
+	printf("APSDE_DATA_indication: dstAddrMode %02x, ", dst_addr_mode);
+	if (dst_addr_mode == ZB_AM_DIRECT)
+		printf("dst_addr %04x, dst_ep %02x, ", *((ushort *) dst_addr), dst_ep);
+	else if (dst_addr_mode == ZB_AM_DIRECT_EX)
+		printf("dst_addr %s (printed in reverse order), dst_ep %02x, ",
+				dst_addr, dst_ep);
+	printf("srcAddrMode %02x, ", src_addr_mode);
+	if (src_addr_mode == ZB_AM_DIRECT) {
+		ushort src_addr;
+		memcpy(&src_addr, src_addr_p, sizeof(ushort));
+		printf(" src_addr %04x, src_ep: %02x, ", src_addr, src_ep);
+	} else if (src_addr_mode == ZB_AM_DIRECT_EX) {
+		printf("src_addr %s, src_ep: %02x, ", ieee_addr2a(src_addr_p), src_ep);
+	}
+	printf("profileId %04X, clusterId %04X, payload ", profile_id, cluster_id);
+	int i;
+	for (i = 0; i < asdu_len; i++) {
+		printf("%02X ", asdu[i]);
+	}
+	printf("\n");
+}
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+
+void ZBPrint_NLME_JOIN_indication (
+		ushort nwk_addr,
+		uchar *ieee_addr,
+		uchar capability_info,
+		uchar secure_join
+) {
+	printf ("NLME_JOIN_indication:\n");
+	printf ("\tnwk_addr: %04x\n", nwk_addr);
+	printf ("\tieee_addr: %s\n", ieee_addr2a(ieee_addr));
+
+	printf ("\tcapability_info: %02X\n", capability_info);
+	printf ("\tsecure_join: %s\n", bool2a(secure_join));
+}
+
+void ZBPrint_MGMT_LEAVE_request (
+		uchar *dev_ieee_addr,
+		uchar remove_children,
+		uchar rejoin,
+		uchar reuse_address,
+		uchar silent
+) {
+	printf ("MGMT_LEAVE_request:\n");
+	printf ("\tieee_addr: %s\n", ieee_addr2a(dev_ieee_addr));
+	printf ("\tremove_children: %s\n", bool2a(remove_children));
+	printf ("\trejoin: %s\n", bool2a(rejoin));
+	printf ("\treuse_address: %s\n", bool2a(reuse_address));
+	printf ("\tsilent: %s\n", bool2a(silent));
+}
+
+void ZBPrint_NLME_LEAVE_confirm (
+		uchar *dev_ieee_addr,
+		uchar status
+) {
+	printf ("NLME_LEAVE_confirm:\n");
+	printf ("\tdev_ieee_addr: %s\n", ieee_addr2a(dev_ieee_addr));
+	printf ("\tstatus: %s (0x%02X)\n", status2a(status), status);
+}
+
+#endif
+
+void ZBPrint_ZDO_ERROR_confirm(uchar status, ushort cluster_id,
+		uchar expected_len) {
+	printf("ZDO_ERROR_confirm:\n");
+	printf("\tstatus: %s (0x%02X)\n", status2a(status), status);
+	printf("\tcluster_id: %04x\n", cluster_id);
+	printf("\texpected_len: %02x\n", expected_len);
+}

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zsdio_if.c
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zsdio_if.c (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zsdio_if.c Fri Oct 19 18:37:43 2012
@@ -1,0 +1,1439 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+/**
+ * High level interface to the ZigBee protocol stack
+ * The stack actually runs on the ZSDIO or on a external
+ * board connected to the system by means of a serial 
+ * connection
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include "zb_conn.h"
+#include "zigbee.h"
+#include "zigbee_local.h"
+#include "zsdio_if.h"
+#include "zigbee_log.h"
+
+#include "zigbee_utils.h"
+
+unsigned char out_buf[200];
+
+static void ZSDIO_Autogen(ZBIF_HANDLE zbif_handle, uchar *data, const int size);
+
+void ZSDIO_ZDO_RESET_request(ZBIF_HANDLE zbif_handle, ushort options);
+
+void ZSDIO_ZDO_START_request(ZBIF_HANDLE zbif_handle);
+
+void ZSDIO_ZDO_NWK_ADDR_request(ZBIF_HANDLE zbif_handle, uchar *ieee_addr,
+		uchar request_type, uchar start_index);
+
+void ZSDIO_ZDO_IEEE_ADDR_request(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar request_type, uchar start_index);
+
+void ZSDIO_ZDO_NODE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr);
+
+void ZSDIO_ZDO_POWER_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr);
+
+void ZSDIO_ZDO_SIMPLE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, uchar endpoint);
+
+void ZSDIO_ZDO_ACTIVE_EP_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr);
+
+void ZSDIO_ZDO_MATCH_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, ushort profile_id, uchar nicl, ushort *icllist,
+		uchar nocl, ushort *ocllist);
+
+void ZSDIO_ZDO_MATCH_DESC_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort dst_addr, uchar match_len, uchar *match_list);
+
+void ZSDIO_ZDO_END_DEVICE_BIND_request(ZBIF_HANDLE zbif_handle,
+		ushort binding_target, uchar *src_ieee_addr, uchar src_ep,
+		ushort profile_id, uchar nicl, ushort *icllist, uchar nocl,
+		ushort *ocllist);
+
+void ZSDIO_APSDE_DATA_request(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, ushort profile_id, ushort cluster_id,
+		uchar src_ep, uchar asdu_len, uchar *asdu, uchar tx_options,
+		uchar radius);
+
+void ZSDIO_APSME_BIND_request(ZBIF_HANDLE zbif_handle, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep);
+
+void ZSDIO_APSME_UNBIND_request(ZBIF_HANDLE zbif_handle, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep);
+
+void ZSDIO_APSME_GET_request(ZBIF_HANDLE zbif_handle, uchar attr);
+
+void ZSDIO_APSME_SET_request(ZBIF_HANDLE zbif_handle, uchar attr,
+		uchar attr_len, uchar *attr_value);
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+
+void ZSDIO_APSME_REMOVE_DEVICE_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *parent_ieee_addr,
+		uchar *child_ieee_addr
+);
+
+void ZSDIO_APSME_TRANSPORT_KEY_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *dst_ieee_addr,
+		uchar key_type,
+		ZB_TRANSPORT_KEY_DATA *transport_key_data
+);
+
+void ZSDIO_NLME_LEAVE_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *dev_ieee_addr,
+		uchar remove_children,
+		uchar rejoin,
+		uchar reuse_address,
+		uchar silent
+);
+
+#endif
+
+void ZSDIO_ZDO_ERROR_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort cluster_id, uchar expected_len);
+
+void ZSDIO_ZDO_RESET_request(ZBIF_HANDLE zbif_handle, uchar options) {
+	uchar *p;
+	p = out_buf + 1;
+
+	PUT_USHORT(p, ZB_ZDO_RESET_REQUEST);
+
+	*p++ = type;
+
+	*out_buf = p - out_buf;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+	return;
+}
+
+void ZSDIO_ZDO_START_request(ZBIF_HANDLE zbif_handle) {
+	uchar *p;
+	p = out_buf + 1;
+
+	PUT_USHORT(p, ZB_ZDO_START_REQUEST);
+
+	*out_buf = p - out_buf;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+	return;
+}
+
+void ZSDIO_ZDO_NWK_ADDR_request(ZBIF_HANDLE zbif_handle, uchar *ieee_addr,
+		uchar request_type, uchar start_index) {
+	uchar *p;
+
+	assert(ieee_addr != NULL);
+
+	p = out_buf + 1;
+
+	PUT_USHORT(p, ZB_ZDO_NWK_ADDR_REQUEST);
+
+	memcpy(p, ieee_addr, IEEE_ADDR_LEN);
+	swap_bytes(p, IEEE_ADDR_LEN);
+
+	p += IEEE_ADDR_LEN;
+	*p++ = request_type;
+	*p++ = start_index;
+
+	*out_buf = p - out_buf;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void ZSDIO_ZDO_IEEE_ADDR_request(ZBIF_HANDLE zbif_handle, ushort nwk_addr,
+		uchar request_type, uchar start_index) {
+	uchar *p;
+	p = out_buf + 1;
+
+	PUT_USHORT(p, ZB_ZDO_IEEE_ADDR_REQUEST);
+
+	*p++ = LSB_USHORT(nwk_addr);
+	*p++ = MSB_USHORT(nwk_addr);
+	*p++ = request_type;
+	*p++ = start_index;
+	*out_buf = p - out_buf;
+
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void ZSDIO_ZDO_NODE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr) {
+	uchar *p;
+	p = out_buf + 1;
+
+	PUT_USHORT(p, ZB_ZDO_NODE_DESC_REQUEST);
+
+	*p++ = LSB_USHORT(dst_addr);
+	*p++ = MSB_USHORT(dst_addr);
+
+	*p++ = LSB_USHORT(nwk_addr);
+	*p++ = MSB_USHORT(nwk_addr);
+	*out_buf = p - out_buf;
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void ZSDIO_ZDO_POWER_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr) {
+	uchar *p;
+	p = out_buf + 1;
+
+	PUT_USHORT(p, ZB_ZDO_POWER_DESC_REQUEST);
+
+	*p++ = LSB_USHORT(dst_addr);
+	*p++ = MSB_USHORT(dst_addr);
+
+	*p++ = LSB_USHORT(nwk_addr);
+	*p++ = MSB_USHORT(nwk_addr);
+	*out_buf = p - out_buf;
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void ZSDIO_ZDO_SIMPLE_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, uchar endpoint) {
+	uchar *p;
+	p = out_buf + 1;
+
+	PUT_USHORT(p, ZB_ZDO_SIMPLE_DESC_REQUEST);
+
+	*p++ = LSB_USHORT(dst_addr);
+	*p++ = MSB_USHORT(dst_addr);
+
+	*p++ = LSB_USHORT(nwk_addr);
+	*p++ = MSB_USHORT(nwk_addr);
+	*p++ = endpoint;
+	*out_buf = p - out_buf;
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void ZSDIO_ZDO_ACTIVE_EP_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr) {
+	uchar *p;
+	p = out_buf + 1;
+
+	PUT_USHORT(p, ZB_ZDO_ACTIVE_EP_DESC_REQUEST);
+
+	*p++ = LSB_USHORT(dst_addr);
+	*p++ = MSB_USHORT(dst_addr);
+
+	*p++ = LSB_USHORT(nwk_addr);
+	*p++ = MSB_USHORT(nwk_addr);
+
+	*out_buf = p - out_buf;
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void ZSDIO_ZDO_MATCH_DESC_request(ZBIF_HANDLE zbif_handle, ushort dst_addr,
+		ushort nwk_addr, ushort profile_id, uchar nicl, ushort *icllist,
+		uchar nocl, ushort *ocllist) {
+	uchar *p;
+	int i;
+
+	p = out_buf + 1;
+
+	assert(icllist != NULL);
+	assert(ocllist != NULL);
+
+	PUT_USHORT(p, ZB_ZDO_MATCH_DESC_REQUEST);
+
+	*p++ = LSB_USHORT(dst_addr);
+	*p++ = MSB_USHORT(dst_addr);
+	*p++ = LSB_USHORT(nwk_addr);
+	*p++ = MSB_USHORT(nwk_addr);
+	*p++ = LSB_USHORT(profile_id);
+	*p++ = MSB_USHORT(profile_id);
+
+	*p++ = nicl;
+
+	for (i = 0; i < nicl; i++) {
+		*p++ = LSB_USHORT(icllist[i]);
+		*p++ = MSB_USHORT(icllist[i]);
+	}
+
+	*p++ = nocl;
+
+	for (i = 0; i < nicl; i++) {
+		*p++ = LSB_USHORT(ocllist[i]);
+		*p++ = MSB_USHORT(ocllist[i]);
+	}
+
+	*out_buf = p - out_buf;
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void ZSDIO_ZDO_MATCH_DESC_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort nwk_addr, uchar match_len, uchar *match_list) {
+	uchar *p;
+	int i;
+
+	p = out_buf + 1;
+
+	PUT_USHORT(p, ZB_ZDO_MATCH_DESC_RESPONSE);
+
+	*p++ = status;
+
+	*p++ = LSB_USHORT(nwk_addr);
+	*p++ = MSB_USHORT(nwk_addr);
+
+	*p++ = match_len;
+
+	for (i = 0; i < match_len; i++) {
+		*p++ = match_list[i];
+	}
+
+	*out_buf = p - out_buf;
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void ZSDIO_ZDO_END_DEVICE_BIND_request(ZBIF_HANDLE zbif_handle,
+		ushort binding_target, uchar *src_ieee_addr, uchar src_ep,
+		ushort profile_id, uchar nicl, ushort *icllist, uchar nocl,
+		ushort *ocllist) {
+	uchar *p;
+	int i;
+
+	p = out_buf + 1;
+
+	PUT_USHORT(p, ZB_ZDO_END_DEVICE_BIND_REQUEST);
+
+	*p++ = LSB_USHORT(binding_target);
+	*p++ = MSB_USHORT(binding_target);
+
+	memcpy(p, src_ieee_addr, IEEE_ADDR_LEN);
+	p += IEEE_ADDR_LEN;
+	*p++ = src_ep;
+
+	*p++ = LSB_USHORT(profile_id);
+	*p++ = MSB_USHORT(profile_id);
+
+	*p++ = nicl;
+
+	for (i = 0; i < nicl; i++) {
+		*p++ = LSB_USHORT(icllist[i]);
+		*p++ = MSB_USHORT(icllist[i]);
+	}
+
+	*p++ = nocl;
+
+	for (i = 0; i < nocl; i++) {
+		*p++ = LSB_USHORT(ocllist[i]);
+		*p++ = MSB_USHORT(ocllist[i]);
+	}
+
+	*out_buf = p - out_buf;
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void ZSDIO_APSDE_DATA_request(ZBIF_HANDLE zbif_handle, uchar dst_addr_mode,
+		uchar *dst_addr, uchar dst_ep, ushort profile_id, ushort cluster_id,
+		uchar src_ep, uchar asdu_len, uchar *asdu, uchar tx_options,
+		uchar radius) {
+	uchar *p;
+	p = out_buf + 1;
+
+	PUT_USHORT(p, ZB_APSDE_DATA_REQUEST);
+
+	*p++ = dst_addr_mode;
+	if (dst_addr_mode == ZB_AM_INDIRECT) {
+		/* Indirect address mode. dst_addr and dst_ep not used */
+	} else if (dst_addr_mode == ZB_AM_DIRECT_GROUP) {
+		/* Direct address mode with short grp_addr */
+		if (dst_addr == NULL) {
+			return;
+		}
+
+		ushort dst = *((ushort *) dst_addr);
+
+		*p++ = LSB_USHORT(dst);
+		*p++ = MSB_USHORT(dst);
+
+		*p++ = dst_ep; /* not used! */
+	} else if (dst_addr_mode == ZB_AM_DIRECT) {
+		/* Direct address mode with short dst_addr */
+		if (dst_addr == NULL) {
+			return;
+		}
+
+		ushort dst = *((ushort *) dst_addr);
+
+		*p++ = LSB_USHORT(dst);
+		*p++ = MSB_USHORT(dst);
+
+		*p++ = dst_ep;
+	} else if (dst_addr_mode == ZB_AM_DIRECT_EX) {
+		/* Direct address mode with long (ieee) dst_addr */
+		if (dst_addr == NULL) {
+			zb_print_error(
+					"ERROR: passed NULL pointer instead of an IEEE address");
+			return;
+		}
+
+		memcpy(p, dst_addr, IEEE_ADDR_LEN);
+		p += IEEE_ADDR_LEN;
+
+		*p++ = dst_ep;
+	} else {
+		/* error! */
+		zb_print_error(
+				"ERROR: unsupported dst_addr_mode: %d", (int) dst_addr_mode);
+		return;
+	}
+
+	*p++ = LSB_USHORT(profile_id);
+	*p++ = MSB_USHORT(profile_id);
+	*p++ = LSB_USHORT(cluster_id);
+	*p++ = MSB_USHORT(cluster_id);
+
+	*p++ = src_ep;
+	*p++ = asdu_len;
+
+	if (asdu_len > 0) {
+		memcpy(p, asdu, asdu_len);
+		p += asdu_len;
+	}
+	*p++ = tx_options;
+	*p++ = radius;
+
+	*out_buf = p - out_buf;
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void ZSDIO_APSME_BIND_request(ZBIF_HANDLE zbif_handle, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep) {
+	uchar *p;
+	p = out_buf + 1;
+
+	assert(src_ieee_addr != NULL);
+
+	PUT_USHORT(p, ZB_APSME_BIND_REQUEST);
+
+	memcpy(p, src_ieee_addr, IEEE_ADDR_LEN);
+	p += IEEE_ADDR_LEN;
+	*p++ = src_ep;
+
+	*p++ = LSB_USHORT(cluster_id);
+	*p++ = MSB_USHORT(cluster_id);
+
+	memcpy(p, dst_ieee_addr, IEEE_ADDR_LEN);
+	p += IEEE_ADDR_LEN;
+	*p++ = dst_ep;
+
+	*out_buf = p - out_buf;
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void ZSDIO_APSME_UNBIND_request(ZBIF_HANDLE zbif_handle, uchar *src_ieee_addr,
+		uchar src_ep, ushort cluster_id, uchar *dst_ieee_addr, uchar dst_ep) {
+	uchar *p;
+
+	p = out_buf + 1;
+
+	assert(src_ieee_addr != NULL);
+
+	PUT_USHORT(p, ZB_APSME_UNBIND_REQUEST);
+
+	memcpy(p, src_ieee_addr, IEEE_ADDR_LEN);
+	p += IEEE_ADDR_LEN;
+	*p++ = src_ep;
+
+	*p++ = LSB_USHORT(cluster_id);
+	*p++ = MSB_USHORT(cluster_id);
+
+	memcpy(p, dst_ieee_addr, IEEE_ADDR_LEN);
+	p += IEEE_ADDR_LEN;
+	*p++ = dst_ep;
+
+	*out_buf = p - out_buf;
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void ZSDIO_APSME_GET_request(ZBIF_HANDLE zbif_handle, uchar attr) {
+	uchar *p;
+
+	p = out_buf + 1;
+
+	PUT_USHORT(p, ZB_APSME_GET_REQUEST);
+
+	*p++ = attr;
+
+	*out_buf = p - out_buf;
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void ZSDIO_APSME_SET_request(ZBIF_HANDLE zbif_handle, uchar attr,
+		uchar attr_len, uchar *attr_value) {
+	uchar *p;
+
+	if (attr == ZB_ATTR_CONFIG_EXTENDEDPANID) {
+		/* generates the APSME_SET_confirm() */
+		p = out_buf;
+
+		ushort op = 1; //APSME_SET_CONFIRM - dummy value
+
+		*p++ = LSB_USHORT(op);
+		*p++ = MSB_USHORT(op);
+
+		*p++ = 0; /* status */
+		*p++ = attr; /* status */
+
+		ZSDIO_Autogen(zbif_handle, out_buf, p - out_buf);
+	} else {
+		p = out_buf + 1;
+
+		PUT_USHORT(p, ZB_APSME_SET_REQUEST);
+
+		*p++ = attr;
+		*p++ = attr_len;
+
+		if (attr_len > 0) {
+			memcpy(p, attr_value, attr_len);
+			p += attr_len;
+		}
+
+		*out_buf = p - out_buf;
+
+		ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+		zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+	}
+}
+
+void ZSDIO_APSME_SET_confirm(uchar status, uchar attr) {
+	zb_print("APSME_SET_confirm: status = 0x%02x\n", status);
+	return;
+}
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+
+/**
+ * TODO: document it!
+ */
+
+void ZSDIO_APSME_REMOVE_DEVICE_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *parent_ieee_addr,
+		uchar *child_ieee_addr
+) {
+	uchar *p;
+
+	assert (parent_ieee_addr != NULL);
+	assert (child_ieee_addr != NULL);
+
+	p = out_buf + 1;
+
+	PUT_USHORT(p, ZB_REMOVE_DEVICE_REQUEST);
+
+	memcpy(p, parent_ieee_addr, IEEE_ADDR_LEN); swap_bytes(p, IEEE_ADDR_LEN); p += IEEE_ADDR_LEN;
+	memcpy(p, child_ieee_addr, IEEE_ADDR_LEN); swap_bytes(p, IEEE_ADDR_LEN); p += IEEE_ADDR_LEN;
+
+	*out_buf = p - out_buf;
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+void ZSDIO_APSME_TRANSPORT_KEY_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *dst_ieee_addr,
+		uchar key_type,
+		ZB_TRANSPORT_KEY_DATA *transport_key_data
+) {
+	uchar *p;
+
+	assert (dst_ieee_addr != NULL);
+
+	p = out_buf + 1;
+
+	PUT_USHORT(p, ZB_APSME_TRANSPORT_KEY_REQUEST);
+
+	memcpy(p, dst_ieee_addr, IEEE_ADDR_LEN); swap_bytes(p, IEEE_ADDR_LEN); p += IEEE_ADDR_LEN;
+	*p++ = key_type;
+
+	switch (key_type) {
+		case ZB_TC_MASTER_KEY:
+		memcpy(p, transport_key_data->tcmk.parent_ieee_addr, IEEE_ADDR_LEN);
+		swap_bytes(p, IEEE_ADDR_LEN); p += IEEE_ADDR_LEN;
+
+		memcpy(p, transport_key_data->tcmk.tc_master_key, ZB_TRANSPORT_KEY_LEN);
+		swap_bytes(p, ZB_TRANSPORT_KEY_LEN); p += ZB_TRANSPORT_KEY_LEN;
+
+		break;
+
+		case ZB_NWK_KEY:
+		*p++ = transport_key_data->nwk_key.key_seq_num;
+		memcpy(p, transport_key_data->nwk_key.nwk_key, ZB_TRANSPORT_KEY_LEN);
+		swap_bytes(p, ZB_TRANSPORT_KEY_LEN); p += ZB_TRANSPORT_KEY_LEN;
+
+		*p++ = transport_key_data->nwk_key.use_parent;
+
+		memcpy (p, transport_key_data->nwk_key.parent_ieee_addr, IEEE_ADDR_LEN);
+		swap_bytes(p, IEEE_ADDR_LEN); p += IEEE_ADDR_LEN;
+		break;
+
+		case ZB_APP_MASTER_KEY:
+		case ZB_APP_LINK_KEY:
+		memcpy (p, transport_key_data->link_key.partner_ieee_addr, IEEE_ADDR_LEN);
+		swap_bytes(p, IEEE_ADDR_LEN); p += IEEE_ADDR_LEN;
+
+		*p++ = transport_key_data->link_key.initiator;
+
+		memcpy (p, transport_key_data->link_key.key, ZB_TRANSPORT_KEY_LEN);
+		swap_bytes(p, ZB_TRANSPORT_KEY_LEN); p += ZB_TRANSPORT_KEY_LEN;
+		break;
+
+	}
+
+	*out_buf = p - out_buf;
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+	return;
+}
+
+void ZSDIO_NLME_LEAVE_request (
+		ZBIF_HANDLE zbif_handle,
+		uchar *dev_ieee_addr,
+		uchar remove_children,
+		uchar rejoin,
+		uchar reuse_address,
+		uchar silent
+) {
+	uchar *p;
+
+	assert (dev_ieee_addr != NULL);
+
+	p = out_buf + 1;
+
+	PUT_USHORT(p, ZB_NLME_LEAVE_REQUEST);
+
+	memcpy(p, dev_ieee_addr, IEEE_ADDR_LEN); p += IEEE_ADDR_LEN;
+	*p++ = remove_children;
+	*p++ = rejoin;
+	*p++ = reuse_address;
+	*p++ = silent;
+
+	*out_buf = p - out_buf;
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+#endif /* INCLUDE_ZIGBEE_SECURITY */
+
+void ZSDIO_ZDO_ERROR_response(ZBIF_HANDLE zbif_handle, uchar status,
+		ushort cluster_id, uchar expected_len) {
+	uchar *p;
+
+	p = out_buf + 1;
+
+	PUT_USHORT(p, ZB_ERROR_RESPONSE);
+
+	*p++ = status;
+
+	*p++ = LSB_USHORT(cluster_id);
+	*p++ = MSB_USHORT(cluster_id);
+
+	*p++ = expected_len;
+
+	*out_buf = p - out_buf;
+	ZB_CONN_HANDLE zb_conn_h = ((zbif_status_t *) zbif_handle)->zb_conn_h;
+	zb_conn_send(zb_conn_h, out_buf, p - out_buf);
+}
+
+/**
+ * This function provides decoding functionalities.
+ * The passed data should not be freed!
+ */
+
+void ZSDIO_ReceiveCb(ZBIF_HANDLE zbif_handle, uchar *data, const int size) {
+	int type, exp_size;
+	uchar *p;
+
+	if (zbif_handle == NULL) {
+		return;
+	}
+
+	ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+	if (zbifCbs == NULL) {
+		/* error! */
+		return;
+	}
+
+	ZB_LOG(zb_print_bytes("ZBIFReceiveCb ", data, size));
+
+	p = data + 1;
+
+	type = *p + (*(p + 1) << 8);
+	p += 2;
+
+	switch (type) {
+
+	case ZB_ZDO_RESET_CONFIRM:
+		if (zbifCbs->ZDO_RESET_confirm) {
+			zbifCbs->ZDO_RESET_confirm(zbif_handle, p[0]);
+		}
+		break;
+
+	case ZB_ZDO_START_CONFIRM:
+		if (zbifCbs->ZDO_START_confirm) {
+			ushort nwk_addr = p[1] | (p[2] << 8);
+			zbifCbs->ZDO_START_confirm(zbif_handle, p[0], nwk_addr);
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_START_confirm (p[0], nwk_addr);
+#endif
+		}
+		break;
+
+	case ZB_ZDO_NWK_ADDR_CONFIRM:
+		if (zbifCbs->ZDO_NWK_ADDR_confirm) {
+			/* invoke the callback */
+			ushort *nwk_addr_assoc_dev = NULL;
+			uchar start_index = 0;
+			uchar num_assoc_dev = 0;
+
+			/* 
+			 * the actual packet format depends on the request_mode
+			 * of the previous request sent. Unfortunately this
+			 * field is not present in the confirm and we need to
+			 * rely on the message size
+			 */
+
+			int len = 14; /* minimum message len (std response) */
+
+			if (size >= (len + 1)) {
+				/* Extended response. Field num_assoc_dev present */
+				num_assoc_dev = p[3 + IEEE_ADDR_LEN];
+				if (num_assoc_dev > 0) {
+					nwk_addr_assoc_dev = (unsigned short *) (p + 5
+							+ IEEE_ADDR_LEN);
+
+					start_index = p[4 + IEEE_ADDR_LEN];
+
+				}
+
+				exp_size = len + 1 + (num_assoc_dev << 1);
+			} else {
+				exp_size = len;
+			}
+
+			if (exp_size != size) {
+				zb_print_error(
+						"WARNING: expected size (%d) different from actual size (%d) "
+						"for ZB_ZDO_NWK_ADDR_CONFIRM\n", exp_size, size);
+			}
+
+			swap_bytes(p + 1, IEEE_ADDR_LEN);
+
+			zbifCbs->ZDO_NWK_ADDR_confirm(zbif_handle, p[0], /* status 	*/
+			p + 1, /* ieee_addr 	*/
+			p[1 + IEEE_ADDR_LEN] | (p[2 + IEEE_ADDR_LEN] << 8), num_assoc_dev, /* num_assoc_dev	*/
+			start_index, /* start_index 		*/
+			nwk_addr_assoc_dev);
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_NWK_ADDR_confirm (
+					p [0], /* status 	*/
+					p + 1, /* ieee_addr 	*/
+					p [1 + IEEE_ADDR_LEN] | (p [2 + IEEE_ADDR_LEN] << 8),
+					num_assoc_dev, /* num_assoc_dev	*/
+					start_index, /* start_index 		*/
+					nwk_addr_assoc_dev
+			);
+#endif
+		}
+		break;
+
+	case ZB_ZDO_IEEE_ADDR_CONFIRM:
+		if (zbifCbs->ZDO_IEEE_ADDR_confirm) {
+			/* invoke the callback */
+			ushort *nwk_addr_assoc_dev = NULL;
+			uchar start_index = 0;
+			uchar num_assoc_dev = 0;
+
+			/* 
+			 * the actual packet format depends on the request_mode
+			 * of the previous request sent. Unfortunately this
+			 * field is not present in the confirm and we need to
+			 * rely on the message size
+			 */
+
+			int len = 14; /* minimum message len (std response) */
+
+			if (size >= (len + 1)) {
+				/* Extended response. Field num_assoc_dev present */
+				num_assoc_dev = p[3 + IEEE_ADDR_LEN];
+				if (num_assoc_dev > 0) {
+					nwk_addr_assoc_dev = (unsigned short *) (p + 5
+							+ IEEE_ADDR_LEN);
+
+					start_index = p[4 + IEEE_ADDR_LEN];
+
+				}
+
+				exp_size = len + 1 + (num_assoc_dev << 1);
+			} else {
+				exp_size = len;
+			}
+
+			if (exp_size != size) {
+				zb_print_error(
+						"WARNING: expected size (%d) different from actual size (%d) "
+						"for ZB_ZDO_IEEE_ADDR_CONFIRM\n", exp_size, size);
+			}
+
+			swap_bytes(p + 1, IEEE_ADDR_LEN);
+
+			zbifCbs->ZDO_IEEE_ADDR_confirm(zbif_handle, p[0], /* status 	*/
+			p + 1, /* ieee_addr 	*/
+			p[1 + IEEE_ADDR_LEN] | (p[2 + IEEE_ADDR_LEN] << 8), num_assoc_dev, /* num_assoc_dev	*/
+			start_index, /* start_index 		*/
+			nwk_addr_assoc_dev);
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_IEEE_ADDR_confirm (
+					p [0], /* status 	*/
+					p + 1, /* ieee_addr 	*/
+					p [1 + IEEE_ADDR_LEN] | (p [2 + IEEE_ADDR_LEN] << 8),
+					num_assoc_dev, /* num_assoc_dev	*/
+					start_index, /* start_index 		*/
+					nwk_addr_assoc_dev
+			);
+#endif
+		}
+		break;
+
+	case ZB_ZDO_NODE_DESC_CONFIRM:
+		if (zbifCbs->ZDO_NODE_DESC_confirm) {
+			ZB_NODE_DESC node_desc;
+
+			memcpy(&node_desc, p + 3, sizeof(ZB_NODE_DESC));
+
+			node_desc.manifact_code = ntohs(node_desc.manifact_code);
+			node_desc.max_transf_size = ntohs(node_desc.max_transf_size);
+
+#ifdef ZIGBEE_2006
+			node_desc.server_mask = ntohs(node_desc.server_mask);
+#endif
+			zbifCbs->ZDO_NODE_DESC_confirm(zbif_handle, p[0], p[1] | p[2] << 8,
+					&node_desc);
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_NODE_DESC_confirm (
+					p [0],
+					p [1] | p [2] << 8,
+					&node_desc
+			);
+#endif
+		}
+		break;
+
+	case ZB_ZDO_POWER_DESC_CONFIRM:
+		if (zbifCbs->ZDO_POWER_DESC_confirm) {
+			ZB_POWER_DESC power_desc;
+
+			memcpy(&power_desc, p + 3, sizeof(ZB_POWER_DESC));
+
+			zbifCbs->ZDO_POWER_DESC_confirm(zbif_handle, p[0], p[1] | p[2] << 8,
+					&power_desc);
+		}
+		break;
+
+	case ZB_ZDO_SIMPLE_DESC_CONFIRM:
+		if (zbifCbs->ZDO_SIMPLE_DESC_confirm) {
+			ZB_SIMPLE_DESC simple_desc;
+			int simple_desc_len;
+
+			simple_desc_len = p[3];
+
+			int additional = sizeof(simple_desc.app_in_cluster_list)
+					+ sizeof(simple_desc.app_out_cluster_count)
+					+ sizeof(simple_desc.app_out_cluster_list);
+
+			memcpy(&simple_desc, p + 4, sizeof(ZB_SIMPLE_DESC) - additional);
+
+			if (simple_desc_len > 0) {
+				/* simple descr present */
+				if (simple_desc.app_in_cluster_count) {
+					simple_desc.app_in_cluster_list = (ushort *) (p + 11);
+				} else {
+					simple_desc.app_in_cluster_list = NULL;
+				}
+
+				simple_desc.app_out_cluster_count = p[11
+						+ simple_desc.app_in_cluster_count * 2];
+				if (simple_desc.app_out_cluster_count) {
+					simple_desc.app_out_cluster_list = (ushort *) (p + 12
+							+ simple_desc.app_in_cluster_count * 2);
+				} else {
+					simple_desc.app_out_cluster_list = NULL;
+				}
+			} else {
+				/* simple descr not present */
+				simple_desc.app_in_cluster_list = NULL;
+				simple_desc.app_out_cluster_count = 0;
+				simple_desc.app_out_cluster_list = NULL;
+			}
+
+			zbifCbs->ZDO_SIMPLE_DESC_confirm(zbif_handle, p[0],
+					p[1] | p[2] << 8, &simple_desc);
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_SIMPLE_DESC_confirm (
+					p [0],
+					p [1] | p [2] << 8,
+					&simple_desc
+			);
+#endif
+		}
+		break;
+
+	case ZB_ZDO_ACTIVE_EP_DESC_CONFIRM:
+		if (zbifCbs->ZDO_ACTIVE_EP_DESC_confirm) {
+			uchar *active_ep_list = NULL;
+			if (p[3] > 0) {
+				/* active ep list is not empty */
+				active_ep_list = p + 4;
+			}
+
+			zbifCbs->ZDO_ACTIVE_EP_DESC_confirm(zbif_handle, p[0], /* status 			*/
+			p[1] | (p[2] << 8), /* nwk_addr			*/
+			p[3], /* active_ep_count	*/
+			active_ep_list /* active_ep_list	*/
+			);
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_ACTIVE_EP_DESC_confirm (
+					p[0], /* status 			*/
+					p[1] | (p[2] << 8), /* nwk_addr			*/
+					p[3], /* active_ep_count	*/
+					active_ep_list /* active_ep_list	*/
+			);
+#endif
+		}
+		break;
+
+	case ZB_ZDO_MATCH_DESC_CONFIRM:
+		if (zbifCbs->ZDO_MATCH_DESC_confirm) {
+			uchar *match_list = NULL;
+			if (p[3] > 0) {
+				/* match list list is not empty */
+				match_list = p + 4;
+			}
+
+			zbifCbs->ZDO_MATCH_DESC_confirm(zbif_handle, p[0], /* status 			*/
+			p[1] | (p[2] << 8), /* nwk_addr			*/
+			p[3], /* match_len		*/
+			match_list /* match_list		*/
+			);
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_MATCH_DESC_confirm (
+					p[0], /* status 			*/
+					p[1] | (p[2] << 8), /* nwk_addr			*/
+					p[3], /* match_len		*/
+					match_list /* match_list		*/
+			);
+#endif
+		}
+		break;
+
+	case ZB_ZDO_MATCH_DESC_INDICATION:
+		if (zbifCbs->ZDO_MATCH_DESC_indication) {
+			ushort *icllist = NULL;
+			ushort *ocllist = NULL;
+			int nicl = p[4];
+			int nocl = 0;
+
+			if (nicl > 0) {
+				icllist = (ushort *) (p + 5);
+			}
+			nocl = p[4 + (nicl << 1)];
+			if (nocl > 0) {
+				ocllist = (ushort *) (p + 6 + (nicl << 1));
+			}
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_MATCH_DESC_indication (
+					p[0] | (p[1] << 8), /* nwk_addr			*/
+					p[2] | (p[3] << 8), /* profile_id		*/
+					nicl, /* nicl				*/
+					icllist, /* input clusters	*/
+					nocl, /* nicl				*/
+					ocllist /* output clusters	*/
+			);
+#endif
+
+			zbifCbs->ZDO_MATCH_DESC_indication(zbif_handle, p[0] | (p[1] << 8), /* nwk_addr			*/
+			p[2] | (p[3] << 8), /* profile_id		*/
+			nicl, /* nicl				*/
+			icllist, /* input clusters	*/
+			nocl, /* nicl				*/
+			ocllist /* output clusters	*/
+			);
+		}
+		break;
+
+	case ZB_ZDO_END_DEVICE_BIND_CONFIRM:
+		if (zbifCbs->ZDO_END_DEVICE_BIND_confirm) {
+			exp_size = 4;
+
+			if (exp_size != size) {
+				zb_print_error(
+						"WARNING: expected size (%d) different from actual size (%d) "
+						"for ZDO_END_DEVICE_BIND_confirm\n", exp_size, size);
+			}
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_END_DEVICE_BIND_confirm (
+					p[0] /* status 			*/
+			);
+#endif
+			zbifCbs->ZDO_END_DEVICE_BIND_confirm(zbif_handle, p[0] /* status 			*/
+			);
+		}
+		break;
+
+	case ZB_ZDO_DEVICE_ANNCE_INDICATION:
+		if (zbifCbs->ZDO_DEVICE_ANNCE_indication) {
+			swap_bytes(p + 2, IEEE_ADDR_LEN);
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_DEVICE_ANNCE_indication (
+					p[0] | (p[1] << 8), /* nwk_addr		*/
+					p + 2, /* ieee_addr	*/
+					p[2 + IEEE_ADDR_LEN] /* capability	*/
+			);
+#endif
+
+			zbifCbs->ZDO_DEVICE_ANNCE_indication(zbif_handle,
+					p[0] | (p[1] << 8), /* nwk_addr		*/
+					p + 2, /* ieee_addr	*/
+					p[2 + IEEE_ADDR_LEN] /* capability	*/
+					);
+		}
+		break;
+
+	case ZB_APSDE_DATA_INDICATION:
+		if (zbifCbs->APSDE_DATA_indication) {
+			/* decode according the dst address mode */
+
+			uchar dst_ep;
+			ushort dst_addr;
+			uchar *dst_addr_p = NULL;
+
+			uchar src_ep;
+			ushort src_addr;
+			uchar *src_addr_p = NULL;
+
+			uchar dst_addr_mode = *p++;
+
+			switch (dst_addr_mode) {
+			case ZB_AM_INDIRECT:
+				/* no dst_ep, no dst_addr */
+				break;
+
+			case ZB_AM_DIRECT:
+#ifdef ZIGBEE_2006
+				case ZB_AM_DIRECT_GROUP:
+#endif
+				/* short dst_addr or grp_addr + dst_ep */
+				dst_addr_p = p;
+				dst_addr = *p | (*(p + 1) << 8);
+				p += 2;
+				memcpy(dst_addr_p, &dst_addr, sizeof(dst_addr));
+				break;
+
+			case ZB_AM_DIRECT_EX:
+				dst_addr_p = p;
+				swap_bytes(dst_addr_p, IEEE_ADDR_LEN);
+				p += IEEE_ADDR_LEN;
+				break;
+
+			default:
+				/* unknown address mode */
+				zb_print_error(
+						"ERROR: unknown address mode 0x%02x\n", dst_addr_mode);
+				return;
+			}
+
+			dst_ep = *p++;
+
+			uchar src_addr_mode = *p++;
+
+			/* decode according the src address mode */
+			switch (src_addr_mode) {
+			case ZB_AM_INDIRECT:
+				/* no src_ep, no src_addr */
+				break;
+
+			case ZB_AM_DIRECT:
+#ifdef ZIGBEE_2006
+				case ZB_AM_DIRECT_GROUP:
+#endif
+				/* short src_addr or grp_addr + src_ep */
+				src_addr_p = p;
+				src_addr = *p | (*(p + 1) << 8);
+				p += 2;
+				memcpy(src_addr_p, &src_addr, sizeof(src_addr));
+				break;
+
+			case ZB_AM_DIRECT_EX:
+				src_addr_p = p;
+				swap_bytes(src_addr_p, IEEE_ADDR_LEN);
+				p += IEEE_ADDR_LEN;
+				break;
+
+			default:
+				/* unknown address mode */
+				zb_print_error(
+						"ERROR: unknown address mode 0x%02x\n", dst_addr_mode);
+				return;
+			}
+
+			src_ep = *p++;
+			ushort profile_id = *p | (*(p + 1) << 8);
+			p += 2;
+			ushort cluster_id = *p | (*(p + 1) << 8);
+			p += 2;
+
+			uchar asdu_len = *p++;
+			uchar *asdu;
+			if (asdu_len > 0) {
+				asdu = p;
+				p += asdu_len;
+			} else {
+				asdu = NULL;
+			}
+
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_APSDE_DATA_indication (
+					dst_addr_mode,
+					dst_addr_p,
+					dst_ep,
+					src_addr_mode,
+					src_addr_p,
+					src_ep,
+					profile_id,
+					cluster_id,
+					asdu_len,
+					asdu,
+					*p,
+					*(p + 1)
+			);
+#endif
+
+			zbifCbs->APSDE_DATA_indication(zbif_handle, dst_addr_mode,
+					dst_addr_p, dst_ep, src_addr_mode, src_addr_p, src_ep,
+					profile_id, cluster_id, asdu_len, asdu, *p, *(p + 1));
+
+		}
+		break;
+
+	case ZB_APSDE_DATA_CONFIRM:
+		if (zbifCbs->APSDE_DATA_confirm) {
+			/* decode according the address mode */
+			if (p[0] == ZB_AM_INDIRECT) {
+				zbifCbs->APSDE_DATA_confirm(zbif_handle, p[0], /* dst_addr_mode	*/
+				NULL, /* dst_addr 		*/
+				p[1], /* dst_ep 			*/
+				p[2], /* src_ep			*/
+				p[3] /* status 			*/
+				);
+#ifdef DEBUG_ZIGBEE_API
+				ZBPrint_APSDE_DATA_confirm (
+						p[0], /* dst_addr_mode	*/
+						NULL, /* dst_addr 		*/
+						p[1], /* dst_ep 			*/
+						p[2], /* src_ep			*/
+						p[3] /* status 			*/
+				);
+#endif
+			} else if ((p[0] == ZB_AM_DIRECT) || (p[0] == ZB_AM_DIRECT_GROUP)) {
+				/* direct mode, short address */
+				ushort addr = p[1] | (p[2] << 8);
+
+#ifdef DEBUG_ZIGBEE_API
+				ZBPrint_APSDE_DATA_confirm (
+						p[0], /* dst_addr_mode	*/
+						(uchar *) &addr, /* dst_addr 		*/
+						p[3], /* dst_ep 			*/
+						p[4], /* src_ep			*/
+						p[5] /* status 			*/
+				);
+#endif
+				zbifCbs->APSDE_DATA_confirm(zbif_handle, p[0], /* dst_addr_mode	*/
+				(uchar *) &addr, /* dst_addr 		*/
+				p[3], /* dst_ep 			*/
+				p[4], /* src_ep			*/
+				p[5] /* status 			*/
+				);
+			} else if (p[0] == ZB_AM_DIRECT_EX) {
+				/* direct mode, short address */
+#ifdef DEBUG_ZIGBEE_API
+				ZBPrint_APSDE_DATA_confirm (
+						p[0], /* dst_addr_mode	*/
+						p + 1, /* dst_addr 		*/
+						p[1 + IEEE_ADDR_LEN], /* dst_ep 			*/
+						p[2 + IEEE_ADDR_LEN], /* src_ep			*/
+						p[3 + IEEE_ADDR_LEN] /* status			*/
+				);
+#endif
+				zbifCbs->APSDE_DATA_confirm(zbif_handle, p[0], /* dst_addr_mode	*/
+				p + 1, /* dst_addr 		*/
+				p[1 + IEEE_ADDR_LEN], /* dst_ep 			*/
+				p[2 + IEEE_ADDR_LEN], /* src_ep			*/
+				p[3 + IEEE_ADDR_LEN] /* status			*/
+				);
+			} else {
+				/* unknown address mode */
+				zb_print_error("ERROR: unknown address mode 0x%02x\n", p[0]);
+				return;
+			}
+		}
+		break;
+
+	case ZB_APSME_BIND_CONFIRM:
+		if (zbifCbs->APSME_BIND_confirm) {
+			ushort cluster_id;
+
+			cluster_id = p[1 + IEEE_ADDR_LEN] | (p[1 + IEEE_ADDR_LEN + 1] << 8);
+
+			zbifCbs->APSME_BIND_confirm(zbif_handle, p[0], /* status			*/
+			p + 1, /* src_ieee_addr 	*/
+			p[1 + IEEE_ADDR_LEN], /* src_ep			*/
+			cluster_id, /* cluster_id 		*/
+			p + 1 + IEEE_ADDR_LEN + 2, /* dst_ieee_addr	*/
+			p[1 + IEEE_ADDR_LEN + 3] /* dst_ep 			*/
+			);
+		}
+		break;
+
+	case ZB_APSME_UNBIND_CONFIRM:
+		zb_print_error("ERROR: unhandled message type 0x%02x\n", type);
+
+	case ZB_APSME_GET_CONFIRM:
+		if (zbifCbs->APSME_GET_confirm) {
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_APSME_GET_confirm (
+					p [0], /* status			*/
+					p [1], /* attr				*/
+					p [2], /* attr_len			*/
+					p + 3 /* attr				*/
+			);
+#endif
+			zbifCbs->APSME_GET_confirm(zbif_handle, p[0], /* status			*/
+			p[1], /* attr				*/
+			p[2], /* attr_len			*/
+			p + 3 /* attr				*/
+			);
+		}
+		break;
+
+	case ZB_APSME_SET_CONFIRM:
+		if (zbifCbs->APSME_SET_confirm) {
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_APSME_SET_confirm (
+					p [0], /* status			*/
+					p [1] /* attr				*/
+			);
+#endif
+			zbifCbs->APSME_SET_confirm(zbif_handle, p[0], /* status			*/
+			p[1] /* attr				*/
+			);
+		}
+		break;
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+		case ZB_APSME_UPDATE_DEVICE_INDICATION:
+		if (zbifCbs->APSME_UPDATE_DEVICE_indication) {
+			swap_bytes(p, IEEE_ADDR_LEN);
+			swap_bytes(p + IEEE_ADDR_LEN, IEEE_ADDR_LEN);
+
+			zbifCbs->APSME_UPDATE_DEVICE_indication (
+					zbif_handle,
+					p, /* src_ieee_addr	*/
+					p + IEEE_ADDR_LEN, /* dev_ieee_addr	*/
+					p[2 * IEEE_ADDR_LEN], /* status */
+					p[2 * IEEE_ADDR_LEN + 1] | (p[2 * IEEE_ADDR_LEN + 2] << 8)
+			);
+		}
+		break;
+
+		case ZB_APSME_REMOVE_DEVICE_CONFIRM:
+		if (zbifCbs->APSME_REMOVE_DEVICE_confirm) {
+			zbifCbs->APSME_REMOVE_DEVICE_confirm (
+					zbif_handle,
+					*p /* status	*/
+			);
+		}
+		break;
+
+		case ZB_APSME_TRANSPORT_KEY_CONFIRM:
+		if (zbifCbs->APSME_TRANSPORT_KEY_confirm) {
+			zbifCbs->APSME_TRANSPORT_KEY_confirm (
+					zbif_handle,
+					*p /* status	*/
+			);
+		}
+		break;
+
+		case ZB_APSME_TRANSPORT_KEY_INDICATION:
+		if (zbifCbs->APSME_TRANSPORT_KEY_indication) {
+			swap_bytes(p, IEEE_ADDR_LEN);
+
+			zbifCbs->APSME_TRANSPORT_KEY_indication (
+					zbif_handle,
+					p, /* dst_ieee_addr	*/
+					p[IEEE_ADDR_LEN], /* key_type	*/
+					(ZB_TRANSPORT_KEY_DATA *) (p + IEEE_ADDR_LEN + 1) /* transport key data */
+			);
+		}
+		break;
+
+		case ZB_NLME_JOIN_INDICATION:
+		if (zbifCbs->NLME_JOIN_indication) {
+			swap_bytes(p + 2, IEEE_ADDR_LEN);
+
+			zbifCbs->NLME_JOIN_indication (
+					zbif_handle,
+					p[0] | (p[1] << 8), /* nwk_addr			*/
+					p + 2, /* ieee_addr		*/
+					p[IEEE_ADDR_LEN + 3], /* capability info	*/
+					p[IEEE_ADDR_LEN + 4] /* secure_join 		*/
+			);
+		}
+		break;
+
+		case ZB_NLME_LEAVE_CONFIRM:
+		if (zbifCbs->NLME_LEAVE_confirm) {
+			swap_bytes(p, IEEE_ADDR_LEN);
+			zbifCbs->NLME_LEAVE_confirm (
+					zbif_handle,
+					p, /* dev_ieee_addr	*/
+					p[IEEE_ADDR_LEN] /* status			*/
+			);
+		}
+		break;
+#endif
+
+	case ZB_ERROR_CONFIRM:
+		if (zbifCbs->ZDO_ERROR_confirm) {
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_ZDO_ERROR_confirm (
+					p [0], /* status 			*/
+					p[1] | (p[2] << 8), /* cluster_id		*/
+					p[3] /* expected_len		*/
+			);
+#endif
+			zbifCbs->ZDO_ERROR_confirm(zbif_handle, p[0], /* status 			*/
+			p[1] | (p[2] << 8), /* cluster_id		*/
+			p[3] /* expected_len		*/
+			);
+
+		}
+		break;
+
+	default:
+		if (zbifCbs->ZDO_ERROR_confirm) {
+			zbifCbs->ZDO_ERROR_confirm(zbif_handle, ZB_ZDO_UNKNOWN_CLUSTER_ID,
+					type, /* cluster_id		*/
+					0 /* expected_len		*/
+					);
+		} else {
+			zb_print_error("ERROR: unknown message type 0x%02x\n", type);
+		}
+		break;
+	}
+}
+
+ZBIFFunctions_t zbZsdioFunctions = { ZSDIO_ZDO_RESET_request,
+		ZSDIO_ZDO_START_request, ZSDIO_ZDO_NWK_ADDR_request,
+		ZSDIO_ZDO_IEEE_ADDR_request, ZSDIO_ZDO_NODE_DESC_request,
+		ZSDIO_ZDO_POWER_DESC_request, ZSDIO_ZDO_SIMPLE_DESC_request,
+		ZSDIO_ZDO_ACTIVE_EP_DESC_request, ZSDIO_ZDO_MATCH_DESC_request,
+		ZSDIO_ZDO_MATCH_DESC_response, ZSDIO_ZDO_END_DEVICE_BIND_request,
+		ZSDIO_APSDE_DATA_request, ZSDIO_APSME_BIND_request,
+		ZSDIO_APSME_UNBIND_request, ZSDIO_APSME_GET_request,
+		ZSDIO_APSME_SET_request,
+
+#ifdef INCLUDE_ZIGBEE_SECURITY
+		ZSDIO_APSME_REMOVE_DEVICE_request,
+		ZSDIO_APSME_TRANSPORT_KEY_request,
+		ZSDIO_NLME_LEAVE_request,
+#endif
+
+		ZSDIO_ZDO_ERROR_response };
+void ZSDIO_Autogen(ZBIF_HANDLE zbif_handle, uchar *data, const int size) {
+	int type;
+	uchar *p;
+
+	if (zbif_handle == NULL) {
+		return;
+	}
+
+	ZBIFCbs_t *zbifCbs = ((zbif_status_t *) zbif_handle)->zbifCbs;
+	if (zbifCbs == NULL) {
+		/* error! */
+		return;
+	}
+
+	ZB_LOG(zb_print_bytes("ZSDIO_Autogen ", data, size));
+
+	p = data;
+	type = *p + (*(p + 1) << 8);
+	p += 2;
+
+	switch (type) {
+
+	case 1: /* APSME_SET_confirm() */
+		if (zbifCbs->APSME_SET_confirm) {
+#ifdef DEBUG_ZIGBEE_API
+			ZBPrint_APSME_SET_confirm (
+					p [0], /* status			*/
+					p [1] /* attr				*/
+			);
+#endif
+			zbifCbs->APSME_SET_confirm(zbif_handle, p[0], p[1]);
+		}
+		break;
+
+	default: {
+		zb_print_error(
+				"ZSDIO_Autogen ERROR: unknown message type 0x%02x\n", type);
+	}
+		break;
+
+	}
+}
+

Added: projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zsdio_if.h
==============================================================================
--- projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zsdio_if.h (added)
+++ projects/zb4osgi/sandbox/telecomItalia/initialContribution/GAL/zigbee/src/zsdio_if.h Fri Oct 19 18:37:43 2012
@@ -1,0 +1,91 @@
+/*
+ Gateway Abstraction Layer (GAL) - A standard ZigBee Gateway Device implementation
+ Copyright 2008-2012 TELECOM ITALIA S.p.A. - http://www.telecomitalia.it
+
+ Part of this computer programs(s) may be used, reproduced, stored in any retrieval system, or
+ transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
+ otherwise, under the Apache License 2.0 with the implicit approval of TELECOM ITALIA.
+ */
+
+#ifndef _ZSDIO_IF_H_
+#define _ZSDIO_IF_H_
+
+extern ZBIFFunctions_t zbZsdioFunctions;
+
+extern void ZSDIO_ReceiveCb(ZBIF_HANDLE zbif_handle, uchar *data,
+		const int size);
+
+#define ZB_ZDO_RESET_REQUEST				0x40D0
+#define ZB_ZDO_RESET_CONFIRM				0x80D0
+
+#define ZB_ZDO_START_REQUEST				0x40D1
+#define ZB_ZDO_START_CONFIRM				0x80D1
+
+/** 
+ * ZigBee Device Profile messages 
+ */
+
+#define ZB_ZDO_NWK_ADDR_REQUEST				0x4000
+#define ZB_ZDO_NWK_ADDR_CONFIRM				0x8000
+#define ZB_ZDO_IEEE_ADDR_REQUEST			0x4001
+#define ZB_ZDO_IEEE_ADDR_CONFIRM			0x8001
+#define ZB_ZDO_NODE_DESC_REQUEST			0x4002
+#define ZB_ZDO_NODE_DESC_CONFIRM			0x8002
+#define ZB_ZDO_POWER_DESC_REQUEST			0x4003
+#define ZB_ZDO_POWER_DESC_CONFIRM			0x8003
+#define ZB_ZDO_SIMPLE_DESC_REQUEST			0x4004
+#define ZB_ZDO_SIMPLE_DESC_CONFIRM			0x8004
+#define ZB_ZDO_SIMPLE_DESC_INDICATION		0x0004
+#define ZB_ZDO_SIMPLE_DESC_RESPONSE			0x2004
+#define ZB_ZDO_ACTIVE_EP_DESC_REQUEST		0x4005
+#define ZB_ZDO_ACTIVE_EP_DESC_CONFIRM		0x8005
+#define ZB_ZDO_ACTIVE_EP_DESC_INDICATION	0x0005
+#define ZB_ZDO_ACTIVE_EP_DESC_RESPONSE		0x2005
+#define ZB_ZDO_MATCH_DESC_REQUEST			0x4006
+#define ZB_ZDO_MATCH_DESC_CONFIRM			0x8006
+#define ZB_ZDO_MATCH_DESC_INDICATION		0x0006	
+#define ZB_ZDO_MATCH_DESC_RESPONSE			0x2006	
+
+#define ZB_ZDO_END_DEVICE_BIND_REQUEST		0x4020
+#define ZB_ZDO_END_DEVICE_BIND_CONFIRM		0x8020
+
+#define ZB_ZDO_DEVICE_ANNCE_INDICATION      0x0013
+
+/** 
+ * ZigBee APS-ME/DE API 
+ */
+
+#define ZB_APSDE_DATA_REQUEST				0x40A0
+#define ZB_APSDE_DATA_CONFIRM				0x80A0
+#define ZB_APSDE_DATA_INDICATION	 		0x00A0
+#define ZB_APSME_BIND_REQUEST				0x40B0
+#define ZB_APSME_BIND_CONFIRM				0x80B0
+#define ZB_APSME_UNBIND_REQUEST				0x40B1
+#define ZB_APSME_UNBIND_CONFIRM				0x80B1
+#define ZB_APSME_GET_REQUEST				0x40B2
+#define ZB_APSME_GET_CONFIRM				0x80B2
+#define ZB_APSME_SET_REQUEST				0x40B3
+#define ZB_APSME_SET_CONFIRM				0x80B3
+
+/* security - related API */
+
+#define ZB_APSME_REMOVE_DEVICE_REQUEST		0x40B4
+#define ZB_APSME_REMOVE_DEVICE_CONFIRM		0x80B4
+#define ZB_APSME_TRANSPORT_KEY_REQUEST		0x40B5
+#define ZB_APSME_TRANSPORT_KEY_CONFIRM		0x80B5
+#define ZB_APSME_TRANSPORT_KEY_INDICATION	0x00B5
+#define ZB_NLME_JOIN_REQUEST				0x40C0
+#define ZB_NLME_JOIN_INDICATION				0x00C0
+#define ZB_NLME_LEAVE_REQUEST				0x40C1
+#define ZB_NLME_LEAVE_CONFIRM				0x80C1
+
+#define ZB_APSME_UPDATE_DEVICE_INDICATION	0x00B6
+#define ZB_REMOVE_DEVICE_REQUEST			0x40B7
+#define ZB_REMOVE_DEVICE_CONFIRM			0x80B7
+
+/* error message */
+
+#define ZB_ERROR_CONFIRM					0x80D2
+#define ZB_ERROR_RESPONSE					0x20D2
+
+#endif /* _ZSDIO_H_ */




More information about the Commit mailing list