CosateQ contribution.
authoredouard
Fri, 12 Nov 2010 22:24:06 +0100
changeset 629 b9274b595650
parent 628 9e496a2aadca
child 630 96919642e99c
CosateQ contribution.
CanFestival-3.vc8.sln
configure
copcican_comedi_howto.txt
copcican_linux_howto.txt
drivers/can_copcican_comedi/Makefile.in
drivers/can_copcican_comedi/can_copcican_comedi.c
drivers/can_copcican_comedi/co_pcicanops.h
drivers/can_copcican_linux/Makefile.in
drivers/can_copcican_linux/can_copcican_linux.c
drivers/can_copcican_linux/co_pcicanops.h
drivers/can_copcican_win32/ReadMe.txt
drivers/can_copcican_win32/can_copcican_win32.cpp
drivers/can_copcican_win32/can_copcican_win32.def
drivers/can_copcican_win32/can_copcican_win32.vcxproj
drivers/can_copcican_win32/can_copcican_win32.vcxproj.filters
drivers/can_copcican_win32/can_copcican_win32.vcxproj.user
drivers/can_copcican_win32/dllmain.cpp
drivers/can_copcican_win32/stdafx.cpp
drivers/can_copcican_win32/stdafx.h
drivers/can_copcican_win32/targetver.h
drivers/timers_kernel/timers_kernel.c
drivers/timers_kernel_xeno/Makefile.in
drivers/timers_kernel_xeno/timers_kernel_xeno.c
drivers/timers_win32/timers_win32.c
drivers/unix/Makefile.in
drivers/unix/unix.c
drivers/win32/win32.c
examples/TestMasterSlave/TestMasterSlave.c
examples/test_copcican_comedi/Makefile.in
examples/test_copcican_comedi/insert.sh
examples/test_copcican_comedi/test_copcican_comedi.c
examples/test_copcican_linux/Makefile.in
examples/test_copcican_linux/test_copcican_linux.c
include/can_driver.h
include/objacces.h
include/timers_kernel_xeno/timerscfg.h
src/Makefile.in
src/objacces.c
src/pdo.c
src/symbols.c
src/timer.c
--- a/CanFestival-3.vc8.sln	Fri Nov 12 22:02:32 2010 +0100
+++ b/CanFestival-3.vc8.sln	Fri Nov 12 22:24:06 2010 +0100
@@ -1,18 +1,16 @@
-
-Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual C++ Express 2008
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CanFestival-3", "CanFestival-3.vc8.vcproj", "{50EF2507-9B87-4525-8B19-80EB42E67079}"
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CanFestival-3", "CanFestival-3.vc8.vcxproj", "{50EF2507-9B87-4525-8B19-80EB42E67079}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "can_uvccm_win32", "drivers\can_uvccm_win32\can_uvccm_win32.vcproj", "{39E3300A-29B4-4AA7-AF62-3B181FC26155}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "can_uvccm_win32", "drivers\can_uvccm_win32\can_uvccm_win32.vcxproj", "{782632D2-B467-DF90-C86E-D767972BAA59}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "can_peak_win32", "drivers\can_peak_win32\can_peak_win32.vcproj", "{732EC5B6-C6F1-4783-9BC8-924FFF67BF5A}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "can_peak_win32", "drivers\can_peak_win32\can_peak_win32.vcxproj", "{C943EB26-ADEA-0DCD-E581-8BF52F0F20F5}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestMasterSlave", "examples\TestMasterSlave\TestMasterSlave.vcproj", "{B51A176D-5320-4534-913B-3025CED5B27E}"
-	ProjectSection(ProjectDependencies) = postProject
-		{50EF2507-9B87-4525-8B19-80EB42E67079} = {50EF2507-9B87-4525-8B19-80EB42E67079}
-	EndProjectSection
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestMasterSlave", "examples\TestMasterSlave\TestMasterSlave.vcxproj", "{B51A176D-5320-4534-913B-3025CED5B27E}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "can_ixxat_win32", "drivers\can_ixxat_win32\can_ixxat_win32.vc8.vcproj", "{8F57E7FF-1B73-4134-A2B2-9C0EADB2AEFB}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "can_ixxat_win32", "drivers\can_ixxat_win32\can_ixxat_win32.vc8.vcxproj", "{8F57E7FF-1B73-4134-A2B2-9C0EADB2AEFB}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "can_copcican_win32", "drivers\can_copcican_win32\can_copcican_win32.vcxproj", "{A18C416F-3CBB-4744-BA24-FA5C5F3CBE0D}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -30,22 +28,22 @@
 		{50EF2507-9B87-4525-8B19-80EB42E67079}.Release UNICODE|Win32.Build.0 = Release|Win32
 		{50EF2507-9B87-4525-8B19-80EB42E67079}.Release|Win32.ActiveCfg = Release|Win32
 		{50EF2507-9B87-4525-8B19-80EB42E67079}.Release|Win32.Build.0 = Release|Win32
-		{39E3300A-29B4-4AA7-AF62-3B181FC26155}.Debug UNICODE|Win32.ActiveCfg = Debug UNICODE|Win32
-		{39E3300A-29B4-4AA7-AF62-3B181FC26155}.Debug UNICODE|Win32.Build.0 = Debug UNICODE|Win32
-		{39E3300A-29B4-4AA7-AF62-3B181FC26155}.Debug|Win32.ActiveCfg = Debug|Win32
-		{39E3300A-29B4-4AA7-AF62-3B181FC26155}.Debug|Win32.Build.0 = Debug|Win32
-		{39E3300A-29B4-4AA7-AF62-3B181FC26155}.Release UNICODE|Win32.ActiveCfg = Release UNICODE|Win32
-		{39E3300A-29B4-4AA7-AF62-3B181FC26155}.Release UNICODE|Win32.Build.0 = Release UNICODE|Win32
-		{39E3300A-29B4-4AA7-AF62-3B181FC26155}.Release|Win32.ActiveCfg = Release|Win32
-		{39E3300A-29B4-4AA7-AF62-3B181FC26155}.Release|Win32.Build.0 = Release|Win32
-		{732EC5B6-C6F1-4783-9BC8-924FFF67BF5A}.Debug UNICODE|Win32.ActiveCfg = Debug UNICODE|Win32
-		{732EC5B6-C6F1-4783-9BC8-924FFF67BF5A}.Debug UNICODE|Win32.Build.0 = Debug UNICODE|Win32
-		{732EC5B6-C6F1-4783-9BC8-924FFF67BF5A}.Debug|Win32.ActiveCfg = Debug|Win32
-		{732EC5B6-C6F1-4783-9BC8-924FFF67BF5A}.Debug|Win32.Build.0 = Debug|Win32
-		{732EC5B6-C6F1-4783-9BC8-924FFF67BF5A}.Release UNICODE|Win32.ActiveCfg = Release UNICODE|Win32
-		{732EC5B6-C6F1-4783-9BC8-924FFF67BF5A}.Release UNICODE|Win32.Build.0 = Release UNICODE|Win32
-		{732EC5B6-C6F1-4783-9BC8-924FFF67BF5A}.Release|Win32.ActiveCfg = Release|Win32
-		{732EC5B6-C6F1-4783-9BC8-924FFF67BF5A}.Release|Win32.Build.0 = Release|Win32
+		{782632D2-B467-DF90-C86E-D767972BAA59}.Debug UNICODE|Win32.ActiveCfg = Debug UNICODE|Win32
+		{782632D2-B467-DF90-C86E-D767972BAA59}.Debug UNICODE|Win32.Build.0 = Debug UNICODE|Win32
+		{782632D2-B467-DF90-C86E-D767972BAA59}.Debug|Win32.ActiveCfg = Debug|Win32
+		{782632D2-B467-DF90-C86E-D767972BAA59}.Debug|Win32.Build.0 = Debug|Win32
+		{782632D2-B467-DF90-C86E-D767972BAA59}.Release UNICODE|Win32.ActiveCfg = Release UNICODE|Win32
+		{782632D2-B467-DF90-C86E-D767972BAA59}.Release UNICODE|Win32.Build.0 = Release UNICODE|Win32
+		{782632D2-B467-DF90-C86E-D767972BAA59}.Release|Win32.ActiveCfg = Release|Win32
+		{782632D2-B467-DF90-C86E-D767972BAA59}.Release|Win32.Build.0 = Release|Win32
+		{C943EB26-ADEA-0DCD-E581-8BF52F0F20F5}.Debug UNICODE|Win32.ActiveCfg = Debug UNICODE|Win32
+		{C943EB26-ADEA-0DCD-E581-8BF52F0F20F5}.Debug UNICODE|Win32.Build.0 = Debug UNICODE|Win32
+		{C943EB26-ADEA-0DCD-E581-8BF52F0F20F5}.Debug|Win32.ActiveCfg = Debug|Win32
+		{C943EB26-ADEA-0DCD-E581-8BF52F0F20F5}.Debug|Win32.Build.0 = Debug|Win32
+		{C943EB26-ADEA-0DCD-E581-8BF52F0F20F5}.Release UNICODE|Win32.ActiveCfg = Release UNICODE|Win32
+		{C943EB26-ADEA-0DCD-E581-8BF52F0F20F5}.Release UNICODE|Win32.Build.0 = Release UNICODE|Win32
+		{C943EB26-ADEA-0DCD-E581-8BF52F0F20F5}.Release|Win32.ActiveCfg = Release|Win32
+		{C943EB26-ADEA-0DCD-E581-8BF52F0F20F5}.Release|Win32.Build.0 = Release|Win32
 		{B51A176D-5320-4534-913B-3025CED5B27E}.Debug UNICODE|Win32.ActiveCfg = Debug|Win32
 		{B51A176D-5320-4534-913B-3025CED5B27E}.Debug UNICODE|Win32.Build.0 = Debug|Win32
 		{B51A176D-5320-4534-913B-3025CED5B27E}.Debug|Win32.ActiveCfg = Debug|Win32
@@ -62,6 +60,14 @@
 		{8F57E7FF-1B73-4134-A2B2-9C0EADB2AEFB}.Release UNICODE|Win32.Build.0 = Release|Win32
 		{8F57E7FF-1B73-4134-A2B2-9C0EADB2AEFB}.Release|Win32.ActiveCfg = Release|Win32
 		{8F57E7FF-1B73-4134-A2B2-9C0EADB2AEFB}.Release|Win32.Build.0 = Release|Win32
+		{A18C416F-3CBB-4744-BA24-FA5C5F3CBE0D}.Debug UNICODE|Win32.ActiveCfg = Debug|Win32
+		{A18C416F-3CBB-4744-BA24-FA5C5F3CBE0D}.Debug UNICODE|Win32.Build.0 = Debug|Win32
+		{A18C416F-3CBB-4744-BA24-FA5C5F3CBE0D}.Debug|Win32.ActiveCfg = Debug|Win32
+		{A18C416F-3CBB-4744-BA24-FA5C5F3CBE0D}.Debug|Win32.Build.0 = Debug|Win32
+		{A18C416F-3CBB-4744-BA24-FA5C5F3CBE0D}.Release UNICODE|Win32.ActiveCfg = Release|Win32
+		{A18C416F-3CBB-4744-BA24-FA5C5F3CBE0D}.Release UNICODE|Win32.Build.0 = Release|Win32
+		{A18C416F-3CBB-4744-BA24-FA5C5F3CBE0D}.Release|Win32.ActiveCfg = Release|Win32
+		{A18C416F-3CBB-4744-BA24-FA5C5F3CBE0D}.Release|Win32.Build.0 = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
--- a/configure	Fri Nov 12 22:02:32 2010 +0100
+++ b/configure	Fri Nov 12 22:24:06 2010 +0100
@@ -2,41 +2,41 @@
 
 #
 # Copyright (C) 2004 Edouard TISSERRANT, Laurent BESSARD
-# Based on Gabriel Gerhardsson's cacheprobe configure script. 
-# 
-# This file is part of CanFestival, a library implementing CanOpen Stack. 
-# 
+# Based on Gabriel Gerhardsson's cacheprobe configure script.
+#
+# This file is part of CanFestival, a library implementing 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
-# 
+#
 
 ###########################################################################
 #                       DEFAULT CANFESTIVAL DEFINES                       #
 ###########################################################################
 
-# Number of can bus to use 
+# Number of can bus to use
 MAX_CAN_BUS_ID=1
 
 # max bytes to transmit by SDO Put 4 if you only support expedited transfert.
 #For a normal transfert, (usually for a string), put the maximum string size to transfer.
 SDO_MAX_LENGTH_TRANSFERT=32
 
-# Number of SDO from differents nodes that the node can manage concurrently.   
+# Number of SDO from differents nodes that the node can manage concurrently.
 #for a slave node, usually put 1.
 SDO_MAX_SIMULTANEOUS_TRANSFERTS=4
 
-# Used for NMTable[bus][nodeId]	  
+# Used for NMTable[bus][nodeId]
 # You can put less of 128 if on the netwo
 # are connected only smaller nodeId node.
 NMT_MAX_NODE_ID=128
@@ -78,7 +78,7 @@
 # Install prefix
 SUB_PREFIX=
 
-# Used for C compiler test/detection 
+# Used for C compiler test/detection
 CFLAGS=
 test=conftest
 rm -f $test $test.c
@@ -96,7 +96,7 @@
 ###########################################################################
 while [ $# -ge 1 ]; do
 	optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
-	
+
 	case $1 in
 	--cc=*)		CC=$optarg;;
 	--cxx=*)	CXX=$optarg;;
@@ -145,11 +145,11 @@
 		echo	"               \"win32\" for win32 systems (native, mingw or VC++)"
 		echo	"               \"hcs12\" for HCS12 micro-controller"
 		echo 	" --can=foo	Use 'foo' as CAN driver"
-		echo	"               \"anagate_linux\" use AnaGate CAN(duo) driver for linux"	
-		echo	"               \"anagate_win32\" use AnaGate CAN(duo) driver for win32"				
+		echo	"               \"anagate_linux\" use AnaGate CAN(duo) driver for linux"
+		echo	"               \"anagate_win32\" use AnaGate CAN(duo) driver for win32"
 		echo	"               \"peak_linux\" use Linux build host installed Peak driver and library"
 		echo	"                 see http://www.peak-system.com/linux/"
-		echo	"               \"peak_win32\" use win32 PcanLight Peak driver and library with Cygwin" 
+		echo	"               \"peak_win32\" use win32 PcanLight Peak driver and library with Cygwin"
 		echo	"                 see http://www.peak-system.com/themen/download_gb.html"
 		echo	"               \"virtual\" use unix pipe based virtual can driver"
 		echo	"               \"virtual_kernel\" use kernel module virtual can driver"
@@ -159,7 +159,11 @@
 		echo	"                 see http://www.ocera.org/download/components/WP7/lincan-0.3.3.html"
 		echo	"               \"can4linux\" can4linux driver"
 		echo	"                 see http://www.port.de/engl/canprod/hw_can4linux.html"
-		echo 	" --timers=foo  Use 'foo' as TIMERS driver (can be 'unix', 'xeno', 'rtai' or 'kernel')"
+		echo	"               \"copcican_linux\" user space driver interface for CO-PCICAN card"
+		echo	"                 see http://www.cosateq.com/"
+		echo	"               \"copcican_comedi\" COMEDI driver interface for CO-PCICAN card"
+		echo	"                 see http://www.cosateq.com/"
+		echo 	" --timers=foo  Use 'foo' as TIMERS driver (can be 'unix', 'xeno', 'rtai', 'kernel' or 'kernel_xeno')"
 		echo 	" --wx=foo      Force result of WxWidgets detection (0 or 1)"
 		echo 	" --binutils=path   Override binutils path detection (as regards \$CC content)"
 		echo 	" --disable-dll Disable run-time dynamic linking of can, led and nvram drivers"
@@ -273,18 +277,24 @@
 # Try to guess can
 if [ "$SUB_CAN_DRIVER" = "" ]; then
 	if [ "$SUB_TARGET" = "unix" ]; then
-		if [ -e /usr/lib/libpcan.so ]; then 
+		if [ -e /usr/lib/libpcan.so ]; then
 			echo "Choosing installed Peak driver as CAN driver."
 			SUB_CAN_DRIVER=peak_linux
 		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 
+			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 [ -e /usr/local/lib/libAnaGateAPIDLL.so ]; then 
+		elif [ -e /usr/local/lib/libAnaGateAPIDLL.so ]; then
 			echo "Choosing installed AnaGate driver as CAN driver. (unix)"
 			SUB_CAN_DRIVER=anagate_linux
