Added Kvaser hardware support, thanks to Giuseppe Massimo Bertani .
authoretisserant
Mon, 18 Feb 2008 17:14:22 +0100
changeset 400 7d845f5d730c
parent 399 8d22c323fe0f
child 401 2c90876b9751
Added Kvaser hardware support, thanks to Giuseppe Massimo Bertani .
configure
drivers/can_kvaser/Makefile.in
drivers/can_kvaser/README
drivers/can_kvaser/can_kvaser.c
examples/Makefile.in
examples/SillySlave/EDS2CSV.py
examples/SillySlave/Makefile.in
examples/SillySlave/README
examples/SillySlave/SillySlave.c
examples/SillySlave/SillySlave.h
examples/SillySlave/SillySlave.od
examples/SillySlave/main.c
examples/SillySlave/main.h
examples/SillySlave/slave.c
examples/SillySlave/slave.h
--- a/configure	Mon Feb 18 14:12:19 2008 +0100
+++ b/configure	Mon Feb 18 17:14:22 2008 +0100
@@ -257,7 +257,7 @@
 ###########################################################################
 #                      DEFAULT TARGET/DRIVERS GUESSING                    #
 ###########################################################################
-# If target not specified, try to gess one
+# If target not specified, try to guess one
 if [ "$SUB_TARGET" = "" ]; then
 	if [ "$SUB_OS_NAME" = "CYGWIN" ]; then
 		echo "Choosing unix (cygwin) target"
@@ -273,7 +273,7 @@
 	fi
 fi
 
-# Try to gess can
+# Try to guess can
 if [ "$SUB_CAN_DRIVER" = "" ]; then
 	if [ "$SUB_TARGET" = "unix" ]; then
 		if [ -e /usr/lib/libpcan.so ]; then 
@@ -282,6 +282,12 @@
 		elif [ "$SUB_OS_NAME" = "CYGWIN" -a "PCAN_LIB" != "" ]; then
 			echo "Choosing installed Peak driver as CAN driver."
 			SUB_CAN_DRIVER=peak_win32		
+		elif [ -e /usr/lib/libcanlib.so ]; then 
+			echo "Choosing installed Kvaser driver as CAN driver. (unix)"
+			SUB_CAN_DRIVER=kvaser
+		elif [ "$SUB_OS_NAME" = "CYGWIN" -a "$KVASER_DLL_PATH" != "" ]; then
+			echo "Choosing installed Kvaser driver as CAN driver. (cygwin)"
+			SUB_CAN_DRIVER=kvaser
 		else
 			echo "Choosing virtual CAN driver."
 			SUB_CAN_DRIVER=virtual
@@ -309,6 +315,21 @@
 	fi
 fi
 
+# Warn for unstalled kvaser driver if choosen
+if [ "$SUB_CAN_DRIVER" = "kvaser" ]; then
+	if [ "$SUB_OS_NAME" = "CYGWIN" ]; then
+        if [ ! -e "$KVASER_DLL_PATH/canlib32.dll" ]; then 
+            echo "Kvaser driver hasn't been installed (cygwin)"
+            exit -1
+        fi
+    elif  [ "$SUB_OS_NAME" = "LINUX" ]; then
+        if [ ! -e /usr/lib/libcanlib.so ]; then 
+            echo "Kvaser driver hasn't been installed (unix)"
+            exit -1
+        fi
+	fi
+fi
+
 ###########################################################################
 #              TARGET/DRIVER SPECIFIC CFLAGS and OPTIONS                  #
 ###########################################################################
@@ -336,13 +357,28 @@
 
 #### CAN_DRIVER ####
 
+if [ "$SUB_CAN_DRIVER" = "kvaser" ]; then
+	if [ "$SUB_TARGET" = "unix" ]; then
+        if  [ "$SUB_OS_NAME" = "LINUX" ]; then
+            SUB_CAN_DLL_CFLAGS=$SUB_CAN_DLL_CFLAGS\ -lcanlib
+		elif [ "$SUB_OS_NAME" = "CYGWIN" ]; then
+	        if [ "$KVASER_INCLUDE_PATH" = "" -o "$KVASER_DLL_PATH" = "" ]; then
+		        echo "!!! ERROR !!! Please set KVASER_DLL_PATH and KVASER_INCLUDE_PATH to appropriate paths ! "
+            else
+                SUB_CAN_DLL_CFLAGS=$SUB_CAN_DLL_CFLAGS\ -L$KVASER_DLL_PATH\ -lcanlib32
+                SUB_PROG_CFLAGS=$SUB_PROG_CFLAGS\ -I$KVASER_INCLUDE_PATH
+            fi
+        fi
+    fi        
+fi
+
 if [ "$SUB_CAN_DRIVER" = "peak_linux" ]; then
     SUB_CAN_DLL_CFLAGS=$SUB_CAN_DLL_CFLAGS\ -lpcan
 fi
 
 PW32DIR=drivers/can_peak_win32
 if [ "$SUB_CAN_DRIVER" = "peak_win32" ]; then
-	if [ "$PCAN_HEADER" = "" -o "PCAN_LIB" = "" ]; then
+	if [ "$PCAN_HEADER" = "" -o "$PCAN_LIB" = "" ]; then
 		echo "!!! ERROR !!! Please set PCAN_LIB PCAN_HEADER [PCAN_INCLUDE] to appropriate paths ! "
 	fi
    	SUB_CAN_DLL_CFLAGS=$SUB_CAN_DLL_CFLAGS\ -liberty\ \'$PCAN_LIB\'
@@ -693,6 +729,7 @@
 	MAKEFILES=$MAKEFILES\
 \	examples/TestMasterSlave/Makefile.in\
 \	examples/TestMasterSlaveLSS/Makefile.in\
+\	examples/SillySlave/Makefile.in\
 \	examples/TestMasterMicroMod/Makefile.in
 fi
 
@@ -700,6 +737,7 @@
 	MAKEFILES=$MAKEFILES\
 \	examples/TestMasterSlave/Makefile.in\
 \	examples/TestMasterSlaveLSS/Makefile.in\
