drivers_win32.cpp

Go to the documentation of this file.
00001 /*
00002 This file is part of CanFestival, a library implementing CanOpen Stack.
00003 
00004 Copyright (C): Edouard TISSERANT and Francis DUPIN
00005 Copyright (C) Win32 Port Leonid Tochinski
00006 
00007 See COPYING file for copyrights details.
00008 
00009 This library is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU Lesser General Public
00011 License as published by the Free Software Foundation; either
00012 version 2.1 of the License, or (at your option) any later version.
00013 
00014 This library is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public
00020 License along with this library; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 */
00023 
00024 /*
00025  CAN driver interface.
00026 */
00027 
00028 #include <windows.h>
00029 
00030 extern "C"
00031    {
00032 #define DLL_CALL(funcname) (*_##funcname)
00033 #define FCT_PTR_INIT =NULL
00034 #include "canfestival.h"
00035 #include "timer.h"
00036 
00037 #include "timers_driver.h"
00038    };
00039 
00040 typedef UNS8 (*CANRECEIVE_DRIVER_PROC)(void* inst, Message *m);
00041 typedef UNS8 (*CANSEND_DRIVER_PROC)(void* inst, const Message *m);
00042 typedef void* (*CANOPEN_DRIVER_PROC)(s_BOARD *board);
00043 typedef int (*CANCLOSE_DRIVER_PROC)(void* inst);
00044 
00045 
00046 class driver_procs
00047    {
00048    public:
00049       driver_procs();
00050       ~driver_procs();
00051 
00052       HMODULE load_canfestival_driver(LPCTSTR driver_name);
00053       bool can_driver_valid() const;
00054 
00055    public:
00056       // can driver
00057       CANRECEIVE_DRIVER_PROC m_canReceive;
00058       CANSEND_DRIVER_PROC m_canSend;
00059       CANOPEN_DRIVER_PROC m_canOpen;
00060       CANCLOSE_DRIVER_PROC m_canClose;
00061 
00062       // driver module habndle
00063       HMODULE m_driver_handle;
00064    };
00065 
00066 driver_procs::driver_procs() : m_canReceive(0),
00067       m_canSend(0),
00068       m_canOpen(0),
00069       m_canClose(0),
00070       m_driver_handle(0)
00071    {}
00072 
00073 driver_procs::~driver_procs()
00074    {
00075    if (m_driver_handle)
00076       ::FreeLibrary(m_driver_handle);
00077    }
00078 
00079 bool driver_procs::can_driver_valid() const
00080    {
00081    return ((m_canReceive != NULL) &&
00082            (m_canSend != NULL) &&
00083            (m_canOpen != NULL) &&
00084            (m_canClose != NULL));
00085    }
00086 
00087 // GetProcAddress doesn't have an UNICODE version for NT
00088 #ifdef UNDER_CE
00089   #define myTEXT(str) TEXT(str)
00090 #else
00091   #define myTEXT(str) str
00092 #endif
00093 
00094 HMODULE driver_procs::load_canfestival_driver(LPCTSTR driver_name)
00095    {
00096    if (can_driver_valid())
00097       return m_driver_handle;
00098    m_driver_handle = ::LoadLibrary(driver_name);
00099    if (m_driver_handle == NULL)
00100       return NULL;
00101 
00102    m_canReceive = (CANRECEIVE_DRIVER_PROC)::GetProcAddress(m_driver_handle, myTEXT("canReceive_driver"));
00103    m_canSend = (CANSEND_DRIVER_PROC)::GetProcAddress(m_driver_handle, myTEXT("canSend_driver"));
00104    m_canOpen = (CANOPEN_DRIVER_PROC)::GetProcAddress(m_driver_handle, myTEXT("canOpen_driver"));
00105    m_canClose = (CANCLOSE_DRIVER_PROC)::GetProcAddress(m_driver_handle, myTEXT("canClose_driver"));
00106    return can_driver_valid()?m_driver_handle:NULL;
00107    }
00108 
00109 struct driver_data
00110    {
00111    CO_Data * d;
00112    HANDLE receive_thread;
00113    void* inst;
00114    volatile bool continue_receive_thread;
00115    };
00116 
00117 driver_procs s_driver_procs;
00118 
00119 LIB_HANDLE LoadCanDriver(char* driver_name)
00120    {
00121                 return s_driver_procs.load_canfestival_driver((LPCTSTR)driver_name);
00122    }
00123 
00124 UNS8 canReceive(CAN_PORT fd0, Message *m)
00125    {
00126    if (fd0 != NULL && s_driver_procs.m_canReceive != NULL)
00127            {
00128                   driver_data* data = (driver_data*)fd0;
00129                   return (*s_driver_procs.m_canReceive)(data->inst, m);
00130            }
00131    return 1;
00132    }
00133 
00134 void* canReceiveLoop(CAN_PORT fd0)
00135    {
00136    driver_data* data = (driver_data*)fd0;
00137    Message m;
00138    while (data->continue_receive_thread)
00139       {
00140       if (!canReceive(fd0, &m))
00141          {
00142          EnterMutex();
00143          canDispatch(data->d, &m);
00144          LeaveMutex();
00145          }
00146       else
00147          {
00148                  break;
00149          ::Sleep(1);
00150          }
00151       }
00152    return 0;
00153    }
00154 
00155 /***************************************************************************/
00156 UNS8 canSend(CAN_PORT fd0, Message *m)
00157    {
00158    if (fd0 != NULL && s_driver_procs.m_canSend != NULL)
00159       {
00160       UNS8 res;
00161       driver_data* data = (driver_data*)fd0;
00162       LeaveMutex();
00163       res = (*s_driver_procs.m_canSend)(data->inst, m);      
00164       EnterMutex();
00165       if (res)
00166          return 0;
00167       }
00168    return 1;
00169    }
00170 
00171 /***************************************************************************/
00172 CAN_HANDLE canOpen(s_BOARD *board, CO_Data * d)
00173    {
00174    if (board != NULL && s_driver_procs.m_canOpen != NULL)
00175       {
00176       void* inst = (*s_driver_procs.m_canOpen)(board);
00177       if (inst != NULL)
00178          {
00179          driver_data* data = new driver_data;
00180          data->d = d;
00181          data->inst = inst;
00182          data->continue_receive_thread = true;
00183          CreateReceiveTask(data, &data->receive_thread, &canReceiveLoop);
00184          EnterMutex();
00185          d->canHandle = data;
00186          LeaveMutex();
00187          return data;
00188          }
00189       }
00190    return NULL;
00191    }
00192 
00193 /***************************************************************************/
00194 int canClose(CO_Data * d)
00195    {
00196    if (s_driver_procs.m_canClose != NULL)
00197       {
00198                   driver_data* data;
00199                   EnterMutex();
00200                   if(d->canHandle != NULL){
00201                         data = (driver_data*)d->canHandle;
00202                         d->canHandle = NULL;
00203                         data->continue_receive_thread = false;}
00204                   LeaveMutex();
00205                   WaitReceiveTaskEnd(&data->receive_thread);
00206                   (*s_driver_procs.m_canClose)(data->inst);
00207                   delete data;
00208                   return 0;
00209       }
00210    return 0;
00211    }
00212 
00213 

Generated on Mon Jul 2 19:10:16 2007 for CanFestival by  doxygen 1.5.1