+		elif [ -e /usr/local/lib/libcanfestival_can_copcican_linux.so ]; then
+			echo "Choosing installed CO-PCICAN driver as CAN driver. (unix)"
+			SUB_CAN_DRIVER=copcican_linux
+		elif [ -e /usr/local/lib/libcanfestival_can_copcican_comedi.so ]; then
+			echo "Choosing installed CO-PCICAN driver as CAN driver. (unix)"
+			SUB_CAN_DRIVER=copcican_comedi
 		elif [ "$SUB_OS_NAME" = "CYGWIN" -a "$KVASER_DLL_PATH" != "" ]; then
 			echo "Choosing installed Kvaser driver as CAN driver. (cygwin)"
 			SUB_CAN_DRIVER=kvaser
@@ -309,7 +319,7 @@
 
 # Warn for unstalled peak driver if choosen
 if [ "$SUB_CAN_DRIVER" = "peak" ]; then
-	if [ ! -e /usr/lib/libpcan.so ]; then 
+	if [ ! -e /usr/lib/libpcan.so ]; then
 		echo "Peak driver hasn't been installed !"
 		exit -1
 	fi
@@ -317,21 +327,29 @@
 
 # Warn for unstalled peak driver if choosen
 if [ "$SUB_CAN_DRIVER" = "anagate_linux" ]; then
-	if [ ! -e /usr/local/lib/libAnaGateAPIDLL.so ]; then 
+	if [ ! -e /usr/local/lib/libAnaGateAPIDLL.so ]; then
 		echo "AnaGateCAN driver hasn't been installed !"
 		exit -1
 	fi
 fi
 
+# Warn for unstalled CO-PCICAN driver if choosen
+if [ "$SUB_CAN_DRIVER" = "copcican_linux" ]; then
+	if [ ! -e /usr/local/lib/libcanfestival_can_copcican_linux.so ]; then
+		echo "CO-PCICAN driver hasn't been installed !"
+		exit -1
+	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 
+        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 
+        if [ ! -e /usr/lib/libcanlib.so ]; then
             echo "Kvaser driver hasn't been installed (unix)"
             exit -1
         fi
@@ -348,20 +366,20 @@
 	# search for gcc hcs12 compiler m6811-elf-gcc or m68hc12-gcc ?
 	if [ "$CC" = "" ]; then
 		which m6811-elf-gcc >/dev/null 2>&1
-		if (( $? )); then 
+		if (( $? )); then
 			which m68hc12-gcc >/dev/null 2>&1
-			if (( $? )); then 
+			if (( $? )); then
 				echo "Please use --cc flag to specify compiler"
 				exit 0
 			else
-				CC=m68hc12-gcc 
+				CC=m68hc12-gcc
 			fi
 		else
 			CC=m6811-elf-gcc
 			SUB_PROG_CFLAGS=-m68hc12
 		fi
 	fi
-fi	
+fi
 
 #### CAN_DRIVER ####
 
@@ -377,7 +395,7 @@
                 SUB_PROG_CFLAGS=$SUB_PROG_CFLAGS\ -I$KVASER_INCLUDE_PATH
             fi
         fi
-    fi        
+    fi
 fi
 
 if [ "$SUB_CAN_DRIVER" = "peak_linux" ]; then
@@ -469,6 +487,20 @@
 	fi
 fi
 
+if [ "$SUB_TIMERS_DRIVER" = "kernel_xeno" ]; then
+	DISABLE_DLL=1
+	if [ "$SUB_KERNELDIR" = "" ]; then
+		# use directory of current kernel
+		SUB_KERNELDIR=/lib/modules/$(uname -r)/build
+	fi
+
+	# Also get the xenomai config
+	RT_LIB_DIR=`$XENO_CONFIG --library-dir`\ -Wl,-rpath\ `$XENO_CONFIG --library-dir`
+    SUB_EXE_CFLAGS=$SUB_EXE_CFLAGS\ `$XENO_CONFIG --xeno-ldflags`\ -L$RT_LIB_DIR\ -lnative\ -lrtdm
+	SUB_PROG_CFLAGS=$SUB_PROG_CFLAGS\ -DUSE_XENO\ `$XENO_CONFIG --xeno-cflags`
+    RTCAN_SOCKET=1
+fi
+
 if [ "$SUB_TIMERS_DRIVER" = "none" ]; then
 	SUB_TIMERS_DRIVER=
 fi
@@ -489,7 +521,7 @@
 		echo "Checking for ${CC2}... No."
 	fi
 	rm -f $test.c $test.o
-	
+
 	# Check for first compiler, CC1
 	cat > $test.c <<EOF
 	int main() { return 0; }
@@ -538,7 +570,7 @@
 	if [ "$SUB_OS_NAME" = "CYGWIN" ]; then
 		SUB_PROG_CFLAGS="-mno-cygwin"
 	fi
-fi	
+fi
 
 if [ "$SUB_TARGET" = "unix" ]; then
 	if [ "$LD" = "" ]; then
@@ -551,12 +583,12 @@
 # Guess prefix as regard cross compiling target machine
 if [ "$SUB_PREFIX" = "" ]; then
 	$CC -dumpspecs |grep -A 1 'cross_compile'|grep -q 1
-	if (( $? )); then 
+	if (( $? )); then
 		SUB_PREFIX=/usr/local
 		echo "Not cross-compiling. Will install in $SUB_PREFIX";
 	else
 		SUB_PREFIX=/usr/`$CC -dumpmachine | tr -d '\r\n'`
-		echo "This is a cross-compiler. Will install in $SUB_PREFIX";			
+		echo "This is a cross-compiler. Will install in $SUB_PREFIX";
 	fi
 fi
 
@@ -642,7 +674,7 @@
 else
 echo "#define $i ${!i}" >> include/config.h
 fi
-done	
+done
 echo "" >> include/config.h
 
 for i in \
@@ -666,7 +698,7 @@
 
 save_ifs="$IFS"; IFS=','
 
-for DEBUG_METHOD in $DEBUG; 
+for DEBUG_METHOD in $DEBUG;
 	do
 	    IFS="$save_ifs"
 	    case $DEBUG_METHOD in
@@ -679,7 +711,7 @@
 	    	  echo "Possible Debug's methods are : \"ERR\", \"WAR\", \"MSG\", \"PDO\""
 	    	  exit -1
 	    	  ;;
-	esac	
+	esac
 done
 
 if [ $WAR ]; then
@@ -720,7 +752,7 @@
 	else
 		SUB_EXE_CFLAGS=$SUB_EXE_CFLAGS\ -ldl
 	fi
-	
+
 fi
 
 
@@ -767,7 +799,13 @@
 
 if [ "$SUB_TARGET" = "unix" -a "$SUB_TIMERS_DRIVER" = "kernel" ]; then
 	MAKEFILES=$MAKEFILES\
-\	examples/kerneltest/Makefile.in
+\	examples/kerneltest/Makefile.in\
+\	examples/test_copcican_comedi/Makefile.in
+
+elif [ "$SUB_TARGET" = "unix" -a "$SUB_TIMERS_DRIVER" = "kernel_xeno" ]; then
+	MAKEFILES=$MAKEFILES\
+\	examples/kerneltest/Makefile.in\
+\	examples/test_copcican_comedi/Makefile.in
 
 elif [ "$SUB_TARGET" = "unix" ]; then
 	MAKEFILES=$MAKEFILES\
@@ -775,7 +813,8 @@
 \	examples/TestMasterSlave/Makefile.in\
 \	examples/TestMasterSlaveLSS/Makefile.in\
 \	examples/SillySlave/Makefile.in\
