etisserant@145: /* etisserant@145: This file is part of CanFestival, a library implementing CanOpen Stack. etisserant@145: etisserant@145: Copyright (C): Edouard TISSERANT and Francis DUPIN etisserant@145: Copyright (C) Win32 Port Leonid Tochinski etisserant@145: etisserant@145: See COPYING file for copyrights details. etisserant@145: etisserant@145: This library is free software; you can redistribute it and/or etisserant@145: modify it under the terms of the GNU Lesser General Public etisserant@145: License as published by the Free Software Foundation; either etisserant@145: version 2.1 of the License, or (at your option) any later version. etisserant@145: etisserant@145: This library is distributed in the hope that it will be useful, etisserant@145: but WITHOUT ANY WARRANTY; without even the implied warranty of etisserant@145: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU etisserant@145: Lesser General Public License for more details. etisserant@145: etisserant@145: You should have received a copy of the GNU Lesser General Public etisserant@145: License along with this library; if not, write to the Free Software etisserant@145: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA etisserant@145: */ etisserant@145: etisserant@145: /* etisserant@145: CAN driver interface. etisserant@145: */ etisserant@145: etisserant@145: #include etisserant@145: etisserant@145: extern "C" etisserant@145: { etisserant@145: #define DLL_CALL(funcname) (*_##funcname) etisserant@145: #define FCT_PTR_INIT =NULL etisserant@145: #include "canfestival.h" etisserant@145: #include "timer.h" etisserant@145: etisserant@145: #include "timers_driver.h" etisserant@145: }; etisserant@145: etisserant@145: typedef UNS8 (*CANRECEIVE_DRIVER_PROC)(void* inst, Message *m); etisserant@145: typedef UNS8 (*CANSEND_DRIVER_PROC)(void* inst, const Message *m); etisserant@145: typedef void* (*CANOPEN_DRIVER_PROC)(s_BOARD *board); etisserant@145: typedef int (*CANCLOSE_DRIVER_PROC)(void* inst); etisserant@145: etisserant@145: etisserant@145: class driver_procs etisserant@145: { etisserant@145: public: etisserant@145: driver_procs(); etisserant@145: ~driver_procs(); etisserant@145: etisserant@145: HMODULE load_canfestival_driver(LPCTSTR driver_name); etisserant@145: bool can_driver_valid() const; etisserant@145: etisserant@145: public: etisserant@145: // can driver etisserant@145: CANRECEIVE_DRIVER_PROC m_canReceive; etisserant@145: CANSEND_DRIVER_PROC m_canSend; etisserant@145: CANOPEN_DRIVER_PROC m_canOpen; etisserant@145: CANCLOSE_DRIVER_PROC m_canClose; etisserant@145: etisserant@145: // driver module habndle etisserant@145: HMODULE m_driver_handle; etisserant@145: }; etisserant@145: etisserant@145: driver_procs::driver_procs() : m_canReceive(0), etisserant@145: m_canSend(0), etisserant@145: m_canOpen(0), etisserant@145: m_canClose(0), etisserant@145: m_driver_handle(0) etisserant@145: {} etisserant@145: etisserant@145: driver_procs::~driver_procs() etisserant@145: { etisserant@145: if (m_driver_handle) etisserant@145: ::FreeLibrary(m_driver_handle); etisserant@145: } etisserant@145: etisserant@145: bool driver_procs::can_driver_valid() const etisserant@145: { etisserant@145: return ((m_canReceive != NULL) && etisserant@145: (m_canSend != NULL) && etisserant@145: (m_canOpen != NULL) && etisserant@145: (m_canClose != NULL)); etisserant@145: } etisserant@145: etisserant@145: // GetProcAddress doesn't have an UNICODE version for NT etisserant@145: #ifdef UNDER_CE etisserant@145: #define myTEXT(str) TEXT(str) etisserant@145: #else etisserant@145: #define myTEXT(str) str etisserant@145: #endif etisserant@145: etisserant@145: HMODULE driver_procs::load_canfestival_driver(LPCTSTR driver_name) etisserant@145: { etisserant@145: if (can_driver_valid()) etisserant@145: return m_driver_handle; etisserant@145: m_driver_handle = ::LoadLibrary(driver_name); etisserant@145: if (m_driver_handle == NULL) etisserant@145: return NULL; etisserant@145: etisserant@145: m_canReceive = (CANRECEIVE_DRIVER_PROC)::GetProcAddress(m_driver_handle, myTEXT("canReceive_driver")); etisserant@145: m_canSend = (CANSEND_DRIVER_PROC)::GetProcAddress(m_driver_handle, myTEXT("canSend_driver")); etisserant@145: m_canOpen = (CANOPEN_DRIVER_PROC)::GetProcAddress(m_driver_handle, myTEXT("canOpen_driver")); etisserant@145: m_canClose = (CANCLOSE_DRIVER_PROC)::GetProcAddress(m_driver_handle, myTEXT("canClose_driver")); etisserant@145: return can_driver_valid()?m_driver_handle:NULL; etisserant@145: } etisserant@145: etisserant@145: struct driver_data etisserant@145: { etisserant@145: CO_Data * d; etisserant@145: HANDLE receive_thread; etisserant@145: void* inst; etisserant@145: volatile bool continue_receive_thread; etisserant@145: }; etisserant@145: etisserant@145: driver_procs s_driver_procs; etisserant@145: etisserant@145: LIB_HANDLE LoadCanDriver(char* driver_name) etisserant@145: { etisserant@145: return s_driver_procs.load_canfestival_driver((LPCTSTR)driver_name); etisserant@145: } etisserant@145: etisserant@145: UNS8 canReceive(CAN_PORT fd0, Message *m) etisserant@145: { etisserant@145: if (fd0 != NULL && s_driver_procs.m_canReceive != NULL) etisserant@145: { etisserant@145: driver_data* data = (driver_data*)fd0; etisserant@145: return (*s_driver_procs.m_canReceive)(data->inst, m); etisserant@145: } etisserant@145: return 1; etisserant@145: } etisserant@145: etisserant@145: void* canReceiveLoop(CAN_PORT fd0) etisserant@145: { etisserant@145: driver_data* data = (driver_data*)fd0; etisserant@145: Message m; etisserant@145: while (data->continue_receive_thread) etisserant@145: { etisserant@145: if (!canReceive(fd0, &m)) etisserant@145: { etisserant@145: EnterMutex(); etisserant@145: canDispatch(data->d, &m); etisserant@145: LeaveMutex(); etisserant@145: } etisserant@145: else etisserant@145: { etisserant@145: break; etisserant@145: ::Sleep(1); etisserant@145: } etisserant@145: } etisserant@145: return 0; etisserant@145: } etisserant@145: etisserant@145: /***************************************************************************/ etisserant@145: UNS8 canSend(CAN_PORT fd0, Message *m) etisserant@145: { etisserant@145: if (fd0 != NULL && s_driver_procs.m_canSend != NULL) etisserant@145: { etisserant@149: UNS8 res; etisserant@145: driver_data* data = (driver_data*)fd0; etisserant@149: LeaveMutex(); etisserant@149: res = (*s_driver_procs.m_canSend)(data->inst, m); etisserant@149: EnterMutex(); etisserant@149: if (res) etisserant@145: return 0; etisserant@145: } etisserant@145: return 1; etisserant@145: } etisserant@145: etisserant@145: /***************************************************************************/ etisserant@145: CAN_HANDLE canOpen(s_BOARD *board, CO_Data * d) etisserant@145: { etisserant@145: if (board != NULL && s_driver_procs.m_canOpen != NULL) etisserant@145: { etisserant@145: void* inst = (*s_driver_procs.m_canOpen)(board); etisserant@145: if (inst != NULL) etisserant@145: { etisserant@145: driver_data* data = new driver_data; etisserant@145: data->d = d; etisserant@145: data->inst = inst; etisserant@145: data->continue_receive_thread = true; etisserant@145: CreateReceiveTask(data, &data->receive_thread, &canReceiveLoop); etisserant@149: EnterMutex(); etisserant@149: d->canHandle = data; etisserant@149: LeaveMutex(); etisserant@145: return data; etisserant@145: } etisserant@145: } etisserant@145: return NULL; etisserant@145: } etisserant@145: etisserant@145: /***************************************************************************/ etisserant@149: int canClose(CO_Data * d) etisserant@145: { etisserant@150: if (s_driver_procs.m_canClose != NULL) etisserant@150: { etisserant@150: driver_data* data; etisserant@150: EnterMutex(); etisserant@150: if(d->canHandle != NULL){ etisserant@150: data = (driver_data*)d->canHandle; etisserant@150: d->canHandle = NULL; etisserant@150: data->continue_receive_thread = false;} etisserant@150: LeaveMutex(); etisserant@150: WaitReceiveTaskEnd(&data->receive_thread); etisserant@150: (*s_driver_procs.m_canClose)(data->inst); etisserant@150: delete data; etisserant@150: return 0; etisserant@145: } etisserant@145: return 0; etisserant@145: } etisserant@145: etisserant@150: