Rewrite win32 code (C only)
authorgreg
Wed, 15 Jul 2009 09:36:36 +0200
changeset 556 8296acd119a9
parent 555 ee24dcbd3e64
child 557 922873e5b409
Rewrite win32 code (C only)
drivers/timers_win32/Makefile.in
drivers/timers_win32/timers_win32.c
drivers/timers_win32/timers_win32.cpp
drivers/win32/Makefile.in
drivers/win32/win32.c
drivers/win32/win32.cpp
--- a/drivers/timers_win32/Makefile.in	Wed Jul 15 09:32:35 2009 +0200
+++ b/drivers/timers_win32/Makefile.in	Wed Jul 15 09:36:36 2009 +0200
@@ -46,7 +46,7 @@
 
 driver: $(OBJS)
 
-%o: %cpp
+%o: %c
 	$(CXX) $(CFLAGS) $(PROG_CFLAGS) ${PROGDEFINES} $(INCLUDES) -o $@ -c $<
 
 install:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/timers_win32/timers_win32.c	Wed Jul 15 09:36:36 2009 +0200
@@ -0,0 +1,161 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+Copyright (C) Win32 Port Leonid Tochinski
+
+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 <windows.h>
+#include <stdlib.h>
+#include <sys/timeb.h>
+
+#include "applicfg.h"
+#include "can_driver.h"
+#include "timer.h"
+#include "timers_driver.h"
+
+
+struct _timeb timebuffer;
+
+/* Synchronization Object Implementation */
+CRITICAL_SECTION CanFestival_mutex;
+HANDLE timer_thread = NULL;
+HANDLE timer = NULL;
+
+stop_timer=0;
+
+static TimerCallback_t init_callback;
+
+
+void EnterMutex(void)
+{
+	EnterCriticalSection(&CanFestival_mutex);
+}
+
+void LeaveMutex(void)
+{
+	LeaveCriticalSection(&CanFestival_mutex);
+}
+
+// --------------- CAN Receive Thread Implementation ---------------
+
+void CreateReceiveTask(CAN_HANDLE fd0, TASK_HANDLE* Thread, void* ReceiveLoopPtr)
+{
+	unsigned long thread_id = 0;
+	*Thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ReceiveLoopPtr, fd0, 0, &thread_id);
+}
+
+void WaitReceiveTaskEnd(TASK_HANDLE *Thread)
+{
+	WaitForSingleObject(*Thread, INFINITE);
+	CloseHandle(*Thread);
+}
+
+int TimerThreadLoop(void)
+{
+	int ret = 0;
+	EnterMutex();
+	// At first, TimeDispatch will call init_callback.
+	SetAlarm(NULL, 0, init_callback, 0, 0);
+	LeaveMutex();
+
+	while(!stop_timer && ret == WAIT_OBJECT_0)
+	{
+		ret = WaitForSingleObject(timer, INFINITE);
+		_ftime(&timebuffer);
+		EnterMutex();
+		TimeDispatch();
+		LeaveMutex();
+	}
+	return 0;
+}
+
+void TimerInit(void)
+{
+	LARGE_INTEGER liDueTime;
+	liDueTime.QuadPart = 0;
+
+	InitializeCriticalSection(&CanFestival_mutex);
+
+	timer = CreateWaitableTimer(NULL, TRUE, NULL);
+	if(NULL == timer)
+    {
+        printf("CreateWaitableTimer failed (%d)\n", GetLastError());
+    }
+
+	// Take first absolute time ref in milliseconds.
+	_ftime(&timebuffer);
+}
+
+void TimerCleanup(void)
+{
+	DeleteCriticalSection(&CanFestival_mutex);
+}
+
+void StopTimerLoop(TimerCallback_t exitfunction)
+{
+	EnterMutex();
+	exitfunction(NULL,0);
+	LeaveMutex();
+
+	stop_timer = 1;
+	CloseHandle(timer);
+	WaitForSingleObject(timer_thread, INFINITE);
+	CloseHandle(timer_thread);
+}
+
+void StartTimerLoop(TimerCallback_t _init_callback)
+{
+	unsigned long timer_thread_id;
+	stop_timer = 0;
+	init_callback = _init_callback;
+	timer_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)TimerThreadLoop, NULL, 0, &timer_thread_id);
+}
+
+/* Set the next alarm */
+void setTimer(TIMEVAL value)
+{
+	if(value == TIMEVAL_MAX)
+	{
+		/* cancel timer */
+		CancelWaitableTimer(timer);
+	}
+	else
+	{
+		LARGE_INTEGER liDueTime;
+
+		/* arg 2 of SetWaitableTimer take 100 ns interval */
+		liDueTime.QuadPart = -value;
+		//printf("SetTimer(%llu)\n", value);
+
+		if (!SetWaitableTimer(timer, &liDueTime, 0, NULL, NULL, FALSE))
+		{
+			printf("SetWaitableTimer failed (%d)\n", GetLastError());
+		}
+	}
+}
+
+/* Get the elapsed time since the last occured alarm */
+TIMEVAL getElapsedTime(void)
+{
+	struct _timeb timetmp;
+	_ftime(&timetmp);
+	return (timetmp.time - timebuffer.time) * 1000000 + (timetmp.millitm - timebuffer.millitm) * 1000;
+}
+
--- a/drivers/timers_win32/timers_win32.cpp	Wed Jul 15 09:32:35 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,246 +0,0 @@
-/*
-This file is part of CanFestival, a library implementing CanOpen Stack.
-
-Copyright (C): Edouard TISSERANT and Francis DUPIN
-Copyright (C) Win32 Port Leonid Tochinski
-
-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 <windows.h>
-#include <stdlib.h>
-
-extern "C"
-{
-#include "applicfg.h"
-#include "can_driver.h"
-#include "timer.h"
-#include "timers_driver.h"
-};
-
-// --------------- Synchronization Object Implementation ---------------
-class ccritical_section
-   {
-   public:
-      ccritical_section()
-         {
-         ::InitializeCriticalSection(&m_cs);
-         }
-      ~ccritical_section()
-         {
-         ::DeleteCriticalSection(&m_cs);
-         }
-      void enter()
-         {
-         ::EnterCriticalSection(&m_cs);
-         }
-      void leave()
-         {
-         ::LeaveCriticalSection(&m_cs);
-         }
-   private:
-      CRITICAL_SECTION m_cs;
-   };
-
-static ccritical_section g_cs;
-
-
-void EnterMutex(void)
-   {
-   g_cs.enter();
-   }
-
-void LeaveMutex(void)
-   {
-   g_cs.leave();
-   }
-// --------------- Synchronization Object Implementation ---------------
-
-
-// --------------- CAN Receive Thread Implementation ---------------
-
-void CreateReceiveTask(CAN_HANDLE fd0, TASK_HANDLE* Thread, void* ReceiveLoopPtr)
-   {
-   unsigned long thread_id = 0;
-   *Thread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ReceiveLoopPtr, fd0, 0, &thread_id);
-   }
-
-void WaitReceiveTaskEnd(TASK_HANDLE *Thread)
-   {
-   ::WaitForSingleObject(*Thread, INFINITE);
-   ::CloseHandle(*Thread);
-   //*Thread = NULL;
-   }
-// --------------- CAN Receive Thread Implementation ---------------
-
-
-// --------------- Timer Thread Implementation ---------------
-class class_timers
-   {
-   public:
-      class_timers();
-      ~class_timers();
-      void start_timer_thread();
-      void resume_timer_thread();
-      void stop_timer_thread();
-      void set_timer(TIMEVAL value);
-      TIMEVAL get_elapsed_time();
-   private:
-      TIMEVAL get_timer() const;   
-      static DWORD WINAPI timer_loop_thread_proc(void* arg);
-   private:
-      TIMEVAL m_last_occured_alarm_time;
-      volatile TIMEVAL m_last_alarm_set_time;
-      HANDLE m_timer_thread;
-      volatile bool m_continue_timer_loop;
-      bool m_use_hi_res_timer;
-      double m_counts_per_usec;
-   };
-
-class_timers::class_timers() : m_last_occured_alarm_time(TIMEVAL_MAX),
-      m_last_alarm_set_time(TIMEVAL_MAX),
-      m_timer_thread(0),
-      m_continue_timer_loop(false),
-      m_use_hi_res_timer(false),
-      m_counts_per_usec(0.)
-   {
-   // initialize hi resolution timer
-   LARGE_INTEGER counts_per_sec = {0, 0};
-   if (::QueryPerformanceFrequency(&counts_per_sec) && counts_per_sec.QuadPart > 0)
-      {
-      m_use_hi_res_timer = true;
-      m_counts_per_usec = counts_per_sec.QuadPart / 1000000.;
-      }
-   m_use_hi_res_timer = true;
-   }
-
-class_timers::~class_timers()
-   {
-   stop_timer_thread();
-   }
-
-// time is in micro seconds
-TIMEVAL class_timers::get_timer() const
-   {
-   if (m_use_hi_res_timer)
-      {
-      LARGE_INTEGER performance_count = {0, 0};
-      ::QueryPerformanceCounter(&performance_count);
-      return (TIMEVAL)(performance_count.QuadPart / m_counts_per_usec);
-      }
-   // hi-res timer is unavailable
-   return 1000 * ::GetTickCount();
-   }
-
-DWORD WINAPI class_timers::timer_loop_thread_proc(void* arg)
-   {
-   class_timers* This = reinterpret_cast<class_timers*>(arg);
-   while (This->m_continue_timer_loop)
-      {
-      TIMEVAL cur_time = This->get_timer();
-      if (cur_time >= This->m_last_alarm_set_time)
-         {
-         This->m_last_occured_alarm_time = cur_time;
-         This->m_last_alarm_set_time = TIMEVAL_MAX;         
-         EnterMutex();
-         TimeDispatch();
-         LeaveMutex();
-         }
-      else
-         {
-         ::Sleep(1);
-         }
-      }
-   return 0;
-   }
-
-void class_timers::start_timer_thread()
-   {
-   if (m_timer_thread == 0)
-      {
-      unsigned long thread_id = 0;
-      m_timer_thread = ::CreateThread(NULL, 0, &timer_loop_thread_proc, this, CREATE_SUSPENDED, &thread_id);
-      m_last_alarm_set_time = TIMEVAL_MAX;
-      m_last_occured_alarm_time = get_timer();
-      }
-   }
-
-void class_timers::resume_timer_thread()
-   {
-   if (m_timer_thread)
-      {
-      m_continue_timer_loop = true;
-      ::ResumeThread(m_timer_thread);
-      }
-   }
-
-void class_timers::stop_timer_thread()
-   {
-   if (m_timer_thread)
-      {
-      m_continue_timer_loop = false;
-      ::WaitForSingleObject(m_timer_thread, INFINITE);
-      ::CloseHandle(m_timer_thread);
-      m_timer_thread = 0;
-      }
-   }
-
-void class_timers::set_timer(TIMEVAL value)
-   {
-   m_last_alarm_set_time = (value == TIMEVAL_MAX) ? TIMEVAL_MAX : get_timer() + value;
-   }
-
-// elapsed time since last occured alarm
-TIMEVAL class_timers::get_elapsed_time()
-   {
-   return get_timer() - m_last_occured_alarm_time;
-   }
-
-// ----------------------------------------------------------
-
-static class_timers s_timers;
-
-void TimerCleanup(void)
-{
-	/* only used in realtime apps */
-}
-
-void StartTimerLoop(TimerCallback_t init_callback)
-   {
-   s_timers.start_timer_thread();
-   // At first, TimeDispatch will call init_callback.
-   if (init_callback != NULL)
-      SetAlarm(NULL, 0, init_callback, (TIMEVAL)0, (TIMEVAL)0);
-   s_timers.resume_timer_thread();
-   }
-
-void StopTimerLoop(TimerCallback_t init_callback)
-   {
-   s_timers.stop_timer_thread();
-   }
-
-void setTimer(TIMEVAL value)
-   {
-   s_timers.set_timer(value);
-   }
-
-TIMEVAL getElapsedTime(void)
-   {
-   return s_timers.get_elapsed_time();
-   }
--- a/drivers/win32/Makefile.in	Wed Jul 15 09:32:35 2009 +0200
+++ b/drivers/win32/Makefile.in	Wed Jul 15 09:36:36 2009 +0200
@@ -54,7 +54,7 @@
 driver: $(OBJS)
 
 