-\	examples/TestMasterMicroMod/Makefile.in
+\	examples/TestMasterMicroMod/Makefile.in\
+\	examples/test_copcican_linux/Makefile.in
 fi
 
 if [ "$SUB_TARGET" = "win32" ]; then
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/copcican_comedi_howto.txt	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,55 @@
+HOW TO configure CanFestival for a CO-PCICAN card for COMEDI in the kernel (optionally with Xenomai):
+
+
+
+pre-actions:
+- install the CO-PCICAN card
+- install and load COMEDI and the corresponding driver co_pcican.ko
+  (COMEDI sources are expected in /usr/src/comedi)
+
+- optionally: install the Xenomai package
+  (Xenomai sources are expected in /usr/xenomai)
+
+
+
+- unpack the package to your target (if not already done)
+
+- perform package configuration:
+  sh ./configure --can=copcican_comedi --timers=kernel --kerneldir='/lib/modules/$(shell uname -r)/build'
+
+  optionally: use --timers=kernel_xeno for the realtime Xenomai timer functions
+
+- patch the sed "s:-I:-I$(src)/:g" statement to
+    's:-I../..:-I/canopeninstalldir:g' in drivers/unix/Makefile
+    's:-I..:-I/canopeninstalldir:g'    in src/Makefile
+  The original statement did not run on my computer !
+
+- build the CanFestival Unix library:
+  cd drivers/unix
+  make
+
+- build the CanFestival library:
+  cd src
+  make
+  make install
+
+- build the CO-PCICAN driver interface:
+  cd drivers/can_copcican_comedi
+  make
+  make install
+
+- build the example application (not for Xenomai):
+  cd examples/test_copcican_comedi
+  make
+  make install
+
+Run test_copcican_comedi with the insert.sh script to see it works...
+
+For Xenomai please use the example /usr/src/scale-rt-canopendemo of the SCALE-RT distribution.
+
+
+
+Copyright (C) 2010 Cosateq GmbH & Co.KG
+              http://www.cosateq.com/
+              http://www.scale-rt.com/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/copcican_linux_howto.txt	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,49 @@
+HOW TO configure CanFestival for a CO-PCICAN card for linux:
+
+
+
+pre-actions:
+- install the CO-PCICAN card
+- install and load the user space driver co_pcicanext.ko
+
+
+
+- unpack the package to your target (if not already done)
+
+- create empty file:
+  touch /usr/local/lib/libcanfestival_can_copcican_linux.so
+
+- perform package configuration:
+  sh ./configure --can=copcican_linux
+
+- build the CanFestival library:
+  cd src
+  make
+  make install
+
+- build the CanFestival Unix library:
+  cd drivers/unix
+  make
+  make install
+
+BUGFIX:
+  copy library into build directory back:
+  cp /usr/local/lib/libcanfestival_unix.a drivers/unix
+
+- build the CO-PCICAN driver interface:
+  cd drivers/can_copcican_linux
+  make
+  make install
+
+- build the example application:
+  cd examples/test_copcican_linux
+  make
+
+Run test_copcican_linux to see it works...
+
+
+
+Copyright (C) 2010 Cosateq GmbH & Co.KG
+              http://www.cosateq.com/
+              http://www.scale-rt.com/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/can_copcican_comedi/Makefile.in	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,60 @@
+#! gmake
+
+#
+# Copyright (C) 2010 Cosateq GmbH & Co.KG
+#               http://www.cosateq.com/
+#               http://www.scale-rt.com/
+#
+# 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
+#
+
+#ifneq ($(KERNELRELEASE),)
+# Kbuild part of Makefile
+TARGET = SUB_TARGET
+CAN_DRIVER = SUB_CAN_DRIVER
+TIMERS_DRIVER = SUB_TIMERS_DRIVER
+
+EXTRA_CFLAGS := -I$(src)/../../include
+EXTRA_CFLAGS += -I$(src)/../../include/$(TARGET)
+EXTRA_CFLAGS += -I$(src)/../../include/$(CAN_DRIVER)
+EXTRA_CFLAGS += -I/usr/src/comedi/include
+EXTRA_CFLAGS += SUB_PROG_CFLAGS
+
+obj-m := can_copcican_comedi.o
+can_copcican_comediko-objs =  $(CAN_DRIVER).o
+
+#else
+# Normal Makefile
+PREFIX = SUB_PREFIX
+KERNELDIR := SUB_KERNELDIR
+
+all: driver
+
+driver:
+	$(MAKE) -C $(KERNELDIR) M=$(shell pwd) modules
+
+clean:
+	$(MAKE) -C $(KERNELDIR) M=$(shell pwd) clean
+	rm -f Module.symvers
+
+mrproper: clean
+
+install:
+	$(MAKE) -C $(KERNELDIR) M=$(shell pwd) modules_install
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/can_copcican_comedi/can_copcican_comedi.c	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,490 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Cosateq GmbH & Co.KG
+               http://www.cosateq.com/
+               http://www.scale-rt.com/
+
+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
+*/
+
+/*
+	COMEDI interface for CO-PCICAN card.
+*/
+
+#include <linux/module.h>
+#include <linux/comedi.h>
+#include <linux/comedilib.h>
+
+#define NEED_PRINT_MESSAGE
+#include "can_driver.h"
+#include "def.h"
+#include "co_pcicanops.h"
+
+MODULE_LICENSE("GPL");
+
+/* at the moment not threadsafe :-( */
+static unsigned char selectedChannelRx = 0, selectedChannelTx = 0;
+
+static int rt_strcmp( const char *src, const char *dst )
+{
+  int ret = 0;
+
+  while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
+  {
+    src++;
+    dst++;
+  }
+
+  if( ret < 0 )
+  {
+    ret = -1 ;
+  }
+  else
+  {
+    if( ret > 0 )
+      ret = 1 ;
+  }
+
+  return ret;
+}
+
+static int TranslateBaudRate( char* optarg )
+{
+  /* values see documentation of CO-PCICAN */
+  if( !rt_strcmp( optarg, "1M"    ) ) return 0;
+  if( !rt_strcmp( optarg, "800K"  ) ) return 1;
+  if( !rt_strcmp( optarg, "500K"  ) ) return 2;
+  if( !rt_strcmp( optarg, "250K"  ) ) return 3;
+  if( !rt_strcmp( optarg, "125K"  ) ) return 4;
+  if( !rt_strcmp( optarg, "100K"  ) ) return 5;
+  if( !rt_strcmp( optarg, "83.3K" ) ) return 6;
+  if( !rt_strcmp( optarg, "10K"   ) ) return 7;
+
+  return -1;
+}
+
+/*********CO-PCICAN specific functions to communicate with the board**********/
+typedef struct
+{
+  char used;
+  CAN_HANDLE fd;
+  void* receiveTask;
+  void* d;
+} CANPort; /* taken from drivers/unix.c */
+
+comedi_t* get_dev_of_port( CAN_PORT port )
+{
+  CANPort *thisPort = (CANPort*)port;
+  CAN_HANDLE thisHandle;
+  comedi_t *dev;
+
+  if( thisPort == NULL )
+  {
+    MSG("can_copcican_comedi: get_dev_of_port(): thisPort is NULL\n");
+    return NULL;
+  }
+
+  thisHandle = thisPort->fd;
+
+  if( thisHandle == NULL )
+  {
+    MSG("can_copcican_comedi: get_dev_of_port(): thisHandle is NULL\n");
+    return NULL;
+  }
+
+  dev = (comedi_t*)thisHandle;
+
+  /*MSG("can_copcican_comedi: get_dev_of_port(): handle is 0x%08x\n", (unsigned int)dev);*/
+
+  return dev;
+}
+
+int co_pcican_enter_run_mode( comedi_t *dev )
+{
+  unsigned int opcmd[15];
+  unsigned int opcode = CMDQ_OPC_ENTER_RUN_MODE;
+  comedi_insn insn;
+
+  if( dev == NULL )
+  {
+    MSG("can_copcican_comedi: co_pcican_enter_run_mode(): dev is NULL\n");
+    return 1;
+  }
+
+  memset( opcmd, 0x00, sizeof(opcmd) );
+  opcmd[0] = 0;
+
+  memset( &insn, 0x00, sizeof(insn) );
+  insn.insn      = INSN_CONFIG;
+  insn.n         = 1;
+  insn.data      = (void*)opcmd;
+  insn.subdev    = 0;
+  insn.unused[0] = opcode; /* in use for CO-PCICAN */
+
+  comedi_do_insn( dev, &insn );
+
+  opcmd[0] = 2;
+  insn.subdev    = 2;
+  insn.unused[0] = opcode; /* in use for CO-PCICAN */
+
+  return comedi_do_insn( dev, &insn );
+}
+
+int co_pcican_enter_config_mode( comedi_t *dev )
+{
+  unsigned int opcmd[15];
+  unsigned int opcode = CMDQ_OPC_ENTER_CONFIG_MODE;
+  comedi_insn insn;
+
+  if( dev == NULL )
+  {
+    MSG("can_copcican_comedi: co_pcican_enter_config_mode(): dev is NULL\n");
+    return 1;
+  }
+
+  memset( opcmd, 0x00, sizeof(opcmd) );
+  opcmd[0] = 0;
+
+  memset( &insn, 0x00, sizeof(insn) );
+  insn.insn      = INSN_CONFIG;
+  insn.n         = 1;
+  insn.data      = (void*)opcmd;
+  insn.subdev    = 0;
+  insn.unused[0] = opcode; /* in use for CO-PCICAN */
+
+  comedi_do_insn( dev, &insn );
+
+  opcmd[0] = 2;
+  insn.subdev    = 2;
+  insn.unused[0] = opcode; /* in use for CO-PCICAN */
+
+  return comedi_do_insn( dev, &insn );
+}
+
+int co_pcican_select_channel( const unsigned char channel, const unsigned int direction )
+{
+  if( channel >= NUM_CAN_CHANNELS )
+  {
+    MSG("can_copcican_comedi: co_pcican_select_channel(): invalid channel\n");
+    return -1;
+  }
+
+  /* at the moment not threadsafe :-( */
+  switch( direction )
+  {
+    case RX: selectedChannelRx = channel;
+             break;
+    case TX: selectedChannelTx = channel;
+             break;
+    default: return -1;
+  }
+
+  return 0;
+}
+
+int co_pcican_configure_selected_channel( comedi_t *dev, s_BOARD *board, const unsigned int direction )
+{
+  unsigned int opcmd[15];
+  unsigned int opcode = CMDQ_OPC_SET_CONFIG_CHANNEL;
+  unsigned int selectedChannel;
+  comedi_insn insn;
+
+  if( dev == NULL )
+  {
+    MSG("can_copcican_comedi: co_pcican_configure_selected_channel(): dev is NULL\n");
+    return -1;
+  }
+
+  if( board == NULL )
+  {
+    MSG("can_copcican_comedi: co_pcican_configure_selected_channel(): board is NULL\n");
+    return -1;
+  }
+
+  if( board->baudrate == NULL )
+  {
+    MSG("can_copcican_comedi: co_pcican_configure_selected_channel(): baudrate is NULL\n");
+    return -1;
+  }
+
+  switch( direction )
+  {
+    case RX: selectedChannel = selectedChannelRx;
+             break;
+    case TX: selectedChannel = selectedChannelTx;
+             break;
+    default: selectedChannel = 0xff;
+  }
+
+  if( selectedChannel >= NUM_CAN_CHANNELS )
+  {
+    MSG("can_copcican_comedi: co_pcican_configure_selected_channel(): invalid channel selected\n");
+    return -1;
+  }
+
+  memset( opcmd, 0x00, sizeof(opcmd) );
+  opcmd[0] = selectedChannel;
+  opcmd[1] = TranslateBaudRate( board->baudrate );
+
+  memset( &insn, 0x00, sizeof(insn) );
+  insn.insn      = INSN_CONFIG;
+  insn.n         = 1;
+  insn.data      = (void*)opcmd;
+
+  if( selectedChannel < 2 )
+    insn.subdev    = 0;
+  else
+    insn.subdev    = 2;
+
+  insn.unused[0] = opcode; /* in use for CO-PCICAN */
+
+  return comedi_do_insn( dev, &insn );
+}
+
+/*********functions which permit to communicate with the board****************/
+UNS8 canReceive_driver( CAN_HANDLE fd0, Message *m )
+{
+  MESSAGE_T canmsg;
+  comedi_insn insn;
+  UNS8 ret = 0;
+  comedi_t *dev = (comedi_t*)fd0;
+
+  if( dev == NULL )
+  {
+    MSG("can_copcican_comedi: canReceive_driver(): dev is NULL\n");
+    return 1;
+  }
+
+  if( selectedChannelRx >= NUM_CAN_CHANNELS )
+  {
+    MSG("can_copcican_comedi: canReceive_driver(): invalid channel selected\n");
+    return 1;
+  }
+
+  if( m == NULL )
+  {
+    MSG("can_copcican_comedi: canReceive_driver(): message is NULL\n");
+    return 1;
+  }
+
+  memset( &canmsg, 0x00, sizeof(MESSAGE_T) );
+
+  memset( &insn, 0x00, sizeof(insn) );
+  insn.insn      = INSN_READ;
+  insn.n         = 1;
+  insn.data      = (void*)&canmsg;
+
+  if( selectedChannelRx < 2 )
+    insn.subdev    = comedi_find_subdevice_by_type(dev, COMEDI_SUBD_DI, 0);
+  else
+    insn.subdev    = comedi_find_subdevice_by_type(dev, COMEDI_SUBD_DI, 2);
+
+  insn.unused[1] = selectedChannelRx; /* in use for CO-PCICAN */
+  insn.unused[2] = sizeof(MESSAGE_T); /* in use for CO-PCICAN */
+
+  comedi_do_insn( dev, &insn );
+
+  if( canmsg.timestamp_lo == 0 )
+  {
+    memset( m, 0x00, sizeof(Message) );
+
+    m->cob_id = 0xffff; /* set to invalid so nothing happens */
+  }
+  else
+  {
+    m->len = canmsg.size;
+    m->cob_id = canmsg.id;
+    m->rtr = canmsg.type & MSG_RTR;
+
+    if( !m->rtr )
+    {
+      /* this is for safety */
+      if( m->len > 8 )
+        m->len = 8;
+
+      memcpy( m->data, canmsg.data, m->len);
+    }
+  }
+
+  return ret;
+}
+
+/***************************************************************************/
+UNS8 canSend_driver( CAN_HANDLE fd0, Message *m )
+{
+  MESSAGE_T canmsg;
+  comedi_insn insn;
+  UNS8 ret = 0;
+  comedi_t *dev = (comedi_t*)fd0;
+
+  if( dev == NULL )
+  {
+    MSG("can_copcican_comedi: canSend_driver(): dev is NULL\n");
+    return 1;
+  }
+
+  if( selectedChannelTx >= NUM_CAN_CHANNELS )
+  {
+    MSG("can_copcican_comedi: canSend_driver(): invalid channel selected\n");
+    return 1;
+  }
+
+  if( m == NULL )
+  {
+    MSG("can_copcican_comedi: canSend_driver(): message is NULL\n");
+    return 1;
+  }
+
+  memset( &canmsg, 0x00, sizeof(MESSAGE_T) );
+  canmsg.size = m->len;
+  canmsg.id = m->cob_id;
+
+  if( canmsg.id >= 0x800 )
+    canmsg.type |= MSG_EXT;
+
+  if( m->rtr )
+  {
+    canmsg.type |= MSG_RTR;
+  }
+  else
+  {
+    /* this is for safety */
+    if( canmsg.size > 8 )
+      canmsg.size = 8;
+
+    memcpy( canmsg.data, m->data, canmsg.size);
+  }
+
+  memset( &insn, 0x00, sizeof(insn) );
+  insn.insn      = INSN_WRITE;
+  insn.n         = 1;
+  insn.data      = (void*)&canmsg;
+
+  if( selectedChannelTx < 2 )
+    insn.subdev    = comedi_find_subdevice_by_type(dev, COMEDI_SUBD_DO, 0);
+  else
+    insn.subdev    = comedi_find_subdevice_by_type(dev, COMEDI_SUBD_DO, 2);
+
+  insn.unused[1] = selectedChannelTx; /* in use for CO-PCICAN */
+  insn.unused[2] = sizeof(MESSAGE_T) - sizeof(unsigned long); /* in use for CO-PCICAN, no timestamp for tx */
+
+  if( comedi_do_insn( dev, &insn ) < 0 )
+    ret = 1;
+
+  return ret;
+}
+
+/***************************************************************************/
+CAN_HANDLE canOpen_driver( s_BOARD *board )
+{
+  comedi_t *dev;
+
+  if( board == NULL )
+  {
+    MSG("can_copcican_comedi: canOpen_driver(): board is NULL\n");
+    return NULL;
+  }
+
+  if( board->busname == NULL )
+  {
+    MSG("can_copcican_comedi: canOpen_driver(): busname is NULL\n");
+    return NULL;
+  }
+
+  dev = comedi_open( board->busname );
+
+  /*MSG("can_copcican_comedi: canOpen_driver(): handle is 0x%08x\n", (unsigned int)dev);*/
+
+  return dev;
+}
+
+/***************************************************************************/
+int canClose_driver( CAN_HANDLE fd0 )
+{
+  comedi_t *dev = (comedi_t*)fd0;
+
+  if( dev == NULL )
+  {
+    MSG("can_copcican_comedi: canClose_driver(): dev is NULL\n");
+    return 1;
+  }
+
+  comedi_close( dev );
+
+  selectedChannelRx = 0;
+  selectedChannelTx = 0;
+
+  return 0;
+}
+
+/***************************************************************************/
+UNS8 canChangeBaudRate_driver( CAN_HANDLE fd0, char* baud )
+{
+  s_BOARD board;
+  UNS8 ret = 0;
+  comedi_t *dev = (comedi_t*)fd0;
+
+  if( dev == NULL )
+  {
+    MSG("can_copcican_comedi: canChangeBaudRate_driver(): dev is NULL\n");
+    return 1;
+  }
+
+  if( baud == NULL )
+  {
+    MSG("can_copcican_comedi: canChangeBaudRate_driver(): baud is NULL\n");
+    return 1;
+  }
+
+  memset( &board, 0x00, sizeof(s_BOARD) );
+  board.baudrate = baud;
+
+  if( co_pcican_configure_selected_channel( dev, &board, RX ) < 0 )
+    ret = 1;
+
+  if( co_pcican_configure_selected_channel( dev, &board, TX ) < 0 )
+    ret = 1;
+
+  return ret;
+}
+
+static int init(void)
+{
+  printk("can_copcican_comedi for CanFestival loaded\n");
+
+  return 0;
+}
+
+static void exit(void)
+{
+  printk("can_copcican_comedi unloaded\n");
+}
+
+module_init(init);
+module_exit(exit);
+
+EXPORT_SYMBOL(get_dev_of_port);
+EXPORT_SYMBOL(co_pcican_enter_run_mode);
+EXPORT_SYMBOL(co_pcican_enter_config_mode);
+EXPORT_SYMBOL(co_pcican_select_channel);
+EXPORT_SYMBOL(co_pcican_configure_selected_channel);
+EXPORT_SYMBOL(canOpen_driver);
+EXPORT_SYMBOL(canClose_driver);
+EXPORT_SYMBOL(canSend_driver);
+EXPORT_SYMBOL(canReceive_driver);
+EXPORT_SYMBOL(canChangeBaudRate_driver);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/can_copcican_comedi/co_pcicanops.h	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,63 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Cosateq GmbH & Co.KG
+               http://www.cosateq.com/
+               http://www.scale-rt.com/
+
+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
+*/
+
+/*
+	COMEDI interface for CO-PCICAN card.
+*/
+
+#ifndef _CO_PCICANOPS_
+#define _CO_PCICANOPS_
+
+#define NUM_CAN_CHANNELS 4
+
+#define CMDQ_OPC_ENTER_RUN_MODE     0x01
+#define CMDQ_OPC_ENTER_CONFIG_MODE  0x02
+#define CMDQ_OPC_SET_CONFIG_CHANNEL 0xA2
+
+typedef struct message_t
+{
+  unsigned long type;
+  unsigned long size;
+  unsigned long id;
+  unsigned char data[8];
+  unsigned long timestamp_lo;
+  unsigned long timestamp_hi;
+} MESSAGE_T;
+
+/*=============================================================================
+  directions
+  ===========================================================================*/
+#define RX         0
+#define TX         1
+
+/*=============================================================================
+  supported types
+  ===========================================================================*/
+#define MSG_EXT    0x00000001
+#define MSG_RTR    0x00000002
+
+
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/can_copcican_linux/Makefile.in	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,70 @@
+#! gmake
+
+#
+# Copyright (C) 2010 Cosateq GmbH & Co.KG
+#               http://www.cosateq.com/
+#               http://www.scale-rt.com/
+#
+# 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
+
+INCLUDES = -I../../include -I../../include/$(TARGET) -I../../include/$(CAN_DRIVER)
+
+OBJS = $(CAN_DRIVER).o
+
+ifeq ($(ENABLE_DLL_DRIVERS),1)
+CFLAGS += -fPIC
+DRIVER = libcanfestival_$(CAN_DRIVER).so
+else
+DRIVER = $(OBJS)
+endif
+
+TARGET_SOFILES = $(PREFIX)/lib/$(DRIVER)
+
+all: driver
+
+driver: $(DRIVER)
+
+%o: %c
+	$(CC) $(CFLAGS) $(PROG_CFLAGS) ${PROGDEFINES} $(INCLUDES) -o $@ -c $<
+
+libcanfestival_$(CAN_DRIVER).so: $(OBJS)
+	$(CC) -shared -Wl,-soname,libcanfestival_$(CAN_DRIVER).so $(CAN_DLL_CFLAGS) -o $@ $<
+
+install: libcanfestival_$(CAN_DRIVER).so
+	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_copcican_linux/can_copcican_linux.c	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,415 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Cosateq GmbH & Co.KG
+               http://www.cosateq.com/
+               http://www.scale-rt.com/
+
+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
+*/
+
+/*
+	CAN driver interface for CO-PCICAN card.
+*/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#define NEED_PRINT_MESSAGE
+#include "can_driver.h"
+#include "def.h"
+#include "co_pcicanops.h"
+
+/* at the moment not threadsafe :-( */
+static unsigned char selectedChannelRx = 0, selectedChannelTx = 0;
+
+static int TranslateBaudRate( char* optarg )
+{
+  /* values see documentation of CO-PCICAN */
+  if( !strcmp( optarg, "1M"    ) ) return 0;
+  if( !strcmp( optarg, "800K"  ) ) return 1;
+  if( !strcmp( optarg, "500K"  ) ) return 2;
+  if( !strcmp( optarg, "250K"  ) ) return 3;
+  if( !strcmp( optarg, "125K"  ) ) return 4;
+  if( !strcmp( optarg, "100K"  ) ) return 5;
+  if( !strcmp( optarg, "83.3K" ) ) return 6;
+  if( !strcmp( optarg, "10K"   ) ) return 7;
+
+  return -1;
+}
+
+/*********CO-PCICAN specific functions to communicate with the board**********/
+typedef struct
+{
+  char used;
+  CAN_HANDLE fd;
+  void* receiveTask;
+  void* d;
+} CANPort; /* taken from drivers/unix.c */
+
+int get_fd_of_port( CAN_PORT port )
+{
+  CANPort *thisPort = (CANPort*)port;
+  CAN_HANDLE thisHandle;
+  int *pfd;
+
+  if( thisPort == NULL )
+  {
+    MSG("can_copcican_linux: get_fd_of_port(): thisPort is NULL\n");
+    return -1;
+  }
+
+  thisHandle = thisPort->fd;
+
+  if( thisHandle == NULL )
+  {
+    MSG("can_copcican_linux: get_fd_of_port(): thisHandle is NULL\n");
+    return -1;
+  }
+
+  pfd = (int*)thisHandle;
+
+  /*MSG("can_copcican_linux: get_fd_of_port(): handle is %d\n", *pfd);*/
+
+  return *pfd;
+}
+
+int co_pcican_enter_run_mode( const int fd )
+{
+  co_pcican_config_t board_config;
+
+  if( fd < 0 )
+  {
+    MSG("can_copcican_linux: co_pcican_enter_run_mode(): invalid file descriptor\n");
+    return -1;
+  }
+
+  memset( &board_config, 0x00, sizeof(co_pcican_config_t) );
+  board_config.opcode = CMDQ_OPC_ENTER_RUN_MODE;
+
+  return ioctl( fd, CAN_CONFIG, &board_config );
+}
+
+int co_pcican_enter_config_mode( const int fd )
+{
+  co_pcican_config_t board_config;
+
+  if( fd < 0 )
+  {
+    MSG("can_copcican_linux: co_pcican_enter_config_mode(): invalid file descriptor\n");
+    return -1;
+  }
+
+  memset( &board_config, 0x00, sizeof(co_pcican_config_t) );
+  board_config.opcode = CMDQ_OPC_ENTER_CONFIG_MODE;
+
+  return ioctl( fd, CAN_CONFIG, &board_config );
+}
+
+int co_pcican_select_channel( const unsigned char channel, const unsigned int direction )
+{
+  if( channel >= NUM_CAN_CHANNELS )
+  {
+    MSG("can_copcican_linux: co_pcican_select_channel(): invalid channel\n");
+    return -1;
+  }
+
+  /* at the moment not threadsafe :-( */
+  switch( direction )
+  {
+    case RX: selectedChannelRx = channel;
+             break;
+    case TX: selectedChannelTx = channel;
+             break;
+    default: return -1;
+  }
+
+  return 0;
+}
+
+int co_pcican_configure_selected_channel( const int fd, s_BOARD *board, const unsigned int direction )
+{
+  co_pcican_config_t board_config;
+  unsigned int selectedChannel;
+
+  if( fd < 0 )
+  {
+    MSG("can_copcican_linux: co_pcican_configure_selected_channel(): invalid file descriptor\n");
+    return -1;
+  }
+
+  if( board == NULL )
+  {
+    MSG("can_copcican_linux: co_pcican_configure_selected_channel(): board is NULL\n");
+    return -1;
+  }
+
+  if( board->baudrate == NULL )
+  {
+    MSG("can_copcican_linux: co_pcican_configure_selected_channel(): baudrate is NULL\n");
+    return -1;
+  }
+
+  switch( direction )
+  {
+    case RX: selectedChannel = selectedChannelRx;
+             break;
+    case TX: selectedChannel = selectedChannelTx;
+             break;
+    default: selectedChannel = 0xff;
+  }
+
+  if( selectedChannel >= NUM_CAN_CHANNELS )
+  {
+    MSG("can_copcican_linux: co_pcican_configure_selected_channel(): invalid channel selected\n");
+    return -1;
+  }
+
+  memset( &board_config, 0x00, sizeof(co_pcican_config_t) );
+  board_config.opcode   = CMDQ_OPC_SET_CONFIG_CHANNEL;
+  board_config.param[0] = selectedChannel;
+  board_config.param[1] = TranslateBaudRate( board->baudrate );
+
+  return ioctl( fd, CAN_CONFIG, &board_config );
+}
+
+/*********functions which permit to communicate with the board****************/
+UNS8 canReceive_driver( CAN_HANDLE fd0, Message *m )
+{
+  co_pcican_message_t canmsg;
+  UNS8 ret = 0;
+  int *pfd = (int*)fd0;
+
+  if( pfd == NULL )
+  {
+    MSG("can_copcican_linux: canReceive_driver(): file descriptor is NULL\n");
+    return 1;
+  }
+
+  if( *pfd < 0 )
+  {
+    MSG("can_copcican_linux: canReceive_driver(): invalid file descriptor\n");
+    return 1;
+  }
+
+  if( selectedChannelRx >= NUM_CAN_CHANNELS )
+  {
+    MSG("can_copcican_linux: canReceive_driver(): invalid channel selected\n");
+    return 1;
+  }
+
+  if( m == NULL )
+  {
+    MSG("can_copcican_linux: canReceive_driver(): message is NULL\n");
+    return 1;
+  }
+
+  memset( &canmsg, 0x00, sizeof(co_pcican_message_t) );
+  canmsg.channelnum = selectedChannelRx;
+
+  ioctl( *pfd, CAN_READ, &canmsg );
+
+  if( canmsg.timestamp_lo == 0 )
+  {
+    memset( m, 0x00, sizeof(Message) );
+
+    m->cob_id = 0xffff; /* set to invalid so nothing happens */
+  }
+  else
+  {
+    m->len = canmsg.size;
+    m->cob_id = canmsg.id;
+    m->rtr = canmsg.type & MSG_RTR;
+
+    if( !m->rtr )
+    {
+      /* this is for safety */
+      if( m->len > 8 )
+        m->len = 8;
+
+      memcpy( m->data, canmsg.data, m->len);
+    }
+  }
+
+  return ret;
+}
+
+/***************************************************************************/
+UNS8 canSend_driver( CAN_HANDLE fd0, Message *m )
+{
+  co_pcican_message_t canmsg;
+  UNS8 ret = 0;
+  int *pfd = (int*)fd0;
+
+  if( pfd == NULL )
+  {
+    MSG("can_copcican_linux: canSend_driver(): file descriptor is NULL\n");
+    return 1;
+  }
+
+  if( *pfd < 0 )
+  {
+    MSG("can_copcican_linux: canSend_driver(): invalid file descriptor\n");
+    return 1;
+  }
+
+  if( selectedChannelTx >= NUM_CAN_CHANNELS )
+  {
+    MSG("can_copcican_linux: canSend_driver(): invalid channel selected\n");
+    return 1;
+  }
+
+  if( m == NULL )
+  {
+    MSG("can_copcican_linux: canSend_driver(): message is NULL\n");
+    return 1;
+  }
+
+  memset( &canmsg, 0x00, sizeof(co_pcican_message_t) );
+  canmsg.channelnum = selectedChannelTx;
+  canmsg.size = m->len;
+  canmsg.id = m->cob_id;
+
+  if( canmsg.id >= 0x800 )
+    canmsg.type |= MSG_EXT;
+
+  if( m->rtr )
+  {
+    canmsg.type |= MSG_RTR;
+  }
+  else
+  {
+    /* this is for safety */
+    if( canmsg.size > 8 )
+      canmsg.size = 8;
+
+    memcpy( canmsg.data, m->data, canmsg.size);
+  }
+
+  if( ioctl( *pfd, CAN_WRITE, &canmsg ) < 0 )
+    ret = 1;
+
+  return ret;
+}
+
+/***************************************************************************/
+CAN_HANDLE canOpen_driver( s_BOARD *board )
+{
+  int *pfd;
+
+  if( board == NULL )
+  {
+    MSG("can_copcican_linux: canOpen_driver(): board is NULL\n");
+    return NULL;
+  }
+
+  if( board->busname == NULL )
+  {
+    MSG("can_copcican_linux: canOpen_driver(): busname is NULL\n");
+    return NULL;
+  }
+
+  /* create dynamically to avoid global variable */
+  pfd = (int*)malloc( sizeof(int) );
+
+  if( pfd == NULL )
+  {
+    MSG("can_copcican_linux: canOpen_driver(): file descriptor is NULL\n");
+    return NULL;
+  }
+
+  *pfd = open( board->busname, O_RDWR, 0 );
+
+  if( *pfd < 0 )
+  {
+    MSG("can_copcican_linux: canOpen_driver(): invalid file descriptor\n");
+
+    /* clear resources if open failed */
+    free( pfd );
+    pfd = NULL;
+  }
+
+  /*MSG("can_copcican_linux: canOpen_driver(): handle is %d\n", *pfd);*/
+
+  return (CAN_HANDLE)pfd;
+}
+
+/***************************************************************************/
+int canClose_driver( CAN_HANDLE fd0 )
+{
+  int *pfd = (int*)fd0;
+
+  if( pfd == NULL )
+  {
+    MSG("can_copcican_linux: canClose_driver(): file descriptor is NULL\n");
+    return -1;
+  }
+
+  if( *pfd < 0 )
+  {
+    MSG("can_copcican_linux: canClose_driver(): invalid file descriptor\n");
+    return -1;
+  }
+
+  close( *pfd );
+  free( pfd );
+  pfd = NULL;
+
+  selectedChannelRx = 0;
+  selectedChannelTx = 0;
+
+  return 0;
+}
+
+/***************************************************************************/
+UNS8 canChangeBaudRate_driver( CAN_HANDLE fd0, char* baud )
+{
+  s_BOARD board;
+  UNS8 ret = 0;
+  int *pfd = (int*)fd0;
+
+  if( pfd == NULL )
+  {
+    MSG("can_copcican_linux: canChangeBaudRate_driver(): file descriptor is NULL\n");
+    return 1;
+  }
+
+  if( *pfd < 0 )
+  {
+    MSG("can_copcican_linux: canChangeBaudRate_driver(): invalid file descriptor\n");
+    return 1;
+  }
+
+  if( baud == NULL )
+  {
+    MSG("can_copcican_linux: canChangeBaudRate_driver(): baud is NULL\n");
+    return 1;
+  }
+
+  memset( &board, 0x00, sizeof(s_BOARD) );
+  board.baudrate = baud;
+
+  if( co_pcican_configure_selected_channel( *pfd, &board, RX ) < 0 )
+    ret = 1;
+
+  if( co_pcican_configure_selected_channel( *pfd, &board, TX ) < 0 )
+    ret = 1;
+
+  return ret;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/can_copcican_linux/co_pcicanops.h	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,77 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Cosateq GmbH & Co.KG
+               http://www.cosateq.com/
+               http://www.scale-rt.com/
+
+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
+*/
+
+/*
+	CAN driver interface for CO-PCICAN card.
+*/
+
+#ifndef _CO_PCICANOPS_
+#define _CO_PCICANOPS_
+
+#define NUM_CAN_CHANNELS 4
+
+#define CMDQ_OPC_ENTER_RUN_MODE     0x01
+#define CMDQ_OPC_ENTER_CONFIG_MODE  0x02
+#define CMDQ_OPC_SET_CONFIG_CHANNEL 0xA2
+
+typedef struct
+{
+  unsigned char opcode;
+  unsigned long param[15];
+} co_pcican_config_t;
+
+typedef struct
+{
+  unsigned char channelnum;
+  unsigned long type;
+  unsigned long size;
+  unsigned long id;
+  unsigned char data[8];
+  unsigned long timestamp_lo;
+  unsigned long timestamp_hi;
+} co_pcican_message_t;
+
+/*=============================================================================
+  supported operations
+  ===========================================================================*/
+#define CAN_CONFIG 2
+#define CAN_WRITE  3
+#define CAN_READ   4
+
+/*=============================================================================
+  directions
+  ===========================================================================*/
+#define RX         0
+#define TX         1
+
+/*=============================================================================
+  supported types
+  ===========================================================================*/
+#define MSG_EXT    0x00000001
+#define MSG_RTR    0x00000002
+
+
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/can_copcican_win32/ReadMe.txt	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,48 @@
+========================================================================
+    DYNAMIC LINK LIBRARY : can_copcican_win32 Project Overview
+========================================================================
+
+AppWizard has created this can_copcican_win32 DLL for you.
+
+This file contains a summary of what you will find in each of the files that
+make up your can_copcican_win32 application.
+
+
+can_copcican_win32.vcxproj
+    This is the main project file for VC++ projects generated using an Application Wizard.
+    It contains information about the version of Visual C++ that generated the file, and
+    information about the platforms, configurations, and project features selected with the
+    Application Wizard.
+
+can_copcican_win32.vcxproj.filters
+    This is the filters file for VC++ projects generated using an Application Wizard. 
+    It contains information about the association between the files in your project 
+    and the filters. This association is used in the IDE to show grouping of files with
+    similar extensions under a specific node (for e.g. ".cpp" files are associated with the
+    "Source Files" filter).
+
+can_copcican_win32.cpp
+    This is the main DLL source file.
+
+	When created, this DLL does not export any symbols. As a result, it
+	will not produce a .lib file when it is built. If you wish this project
+	to be a project dependency of some other project, you will either need to
+	add code to export some symbols from the DLL so that an export library
+	will be produced, or you can set the Ignore Input Library property to Yes
+	on the General propert page of the Linker folder in the project's Property
+	Pages dialog box.
+
+/////////////////////////////////////////////////////////////////////////////
+Other standard files:
+
+StdAfx.h, StdAfx.cpp
+    These files are used to build a precompiled header (PCH) file
+    named can_copcican_win32.pch and a precompiled types file named StdAfx.obj.
+
+/////////////////////////////////////////////////////////////////////////////
+Other notes:
+
+AppWizard uses "TODO:" comments to indicate parts of the source code you
+should add to or customize.
+
+/////////////////////////////////////////////////////////////////////////////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/can_copcican_win32/can_copcican_win32.cpp	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,249 @@
+// can_copcican_win32.cpp : Defines the exported functions for the DLL application.
+//
+
+
+#include "stdafx.h"
+
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Cosateq GmbH & Co.KG
+               http://www.cosateq.com/
+               http://www.scale-rt.com/
+
+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
+*/
+
+/*
+	CAN driver interface for CO-PCICAN card.
+*/
+
+#include <stdio.h>
+//#include <unistd.h>
+#include <fcntl.h>
+
+//#define NEED_PRINT_MESSAGE
+static int initdone = 0;
+
+inline void * maskDevID(int devId){	return ((void*)( (devId & 0x0000000F) | 0xC05A0000)); }
+inline int unmaskDevID(void * Ptr){	return ((int)((int)Ptr & 0x0000000F)); }
+
+/* at the moment not threadsafe :-( */
+static unsigned char selectedChannelRx = 1, selectedChannelTx = 1;
+
+static cosateq::devices::can::co_baudrate_t TranslateBaudRate( char* optarg )
+{
+  /* values see documentation of CO-PCICAN */
+	if( !strcmp( optarg, "1M"    ) ) return cosateq::devices::can::CO_BAUD_1M;
+	if( !strcmp( optarg, "800K"  ) ) return cosateq::devices::can::CO_BAUD_800k;
+	if( !strcmp( optarg, "500K"  ) ) return cosateq::devices::can::CO_BAUD_500k;
+  if( !strcmp( optarg, "250K"  ) ) return cosateq::devices::can::CO_BAUD_250k;
+  if( !strcmp( optarg, "125K"  ) ) return cosateq::devices::can::CO_BAUD_125k;
+  if( !strcmp( optarg, "100K"  ) ) return cosateq::devices::can::CO_BAUD_100k;
+  if( !strcmp( optarg, "83.3K" ) ) return cosateq::devices::can::CO_BAUD_83k;
+  if( !strcmp( optarg, "10K"   ) ) return cosateq::devices::can::CO_BAUD_10k;
+
+  return (cosateq::devices::can::co_baudrate_t)-1;
+}
+
+int co_pcican_select_channel( const unsigned char channel, const unsigned int direction )
+{
+  if( channel >= CHANNELS )
+  {
+    MSG("can_copcican_linux: co_pcican_select_channel(): invalid channel\n");
+    return -1;
+  }
+
+  /* at the moment not threadsafe :-( */
+  switch( direction )
+  {
+    case cosateq::devices::can::CO_CAN_RX: selectedChannelRx = channel;
+             break;
+    case cosateq::devices::can::CO_CAN_TX: selectedChannelTx = channel;
+             break;
+    default: return -1;
+  }
+
+  return 0;
+}
+
+int co_pcican_configure_selected_channel( const int fd, s_BOARD *board, const unsigned int direction )
+{
+  unsigned int selectedChannel;
+  int ret = 0;
+
+  if( fd < 0 )
+  {
+    MSG("can_copcican_linux: co_pcican_configure_selected_channel(): invalid file descriptor\n");
+    return -1;
+  }
+
+  if( board == NULL )
+  {
+    MSG("can_copcican_linux: co_pcican_configure_selected_channel(): board is NULL\n");
+    return -1;
+  }
+
+  if( board->baudrate == NULL )
+  {
+    MSG("can_copcican_linux: co_pcican_configure_selected_channel(): baudrate is NULL\n");
+    return -1;
+  }
+
+  switch( direction )
+  {
+    case cosateq::devices::can::CO_CAN_RX: selectedChannel = selectedChannelRx;
+             break;
+    case cosateq::devices::can::CO_CAN_TX: selectedChannel = selectedChannelTx;
+             break;
+    default: selectedChannel = 0xff;
+  }
+
+  if( selectedChannel >= CHANNELS )
+  {
+    MSG("can_copcican_linux: co_pcican_configure_selected_channel(): invalid channel selected\n");
+    return -1;
+  }
+
+  ret = can_setChannelConfig( TranslateBaudRate( board->baudrate ),0x0,unmaskDevID((void*)fd),selectedChannel);
+  if ( ret != 0 ) {
+	  can_enterRunMode(unmaskDevID((void*)fd),selectedChannel/2);
+	  return -ret;
+  }else{
+	  ret = can_setIrqMode(unmaskDevID((void*)fd),selectedChannel);
+	  can_enterRunMode(unmaskDevID((void*)fd),selectedChannel/2);
+  }
+  return ret;
+}
+
+/*********functions which permit to communicate with the board****************/
+
+UNS8 __stdcall canReceive_driver( CAN_HANDLE fd0, Message *m )
+{
+  cosateq::devices::can::co_can_packet_t p;
+  int ret = 0;
+
+  if ( !m )
+	  return 0;
+
+  memset(&p,0,sizeof(cosateq::devices::can::co_can_packet_t));
+  ret = can_receive(&p,unmaskDevID(fd0),selectedChannelRx);
+  //printf("rec: %d\n",ret);
+  if ( ret != 0 )
+	  return 1;
+
+  //printf("rec2: %d\n",ret);
+  if ( p.size > 8 )
+	  p.size = 8;
+
+  if ( !(p.type & MSG_RTR ) )
+    memcpy(m->data,p.data,p.size);
+
+  m->cob_id = p.id;
+  m->len = p.size;
+  m->rtr = p.type & MSG_RTR;
+  
+  return 0;
+}
+
+/***************************************************************************/
+
+UNS8 __stdcall canSend_driver( CAN_HANDLE fd0, Message *m )
+{
+  cosateq::devices::can::co_can_packet_t p;
+  
+  if ( !m )
+	  return 0;
+  memset(&p,0,sizeof(cosateq::devices::can::co_can_packet_t));
+  p.id = m->cob_id;
+  p.size = (m->len > 8) ? 8 : m->len;
+  p.type = ( m->rtr ) ? 0x2:0x0;
+  if ( p.id > 0x800 )
+	  p.type |= MSG_EXT;
+  memcpy(p.data,m->data,p.size);
+
+  return can_send(&p,unmaskDevID(fd0),selectedChannelTx);
+}
+
+
+
+/***************************************************************************/
+
+UNS8 __stdcall canChangeBaudRate_driver( CAN_HANDLE fd0, char* baud )
+{
+  UNS8 ret = 0;
+
+  ret = can_enterCfgMode(unmaskDevID(fd0),0);
+  if ( ret != 0)
+    MSG("Enter config mode for Channelpair 0 failed in Function %s! Error: %d\n",__FUNCTION__,ret);
+  ret = can_enterCfgMode(unmaskDevID(fd0),1);
+  if ( ret != 0)
+    MSG("Enter config mode for Channelpair 1 failed in Function %s! Error: %d\n",__FUNCTION__,ret);
+
+  for ( int i = 0; i < 4; i++ ) {
+      ret = can_setChannelConfig(TranslateBaudRate(baud),0x0,unmaskDevID(fd0),i);
+      if ( ret != 0)
+        MSG("Set config for channel %d failed in Function %s! Error: %d\n",i,__FUNCTION__,ret);
+	  can_setIrqMode(unmaskDevID(fd0),i);
+  }
+  ret = can_enterRunMode(unmaskDevID(fd0),0);
+  if ( ret != 0)
+    MSG("Enter run mode for Channelpair 1 failed in Function %s! Error: %d\n",__FUNCTION__,ret);
+
+  ret = can_enterRunMode(unmaskDevID(fd0),1);
+  if ( ret != 0)
+    MSG("Enter run mode for Channelpair 1 failed in Function %s! Error: %d\n",__FUNCTION__,ret);
+
+  return ret;
+}
+
+CAN_HANDLE __stdcall canOpen_driver( s_BOARD *board )
+{
+	int ret = 0;
+	int devId = 0;
+	if ( !board )
+		return NULL;
+	if ( !board->busname )
+		return NULL;
+	//TODO find out how boardname resolves
+
+	//printf("BOARD: 0x%x %s\n",board,board->busname);
+	//sscanf_s(board->busname,"%d",&devId);
+
+	if ( devId < 0 || devId > 15 )
+		return NULL;
+
+	//return (can_HANDLE)NULL;
+	if ( !initdone ) {
+		can_init();
+		initdone = 1;
+	}
+
+	ret = can_open(devId);
+	if ( ret < 0 )
+		return (CAN_HANDLE)NULL;
+	
+	canChangeBaudRate_driver( maskDevID(devId),board->baudrate );
+	
+	return maskDevID(devId);
+}
+
+int __stdcall canClose_driver(CAN_HANDLE fd0 )
+{
+	return can_close(unmaskDevID(fd0));
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/can_copcican_win32/can_copcican_win32.def	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,28 @@
+; This file is part of CanFestival, a library implementing CanOpen Stack. 
+;
+; CanFestival Copyright (C): Edouard TISSERANT and Francis DUPIN
+; CanFestival Win32 port Copyright (C) 2007 Leonid Tochinski, ChattenAssociates, Inc.
+;
+; 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
+
+LIBRARY	can_copcican_win32
+
+EXPORTS
+   canReceive_driver
+   canSend_driver
+   canOpen_driver
+   canClose_driver
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/can_copcican_win32/can_copcican_win32.vcxproj	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{A18C416F-3CBB-4744-BA24-FA5C5F3CBE0D}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>can_copcican_win32</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;CAN_COPCICAN_WIN32_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(SolutionDir)\include;$(SolutionDir)\include\win32;$(SolutionDir)\..\driver_windows\Cosateq_4Port_CAN_SDK\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>$(SolutionDir)\..\driver_windows\Cosateq_4Port_CAN_SDK\lib\co_can_lib.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <ModuleDefinitionFile>can_copcican_win32.def</ModuleDefinitionFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CAN_COPCICAN_WIN32_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <ModuleDefinitionFile>can_copcican_win32.def</ModuleDefinitionFile>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <None Include="can_copcican_win32.def" />
+    <None Include="ReadMe.txt" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="stdafx.h" />
+    <ClInclude Include="targetver.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="can_copcican_win32.cpp" />
+    <ClCompile Include="dllmain.cpp">
+      <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="stdafx.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+    </ClCompile>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/can_copcican_win32/can_copcican_win32.vcxproj.filters	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="ReadMe.txt" />
+    <None Include="can_copcican_win32.def">
+      <Filter>Source Files</Filter>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="stdafx.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="targetver.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="stdafx.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="can_copcican_win32.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="dllmain.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/can_copcican_win32/can_copcican_win32.vcxproj.user	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/can_copcican_win32/dllmain.cpp	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,22 @@
+// dllmain.cpp : Defines the entry point for the DLL application.
+#include "stdafx.h"
+
+BOOL APIENTRY DllMain( HMODULE hModule,
+                       DWORD  ul_reason_for_call,
+                       LPVOID lpReserved
+					 )
+{
+	switch (ul_reason_for_call)
+	{
+	case DLL_PROCESS_ATTACH:
+	case DLL_THREAD_ATTACH:
+
+		break;
+	case DLL_THREAD_DETACH:
+	case DLL_PROCESS_DETACH:
+
+		break;
+	}
+	return TRUE;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/can_copcican_win32/stdafx.cpp	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// can_copcican_win32.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/can_copcican_win32/stdafx.h	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,20 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
+// Windows Header Files:
+#include <windows.h>
+
+
+//#include "co_can.h"
+#include "public.h"
+#include "can_driver.h"
+#include "co_can_cinterface.h"
+
+// TODO: reference additional headers your program requires here
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/can_copcican_win32/targetver.h	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include <SDKDDKVer.h>
--- a/drivers/timers_kernel/timers_kernel.c	Fri Nov 12 22:02:32 2010 +0100
+++ b/drivers/timers_kernel/timers_kernel.c	Fri Nov 12 22:24:06 2010 +0100
@@ -1,5 +1,5 @@
 /*
-This file is part of CanFestival, a library implementing CanOpen Stack. 
+This file is part of CanFestival, a library implementing CanOpen Stack.
 
 Copyright (C): Edouard TISSERANT and Francis DUPIN
 
@@ -111,5 +111,9 @@
 
 void WaitReceiveTaskEnd(TASK_HANDLE *Thread)
 {
-	force_sig (SIGTERM, *Thread);
+        /* join thread here because force_sig() does not work */
+	while((*Thread)->state <= 0)
+	{
+	  ; /* >0 means stopped */
+	}
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/timers_kernel_xeno/Makefile.in	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,59 @@
+#! gmake
+
+#
+# Copyright (C) 2010 Cosateq GmbH & Co.KG
+#               http://www.cosateq.com/
+#               http://www.scale-rt.com/
+#
+# 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
+#
+
+#ifneq ($(KERNELRELEASE),)
+# Kbuild part of Makefile
+TARGET = SUB_TARGET
+CAN_DRIVER = SUB_CAN_DRIVER
+TIMERS_DRIVER = SUB_TIMERS_DRIVER
+
+EXTRA_CFLAGS := -I$(src)/../../include
+EXTRA_CFLAGS += -I$(src)/../../include/$(TARGET)
+EXTRA_CFLAGS += -I$(src)/../../include/$(CAN_DRIVER)
+EXTRA_CFLAGS += -I$(src)/../../include/$(TIMERS_DRIVER)
+EXTRA_CFLAGS += SUB_PROG_CFLAGS
+
+obj-m := $(TIMERS_DRIVER).o
+
+#else
+# Normal Makefile
+PREFIX = SUB_PREFIX
+KERNELDIR := SUB_KERNELDIR
+
+all: driver
+
+driver:
+	$(MAKE) -C $(KERNELDIR) M=$(shell pwd) modules
+
+clean:
+	$(MAKE) -C $(KERNELDIR) M=$(shell pwd) clean
+	rm -f Module.symvers
+
+mrproper: clean
+
+install:
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/timers_kernel_xeno/timers_kernel_xeno.c	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,288 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Cosateq GmbH & Co.KG
+               http://www.cosateq.com/
+               http://www.scale-rt.com/
+
+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
+*/
+
+#include <asm/current.h>
+
+#include <native/task.h>
+#include <native/timer.h>
+#include <native/sem.h>
+#include <native/mutex.h>
+#include <native/cond.h>
+#include <native/alarm.h>
+
+#include "applicfg.h"
+#include "can_driver.h"
+#include "timer.h"
+
+#define TIMERLOOP_TASK_CREATED        1
+
+TimerCallback_t exitall;
+
+RT_MUTEX condition_mutex;
+RT_SEM CanFestival_mutex;
+RT_SEM control_task;
+RT_COND timer_set;
+RT_TASK timerloop_task;
+
+RTIME last_time_read;
+RTIME last_occured_alarm;
+RTIME last_timeout_set;
+
+int stop_timer = 0;
+
+/**
+ * Init Mutex, Semaphores and Condition variable
+ */
+void TimerInit(void)
+{
+  	int ret = 0;
+  	char taskname[32];
+
+	// lock process in to RAM
+  	//mlockall(MCL_CURRENT | MCL_FUTURE);
+
+  	snprintf(taskname, sizeof(taskname), "S1-%d", current->pid);
+	rt_sem_create(&CanFestival_mutex, taskname, 1, S_FIFO);
+
+  	snprintf(taskname, sizeof(taskname), "S2-%d", current->pid);
+  	rt_sem_create(&control_task, taskname, 0, S_FIFO);
+
+  	snprintf(taskname, sizeof(taskname), "M1-%d", current->pid);
+  	rt_mutex_create(&condition_mutex, taskname);
+
+  	snprintf(taskname, sizeof(taskname), "C1-%d", current->pid);
+  	rt_cond_create(&timer_set, taskname);
+}
+
+/**
+ * Stop Timer Task
+ * @param exitfunction
+ */
+void StopTimerLoop(TimerCallback_t exitfunction)
+{
+	exitall = exitfunction;
+	stop_timer = 1;
+	rt_cond_signal(&timer_set);
+}
+
+void cleanup_all(void)
+{
+	/* normally this will fail with a non-periodic task that has already ended at this time */
+	if (rt_task_suspend(&timerloop_task) != 0){
+		printk("Failed to join with Timerloop task\n");
+	}
+	rt_task_delete(&timerloop_task);
+}
+
+/**
+ * Clean all Semaphores, mutex, condition variable and main task
+ */
+void TimerCleanup(void)
+{
+	rt_sem_delete(&CanFestival_mutex);
+	rt_mutex_delete(&condition_mutex);
+	rt_cond_delete(&timer_set);
+	rt_sem_delete(&control_task);
+
+	/* normally this will fail with a non-periodic task that has already ended at this time */
+	if (rt_task_suspend(&timerloop_task) != 0){
+		printk("Failed to join with Timerloop task\n");
+	}
+	rt_task_delete(&timerloop_task);
+}
+
+/**
+ * Take a semaphore
+ */
+void EnterMutex(void)
+{
+	rt_sem_p(&CanFestival_mutex, TM_INFINITE);
+}
+
+/**
+ * Signaling a semaphore
+ */
+void LeaveMutex(void)
+{
+	rt_sem_v(&CanFestival_mutex);
+}
+
+static TimerCallback_t init_callback;
+
+/**
+ * Timer Task
+ */
+void timerloop_task_proc(void *arg)
+{
+	int ret = 0;
+
+	getElapsedTime();
+	last_timeout_set = 0;
+	last_occured_alarm = last_time_read;
+
+	/* trigger first alarm */
+	SetAlarm(NULL, 0, init_callback, 0, 0);
+	RTIME current_time;
+	RTIME real_alarm;
+	do{
+
+		rt_mutex_acquire(&condition_mutex, TM_INFINITE);
+		if(last_timeout_set == TIMEVAL_MAX)
+		{
+			ret = rt_cond_wait(
+				&timer_set,
+				&condition_mutex,
+				TM_INFINITE
+				);		/* Then sleep until next message*/
+			rt_mutex_release(&condition_mutex);
+		}else{
+			current_time = rt_timer_read();
+			real_alarm = last_time_read + last_timeout_set;
+			ret = rt_cond_wait( /* sleep until next deadline */
+				&timer_set,
+				&condition_mutex,
+				(real_alarm - current_time)); /* else alarm consider expired */
+			if(ret == -ETIMEDOUT){
+				last_occured_alarm = real_alarm;
+				rt_mutex_release(&condition_mutex);
+				EnterMutex();
+				TimeDispatch();
+				LeaveMutex();
+			}else{
+				rt_mutex_release(&condition_mutex);
+			}
+		}
+	}while ((ret == 0 || ret == -EINTR || ret == -ETIMEDOUT) && !stop_timer);
+
+	if(exitall){
+		EnterMutex();
+		exitall(NULL,0);
+		LeaveMutex();
+	}
+}
+
+/**
+ * Create the Timer Task
+ * @param _init_callback
+ */
+void StartTimerLoop(TimerCallback_t _init_callback)
+{
+	int ret = 0;
+	stop_timer = 0;
+	init_callback = _init_callback;
+
+	char taskname[32];
+	snprintf(taskname, sizeof(taskname), "timerloop-%d", current->pid);
+
+	/* create timerloop_task */
+	ret = rt_task_create(&timerloop_task, taskname, 0, 50, 0); /* T_JOINABLE only in user space */
+	if (ret) {
+		printk("Failed to create timerloop_task, code %d\n",ret);
+		return;
+	}
+
+	/* start timerloop_task */
+	ret = rt_task_start(&timerloop_task,&timerloop_task_proc,NULL);
+	if (ret) {
+		printk("Failed to start timerloop_task, code %u\n",ret);
+		goto error;
+	}
+
+	return;
+
+error:
+	cleanup_all();
+}
+
+/**
+ * Create the CAN Receiver Task
+ * @param fd0 CAN port
+ * @param *ReceiveLoop_task CAN receiver task
+ * @param *ReceiveLoop_task_proc CAN receiver function
+ */
+void CreateReceiveTask(CAN_PORT fd0, TASK_HANDLE *ReceiveLoop_task, void* ReceiveLoop_task_proc)
+{
+	int ret;
+	static int id = 0;
+	char taskname[32];
+	snprintf(taskname, sizeof(taskname), "canloop%d-%d", id, current->pid);
+	id++;
+
+	/* create ReceiveLoop_task */
+	ret = rt_task_create(ReceiveLoop_task,taskname,0,50,0); /* T_JOINABLE only in user space */
+	if (ret) {
+		printk("Failed to create ReceiveLoop_task number %d, code %d\n", id, ret);
+		return;
+	}
+
+	/* periodic task for Xenomai kernel realtime */
+	rt_task_set_periodic(ReceiveLoop_task, 0, 1 * 1000 * 1000); /* 1ms */
+
+	/* start ReceiveLoop_task */
+	ret = rt_task_start(ReceiveLoop_task, ReceiveLoop_task_proc,(void*)fd0);
+	if (ret) {
+		printk("Failed to start ReceiveLoop_task number %d, code %d\n", id, ret);
+		return;
+	}
+	rt_sem_v(&control_task);
+}
+
+/**
+ * Wait for the CAN Receiver Task end
+ * @param *ReceiveLoop_task CAN receiver thread
+ */
+void WaitReceiveTaskEnd(TASK_HANDLE *ReceiveLoop_task)
+{
+	/* normally this will fail with a non-periodic task that has already ended at this time */
+	if (rt_task_suspend(ReceiveLoop_task) != 0){
+		printk("Failed to join with Receive task\n");
+	}
+	rt_task_delete(ReceiveLoop_task);
+}
+
+/**
+ * Set timer for the next wakeup
+ * @param value
+ */
+void setTimer(TIMEVAL value)
+{
+	rt_mutex_acquire(&condition_mutex, TM_INFINITE);
+	last_timeout_set = value;
+	rt_mutex_release(&condition_mutex);
+	rt_cond_signal(&timer_set);
+}
+
+/**
+ * Get the elapsed time since the last alarm
+ * @return a time in nanoseconds
+ */
+TIMEVAL getElapsedTime(void)
+{
+	RTIME res;
+	rt_mutex_acquire(&condition_mutex, TM_INFINITE);
+	last_time_read = rt_timer_read();
+	res = last_time_read - last_occured_alarm;
+	rt_mutex_release(&condition_mutex);
+	return res;
+}
--- a/drivers/timers_win32/timers_win32.c	Fri Nov 12 22:02:32 2010 +0100
+++ b/drivers/timers_win32/timers_win32.c	Fri Nov 12 22:24:06 2010 +0100
@@ -77,7 +77,11 @@
 	CloseHandle(*Thread);
 }
 
+#if !defined(WIN32) || defined(__CYGWIN__)
 int TimerThreadLoop(void)
+#else
+DWORD TimerThreadLoop(LPVOID arg)
+#endif
 {
 
 
--- a/drivers/unix/Makefile.in	Fri Nov 12 22:02:32 2010 +0100
+++ b/drivers/unix/Makefile.in	Fri Nov 12 22:24:06 2010 +0100
@@ -2,24 +2,24 @@
 
 #
 # 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
-# 
+#
 
 #ifneq ($(KERNELRELEASE),)
 # Kbuild part of Makefile
@@ -56,6 +56,13 @@
 all: driver
 
 ifeq ($(TIMERS_DRIVER), timers_kernel)
+USE_KERNEL_TIMER = true
+endif
+ifeq ($(TIMERS_DRIVER), timers_kernel_xeno)
+USE_KERNEL_TIMER = true
+endif
+
+ifeq ($(USE_KERNEL_TIMER), true)
 OBJS := $(shell echo $(OBJS) | sed "s:$(TARGET)_::g")
 EXTRA_CFLAGS := $(shell echo $(INCLUDES) | sed "s:-I:-I$(src)/:g")
 EXTRA_CFLAGS += $(PROG_CFLAGS)
@@ -75,7 +82,7 @@
 	rm -f Module.symvers
 
 install:
-	
+
 
 else
 CFLAGS = SUB_OPT_CFLAGS
--- a/drivers/unix/unix.c	Fri Nov 12 22:02:32 2010 +0100
+++ b/drivers/unix/unix.c	Fri Nov 12 22:24:06 2010 +0100
@@ -1,5 +1,5 @@
 /*
-This file is part of CanFestival, a library implementing CanOpen Stack. 
+This file is part of CanFestival, a library implementing CanOpen Stack.
 
 Copyright (C): Edouard TISSERANT and Francis DUPIN
 
@@ -26,6 +26,7 @@
 #else
 #include <linux/module.h>
 #endif
+#include <linux/delay.h>
 
 #ifndef NOT_USE_DYNAMIC_LOADING
 #define DLL_CALL(funcname) (* funcname##_driver)
@@ -95,7 +96,7 @@
 {
 	LIB_HANDLE handle = NULL;
 	char *error;
-	
+
 
 	if(handle==NULL)
 	{
@@ -106,7 +107,7 @@
 		fprintf (stderr, "%s\n", dlerror());
         	return NULL;
 	}
- 
+
 	/*Get function ptr*/
 	DLSYM(canReceive)
 	DLSYM(canSend)
@@ -142,7 +143,7 @@
 		res = DLL_CALL(canSend)(((CANPort*)port)->fd, m);
 		//EnterMutex();
 		return res; // OK
-	}               
+	}
 	return 1; // NOT OK
 }
 