+\	examples/SillySlave/Makefile.in\
 \	examples/TestMasterMicroMod/Makefile.in
 fi
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/can_kvaser/Makefile.in	Mon Feb 18 17:14:22 2008 +0100
@@ -0,0 +1,77 @@
+#! gmake
+
+#
+# Copyright (C) 2006 Giuseppe Massimo Bertani and Laurent Bessard
+# 
+# This file is part of canfestival, a library implementing the canopen
+# stack
+# 
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# 
+
+CC = SUB_CC
+OPT_CFLAGS = -O2
+CFLAGS = SUB_OPT_CFLAGS
+PROG_CFLAGS = SUB_PROG_CFLAGS
+PREFIX = SUB_PREFIX
+TARGET = SUB_TARGET
+CAN_DRIVER = SUB_CAN_DRIVER
+TIMERS_DRIVER = SUB_TIMERS_DRIVER
+ENABLE_DLL_DRIVERS = SUB_ENABLE_DLL_DRIVERS
+CAN_DLL_CFLAGS = SUB_CAN_DLL_CFLAGS
+OS_NAME = SUB_OS_NAME
+
+INCLUDES = -I../../include -I../../include/$(TARGET) -I../../include/$(CAN_DRIVER)
+
+OBJS = $(CAN_DRIVER).o
+
+#GMB: must detect if we are under cygwin (produces a DLL driver)
+#or under a real unix machine (produces a .so driver)
+ifeq ($(ENABLE_DLL_DRIVERS),1)
+    ifeq ($(OS_NAME),CYGWIN)
+        DRIVER = libcanfestival_$(CAN_DRIVER).dll
+    else
+        ifeq ($(TARGET),unix)
+            CFLAGS += -fPIC
+            DRIVER = libcanfestival_$(CAN_DRIVER).so
+        endif
+    endif
+else
+DRIVER = $(OBJS)
+endif
+
+TARGET_SOFILES = $(PREFIX)/lib/$(DRIVER)
+
+all: driver
+
+driver: $(DRIVER)
+
+%o: %c
+	$(CC) $(CFLAGS) $(PROG_CFLAGS) ${PROGDEFINES} $(INCLUDES) -o $@ -c $<
+
+$(DRIVER): $(OBJS)
+	$(CC) -shared -Wl,-soname,$(DRIVER) $(CAN_DLL_CFLAGS) -o $@ $< 
+
+install: $(DRIVER)
+	mkdir -p $(PREFIX)/lib/
+	cp $< $(PREFIX)/lib/
+		
+uninstall:
+	rm -f $(TARGET_SOFILES)
+
+clean:
+	rm -f $(OBJS)
+
+mrproper: clean
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/can_kvaser/README	Mon Feb 18 17:14:22 2008 +0100
@@ -0,0 +1,31 @@
+Kvaser driver for CANfestival, the open source CANopen stack.
+(C)2008 Giuseppe Massimo Bertani 
+
+
+This driver should work with any Kvaser product compatible with Kvaser's CANLIB4.
+I tested it with CAN Leaf Professional (USB-CAN adapter) on a Suse10.1 Linux box
+and CANLIB 4.72 Beta (Oct 1,2007). 
+
+In order to compile the driver, you should already be able to run the CANlib examples,
+and tools, to be sure that CANLIB is able to detect and drive your device. 
+ 
+-------------------------------------------------------------------------------------------------
+NOTES ABOUT CANLIB4
+
+Since the "Leaf" device was added recently to CANLIB, I had to download the latest linuxcan4
+library sources from http://www.kvaser.com instead of use the CD software shipped with the device.
+
+--------------------------------------------------------------------------------------------------
+NOTES ABOUT WINDOWS
+
+Sadly, Kvaser's Win32 CANLIB is not provided with sources, so CANLIB cannot be build with GNU
+tools. LIB files for MSVC and BCC are provided with the DLL but the DLL itself is stripped and
+I've tried an entire day to compile this driver under Cygwin without success, despite 
+Wu Yongwei's hints (http://www.geocities.com/yongweiwu/dllfaq.htm).
+
+This does not mean that it's an impossible task, but probably I left out something important. 
+Temporary KO.
+
+-------------------------------------------------------------------------------------------------
+
+GMB 23/1/08
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/can_kvaser/can_kvaser.c	Mon Feb 18 17:14:22 2008 +0100
@@ -0,0 +1,307 @@
+
+/*
+Copyright (C): Giuseppe Massimo BERTANI
+gmbertani@users.sourceforge.net
+
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/**
+ * @file can_kvaser.c
+ * @author GMB
+ * @date 17/1/08
+ *
+ * This file is needed to interface Kvaser's CAN Leaf (USB-CAN adapter) 
+ * and probably others Kvaser's products compatible with Kvaser's CANLIB,
+ * to CANfestival open source CANopen stack.
+ *
+ * It was tested under Linux 2.6 with "Leaf Professional" and CANLIB 4.72 Beta (Oct 1,2007)
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+
+/* includes Kvaser's CANLIB header */
+#include <canlib.h>
+
+#include "can_driver.h"
+ 
+    
+/**
+ * CAN_HANDLES must have value >=1 while CANLIB wants handles >= 0
+ * so fd0 needs to be decremented before use.
+ *
+ */ 
+UNS8 canReceive_driver(CAN_HANDLE fd0, Message *m)
+{
+canStatus retval = canOK;
+unsigned flags = 0;
+unsigned long timeStamp;
+
+    fd0--;
+
+    /* checking for input message (blocking) */
+    retval = canReadWait((int)fd0, (long*)&m->cob_id, &m->data, (unsigned*)&m->len, &flags, &timeStamp, -1);
+    if (retval != canOK)
+    {
+  	    fprintf(stderr, "canReceive_driver (Kvaser) : canReadWait() error, cob_id=%08X, len=%u, flags=%08X, returned value = %d\n", 
+                m->cob_id, m->len, flags, retval);
+        canClose((int)fd0);
+        return retval;
+    }
+
+    m->rtr = 0;
+    if (flags & canMSG_RTR)
+    {
+        m->rtr = 1;
+    }
+
+    if (flags & canMSG_EXT)
+    {
+        /* TODO: is it correct to set this info in cob_id? */
+        m->cob_id |= 0x20000000;
+    }
+    
+    //fprintf(stderr, "canReceive_driver (Kvaser) : canReadWait() received packet, cob_id=%08X, len=%u, flags=%08X, timestamp=%d  returned value = %d\n", 
+    //       m->cob_id, m->len, flags, timeStamp, retval);
+
+    return retval;
+}
+
+/**
+ *
+ * CAN_HANDLES must have value >=1 while CANLIB wants handles >= 0
+ * so fd0 needs to be decremented before use.
+ *
+ */ 
+UNS8 canSend_driver(CAN_HANDLE fd0, Message *m)
+{
+canStatus retval = canOK;
+unsigned flags = 0;
+
+    fd0--;
+
+    flags |= canMSG_STD;
+    
+    if (m->cob_id & 0x20000000)
+    {
+        /* TODO: is it correct to desume this info from cob_id? */
+        flags |= canMSG_EXT;
+    }
+
+    if (m->cob_id & 0x40000000)
+    {
+        flags |= canMSG_RTR;
+    }
+
+    /*
+     * TODO: when should I set canMSG_ERROR_FRAME?
+     */ 
+    
+    retval = canWriteWait((int)fd0, m->cob_id, m->data, m->len, 10000, flags);
+    if (retval != canOK)
+    {
+  	    fprintf(stderr, "canSend_driver (Kvaser) :  canWriteWait() error, cob_id=%08X, len=%u, flags=%08X, returned value = %d\n", 
+                m->cob_id, m->len, flags, retval);
+        canClose((int)fd0);
+        return retval;
+    }
+   
+    //fprintf(stderr, "canSend_driver (Kvaser) :  canWriteWait() send packet, cob_id=%08X, len=%u, flags=%08X, returned value = %d\n", 
+    //            m->cob_id, m->len, flags, retval);
+    return retval; 
+
+}
+
+
+/**
+ * 
+ */ 
+int TranslateBaudRate(char* optarg)
+{
+	if(!strcmp( optarg, "1M")) 
+        return BAUD_1M;
+	if(!strcmp( optarg, "500K")) 
+        return BAUD_500K;
+	if(!strcmp( optarg, "250K")) 
+        return BAUD_250K;
+	if(!strcmp( optarg, "125K")) 
+        return BAUD_125K;
+	if(!strcmp( optarg, "100K")) 
+        return BAUD_100K;
+	if(!strcmp( optarg, "62K")) 
+        return BAUD_62K;
+	if(!strcmp( optarg, "50K")) 
+        return BAUD_50K;
+
+	return 0;
+}
+
+/**
+ * Channels and their descriptors are numbered starting from zero.
+ * So I need to increment by 1 the handle returned by CANLIB because
+ * CANfestival CAN_HANDLEs with value zero are considered NOT VALID. 
+ * 
+ * The baud rate could be given directly as bit/s
+ * or using one of the BAUD_* constants defined
+ * in canlib.h
+ */ 
+CAN_HANDLE canOpen_driver(s_BOARD *board)
+{
+int fd0 = -1;
+int channel, baud;
+canStatus retval = canOK;
+
+    fd0--;
+
+    sscanf(board->busname, "%d", &channel);  
+
+    baud = TranslateBaudRate(board->baudrate);
+
+    if (baud == 0)
+    {
+        sscanf(board->baudrate, "%d", &baud);
+    }
+
+    fd0 = canOpenChannel(channel, canWANT_EXCLUSIVE|canWANT_EXTENDED);
+    if (fd0 < 0)
+    {
+  	    fprintf(stderr, "canOpen_driver (Kvaser) : error opening channel %d\n", channel);
+        return (CAN_HANDLE)(fd0+1);
+    }
+    canBusOff(fd0);
+
+    /* values for tseg1, tseg2, sjw, noSamp and  syncmode
+     * come from canlib example "simplewrite.c". The doc
+     * says that default values will be taken if baud is one of
+     * the BAUD_* values
+     */ 
+    retval = canSetBusParams(fd0, baud, 4, 3, 1, 1, 0);
+    if (retval != canOK)
+    {
+  	    fprintf(stderr, "canOpen_driver (Kvaser) :  canSetBusParams() error, returned value = %d, baud=%d, \n", retval, baud);
+        canClose((int)fd0);
+        return (CAN_HANDLE)retval;
+    }
+    
+    canSetBusOutputControl(fd0, canDRIVER_NORMAL);
+    if (retval != canOK)
+    {
+  	    fprintf(stderr, "canOpen_driver (Kvaser) :  canSetBusOutputControl() error, returned value = %d\n", retval);
+        canClose((int)fd0);
+        return (CAN_HANDLE)retval;
+    }
+
+
+
+    
+    retval = canBusOn(fd0);
+    if (retval != canOK)
+    {
+  	    fprintf(stderr, "canOpen_driver (Kvaser) :  canBusOn() error, returned value = %d\n", retval);
+        canClose((int)fd0);
+        return (CAN_HANDLE)retval;
+    }
+    
+    return (CAN_HANDLE)(fd0+1);
+
+}
+
+UNS8 canChangeBaudRate_driver( CAN_HANDLE fd0, char* baud)
+{
+int baudrate;
+canStatus retval = canOK;
+
+
+    baudrate = TranslateBaudRate(baud);
+    if (baudrate == 0)
+    {
+        sscanf(baud, "%d", &baudrate);
+    }
+
+
+    fprintf(stderr, "%x-> changing to baud rate %s[%d]\n", (int)fd0, baud, baudrate); 
+    
+    canBusOff((int)fd0);
+
+    /* values for tseg1, tseg2, sjw, noSamp and  syncmode
+     * come from canlib example "simplewrite.c". The doc
+     * says that default values will be taken if baud is one of
+     * the BAUD_* values
+     */ 
+    retval = canSetBusParams((int)fd0, baudrate, 4, 3, 1, 1, 0);
+    if (retval != canOK)
+    {
+  	    fprintf(stderr, "canChangeBaudRate_driver (Kvaser) :  canSetBusParams() error, returned value = %d, baud=%d, \n", retval, baud);
+        canClose((int)fd0);
+        return (UNS8)retval;
+    }
+    
+    canSetBusOutputControl((int)fd0, canDRIVER_NORMAL);
+    if (retval != canOK)
+    {
+  	    fprintf(stderr, "canChangeBaudRate_driver (Kvaser) :  canSetBusOutputControl() error, returned value = %d\n", retval);
+        canClose((int)fd0);
+        return (UNS8)retval;
+    }
+    
+    retval = canBusOn((int)fd0);
+    if (retval != canOK)
+    {
+  	    fprintf(stderr, "canChangeBaudRate_driver (Kvaser) :  canBusOn() error, returned value = %d\n", retval);
+        canClose((int)fd0);
+        return (UNS8)retval;
+    }
+
+    return 0;
+}
+
+
+/**
+ *
+ * CAN_HANDLES must have value >=1 while CANLIB wants handles >= 0
+ * so fd0 needs to be decremented before use.
+ */ 
+int canClose_driver(CAN_HANDLE fd0)
+{
+canStatus retval = canOK;
+
+    fd0--;
+    
+    retval = canBusOff((int)fd0);
+    if (retval != canOK)
+    {
+  	    fprintf(stderr, "canClose_driver (Kvaser) :  canBusOff() error, returned value = %d\n", retval);
+        canClose((int)fd0);
+        return retval;
+    }
+    
+    retval = canClose((int)fd0);
+    if (retval != canOK)
+    {
+  	    fprintf(stderr, "canClose_driver (Kvaser) :  canClose() error, returned value = %d\n", retval);
+        return retval;
+    }
+    
+    return retval;
+}
+
--- a/examples/Makefile.in	Mon Feb 18 14:12:19 2008 +0100
+++ b/examples/Makefile.in	Mon Feb 18 17:14:22 2008 +0100
@@ -46,6 +46,7 @@
 	$(MAKE) -C TestMasterSlave $@
 	$(MAKE) -C TestMasterSlaveLSS $@
 	$(MAKE) -C TestMasterMicroMod $@
