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