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