@@ -161,6 +162,13 @@
                EnterMutex();
                canDispatch(((CANPort*)port)->d, &m);
                LeaveMutex();
+
+#ifdef __KERNEL__
+#ifdef USE_XENO
+               /* periodic task for Xenomai kernel realtime */
+               rt_task_wait_period(NULL);
+#endif
+#endif
        }
 }
 
@@ -178,19 +186,19 @@
 		if(!canports[i].used)
 		break;
 	}
-	
+
 #ifndef NOT_USE_DYNAMIC_LOADING
 	if (&DLL_CALL(canOpen)==NULL) {
         	fprintf(stderr,"CanOpen : Can Driver dll not loaded\n");
         	return NULL;
 	}
-#endif	
+#endif
 	CAN_HANDLE fd0 = DLL_CALL(canOpen)(board);
 	if(fd0){
 		canports[i].used = 1;
 		canports[i].fd = fd0;
 		canports[i].d = d;
-		d->canHandle = (CAN_PORT)&canports[i];		
+		d->canHandle = (CAN_PORT)&canports[i];
 		CreateReceiveTask(&(canports[i]), &canports[i].receiveTask, &canReceiveLoop);
 		return (CAN_PORT)&canports[i];
 	}else{
@@ -207,17 +215,18 @@
 int canClose(CO_Data * d)
 {
 	UNS8 res;
-	
+
 	((CANPort*)d->canHandle)->used = 0;
 	CANPort* tmp = (CANPort*)d->canHandle;
-	d->canHandle = NULL;
-	
+
+	// kill receiver task before port is closed and handle set to NULL
+	WaitReceiveTaskEnd(&tmp->receiveTask);
+
 	// close CAN port
 	res = DLL_CALL(canClose)(tmp->fd);
 
-	// kill receiver task
-	WaitReceiveTaskEnd(&tmp->receiveTask);
-	
+	d->canHandle = NULL;
+
 	return res;
 }
 
@@ -236,7 +245,7 @@
 		res = DLL_CALL(canChangeBaudRate)(((CANPort*)port)->fd, baud);
 		//EnterMutex();
 		return res; // OK
-	}               
+	}
 	return 1; // NOT OK
 }
 