-%o: %cpp
+%o: %c
 	$(CXX) $(CFLAGS) $(PROG_CFLAGS) ${PROGDEFINES} $(INCLUDES) -o $@ -c $<
 
 #../$(TIMERS_DRIVER)/$(TIMERS_DRIVER).o:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/win32/win32.c	Wed Jul 15 09:36:36 2009 +0200
@@ -0,0 +1,200 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+Copyright (C) Win32 Port Leonid Tochinski
+
+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.
+*/
+
+#include <windows.h>
+
+#include "canfestival.h"
+#include "timer.h"
+#include "timers_driver.h"
+
+// GetProcAddress doesn't have an UNICODE version for NT
+#ifdef UNDER_CE
+  #define myTEXT(str) TEXT(str)
+#else
+  #define myTEXT(str) str
+#endif
+
+#define MAX_NB_CAN_PORTS 16
+
+typedef UNS8 (CALLBACK* CANRECEIVE_DRIVER_PROC)(void* inst, Message *m);
+typedef UNS8 (CALLBACK* CANSEND_DRIVER_PROC)(void* inst, const Message *m);
+typedef void* (CALLBACK* CANOPEN_DRIVER_PROC)(s_BOARD *board);
+typedef int (CALLBACK* CANCLOSE_DRIVER_PROC)(void* inst);
+typedef UNS8 (CALLBACK* CANCHANGEBAUDRATE_DRIVER_PROC)(void* fd, char* baud);
+
+CANRECEIVE_DRIVER_PROC m_canReceive;
+CANSEND_DRIVER_PROC m_canSend;
+CANOPEN_DRIVER_PROC m_canOpen;
+CANCLOSE_DRIVER_PROC m_canClose;
+CANCHANGEBAUDRATE_DRIVER_PROC m_canChangeBaudRate;
+
+/* CAN port structure */
+typedef struct
+{
+  char used;  /**< flag indicating CAN port usage, will be used to abort Receiver task*/
+  CAN_HANDLE fd; /**< CAN port file descriptor*/
+  TASK_HANDLE receiveTask; /**< CAN Receiver task*/
+  CO_Data* d; /**< CAN object data*/
+}CANPort;
+
+CANPort canports[MAX_NB_CAN_PORTS] = {{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,}};
+
+
+/***************************************************************************/
+UNS8 UnLoadCanDriver(LIB_HANDLE handle)
+{
+	if(handle != NULL)
+	{
+		FreeLibrary(handle);
+		handle=NULL;
+		return 0;
+	}
+	return -1;
+}
+
+/***************************************************************************/
+/**
+ * Loads the dll and get funcs ptr
+ *
+ * @param driver_name String containing driver's dynamic library name
+ * @return Library handle
+ */
+LIB_HANDLE LoadCanDriver(LPCTSTR driver_name)
+{
+	// driver module handle
+	LIB_HANDLE handle = NULL;
+
+	if(handle == NULL)
+	{
+		handle = LoadLibrary(driver_name);
+	}
+	
+	if (!handle) 
+	{
+		fprintf (stderr, "%s\n", GetLastError());
+    	return NULL;
+	}
+
+	m_canReceive = (CANRECEIVE_DRIVER_PROC)GetProcAddress(handle, myTEXT("canReceive_driver"));
+	m_canSend = (CANSEND_DRIVER_PROC)GetProcAddress(handle, myTEXT("canSend_driver"));
+	m_canOpen = (CANOPEN_DRIVER_PROC)GetProcAddress(handle, myTEXT("canOpen_driver"));
+	m_canClose = (CANCLOSE_DRIVER_PROC)GetProcAddress(handle, myTEXT("canClose_driver"));
+	m_canChangeBaudRate = (CANCHANGEBAUDRATE_DRIVER_PROC)GetProcAddress(handle, myTEXT("canChangeBaudRate_driver"));
+	
+	return handle;
+}
+
+/***************************************************************************/
+UNS8 canSend(CAN_PORT port, Message *m)
+{
+	UNS8 res;
+	if (port && (m_canSend != NULL))
+	{
+		res = m_canSend(((CANPort*)port)->fd, m);
+		if (res) return 1; // OK
+	}
+	return 0; // NOT OK
+}
+
+/***************************************************************************/
+void canReceiveLoop(CAN_PORT port)
+{
+	Message m;
+	while(((CANPort*)port)->used)
+	{
+		if(m_canReceive(((CANPort*)port)->fd, &m) != 0) break;
+		EnterMutex();
+		canDispatch(((CANPort*)port)->d, &m);
+		LeaveMutex();
+	}
+}
+
+/***************************************************************************/
+CAN_HANDLE canOpen(s_BOARD *board, CO_Data * d)
+{
+	int i;
+	for(i=0; i < MAX_NB_CAN_PORTS; i++)
+	{
+		if(!canports[i].used)
+		break;
+	}
+
+	#ifndef NOT_USE_DYNAMIC_LOADING	
+	if (m_canOpen == NULL)
+	{
+	   	fprintf(stderr,"CanOpen : Can Driver dll not loaded\n");
+	   	return NULL;
+	}
+	#endif
+	
+	CAN_HANDLE fd0 = m_canOpen(board);
+	if(fd0)
+	{
+		canports[i].used = 1;
+		canports[i].fd = fd0;
+		canports[i].d = d;
+		d->canHandle = (CAN_PORT)&canports[i];
+		CreateReceiveTask(&(canports[i]), &canports[i].receiveTask, &canReceiveLoop);
+		return (CAN_PORT)&canports[i];
+	}
+	else
+	{
+		MSG("CanOpen : Cannot open board {busname='%s',baudrate='%s'}\n",board->busname, board->baudrate);
+		return NULL;
+	}
+}
+
+/***************************************************************************/
+int canClose(CO_Data * d)
+{
+	UNS8 res;
+	
+	((CANPort*)d->canHandle)->used = 0;
+	CANPort* tmp = (CANPort*)d->canHandle;
+	d->canHandle = NULL;
+	
+	// close CAN port
+	res = m_canClose(tmp->fd);
+
+	// kill receiver task
+	WaitReceiveTaskEnd(&tmp->receiveTask);
+	
+	return res;
+}
+
+UNS8 canChangeBaudRate(CAN_PORT port, char* baud)
+{
+   if(port){
+		UNS8 res;
+	    //LeaveMutex();
+		res = m_canChangeBaudRate(((CANPort*)port)->fd, baud);
+		//EnterMutex();
+		return res; // OK
+	}               
+	return 1; // NOT OK
+}
+
--- a/drivers/win32/win32.cpp	Wed Jul 15 09:32:35 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,218 +0,0 @@
-/*
-This file is part of CanFestival, a library implementing CanOpen Stack.
-
-Copyright (C): Edouard TISSERANT and Francis DUPIN
-Copyright (C) Win32 Port Leonid Tochinski
-
-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.
-*/
-
-#include <windows.h>
-
-extern "C"
-   {
-#define DLL_CALL(funcname) (*_##funcname)
-#define FCT_PTR_INIT =NULL
-#include "canfestival.h"
-#include "timer.h"
-
-#include "timers_driver.h"
-   };
-
-typedef UNS8 (*CANRECEIVE_DRIVER_PROC)(void* inst, Message *m);
-typedef UNS8 (*CANSEND_DRIVER_PROC)(void* inst, const Message *m);
-typedef void* (*CANOPEN_DRIVER_PROC)(s_BOARD *board);
-typedef int (*CANCLOSE_DRIVER_PROC)(void* inst);
-
-
-class driver_procs
-   {
-   public:
-      driver_procs();
-      ~driver_procs();
-
-      HMODULE load_canfestival_driver(LPCTSTR driver_name);
-      bool can_driver_valid() const;
-
-   public:
-      // can driver
-      CANRECEIVE_DRIVER_PROC m_canReceive;
-      CANSEND_DRIVER_PROC m_canSend;
-      CANOPEN_DRIVER_PROC m_canOpen;
-      CANCLOSE_DRIVER_PROC m_canClose;
-
-      // driver module habndle
-      HMODULE m_driver_handle;
-   };
-
-driver_procs::driver_procs() : m_canReceive(0),
-      m_canSend(0),
-      m_canOpen(0),
-      m_canClose(0),
-      m_driver_handle(0)
-   {}
-
-driver_procs::~driver_procs()
-   {
-   if (m_driver_handle)
-      ::FreeLibrary(m_driver_handle);
-   }
-
-bool driver_procs::can_driver_valid() const
-   {
-   return ((m_canReceive != NULL) &&
-           (m_canSend != NULL) &&
-           (m_canOpen != NULL) &&
-           (m_canClose != NULL));
-   }
-
-// GetProcAddress doesn't have an UNICODE version for NT
-#ifdef UNDER_CE
-  #define myTEXT(str) TEXT(str)
-#else
-  #define myTEXT(str) str
-#endif
-
-HMODULE driver_procs::load_canfestival_driver(LPCTSTR driver_name)
-   {
-  //LPCTSTR driver1 = "C:\\msys\\1.0\\home\\Ontaide\\can\\CanFestival-3\\drivers\\can_peak_win32\\cygcan_peak_win32.dll";
-  //LPCTSTR driver2 = "C:\\msys\\1.0\\home\\Ontaide\\can\\CanFestival-3\\drivers\\can_peak_win32\\cygcan_peak_win32.dll";
-  //printf("can_driver_valid=%d\n",can_driver_valid());
-   if (can_driver_valid())
-      return m_driver_handle;
-   printf("driver_name=%s\n",driver_name);
-   m_driver_handle = ::LoadLibrary(driver_name);
-   //printf("m_driver_handle=%d\n",m_driver_handle);
-   //printf("testerror =%s\n",GetLastError());
-   if (m_driver_handle == NULL)
-      return NULL;
-
-   m_canReceive = (CANRECEIVE_DRIVER_PROC)::GetProcAddress(m_driver_handle, myTEXT("canReceive_driver"));
-   m_canSend = (CANSEND_DRIVER_PROC)::GetProcAddress(m_driver_handle, myTEXT("canSend_driver"));
-   m_canOpen = (CANOPEN_DRIVER_PROC)::GetProcAddress(m_driver_handle, myTEXT("canOpen_driver"));
-   m_canClose = (CANCLOSE_DRIVER_PROC)::GetProcAddress(m_driver_handle, myTEXT("canClose_driver"));
-   return can_driver_valid()?m_driver_handle:NULL;
-   }
-
-struct driver_data
-   {
-   CO_Data * d;
-   HANDLE receive_thread;
-   void* inst;
-   volatile bool continue_receive_thread;
-   };
-
-driver_procs s_driver_procs;
-
-LIB_HANDLE LoadCanDriver(const char* driver_name)
-   {
-		return s_driver_procs.load_canfestival_driver((LPCTSTR)driver_name);
-   }
-
-UNS8 canReceive(CAN_PORT fd0, Message *m)
-   {
-  
-   if (fd0 != NULL && s_driver_procs.m_canReceive != NULL)
-	   {
-		  driver_data* data = (driver_data*)fd0;
-		  return (*s_driver_procs.m_canReceive)(data->inst, m);
-	   }
-   return 1;
-   }
-
-void* canReceiveLoop(CAN_PORT fd0)
-   {
-   driver_data* data = (driver_data*)fd0;
-   Message m;
-   while (data->continue_receive_thread)
-      {
-      if (!canReceive(fd0, &m))
-         {
-         EnterMutex();
-         canDispatch(data->d, &m);
-         LeaveMutex();
-         }
-      else
-         {
-		 break;
-         ::Sleep(1);
-         }
-      }
-   return 0;
-   }
-
-/***************************************************************************/
-UNS8 canSend(CAN_PORT fd0, Message *m)
-   {   
-   if (fd0 != NULL && s_driver_procs.m_canSend != NULL)
-      {
-      UNS8 res;
-      driver_data* data = (driver_data*)fd0;
-      res = (*s_driver_procs.m_canSend)(data->inst, m);      
-      if (res)
-         return 1; // OK
-      }
-   return 0; // NOT OK
-   }
-
-/***************************************************************************/
-CAN_HANDLE canOpen(s_BOARD *board, CO_Data * d)
-   {
-   if (board != NULL && s_driver_procs.m_canOpen != NULL)
-      {
-      void* inst = (*s_driver_procs.m_canOpen)(board);
-      if (inst != NULL)
-         {
-         driver_data* data = new driver_data;
-         data->d = d;
-         data->inst = inst;
-         data->continue_receive_thread = true;
-         CreateReceiveTask(data, &data->receive_thread, (void*)&canReceiveLoop);
-	 EnterMutex();
-         d->canHandle = data;
-         LeaveMutex();
-         return data;
-         }
-      }
-   return NULL;
-   }
-
-/***************************************************************************/
-int canClose(CO_Data * d)
-   {
-   if (s_driver_procs.m_canClose != NULL)
-      {
-		  driver_data* data;
-		  EnterMutex();
-		  if(d->canHandle != NULL){
-			data = (driver_data*)d->canHandle;
-			d->canHandle = NULL;
-			data->continue_receive_thread = false;}
-		  LeaveMutex();
-		  (*s_driver_procs.m_canClose)(data->inst);
-		  WaitReceiveTaskEnd(&data->receive_thread);
-		  delete data;
-		  return 0;
-      }
-   return 0;
-   }
-
-