+	$(MAKE) -C SillySlave $@
 	$(build_command_seq_wx)
 endef
 else
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/SillySlave/EDS2CSV.py	Mon Feb 18 17:14:22 2008 +0100
@@ -0,0 +1,63 @@
+#! /usr/bin/env python
+#
+# -*- coding: iso-8859-1 -*-
+#
+#
+# FILE:         EDS2CSV.py
+# BEGIN:        Nov 30,2007
+# AUTHOR:       Giuseppe Massimo Bertani
+# EMAIL         gmbertani@users.sourceforge.net
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+#
+#  Coding style params:
+#  <TAB> skips=4
+#  <TAB> are replaced with blanks
+#
+#
+
+import sys
+import os
+import ConfigParser as cp
+
+if (len(sys.argv) != 2):
+    print "Usage:"
+    print 
+    print "EDS2CSV.py <input file> "
+    print
+    print
+    sys.exit(0)
+
+EDSname = os.path.abspath( os.path.dirname(sys.argv[1]) ) + '/' + sys.argv[1] 
+
+if (os.path.exists(EDSname) is not True):
+    print 
+    print "Input file ",EDS2CSV," not found."
+    print
+    print
+    sys.exit(0)
+
+eds = cp.ConfigParser()
+eds.read(EDSname)
+    
+ssorted = sorted(eds.sections())
+
+# dump entire EDS file to stdout in CSV format comma separated
+print "Object Dictionary,",sys.argv[1]
+print
+for section in ssorted:
+    print section
+    print ",", 
+    osorted = sorted(eds.options(section))
+    for option in osorted:
+        print option, ",", 
+    print
+    print ",", 
+    for option in osorted:
+        print eds.get(section, option), ",",    
+    print
+    print
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/SillySlave/Makefile.in	Mon Feb 18 17:14:22 2008 +0100
@@ -0,0 +1,79 @@
+#! gmake
+
+#
+# Copyright (C) 2006 Laurent Bessard
+# 
+# This file is part of canfestival, a library implementing the canopen
+# stack
+# 
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# 
+
+CC = SUB_CC
+CXX = SUB_CXX
+LD = SUB_LD
+OPT_CFLAGS = -O2
+CFLAGS = SUB_OPT_CFLAGS
+PROG_CFLAGS = SUB_PROG_CFLAGS
+EXE_CFLAGS = SUB_EXE_CFLAGS
+OS_NAME = SUB_OS_NAME
+ARCH_NAME = SUB_ARCH_NAME
+PREFIX = SUB_PREFIX
+TARGET = SUB_TARGET
+CAN_DRIVER = SUB_CAN_DRIVER
+TIMERS_DRIVER = SUB_TIMERS_DRIVER
+
+INCLUDES = -I../../include -I../../include/$(TARGET) -I../../include/$(CAN_DRIVER) -I../../include/$(TIMERS_DRIVER)
+
+SILLYSLAVE_OBJS = SillySlave.o slave.o main.o
+
+OBJS = $(SILLYSLAVE_OBJS) ../../src/libcanfestival.a ../../drivers/$(TARGET)/libcanfestival_$(TARGET).a -lcanlib
+
+ifeq ($(TIMERS_DRIVER),timers_xeno)
+	PROGDEFINES = -DUSE_XENO
+endif
+
+all: SillySlave
+
+../../drivers/$(TARGET)/libcanfestival_$(TARGET).a:
+	$(MAKE) -C ../../drivers/$(TARGET) libcanfestival_$(TARGET).a
+
+
+SillySlave: SillySlave.c $(OBJS)
+	$(LD) $(CFLAGS) $(PROG_CFLAGS) ${PROGDEFINES} $(INCLUDES) -o $@ $(OBJS) $(EXE_CFLAGS)
+
+	
+SillySlave.c: SillySlave.od
+	$(MAKE) -C ../../objdictgen gnosis
+	python ../../objdictgen/objdictgen.py SillySlave.od SillySlave.c
+
+%o: %c
+	$(CC) $(CFLAGS) $(PROG_CFLAGS) ${PROGDEFINES} $(INCLUDES) -o $@ -c $<
+
+clean:
+	rm -f $(SILLYSLAVE_OBJS)
+	rm -f SillySlave
+
+mrproper: clean
+	rm -f SillySlave.c
+	
+install: SillySlave
+	mkdir -p $(PREFIX)/bin/
+	cp $< $(PREFIX)/bin/
+	
+uninstall:
+	rm -f $(PREFIX)/bin/SillySlave
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/SillySlave/README	Mon Feb 18 17:14:22 2008 +0100
@@ -0,0 +1,16 @@
+SillySlave example for CANfestival
+
+Its purpose is only to check if the selected
+driver works at least a minimum. The PC running this demo
+must be connected through CAN bus to a working master that 
+recognizes the slave nodeId. The slave should be configured
+by the master, then switched to operative. After that, when
+the master sends a SYNC, the slave answers with PDO1, 
+containing an integer that increments each time it is sent.
+
+Please have a look to main.h to tune the master and slave node IDs
+
+It's all. Enjoy it.
+GMB
+jan 17,2008
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/SillySlave/SillySlave.c	Mon Feb 18 17:14:22 2008 +0100
@@ -0,0 +1,247 @@
+
+/* File generated by gen_cfile.py. Should not be modified. */
+
+#include "SillySlave.h"
+
+/**************************************************************************/
+/* Declaration of the mapped variables                                    */
+/**************************************************************************/
+UNS8 LifeSignal = 0x0;		/* Mapped at index 0x2001, subindex 0x00 */
+
+/**************************************************************************/
+/* Declaration of the value range types                                   */
+/**************************************************************************/
+
+#define valueRange_EMC 0x9F /* Type for index 0x1003 subindex 0x00 (only set of value 0 is possible) */
+UNS32 SillySlave_valueRangeTest (UNS8 typeValue, void * value)
+{
+  switch (typeValue) {
+    case valueRange_EMC:
+      if (*(UNS8*)value != (UNS8)0) return OD_VALUE_RANGE_EXCEEDED;
+      break;
+  }
+  return 0;
+}
+
+/**************************************************************************/
+/* The node id                                                            */
+/**************************************************************************/
+/* node_id default value.*/
+UNS8 SillySlave_bDeviceNodeId = 0x00;
+
+/**************************************************************************/
+/* Array of message processing information */
+
+const UNS8 SillySlave_iam_a_slave = 1;
+
+TIMER_HANDLE SillySlave_heartBeatTimers[1];
+
+/*
+$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
+
+                               OBJECT DICTIONARY
+
+$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
+*/
+
+/* index 0x1000 :   Device Type. */
+                    UNS32 SillySlave_obj1000 = 0x2000000;	/* 33554432 */
+                    subindex SillySlave_Index1000[] = 
+                     {
+                       { RO, uint32, sizeof (UNS32), (void*)&SillySlave_obj1000 }
+                     };
+
+/* index 0x1001 :   Error Register. */
+                    UNS8 SillySlave_obj1001 = 0x0;	/* 0 */
+                    subindex SillySlave_Index1001[] = 
+                     {
+                       { RO, uint8, sizeof (UNS8), (void*)&SillySlave_obj1001 }
+                     };
+
+/* index 0x1003 :   Pre-defined Error Field */
+                    UNS8 SillySlave_highestSubIndex_obj1003 = 0; /* number of subindex - 1*/
+                    UNS32 SillySlave_obj1003[] = 
+                    {
+                      0x0	/* 0 */
+                    };
+                    ODCallback_t SillySlave_Index1003_callbacks[] = 
+                     {
+                       NULL,
+                       NULL,
+                     };
+                    subindex SillySlave_Index1003[] = 
+                     {
+                       { RW, valueRange_EMC, sizeof (UNS8), (void*)&SillySlave_highestSubIndex_obj1003 },
+                       { RO, uint32, sizeof (UNS32), (void*)&SillySlave_obj1003[0] }
+                     };
+
+/* index 0x1005 :   SYNC COB ID */
+                    UNS32 SillySlave_obj1005 = 0x0;   /* 0 */
+
+/* index 0x1006 :   Communication / Cycle Period */
+                    UNS32 SillySlave_obj1006 = 0x0;   /* 0 */
+
+/* index 0x1012 :   TIME COB ID. */
+                    UNS32 SillySlave_obj1012 = 0x80000100;	/* 2147483904 */
+                    subindex SillySlave_Index1012[] = 
+                     {
+                       { RW, uint32, sizeof (UNS32), (void*)&SillySlave_obj1012 }
+                     };
+
+/* index 0x1013 :   High Resolution Timestamp. */
+                    UNS32 SillySlave_obj1013 = 0x0;	/* 0 */
+                    subindex SillySlave_Index1013[] = 
+                     {
+                       { RW, uint32, sizeof (UNS32), (void*)&SillySlave_obj1013 }
+                     };
+
+/* index 0x1014 :   Emergency COB ID */
+                    UNS32 SillySlave_obj1014 = 0x0;   /* 0 */
+
+/* index 0x1016 :   Consumer Heartbeat Time */
+                    UNS8 SillySlave_highestSubIndex_obj1016 = 0;
+                    UNS32 SillySlave_obj1016[]={0};
+
+/* index 0x1017 :   Producer Heartbeat Time */ 
+                    UNS16 SillySlave_obj1017 = 0x0;   /* 0 */
+
+/* index 0x1018 :   Identity. */
+                    UNS8 SillySlave_highestSubIndex_obj1018 = 4; /* number of subindex - 1*/
+                    UNS32 SillySlave_obj1018_Vendor_ID = 0x4321;	/* 17185 */
+                    UNS32 SillySlave_obj1018_Product_Code = 0x12;	/* 18 */
+                    UNS32 SillySlave_obj1018_Revision_Number = 0x1;	/* 1 */
+                    UNS32 SillySlave_obj1018_Serial_Number = 0x1;	/* 1 */
+                    subindex SillySlave_Index1018[] = 
+                     {
+                       { RO, uint8, sizeof (UNS8), (void*)&SillySlave_highestSubIndex_obj1018 },
+                       { RO, uint32, sizeof (UNS32), (void*)&SillySlave_obj1018_Vendor_ID },
+                       { RO, uint32, sizeof (UNS32), (void*)&SillySlave_obj1018_Product_Code },
+                       { RO, uint32, sizeof (UNS32), (void*)&SillySlave_obj1018_Revision_Number },
+                       { RO, uint32, sizeof (UNS32), (void*)&SillySlave_obj1018_Serial_Number }
+                     };
+
+/* index 0x1200 :   Server SDO Parameter. */
+                    UNS8 SillySlave_highestSubIndex_obj1200 = 2; /* number of subindex - 1*/
+                    UNS32 SillySlave_obj1200_COB_ID_Client_to_Server_Receive_SDO = 0x600;	/* 1536 */
+                    UNS32 SillySlave_obj1200_COB_ID_Server_to_Client_Transmit_SDO = 0x580;	/* 1408 */
+                    ODCallback_t SillySlave_Index1200_callbacks[] = 
+                     {
+                       NULL,
+                       NULL,
+                       NULL,
+                     };
+                    subindex SillySlave_Index1200[] = 
+                     {
+                       { RO, uint8, sizeof (UNS8), (void*)&SillySlave_highestSubIndex_obj1200 },
+                       { RO, uint32, sizeof (UNS32), (void*)&SillySlave_obj1200_COB_ID_Client_to_Server_Receive_SDO },
+                       { RO, uint32, sizeof (UNS32), (void*)&SillySlave_obj1200_COB_ID_Server_to_Client_Transmit_SDO }
+                     };
+
+/* index 0x1800 :   Transmit PDO 1 Parameter. */
+                    UNS8 SillySlave_highestSubIndex_obj1800 = 5; /* number of subindex - 1*/
+                    UNS32 SillySlave_obj1800_COB_ID_used_by_PDO = 0x180;	/* 384 */
+                    UNS8 SillySlave_obj1800_Transmission_Type = 0x1;	/* 1 */
+                    UNS16 SillySlave_obj1800_Inhibit_Time = 0x64;	/* 100 */
+                    UNS8 SillySlave_obj1800_Compatibility_Entry = 0x0;	/* 0 */
+                    UNS16 SillySlave_obj1800_Event_Timer = 0x0;	/* 0 */
+                    ODCallback_t SillySlave_Index1800_callbacks[] = 
+                     {
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                       NULL,
+                     };
+                    subindex SillySlave_Index1800[] = 
+                     {
+                       { RO, uint8, sizeof (UNS8), (void*)&SillySlave_highestSubIndex_obj1800 },
+                       { RW, uint32, sizeof (UNS32), (void*)&SillySlave_obj1800_COB_ID_used_by_PDO },
+                       { RW, uint8, sizeof (UNS8), (void*)&SillySlave_obj1800_Transmission_Type },
+                       { RW, uint16, sizeof (UNS16), (void*)&SillySlave_obj1800_Inhibit_Time },
+                       { RW, uint8, sizeof (UNS8), (void*)&SillySlave_obj1800_Compatibility_Entry },
+                       { RW, uint16, sizeof (UNS16), (void*)&SillySlave_obj1800_Event_Timer }
+                     };
+
+/* index 0x1A00 :   Transmit PDO 1 Mapping. */
+                    UNS8 SillySlave_highestSubIndex_obj1A00 = 1; /* number of subindex - 1*/
+                    UNS32 SillySlave_obj1A00[] = 
+                    {
+                      0x20010008	/* 536936456 */
+                    };
+                    subindex SillySlave_Index1A00[] = 
+                     {
+                       { RW, uint8, sizeof (UNS8), (void*)&SillySlave_highestSubIndex_obj1A00 },
+                       { RW, uint32, sizeof (UNS32), (void*)&SillySlave_obj1A00[0] }
+                     };
+
+/* index 0x2001 :   Mapped variable LifeSignal */
+                    subindex SillySlave_Index2001[] = 
+                     {
+                       { RO, uint8, sizeof (UNS8), (void*)&LifeSignal }
+                     };
+
+const indextable SillySlave_objdict[] = 
+{
+  { (subindex*)SillySlave_Index1000,sizeof(SillySlave_Index1000)/sizeof(SillySlave_Index1000[0]), 0x1000},
+  { (subindex*)SillySlave_Index1001,sizeof(SillySlave_Index1001)/sizeof(SillySlave_Index1001[0]), 0x1001},
+  { (subindex*)SillySlave_Index1012,sizeof(SillySlave_Index1012)/sizeof(SillySlave_Index1012[0]), 0x1012},
+  { (subindex*)SillySlave_Index1013,sizeof(SillySlave_Index1013)/sizeof(SillySlave_Index1013[0]), 0x1013},
+  { (subindex*)SillySlave_Index1018,sizeof(SillySlave_Index1018)/sizeof(SillySlave_Index1018[0]), 0x1018},
+  { (subindex*)SillySlave_Index1200,sizeof(SillySlave_Index1200)/sizeof(SillySlave_Index1200[0]), 0x1200},
+  { (subindex*)SillySlave_Index1800,sizeof(SillySlave_Index1800)/sizeof(SillySlave_Index1800[0]), 0x1800},
+  { (subindex*)SillySlave_Index1A00,sizeof(SillySlave_Index1A00)/sizeof(SillySlave_Index1A00[0]), 0x1A00},
+  { (subindex*)SillySlave_Index2001,sizeof(SillySlave_Index2001)/sizeof(SillySlave_Index2001[0]), 0x2001},
+};
+
+const indextable * SillySlave_scanIndexOD (UNS16 wIndex, UNS32 * errorCode, ODCallback_t **callbacks)
+{
+	int i;
+	*callbacks = NULL;
+	switch(wIndex){
+		case 0x1000: i = 0;break;
+		case 0x1001: i = 1;break;
+		case 0x1012: i = 2;break;
+		case 0x1013: i = 3;break;
+		case 0x1018: i = 4;break;
+		case 0x1200: i = 5;*callbacks = SillySlave_Index1200_callbacks; break;
+		case 0x1800: i = 6;*callbacks = SillySlave_Index1800_callbacks; break;
+		case 0x1A00: i = 7;break;
+		case 0x2001: i = 8;break;
+		default:
+			*errorCode = OD_NO_SUCH_OBJECT;
+			return NULL;
+	}
+	*errorCode = OD_SUCCESSFUL;
+	return &SillySlave_objdict[i];
+}
+
+/* 
+ * To count at which received SYNC a PDO must be sent.
+ * Even if no pdoTransmit are defined, at least one entry is computed
+ * for compilations issues.
+ */
+s_PDO_status SillySlave_PDO_status[1] = {s_PDO_status_Initializer};
+
+quick_index SillySlave_firstIndex = {
+  5, /* SDO_SVR */
+  0, /* SDO_CLT */
+  0, /* PDO_RCV */
+  0, /* PDO_RCV_MAP */
+  6, /* PDO_TRS */
+  7 /* PDO_TRS_MAP */
+};
+
+quick_index SillySlave_lastIndex = {
+  5, /* SDO_SVR */
+  0, /* SDO_CLT */
+  0, /* PDO_RCV */
+  0, /* PDO_RCV_MAP */
+  6, /* PDO_TRS */
+  7 /* PDO_TRS_MAP */
+};
+
+UNS16 SillySlave_ObjdictSize = sizeof(SillySlave_objdict)/sizeof(SillySlave_objdict[0]); 
+
+CO_Data SillySlave_Data = CANOPEN_NODE_DATA_INITIALIZER(SillySlave);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/SillySlave/SillySlave.h	Mon Feb 18 17:14:22 2008 +0100
@@ -0,0 +1,19 @@
+
+/* File generated by gen_cfile.py. Should not be modified. */
+
+#ifndef SILLYSLAVE_H
+#define SILLYSLAVE_H
+
+#include "data.h"
+
+/* Prototypes of function provided by object dictionnary */
+UNS32 SillySlave_valueRangeTest (UNS8 typeValue, void * value);
+const indextable * SillySlave_scanIndexOD (UNS16 wIndex, UNS32 * errorCode, ODCallback_t **callbacks);
+
+/* Master node data struct */
+extern CO_Data SillySlave_Data;
+extern ODCallback_t Server_SDO_Parameter_callbacks[];		/* Callbacks of index0x1200 */
+extern ODCallback_t Transmit_PDO_1_Parameter_callbacks[];		/* Callbacks of index0x1800 */
+extern UNS8 LifeSignal;		/* Mapped at index 0x2001, subindex 0x00*/
+
+#endif // SILLYSLAVE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/SillySlave/SillySlave.od	Mon Feb 18 17:14:22 2008 +0100
@@ -0,0 +1,309 @@
+<?xml version="1.0"?>
+<!DOCTYPE PyObject SYSTEM "PyObjects.dtd">
+<PyObject module="node" class="Node" id="-1268630260">
+<attr name="Profile" type="dict" id="-1268626332" >
+</attr>
+<attr name="Description" type="string">Silly Slave example for CANfestival,  (C)GMB 2008</attr>
+<attr name="Dictionary" type="dict" id="-1268621556" >
+  <entry>
+    <key type="numeric" value="4096" />
+    <val type="numeric" value="33554432" />
+  </entry>
+  <entry>
+    <key type="numeric" value="4097" />
+    <val type="numeric" value="0" />
+  </entry>
+  <entry>
+    <key type="numeric" value="6144" />
+    <val type="list" id="-1214451316" >
+      <item type="string" value="{True:&quot;$NODEID+0x%X80&quot;%(base+1),False:0}[base&lt;4]" />
+      <item type="numeric" value="1" />
+      <item type="numeric" value="100" />
+      <item type="numeric" value="0" />
+      <item type="numeric" value="0" />
+    </val>
+  </entry>
+  <entry>
+    <key type="numeric" value="8193" />
+    <val type="numeric" value="0" />
+  </entry>
+  <entry>
+    <key type="numeric" value="4114" />
+    <val type="numeric" value="2147483904L" />
+  </entry>
+  <entry>
+    <key type="numeric" value="4115" />
+    <val type="numeric" value="0" />
+  </entry>
+  <entry>
+    <key type="numeric" value="6656" />
+    <val type="list" id="-1214450420" >
+      <item type="numeric" value="536936456" />
+    </val>
+  </entry>
+  <entry>
+    <key type="numeric" value="4120" />
+    <val type="list" id="-1214449748" >
+      <item type="numeric" value="17185" />
+      <item type="numeric" value="18" />
+      <item type="numeric" value="1" />
+      <item type="numeric" value="1" />
+    </val>
+  </entry>
+  <entry>
+    <key type="numeric" value="4608" />
+    <val type="list" id="-1214449460" >
+      <item type="string" value="&quot;$NODEID+0x600&quot;" />
+      <item type="string" value="&quot;$NODEID+0x580&quot;" />
+    </val>
+  </entry>
+</attr>
+<attr name="SpecificMenu" type="list" id="-1214449556" >
+</attr>
+<attr name="ParamsDictionary" type="dict" id="-1268617172" >
+  <entry>
+    <key type="numeric" value="4096" />
+    <val type="dict" id="-1268617036" >
+      <entry>
+        <key type="string" value="comment" />
+        <val type="string" value="fake nr" />
+      </entry>
+    </val>
+  </entry>
+  <entry>
+    <key type="numeric" value="4608" />
+    <val type="dict" id="-1268616900" >
+      <entry>
+        <key type="string" value="callback" />
+        <val type="True" value="" />
+      </entry>
+    </val>
+  </entry>
+  <entry>
+    <key type="numeric" value="6144" />
+    <val type="dict" id="-1268616764" >
+      <entry>
+        <key type="numeric" value="2" />
+        <val type="dict" id="-1268616628" >
+          <entry>
+            <key type="string" value="comment" />
+            <val type="string" value="send PDO1 after each SYNC" />
+          </entry>
+        </val>
+      </entry>
+      <entry>
+        <key type="numeric" value="3" />
+        <val type="dict" id="-1268616492" >
+          <entry>
+            <key type="string" value="comment" />
+            <val type="string" value="10mS" />
+          </entry>
+        </val>
+      </entry>
+      <entry>
+        <key type="numeric" value="5" />
+        <val type="dict" id="-1268616356" >
+          <entry>
+            <key type="string" value="comment" />
+            <val type="string" value="not used with SYNC" />
+          </entry>
+        </val>
+      </entry>
+    </val>
+  </entry>
+  <entry>
+    <key type="numeric" value="5120" />
+    <val type="dict" id="-1268616220" >
+      <entry>
+        <key type="numeric" value="1" />
+        <val type="dict" id="-1268616084" >
+          <entry>
+            <key type="string" value="comment" />
+            <val type="string" value="" />
+          </entry>
+        </val>
+      </entry>
+      <entry>
+        <key type="numeric" value="2" />
+        <val type="dict" id="-1268615948" >
+          <entry>
+            <key type="string" value="comment" />
+            <val type="string" value="" />
+          </entry>
+        </val>
+      </entry>
+      <entry>
+        <key type="numeric" value="3" />
+        <val type="dict" id="-1268615812" >
+          <entry>
+            <key type="string" value="comment" />
+            <val type="string" value="" />
+          </entry>
+        </val>
+      </entry>
+      <entry>
+        <key type="numeric" value="4" />
+        <val type="dict" id="-1268615676" >
+          <entry>
+            <key type="string" value="comment" />
+            <val type="string" value="" />
+          </entry>
+        </val>
+      </entry>
+      <entry>
+        <key type="numeric" value="5" />
+        <val type="dict" id="-1268615540" >
+          <entry>
+            <key type="string" value="comment" />
+            <val type="string" value="" />
+          </entry>
+        </val>
+      </entry>
+      <entry>
+        <key type="string" value="callback" />
+        <val type="False" value="" />
+      </entry>
+    </val>
+  </entry>
+  <entry>
+    <key type="numeric" value="6145" />
+    <val type="dict" id="-1268615404" >
+      <entry>
+        <key type="numeric" value="2" />
+        <val type="dict" id="-1268615268" >
+          <entry>
+            <key type="string" value="comment" />
+            <val type="string" value="Invio ogni 2 SYNC" />
+          </entry>
+        </val>
+      </entry>
+      <entry>
+        <key type="numeric" value="3" />
+        <val type="dict" id="-1268615132" >
+          <entry>
+            <key type="string" value="comment" />
+            <val type="string" value="10 mS" />
+          </entry>
+        </val>
+      </entry>
+    </val>
+  </entry>
+  <entry>
+    <key type="numeric" value="4114" />
+    <val type="dict" id="-1268614996" >
+      <entry>
+        <key type="string" value="comment" />
+        <val type="string" value="for timestamp" />
+      </entry>
+    </val>
+  </entry>
+  <entry>
+    <key type="numeric" value="6657" />
+    <val type="dict" id="-1268614860" >
+      <entry>
+        <key type="numeric" value="1" />
+        <val type="dict" id="-1268614724" >
+          <entry>
+            <key type="string" value="comment" />
+            <val type="string" value="Rx dal punto di vista del master, MCA lo trasmette" />
+          </entry>
+        </val>
+      </entry>
+    </val>
+  </entry>
+  <entry>
+    <key type="numeric" value="5632" />
+    <val type="dict" id="-1268614588" >
+      <entry>
+        <key type="numeric" value="1" />
+        <val type="dict" id="-1268614452" >
+          <entry>
+            <key type="string" value="comment" />
+            <val type="string" value="Tx dal punto di vista del master, MC lo riceve" />
+          </entry>
+        </val>
+      </entry>
+    </val>
+  </entry>
+  <entry>
+    <key type="numeric" value="4120" />
+    <val type="dict" id="-1268614316" >
+      <entry>
+        <key type="numeric" value="0" />
+        <val type="dict" id="-1268614180" >
+          <entry>
+            <key type="string" value="comment" />
+            <val type="string" value="4 pseudorandomic numbers:" />
+          </entry>
+        </val>
+      </entry>
+      <entry>
+        <key type="numeric" value="1" />
+        <val type="dict" id="-1268614044" >
+          <entry>
+            <key type="string" value="comment" />
+            <val type="string" value="" />
+          </entry>
+        </val>
+      </entry>
+      <entry>
+        <key type="numeric" value="2" />
+        <val type="dict" id="-1268613908" >
+          <entry>
+            <key type="string" value="comment" />
+            <val type="string" value="" />
+          </entry>
+        </val>
+      </entry>
+    </val>
+  </entry>
+</attr>
+<attr name="UserMapping" type="dict" id="-1268613772" >
+  <entry>
+    <key type="numeric" value="8193" />
+    <val type="dict" id="-1268613636" >
+      <entry>
+        <key type="string" value="need" />
+        <val type="False" value="" />
+      </entry>
+      <entry>
+        <key type="string" value="values" />
+        <val type="list" id="-1214456756" >
+          <item type="dict" id="-1268613500" >
+            <entry>
+              <key type="string" value="access" />
+              <val type="string" value="ro" />
+            </entry>
+            <entry>
+              <key type="string" value="pdo" />
+              <val type="True" value="" />
+            </entry>
+            <entry>
+              <key type="string" value="type" />
+              <val type="numeric" value="5" />
+            </entry>
+            <entry>
+              <key type="string" value="name" />
+              <val type="string">LifeSignal</val>
+            </entry>
+          </item>
+        </val>
+      </entry>
+      <entry>
+        <key type="string" value="name" />
+        <val type="string">LifeSignal</val>
+      </entry>
+      <entry>
+        <key type="string" value="struct" />
+        <val type="numeric" value="1" />
+      </entry>
+    </val>
+  </entry>
+</attr>
+<attr name="DS302" type="dict" id="-1268613364" >
+</attr>
+<attr name="ProfileName" type="string" value="DS-301" />
+<attr name="Type" type="string">slave</attr>
+<attr name="ID" type="numeric" value="0" />
+<attr name="Name" type="string">SillySlave</attr>
+</PyObject>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/SillySlave/main.c	Mon Feb 18 17:14:22 2008 +0100
@@ -0,0 +1,74 @@
+/*
+Copyright (C): Giuseppe Massimo BERTANI
+gmbertani@users.sourceforge.net
+
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/**
+ * @file main.c
+ * @author GMB
+ * @date 17/1/08
+ *
+ * This file is part of SillySlave demo for CANfestival
+ * open source CANopen stack.
+ */ 
+
+
+#include "main.h"                   
+#include "slave.h"
+
+#if !defined(WIN32) || defined(__CYGWIN__)
+void catch_signal(int sig)
+{
+  signal(SIGTERM, catch_signal);
+  signal(SIGINT, catch_signal);
+  
+  printf("Got Signal %d\n",sig);
+}
+#endif
+
+
+/**
+ * Please edit main.h defines before compiling
+ */ 
+int main(int argc,char **argv)
+{
+    char* LibraryPath= DRIVER_LIBRARY; 
+    
+#if !defined(WIN32) || defined(__CYGWIN__)
+    /* install signal handler for manual break */
+	signal(SIGTERM, catch_signal);
+	signal(SIGINT, catch_signal);
+#endif
+
+#ifndef NOT_USE_DYNAMIC_LOADING
+	LoadCanDriver(LibraryPath);
+#endif		
+
+    
+    if(InitCANdevice( BUS, BAUDRATE,  NODE_SLAVE ) < 0)
+    {
+        printf("\nInitCANdevice() failed, exiting.\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/SillySlave/main.h	Mon Feb 18 17:14:22 2008 +0100
@@ -0,0 +1,65 @@
+/*
+Copyright (C): Giuseppe Massimo BERTANI
+gmbertani@users.sourceforge.net
+
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/**
+ * @file main.h
+ * @author GMB
+ * @date 17/1/08
+ *
+ * This file is part of SillySlave demo for CANfestival
+ * open source CANopen stack.
+ */ 
+
+
+
+#ifndef _MAIN_H
+ #define _MAIN_H
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+#include <windows.h>
+#include "getopt.h"
+void pause(void)
+{
+	system("PAUSE");
+}
+#else
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#endif
+
+#include "canfestival.h"
+
+/*
+ * Please tune the following defines to suit your needs:
+ */
+#define NODE_MASTER 0x1        
+#define NODE_SLAVE  0x12        
+#define DRIVER_LIBRARY "libcanfestival_can_kvaser.so"
+#define BAUDRATE 250000
+#define BUS 0
+
+#endif /* _MAIN_H */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/SillySlave/slave.c	Mon Feb 18 17:14:22 2008 +0100
@@ -0,0 +1,164 @@
+/*
+Copyright (C): Giuseppe Massimo BERTANI
+gmbertani@users.sourceforge.net
+
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/**
+ * @file slave.c
+ * @author GMB
+ * @date 17/1/08
+ *
+ * This file is part of SillySlave demo for CANfestival
+ * open source CANopen stack.
+ */ 
+
+#include "SillySlave.h"
+#include "slave.h"
+#include "main.h"
+
+
+static UNS8 slaveNode = 0;  
+
+void InitNode(CO_Data* d, UNS32 id)
+{
+    /* Defining the node Id */
+    setNodeId(&SillySlave_Data, slaveNode);
+    /* CAN init */
+    setState(&SillySlave_Data, Initialisation);
+}
+
+INTEGER8 InitCANdevice( UNS8 bus, UNS32 baudrate, UNS8 node )
+{ 
+char busName[2];
+char baudRate[7];
+s_BOARD board;
+
+    sprintf(busName, "%u", bus);
+    sprintf(baudRate, "%u", baudrate);
+    board.busname = busName;
+    board.baudrate = baudRate;
+
+    slaveNode = node;
+
+    SillySlave_Data.heartbeatError = SillySlave_heartbeatError;
+    SillySlave_Data.initialisation = SillySlave_initialisation;
+    SillySlave_Data.preOperational = SillySlave_preOperational;
+    SillySlave_Data.operational = SillySlave_operational;
+    SillySlave_Data.stopped = SillySlave_stopped;
+    SillySlave_Data.post_sync = SillySlave_post_sync;
+    SillySlave_Data.post_TPDO = SillySlave_post_TPDO;
+    SillySlave_Data.storeODSubIndex = SillySlave_storeODSubIndex;
+    SillySlave_Data.post_emcy = SillySlave_post_emcy;
+    
+    if(!canOpen(&board, &SillySlave_Data))
+    {
+        printf("\n\aInitCANdevice() CAN bus %s opening error, baudrate=%s\n",board.busname, board.baudrate);
+        return -1;
+    }
+
+
+    printf("\nInitCANdevice(), canOpen() OK, starting timer loop...\n");
+
+    /* Start timer thread */
+    StartTimerLoop(&InitNode); 
+    
+	/* wait Ctrl-C */
+	pause();
+	printf("\nFinishing.\n");
+	
+	/* Stop slave */
+    setState(&SillySlave_Data, Stopped);
+	
+	/* Stop timer thread */
+	StopTimerLoop();
+    return 0;
+}
+
+void SillySlave_heartbeatError(CO_Data* d, UNS8 heartbeatID)
+{
+    printf("SillySlave_heartbeatError %d\n", heartbeatID);
+}
+
+void SillySlave_initialisation(CO_Data* d )
+{
+    UNS32 PDO1_COBID = 0x0180 + NODE_MASTER; 
+    UNS8 size = sizeof(PDO1_COBID); 
+    
+    printf("SillySlave_initialisation\n");
+
+    /* sets TXPDO1 COB-ID to match master node ID */
+    writeLocalDict( 
+            &SillySlave_Data,       /*CO_Data* d*/
+            0x1800,                 /*UNS16 index*/
+            0x01,                   /*UNS8 subind*/ 
+            &PDO1_COBID,            /*void * pSourceData,*/ 
+            &size,                  /* UNS8 * pExpectedSize*/
+            RW);                    /* UNS8 checkAccess */
+            
+    /* value sent to master at each SYNC received */
+    LifeSignal = 0;
+}
+
+void SillySlave_preOperational(CO_Data* d)
+{
+    printf("SillySlave_preOperational\n");
+}
+
+void SillySlave_operational(CO_Data* d)
+{
+    printf("SillySlave_operational\n");
+}
+
+void SillySlave_stopped(CO_Data* d)
+{
+    printf("SillySlave_stopped\n");
+}
+
+void SillySlave_post_sync(CO_Data* d)
+{
+    printf("SillySlave_post_sync: \n");
+    LifeSignal++;
+}
+
+void SillySlave_post_TPDO(CO_Data* d)
+{
+    printf("SillySlave_post_TPDO: \n");
+    printf("LifeSignal = %u\n", LifeSignal);    
+}
+
+void SillySlave_storeODSubIndex(CO_Data* d, UNS16 wIndex, UNS8 bSubindex)
+{
+    /*TODO : 
+     * - call getODEntry for index and subindex, 
+     * - save content to file, database, flash, nvram, ...
+     * 
+     * To ease flash organisation, index of variable to store
+     * can be established by scanning d->objdict[d->ObjdictSize]
+     * for variables to store.
+     * 
+     * */
+    printf("SillySlave_storeODSubIndex : %4.4x %2.2xh\n", wIndex,  bSubindex);
+}
+
+void SillySlave_post_emcy(CO_Data* d, UNS8 nodeID, UNS16 errCode, UNS8 errReg)
+{
+    printf("Slave received EMCY message. Node: %2.2xh  ErrorCode: %4.4x  ErrorRegister: %2.2xh\n", nodeID, errCode, errReg);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/SillySlave/slave.h	Mon Feb 18 17:14:22 2008 +0100
@@ -0,0 +1,51 @@
+/*
+Copyright (C): Giuseppe Massimo BERTANI
+gmbertani@users.sourceforge.net
+
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/**
+ * @file slave.h
+ * @author GMB
+ * @date 17/1/08
+ *
+ * This file is part of SillySlave demo for CANfestival
+ * open source CANopen stack.
+ */ 
+
+
+
+#include "data.h"
+
+INTEGER8 InitCANdevice( UNS8 bus, UNS32 baudrate, UNS8 node );
+
+void SillySlave_heartbeatError(CO_Data* d, UNS8);
+
+UNS8 SillySlave_canSend(Message *);
+
+void SillySlave_initialisation(CO_Data* d);
+void SillySlave_preOperational(CO_Data* d);
+void SillySlave_operational(CO_Data* d);
+void SillySlave_stopped(CO_Data* d);
+
+void SillySlave_post_sync(CO_Data* d);
+void SillySlave_post_TPDO(CO_Data* d);
+void SillySlave_storeODSubIndex(CO_Data* d, UNS16 wIndex, UNS8 bSubindex);
+void SillySlave_post_emcy(CO_Data* d, UNS8 nodeID, UNS16 errCode, UNS8 errReg);
+