--- a/drivers/win32/win32.c	Fri Nov 12 22:02:32 2010 +0100
+++ b/drivers/win32/win32.c	Fri Nov 12 22:24:06 2010 +0100
@@ -190,16 +190,18 @@
 	}
 
 	tmp = (CANPort*)d->canHandle;
-	d->canHandle = NULL;
 
 	if(tmp)
 	{
+	  // kill receiver task before port is closed and handle set to NULL
+	  WaitReceiveTaskEnd(&tmp->receiveTask);
+
 	  // close CAN port
 	  res = m_canClose(tmp->fd);
-
-	  // kill receiver task
-	  WaitReceiveTaskEnd(&tmp->receiveTask);
-	}
+	}
+
+	d->canHandle = NULL;
+
 	return res;
 }
 
--- a/examples/TestMasterSlave/TestMasterSlave.c	Fri Nov 12 22:02:32 2010 +0100
+++ b/examples/TestMasterSlave/TestMasterSlave.c	Fri Nov 12 22:24:06 2010 +0100
@@ -189,8 +189,10 @@
   /* install signal handler for manual break */
 	signal(SIGTERM, catch_signal);
 	signal(SIGINT, catch_signal);
+#endif
+	// Also Windows needs to initialize the Timer!
+	// Moving this line into the ifndef leads to a lethal crash!
 	TimerInit();
-#endif
 
 #ifndef NOT_USE_DYNAMIC_LOADING
 	if (LoadCanDriver(LibraryPath) == NULL)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/test_copcican_comedi/Makefile.in	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,66 @@
+#! gmake
+
+#
+# Copyright (C) 2010 Cosateq GmbH & Co.KG
+#               http://www.cosateq.com/
+#               http://www.scale-rt.com/
+#
+# 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
+#
+
+#ifneq ($(KERNELRELEASE),)
+# Kbuild part of Makefile
+TARGET = SUB_TARGET
+CAN_DRIVER = SUB_CAN_DRIVER
+TIMERS_DRIVER = SUB_TIMERS_DRIVER
+
+EXTRA_CFLAGS := -I$(src)/../../include
+EXTRA_CFLAGS += -I$(src)/../../include/$(TARGET)
+EXTRA_CFLAGS += -I$(src)/../../include/$(CAN_DRIVER)
+EXTRA_CFLAGS += -I$(src)/../../include/$(TIMERS_DRIVER)
+EXTRA_CFLAGS += -I/usr/src/comedi/include
+EXTRA_CFLAGS += SUB_PROG_CFLAGS
+
+OBJS := test_copcican_comedi.o
+
+obj-m := test_copcican_comedi.o
+test_copcican_comediko-objs := $(OBJS)
+
+#else
+# Normal Makefile
+CC = SUB_CC
+PREFIX = SUB_PREFIX
+KERNELDIR := SUB_KERNELDIR
+
+all: test_copcican_comedi
+
+test_copcican_comedi:
+	cat ../../drivers/can_copcican_comedi/Module.symvers > Module.symvers
+	$(MAKE) -C $(KERNELDIR) M=$(shell pwd) modules
+
+clean:
+	$(MAKE) -C $(KERNELDIR) M=$(shell pwd) clean
+	rm -f Module.symvers
+
+mrproper: clean
+	rm -f test_copcican_comedi.c
+
+install:
+	$(MAKE) -C $(KERNELDIR) M=$(shell pwd) modules_install
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/test_copcican_comedi/insert.sh	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+module="test_copcican_comedi"
+device="test_copcican_comedi"
+mode="664"
+
+# insert neccessary modules
+/sbin/insmod ../../drivers/can_copcican_comedi/can_copcican_comedi.ko
+/sbin/insmod ../../src/canfestival.ko
+
+# insert module with all arguments we got
+# and use a pathname, as newer modutils don't look in . by default
+/sbin/insmod ./$module.ko $* || exit 1
+
+# stale nodes and device files are created by COMEDI
+
+rmmod $module
+rmmod canfestival
+rmmod can_copcican_comedi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/test_copcican_comedi/test_copcican_comedi.c	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,120 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Cosateq GmbH & Co.KG
+               http://www.cosateq.com/
+               http://www.scale-rt.com/
+
+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
+*/
+
+/*
+	example for application with CO-PCICAN card.
+*/
+
+#include <linux/module.h>
+#include <linux/comedi.h>
+#include <linux/comedilib.h>
+#include "canfestival.h"
+
+/* only for mdelay() */
+#include <linux/delay.h>
+
+MODULE_LICENSE("GPL");
+
+#define CHTX 2 /* channel number of the CO-PCICAN */
+#define CHRX 0 /* channel number of the CO-PCICAN */
+
+void mySyncHandler( CO_Data* d )
+{
+  printk( "test_copcican_comedi:   got a SYNC message...\n" );
+}
+
+static int main( void )
+{
+  s_BOARD  bd;
+  CO_Data  myData;
+  CAN_PORT port;
+  Message myMessage;
+  const char busname[]  = "/dev/comedi0";
+  const char baudrate[] = "1M";
+  comedi_t *dev;
+
+  memset( &myData, 0x00, sizeof(CO_Data) );
+  myData.CurrentCommunicationState.csSYNC = 1;
+  myData.post_sync = mySyncHandler;
+  bd.busname  = (char*)busname;
+  bd.baudrate = (char*)baudrate;
+
+  printk( "test_copcican_comedi: This example sends three SYNCs from port#%u to port#%u with a CO-PCICAN card\n", CHTX, CHRX );
+
+  /* direction: 0=RX, 1=TX */
+  co_pcican_select_channel( CHRX, 0 );
+  co_pcican_select_channel( CHTX, 1 );
+
+  port = canOpen( &bd, &myData );
+
+  if( port == NULL )
+  {
+    /* something strange happenend */
+    return 0;
+  }
+
+  /* get device pointer to control the opened device */
+  dev = get_dev_of_port( port );
+
+  co_pcican_enter_config_mode( dev );
+  co_pcican_configure_selected_channel( dev, &bd, 0 );
+  co_pcican_configure_selected_channel( dev, &bd, 1 );
+  co_pcican_enter_run_mode( dev );
+
+  memset( &myMessage, 0x00, sizeof(Message) );
+  myMessage.cob_id = 0x80; /* SYNC message */
+  myMessage.len = 1;
+  myMessage.data[0] = 0xA5;
+
+  /* SEND HERE */
+  canSend( port, &myMessage );
+
+  myMessage.data[0] = 0x5A;
+  canSend( port, &myMessage );
+
+  myMessage.data[0] = 0xA5;
+  canSend( port, &myMessage );
+
+  /* mySyncHandler() is called by the receive thread and shows a received SYNC message in the kernel log */
+  mdelay( 1*1000 ); /* 1s */
+
+  canClose( &myData );
+
+  return 0;
+}
+
+static int init(void)
+{
+  printk("test_copcican_comedi for CanFestival loaded\n");
+
+  return main();
+}
+
+static void exit(void)
+{
+  printk("test_copcican_comedi unloaded\n");
+}
+
+module_init(init);
+module_exit(exit);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/test_copcican_linux/Makefile.in	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,76 @@
+#! gmake
+
+#
+# Copyright (C) 2010 Cosateq GmbH & Co.KG
+#               http://www.cosateq.com/
+#               http://www.scale-rt.com/
+#
+# 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)
+
+TEST_COPCICAN_LINUX_OBJS = test_copcican_linux.o
+
+OBJS = $(TEST_COPCICAN_LINUX_OBJS) ../../drivers/$(TARGET)/libcanfestival_$(TARGET).a ../../src/libcanfestival.a
+
+all: test_copcican_linux
+
+../../src/libcanfestival.a:
+	$(MAKE) -C ../../src libcanfestival.a
+
+
+../../drivers/$(TARGET)/libcanfestival_$(TARGET).a:
+	$(MAKE) -C ../../drivers/$(TARGET) libcanfestival_$(TARGET).a
+
+
+test_copcican_linux: test_copcican_linux.c $(OBJS)
+	$(LD) $(CFLAGS) $(PROG_CFLAGS) ${PROGDEFINES} $(INCLUDES) -o $@ $(OBJS) $(EXE_CFLAGS)
+
+%o: %c
+	$(CC) $(CFLAGS) $(PROG_CFLAGS) ${PROGDEFINES} $(INCLUDES) -o $@ -c $<
+
+clean:
+	rm -f $(TEST_COPCICAN_LINUX_OBJS)
+	rm -f test_copcican_linux
+
+mrproper: clean
+	rm -f test_copcican_linux.c
+
+install: test_copcican_linux
+	mkdir -p $(PREFIX)/bin/
+	cp $< $(PREFIX)/bin/
+
+uninstall:
+	rm -f $(PREFIX)/bin/test_copcican_linux
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/test_copcican_linux/test_copcican_linux.c	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,130 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Cosateq GmbH & Co.KG
+               http://www.cosateq.com/
+               http://www.scale-rt.com/
+
+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
+*/
+
+/*
+	example for application with CO-PCICAN card.
+*/
+
+#include <stdio.h>
+#include "canfestival.h"
+
+/* only for usleep() */
+#include <linux/delay.h>
+
+#define CHTX 2 /* channel number of the CO-PCICAN */
+#define CHRX 0 /* channel number of the CO-PCICAN */
+
+void mySyncHandler( CO_Data* d )
+{
+  printf( "  got a SYNC message...\n" );
+}
+
+int main()
+{
+  LIB_HANDLE driver;
+
+  /* handles for additional CO-PCICAN functions */
+  int (*get_fd_of_port)( CAN_PORT port );
+  int (*co_pcican_enter_run_mode)( const int fd );
+  int (*co_pcican_enter_config_mode)( const int fd );
+  int (*co_pcican_select_channel)( const unsigned char channel, const unsigned int direction );
+  int (*co_pcican_configure_selected_channel)( const int fd, s_BOARD *board, const unsigned int direction );
+
+  s_BOARD  bd;
+  CO_Data  myData;
+  CAN_PORT port;
+  Message myMessage;
+  const char busname[]  = "/dev/co_pcican-0";
+  const char baudrate[] = "1M";
+  int fd;
+
+  memset( &myData, 0x00, sizeof(CO_Data) );
+  myData.CurrentCommunicationState.csSYNC = 1;
+  myData.post_sync = mySyncHandler;
+  bd.busname  = (char*)busname;
+  bd.baudrate = (char*)baudrate;
+
+  printf( "This example sends three SYNCs from port#%u to port#%u with a CO-PCICAN card\n", CHTX, CHRX );
+
+  driver = LoadCanDriver( "/usr/local/lib/libcanfestival_can_copcican_linux.so" );
+
+  if( driver == NULL )
+  {
+    /* something strange happenend */
+    return 0;
+  }
+
+  /* dynamic load of additional library functions */
+  get_fd_of_port = dlsym( driver, "get_fd_of_port" );
+  co_pcican_enter_run_mode = dlsym( driver, "co_pcican_enter_run_mode" );
+  co_pcican_enter_config_mode = dlsym( driver, "co_pcican_enter_config_mode" );
+  co_pcican_select_channel = dlsym( driver, "co_pcican_select_channel" );
+  co_pcican_configure_selected_channel = dlsym( driver, "co_pcican_configure_selected_channel" );
+
+  /* direction: 0=RX, 1=TX */
+  co_pcican_select_channel( CHRX, 0 );
+  co_pcican_select_channel( CHTX, 1 );
+
+  port = canOpen( &bd, &myData );
+
+  if( port == NULL )
+  {
+    UnLoadCanDriver( driver );
+
+    /* something strange happenend */
+    return 0;
+  }
+
+  /* get file descriptor to control the opened device */
+  fd = get_fd_of_port( port );
+
+  co_pcican_enter_config_mode( fd );
+  co_pcican_configure_selected_channel( fd, &bd, 0 );
+  co_pcican_configure_selected_channel( fd, &bd, 1 );
+  co_pcican_enter_run_mode( fd );
+
+  memset( &myMessage, 0x00, sizeof(Message) );
+  myMessage.cob_id = 0x80; /* SYNC message */
+  myMessage.len = 1;
+  myMessage.data[0] = 0xA5;
+
+  /* SEND HERE */
+  canSend( port, &myMessage );
+
+  myMessage.data[0] = 0x5A;
+  canSend( port, &myMessage );
+
+  myMessage.data[0] = 0xA5;
+  canSend( port, &myMessage );
+
+  /* mySyncHandler() is called by the receive thread and shows a received SYNC message on console */
+  usleep( 1*1000*1000 ); /* 1s */
+
+  canClose( &myData );
+
+  UnLoadCanDriver( driver );
+
+  return 0;
+}
+
--- a/include/can_driver.h	Fri Nov 12 22:02:32 2010 +0100
+++ b/include/can_driver.h	Fri Nov 12 22:24:06 2010 +0100
@@ -46,7 +46,11 @@
 };
 
 #ifndef DLL_CALL
+#if !defined(WIN32) || defined(__CYGWIN__)
 #define DLL_CALL(funcname) funcname##_driver
+#else
+//Windows was missing the definition of the calling convention
+#define DLL_CALL(funcname) __stdcall funcname##_driver
 #endif
 
 #ifndef FCT_PTR_INIT
--- a/include/objacces.h	Fri Nov 12 22:02:32 2010 +0100
+++ b/include/objacces.h	Fri Nov 12 22:24:06 2010 +0100
@@ -1,287 +1,287 @@
-/*
-This file is part of CanFestival, a library implementing CanOpen Stack. 
-
-Copyright (C): Edouard TISSERANT and Francis DUPIN
-
-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
- *  @brief Responsible for accessing the object dictionary.
- *
- *  This file contains functions for accessing the object dictionary and
- *  variables that are contained by the object dictionary.
- *  Accessing the object dictionary contains setting local variables
- *  as PDOs and accessing (read/write) all entries of the object dictionary
- *  @warning Only the basic entries of an object dictionary are included
- *           at the moment.
- */
-
-/** @defgroup od Object Dictionary Management
- *  @brief The Object Dictionary is the heart of each CANopen device containing all communication and application objects.
- *  @ingroup userapi
- */
- 
-#ifndef __objacces_h__
-#define __objacces_h__
-
-#include <applicfg.h>
-
-
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack. 
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+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
+ *  @brief Responsible for accessing the object dictionary.
+ *
+ *  This file contains functions for accessing the object dictionary and
+ *  variables that are contained by the object dictionary.
+ *  Accessing the object dictionary contains setting local variables
+ *  as PDOs and accessing (read/write) all entries of the object dictionary
+ *  @warning Only the basic entries of an object dictionary are included
+ *           at the moment.
+ */
+
+/** @defgroup od Object Dictionary Management
+ *  @brief The Object Dictionary is the heart of each CANopen device containing all communication and application objects.
+ *  @ingroup userapi
+ */
+ 
+#ifndef __objacces_h__
+#define __objacces_h__
+
+#include <applicfg.h>
+
+
 #ifdef __cplusplus
 extern "C" {
-#endif
-
-
-typedef UNS32 (*valueRangeTest_t)(UNS8 typeValue, void *Value);
-typedef void (* storeODSubIndex_t)(CO_Data* d, UNS16 wIndex, UNS8 bSubindex);
-void _storeODSubIndex (CO_Data* d, UNS16 wIndex, UNS8 bSubindex);
-
-/**
- * @brief Print MSG_WAR (s) if error to the access to the object dictionary occurs.
- * 
- * You must uncomment the lines in the file objaccess.c :\n
- * //#define DEBUG_CAN\n
- * //#define DEBUG_WAR_CONSOLE_ON\n
- * //#define DEBUG_ERR_CONSOLE_ON\n\n
- * Beware that sometimes, we force the sizeDataDict or sizeDataGiven to 0, when we wants to use
- * this function but we do not have the access to the right value. One example is
- * getSDOerror(). So do not take attention to these variables if they are null.
- * @param index
- * @param subIndex
- * @param sizeDataDict Size of the data defined in the dictionary
- * @param sizeDataGiven Size data given by the user.
- * @param code error code to print. (SDO abort code. See file def.h)
- * @return
- */ 
-UNS8 accessDictionaryError(UNS16 index, UNS8 subIndex, 
-			   UNS32 sizeDataDict, UNS32 sizeDataGiven, UNS32 code);
-
-
-/* _getODentry() Reads an entry from the object dictionary.\n
- * 
- *    use getODentry() macro to read from object and endianize
- *    use readLocalDict() macro to read from object and not endianize   
- *
- * @code
- * // Example usage:
- * UNS8  *pbData;
- * UNS8 length;
- * UNS32 returnValue;
- *
- * returnValue = getODentry( (UNS16)0x100B, (UNS8)1, 
- * (void * *)&pbData, (UNS8 *)&length );
- * if( returnValue != SUCCESSFUL )
- * {
- *     // error handling
- * }
- * @endcode 
- * @param *d Pointer to a CAN object data structure
- * @param wIndex The index in the object dictionary where you want to read
- *               an entry
- * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is
- *                  used to tell you how many valid entries you can find
- *                  in this index. Look at the canopen standard for further
- *                  information
- * @param *pDestData Pointer to the pointer which points to the variable where
- *                   the value of this object dictionary entry should be copied
- * @param pExpectedSize This function writes the size of the copied value (in Byte)
- *                      into this variable.
- * @param *pDataType Pointer to the type of the data. See objdictdef.h
- * @param CheckAccess if other than 0, do not read if the data is Write Only
- *                    [Not used today. Put always 0].
- * @param Endianize  When not 0, data is endianized into network byte order
- *                   when 0, data is not endianized and copied in machine native
- *                   endianness 
- * @return 
- * - OD_SUCCESSFUL is returned upon success. 
- * - SDO abort code is returned if error occurs . (See file def.h)
- */
-UNS32 _getODentry( CO_Data* d,
-                   UNS16 wIndex,
-                   UNS8 bSubindex,
-                   void * pDestData,
-                   UNS32 * pExpectedSize,
-                   UNS8 * pDataType,
-                   UNS8 checkAccess,
-                   UNS8 endianize);
-
-/** 
- * @ingroup od
- * @brief getODentry() to read from object and endianize
- * @param OD Pointer to a CAN object data structure
- * @param wIndex The index in the object dictionary where you want to read
- *                an entry
- * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is
- *                  used to tell you how many valid entries you can find
- *                  in this index. Look at the canopen standard for further
- *                  information
- * @param *pDestData Pointer to the pointer which points to the variable where
- *                   the value of this object dictionary entry should be copied
- * @param pExpectedSize This function writes the size of the copied value (in Byte)
- *                      into this variable.
- * @param *pDataType Pointer to the type of the data. See objdictdef.h
- * @param checkAccess Flag that indicate if a check rights must be perfomed (0 : no , other than 0 : yes)
- * @param endianize  Set to 1 : endianized into network byte order 
- * @return 
- * - OD_SUCCESSFUL is returned upon success. 
- * - SDO abort code is returned if error occurs . (See file def.h)
- */
-#define getODentry( OD, wIndex, bSubindex, pDestData, pExpectedSize, \
-		          pDataType,  checkAccess)                         \
-       _getODentry( OD, wIndex, bSubindex, pDestData, pExpectedSize, \
-		          pDataType,  checkAccess, 1)            
-
-/** 
- * @ingroup od
- * @brief readLocalDict() reads an entry from the object dictionary, but in 
- * contrast to getODentry(), readLocalDict() doesn't endianize entry and reads
- * entry in machine native endianness. 
- * @param OD Pointer to a CAN object data structure
- * @param wIndex The index in the object dictionary where you want to read
- *                an entry
- * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is
- *                  used to tell you how many valid entries you can find
- *                  in this index. Look at the canopen standard for further
- *                  information
- * @param *pDestData Pointer to the pointer which points to the variable where
- *                   the value of this object dictionary entry should be copied
- * @param pExpectedSize This function writes the size of the copied value (in Byte)
- *                      into this variable.
- * @param *pDataType Pointer to the type of the data. See objdictdef.h
- * @param checkAccess if other than 0, do not read if the data is Write Only
- *                    [Not used today. Put always 0].
- * @param endianize Set to 0, data is not endianized and copied in machine native
- *                  endianness 
- * @return 
- * - OD_SUCCESSFUL is returned upon success. 
- * - SDO abort code is returned if error occurs . (See file def.h)
- */
-#define readLocalDict( OD, wIndex, bSubindex, pDestData, pExpectedSize, \
-		          pDataType,  checkAccess)                         \
-       _getODentry( OD, wIndex, bSubindex, pDestData, pExpectedSize, \
-		          pDataType,  checkAccess, 0)
-
-/* By this function you can write an entry into the object dictionary
- * @param *d Pointer to a CAN object data structure
- * @param wIndex The index in the object dictionary where you want to write
- *               an entry
- * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is
- *                  used to tell you how many valid entries you can find
- *                  in this index. Look at the canopen standard for further
- *                  information
- * @param *pSourceData Pointer to the variable that holds the value that should
- *                     be copied into the object dictionary
- * @param *pExpectedSize The size of the value (in Byte).
- * @param checkAccess Flag that indicate if a check rights must be perfomed (0 : no , other than 0 : yes)
- * @param endianize When not 0, data is endianized into network byte order
- *                  when 0, data is not endianized and copied in machine native
- *                  endianness   
- * @return 
- * - OD_SUCCESSFUL is returned upon success. 
- * - SDO abort code is returned if error occurs . (See file def.h)
- */
-UNS32 _setODentry( CO_Data* d,
-                   UNS16 wIndex,
-                   UNS8 bSubindex,
-                   void * pSourceData,
-                   UNS32 * pExpectedSize,
-                   UNS8 checkAccess,
-                   UNS8 endianize);
-
-/**
- * @ingroup od
- * @brief setODentry converts SourceData from network byte order to machine native 
- * format, and writes that to OD.
- * @code
- * // Example usage:
- * UNS8 B;
- * B = 0xFF; // set transmission type
- *
- * retcode = setODentry( (UNS16)0x1800, (UNS8)2, &B, sizeof(UNS8), 1 );
- * @endcode
- * @param d Pointer to a CAN object data structure
- * @param wIndex The index in the object dictionary where you want to write
- *               an entry
- * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is
- *                  used to tell you how many valid entries you can find
- *                  in this index. Look at the canopen standard for further
- *                  information
- * @param *pSourceData Pointer to the variable that holds the value that should
- *                     be copied into the object dictionary
- * @param *pExpectedSize The size of the value (in Byte).
- * @param checkAccess Flag that indicate if a check rights must be perfomed (0 : no , other than 0 : yes)
- * @param endianize Set to 1 : endianized into network byte order
- * @return 
- * - OD_SUCCESSFUL is returned upon success. 
- * - SDO abort code is returned if error occurs . (See file def.h)
- */
-#define setODentry( d, wIndex, bSubindex, pSourceData, pExpectedSize, \
-                  checkAccess) \
-       _setODentry( d, wIndex, bSubindex, pSourceData, pExpectedSize, \
-                  checkAccess, 1)
-
-/** @fn UNS32 writeLocalDict(d, wIndex, bSubindex, pSourceData, pExpectedSize, checkAccess)
- * @ingroup od
- * @hideinitializer
- * @brief Writes machine native SourceData to OD.
- * @param d Pointer to a CAN object data structure
- * @param wIndex The index in the object dictionary where you want to write
- *               an entry
- * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is
- *                  used to tell you how many valid entries you can find
- *                  in this index. Look at the canopen standard for further
- *                  information
- * @param *pSourceData Pointer to the variable that holds the value that should
- *                     be copied into the object dictionary
- * @param *pExpectedSize The size of the value (in Byte).
- * @param checkAccess Flag that indicate if a check rights must be perfomed (0 : no , other than 0 : yes)
- * @param endianize Data is not endianized and copied in machine native endianness 
- * @return 
- * - OD_SUCCESSFUL is returned upon success. 
- * - SDO abort code is returned if error occurs . (See file def.h)
- * \n\n
- * @code
- * // Example usage:
- * UNS8 B;
- * B = 0xFF; // set transmission type
- *
- * retcode = writeLocalDict( (UNS16)0x1800, (UNS8)2, &B, sizeof(UNS8), 1 );
- * @endcode
- */
-#define writeLocalDict( d, wIndex, bSubindex, pSourceData, pExpectedSize, checkAccess) \
-       _setODentry( d, wIndex, bSubindex, pSourceData, pExpectedSize, checkAccess, 0)
-
-
-
-/**
- * @brief Scan the index of object dictionary. Used only by setODentry and getODentry.
- * @param *d Pointer to a CAN object data structure
- * @param wIndex
- * @param *errorCode :  OD_SUCCESSFUL if index foundor SDO abort code. (See file def.h)
- * @param **Callback
- * @return NULL if index not found. Else : return the table part of the object dictionary.
- */
- const indextable * scanIndexOD (CO_Data* d, UNS16 wIndex, UNS32 *errorCode, ODCallback_t **Callback);
-
-UNS32 RegisterSetODentryCallBack(CO_Data* d, UNS16 wIndex, UNS8 bSubindex, ODCallback_t Callback);
-
+#endif
+
+
+typedef UNS32 (*valueRangeTest_t)(UNS8 typeValue, void *Value);
+typedef void (* storeODSubIndex_t)(CO_Data* d, UNS16 wIndex, UNS8 bSubindex);
+void _storeODSubIndex (CO_Data* d, UNS16 wIndex, UNS8 bSubindex);
+
+/**
+ * @brief Print MSG_WAR (s) if error to the access to the object dictionary occurs.
+ * 
+ * You must uncomment the lines in the file objaccess.c :\n
+ * //#define DEBUG_CAN\n
+ * //#define DEBUG_WAR_CONSOLE_ON\n
+ * //#define DEBUG_ERR_CONSOLE_ON\n\n
+ * Beware that sometimes, we force the sizeDataDict or sizeDataGiven to 0, when we wants to use
+ * this function but we do not have the access to the right value. One example is
+ * getSDOerror(). So do not take attention to these variables if they are null.
+ * @param index
+ * @param subIndex
+ * @param sizeDataDict Size of the data defined in the dictionary
+ * @param sizeDataGiven Size data given by the user.
+ * @param code error code to print. (SDO abort code. See file def.h)
+ * @return
+ */ 
+UNS8 accessDictionaryError(UNS16 index, UNS8 subIndex, 
+			   UNS32 sizeDataDict, UNS32 sizeDataGiven, UNS32 code);
+
+
+/* _getODentry() Reads an entry from the object dictionary.\n
+ * 
+ *    use getODentry() macro to read from object and endianize
+ *    use readLocalDict() macro to read from object and not endianize   
+ *
+ * @code
+ * // Example usage:
+ * UNS8  *pbData;
+ * UNS8 length;
+ * UNS32 returnValue;
+ *
+ * returnValue = getODentry( (UNS16)0x100B, (UNS8)1, 
+ * (void * *)&pbData, (UNS8 *)&length );
+ * if( returnValue != SUCCESSFUL )
+ * {
+ *     // error handling
+ * }
+ * @endcode 
+ * @param *d Pointer to a CAN object data structure
+ * @param wIndex The index in the object dictionary where you want to read
+ *               an entry
+ * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is
+ *                  used to tell you how many valid entries you can find
+ *                  in this index. Look at the canopen standard for further
+ *                  information
+ * @param *pDestData Pointer to the pointer which points to the variable where
+ *                   the value of this object dictionary entry should be copied
+ * @param pExpectedSize This function writes the size of the copied value (in Byte)
+ *                      into this variable.
+ * @param *pDataType Pointer to the type of the data. See objdictdef.h
+ * @param CheckAccess if other than 0, do not read if the data is Write Only
+ *                    [Not used today. Put always 0].
+ * @param Endianize  When not 0, data is endianized into network byte order
+ *                   when 0, data is not endianized and copied in machine native
+ *                   endianness 
+ * @return 
+ * - OD_SUCCESSFUL is returned upon success. 
+ * - SDO abort code is returned if error occurs . (See file def.h)
+ */
+UNS32 _getODentry( CO_Data* d,
+                   UNS16 wIndex,
+                   UNS8 bSubindex,
+                   void * pDestData,
+                   UNS32 * pExpectedSize,
+                   UNS8 * pDataType,
+                   UNS8 checkAccess,
+                   UNS8 endianize);
+
+/** 
+ * @ingroup od
+ * @brief getODentry() to read from object and endianize
+ * @param OD Pointer to a CAN object data structure
+ * @param wIndex The index in the object dictionary where you want to read
+ *                an entry
+ * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is
+ *                  used to tell you how many valid entries you can find
+ *                  in this index. Look at the canopen standard for further
+ *                  information
+ * @param *pDestData Pointer to the pointer which points to the variable where
+ *                   the value of this object dictionary entry should be copied
+ * @param pExpectedSize This function writes the size of the copied value (in Byte)
+ *                      into this variable.
+ * @param *pDataType Pointer to the type of the data. See objdictdef.h
+ * @param checkAccess Flag that indicate if a check rights must be perfomed (0 : no , other than 0 : yes)
+ * @param endianize  Set to 1 : endianized into network byte order 
+ * @return 
+ * - OD_SUCCESSFUL is returned upon success. 
+ * - SDO abort code is returned if error occurs . (See file def.h)
+ */
+#define getODentry( OD, wIndex, bSubindex, pDestData, pExpectedSize, \
+		          pDataType,  checkAccess)                         \
+       _getODentry( OD, wIndex, bSubindex, pDestData, pExpectedSize, \
+		          pDataType,  checkAccess, 1)            
+
+/** 
+ * @ingroup od
+ * @brief readLocalDict() reads an entry from the object dictionary, but in 
+ * contrast to getODentry(), readLocalDict() doesn't endianize entry and reads
+ * entry in machine native endianness. 
+ * @param OD Pointer to a CAN object data structure
+ * @param wIndex The index in the object dictionary where you want to read
+ *                an entry
+ * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is
+ *                  used to tell you how many valid entries you can find
+ *                  in this index. Look at the canopen standard for further
+ *                  information
+ * @param *pDestData Pointer to the pointer which points to the variable where
+ *                   the value of this object dictionary entry should be copied
+ * @param pExpectedSize This function writes the size of the copied value (in Byte)
+ *                      into this variable.
+ * @param *pDataType Pointer to the type of the data. See objdictdef.h
+ * @param checkAccess if other than 0, do not read if the data is Write Only
+ *                    [Not used today. Put always 0].
+ * @param endianize Set to 0, data is not endianized and copied in machine native
+ *                  endianness 
+ * @return 
+ * - OD_SUCCESSFUL is returned upon success. 
+ * - SDO abort code is returned if error occurs . (See file def.h)
+ */
+#define readLocalDict( OD, wIndex, bSubindex, pDestData, pExpectedSize, \
+		          pDataType,  checkAccess)                         \
+       _getODentry( OD, wIndex, bSubindex, pDestData, pExpectedSize, \
+		          pDataType,  checkAccess, 0)
+
+/* By this function you can write an entry into the object dictionary
+ * @param *d Pointer to a CAN object data structure
+ * @param wIndex The index in the object dictionary where you want to write
+ *               an entry
+ * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is
+ *                  used to tell you how many valid entries you can find
+ *                  in this index. Look at the canopen standard for further
+ *                  information
+ * @param *pSourceData Pointer to the variable that holds the value that should
+ *                     be copied into the object dictionary
+ * @param *pExpectedSize The size of the value (in Byte).
+ * @param checkAccess Flag that indicate if a check rights must be perfomed (0 : no , other than 0 : yes)
+ * @param endianize When not 0, data is endianized into network byte order
+ *                  when 0, data is not endianized and copied in machine native
+ *                  endianness   
+ * @return 
+ * - OD_SUCCESSFUL is returned upon success. 
+ * - SDO abort code is returned if error occurs . (See file def.h)
+ */
+UNS32 _setODentry( CO_Data* d,
+                   UNS16 wIndex,
+                   UNS8 bSubindex,
+                   void * pSourceData,
+                   UNS32 * pExpectedSize,
+                   UNS8 checkAccess,
+                   UNS8 endianize);
+
+/**
+ * @ingroup od
+ * @brief setODentry converts SourceData from network byte order to machine native 
+ * format, and writes that to OD.
+ * @code
+ * // Example usage:
+ * UNS8 B;
+ * B = 0xFF; // set transmission type
+ *
+ * retcode = setODentry( (UNS16)0x1800, (UNS8)2, &B, sizeof(UNS8), 1 );
+ * @endcode
+ * @param d Pointer to a CAN object data structure
+ * @param wIndex The index in the object dictionary where you want to write
+ *               an entry
+ * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is
+ *                  used to tell you how many valid entries you can find
+ *                  in this index. Look at the canopen standard for further
+ *                  information
+ * @param *pSourceData Pointer to the variable that holds the value that should
+ *                     be copied into the object dictionary
+ * @param *pExpectedSize The size of the value (in Byte).
+ * @param checkAccess Flag that indicate if a check rights must be perfomed (0 : no , other than 0 : yes)
+ * @param endianize Set to 1 : endianized into network byte order
+ * @return 
+ * - OD_SUCCESSFUL is returned upon success. 
+ * - SDO abort code is returned if error occurs . (See file def.h)
+ */
+#define setODentry( d, wIndex, bSubindex, pSourceData, pExpectedSize, \
+                  checkAccess) \
+       _setODentry( d, wIndex, bSubindex, pSourceData, pExpectedSize, \
+                  checkAccess, 1)
+
+/** @fn UNS32 writeLocalDict(d, wIndex, bSubindex, pSourceData, pExpectedSize, checkAccess)
+ * @ingroup od
+ * @hideinitializer
+ * @brief Writes machine native SourceData to OD.
+ * @param d Pointer to a CAN object data structure
+ * @param wIndex The index in the object dictionary where you want to write
+ *               an entry
+ * @param bSubindex The subindex of the Index. e.g. mostly subindex 0 is
+ *                  used to tell you how many valid entries you can find
+ *                  in this index. Look at the canopen standard for further
+ *                  information
+ * @param *pSourceData Pointer to the variable that holds the value that should
+ *                     be copied into the object dictionary
+ * @param *pExpectedSize The size of the value (in Byte).
+ * @param checkAccess Flag that indicate if a check rights must be perfomed (0 : no , other than 0 : yes)
+ * @param endianize Data is not endianized and copied in machine native endianness 
+ * @return 
+ * - OD_SUCCESSFUL is returned upon success. 
+ * - SDO abort code is returned if error occurs . (See file def.h)
+ * \n\n
+ * @code
+ * // Example usage:
+ * UNS8 B;
+ * B = 0xFF; // set transmission type
+ *
+ * retcode = writeLocalDict( (UNS16)0x1800, (UNS8)2, &B, sizeof(UNS8), 1 );
+ * @endcode
+ */
+#define writeLocalDict( d, wIndex, bSubindex, pSourceData, pExpectedSize, checkAccess) \
+       _setODentry( d, wIndex, bSubindex, pSourceData, pExpectedSize, checkAccess, 0)
+
+
+
+/**
+ * @brief Scan the index of object dictionary. Used only by setODentry and getODentry.
+ * @param *d Pointer to a CAN object data structure
+ * @param wIndex
+ * @param *errorCode :  OD_SUCCESSFUL if index foundor SDO abort code. (See file def.h)
+ * @param **Callback
+ * @return NULL if index not found. Else : return the table part of the object dictionary.
+ */
+ const indextable * scanIndexOD (CO_Data* d, UNS16 wIndex, UNS32 *errorCode, ODCallback_t **Callback);
+
+UNS32 RegisterSetODentryCallBack(CO_Data* d, UNS16 wIndex, UNS8 bSubindex, ODCallback_t Callback);
+
 #ifdef __cplusplus
 }
-#endif
-
-#endif /* __objacces_h__ */
+#endif
+
+#endif /* __objacces_h__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/timers_kernel_xeno/timerscfg.h	Fri Nov 12 22:24:06 2010 +0100
@@ -0,0 +1,42 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack. 
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+
+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
+*/
+
+#ifndef __TIMERSCFG_H__
+#define __TIMERSCFG_H__
+
+#include <native/task.h>
+#include <native/timer.h>
+#include <native/mutex.h>
+#include <native/cond.h>
+#include <native/sem.h>
+#include <native/alarm.h>
+
+// Time unit : ns
+// Time resolution : 64bit (~584 years)
+#define TIMEVAL RTIME
+#define TIMEVAL_MAX ~(RTIME)0
+#define MS_TO_TIMEVAL(ms)  rt_timer_ns2ticks((RTIME)ms*1000000)
+#define US_TO_TIMEVAL(us)  rt_timer_ns2ticks((RTIME)us*1000)
+
+#define TASK_HANDLE RT_TASK
+
+#endif
--- a/src/Makefile.in	Fri Nov 12 22:02:32 2010 +0100
+++ b/src/Makefile.in	Fri Nov 12 22:24:06 2010 +0100
@@ -2,24 +2,24 @@
 
 #
 # 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
-# 
+#
 
 ifneq ($(KERNELRELEASE),)
 # Kbuild part of Makefile
@@ -60,11 +60,18 @@
 OPT_CFLAGS = -O2
 endif
 
-# # # # Options # # # # 
+# # # # Options # # # #
 
 all: canfestival
 
 ifeq ($(TIMERS_DRIVER), timers_kernel)
+USE_KERNEL_TIMER = true
+endif
+ifeq ($(TIMERS_DRIVER), timers_kernel_xeno)
+USE_KERNEL_TIMER = true
+endif
+
+ifeq ($(USE_KERNEL_TIMER), true)
 OBJS := $(shell echo $(OBJS) | sed "s:$(TARGET)_::g")
 OBJS += symbols.o
 OBJS += ../drivers/unix/libcanfestival_$(TARGET).o
--- a/src/objacces.c	Fri Nov 12 22:02:32 2010 +0100
+++ b/src/objacces.c	Fri Nov 12 22:24:06 2010 +0100
@@ -40,10 +40,12 @@
 
 #include "data.h"
 
-#ifdef DEBUG_WAR_CONSOLE_ON
+//We need the function implementation for linking
+//Only a placeholder with a define isnt enough!
 UNS8 accessDictionaryError(UNS16 index, UNS8 subIndex,
                            UNS32 sizeDataDict, UNS32 sizeDataGiven, UNS32 code)
 {
+#ifdef DEBUG_WAR_CONSOLE_ON
   MSG_WAR(0x2B09,"Dictionary index : ", index);
   MSG_WAR(0X2B10,"           subindex : ", subIndex);
   switch (code) {
@@ -72,11 +74,10 @@
   default :
     MSG_WAR(0x2B20, "Unknown error code : ", code);
   }
+  #endif
+
   return 0;
 }
-#else
-#define accessDictionaryError(index, subIndex, sizeDataDict, sizeDataGiven, code)
-#endif
 
 UNS32 _getODentry( CO_Data* d,
                    UNS16 wIndex,
--- a/src/pdo.c	Fri Nov 12 22:02:32 2010 +0100
+++ b/src/pdo.c	Fri Nov 12 22:24:06 2010 +0100
@@ -487,8 +487,8 @@
 {
   /*store_as_last_message */
   d->PDO_status[pdoNum].last_message = *pdo;
-  MSG_WAR (0x396D, "sendPDO cobId :", UNS16_LE(pdo->cob_id));
-  MSG_WAR (0x396E, "     Nb octets  : ", pdo->len);
+  MSG_WAR (0x396D, "sendPDO cobId :", UNS16_LE(pdo.cob_id));
+  MSG_WAR (0x396E, "     Nb octets  : ", pdo.len);
 
   canSend (d->canHandle, pdo);
 }
@@ -512,16 +512,18 @@
 UNS8
 sendOnePDOevent (CO_Data * d, UNS32 pdoNum)
 {
+  UNS16 offsetObjdict;
+  Message pdo;
   if (!d->CurrentCommunicationState.csPDO ||
-      (d->PDO_status[pdoNum].transmit_type_parameter & PDO_INHIBITED))
+      !(d->PDO_status[pdoNum].transmit_type_parameter & PDO_INHIBITED))
     {
       return 0;
     }
 
-  UNS16 offsetObjdict = d->firstIndex->PDO_TRS + pdoNum;
+  offsetObjdict = d->firstIndex->PDO_TRS + pdoNum;
   MSG_WAR (0x3968, "  PDO is on EVENT. Trans type : ",
            *pTransmissionType);
-  Message pdo;
+  
   memset(&pdo, 0, sizeof(pdo));
   if (buildPDO (d, pdoNum, &pdo))
     {
--- a/src/symbols.c	Fri Nov 12 22:02:32 2010 +0100
+++ b/src/symbols.c	Fri Nov 12 22:24:06 2010 +0100
@@ -50,10 +50,12 @@
 
 // objacces.h
 EXPORT_SYMBOL (_storeODSubIndex);
+#ifdef DEBUG_WAR_CONSOLE_ON
 EXPORT_SYMBOL (accessDictionaryError);
-EXPORT_SYMBOL (getODentry);
-EXPORT_SYMBOL (setODentry);
-EXPORT_SYMBOL (writeLocalDict);
+#endif
+EXPORT_SYMBOL (_getODentry);
+EXPORT_SYMBOL (_setODentry);
+//EXPORT_SYMBOL (writeLocalDict);
 EXPORT_SYMBOL (scanIndexOD);
 EXPORT_SYMBOL (RegisterSetODentryCallBack);
 
--- a/src/timer.c	Fri Nov 12 22:02:32 2010 +0100
+++ b/src/timer.c	Fri Nov 12 22:24:06 2010 +0100
@@ -124,7 +124,7 @@
 	TIMEVAL next_wakeup = TIMEVAL_MAX; /* used to compute when should normaly occur next wakeup */
 	/* First run : change timer state depending on time */
 	/* Get time since timer signal */
-	TIMEVAL overrun = getElapsedTime();
+	UNS32 overrun = (UNS32)getElapsedTime();
 
 	TIMEVAL real_total_sleep_time = total_sleep_time + overrun;
 
@@ -142,8 +142,9 @@
 				}
 				else /* or period have expired */
 				{
-					/* set val as interval, with overrun correction */
-					row->val = row->interval - (overrun % row->interval);
+					/* set val as interval, with 32 bit overrun correction, */
+					/* modulo for 64 bit not available on all platforms     */
+					row->val = row->interval - (overrun % (UNS32)row->interval);
 					row->state = TIMER_TRIG_PERIOD; /* ask for trig, periodic */
 					/* Check if this new timer value is the soonest */
 					if(row->val < next_wakeup)