greg@556: /* greg@556: This file is part of CanFestival, a library implementing CanOpen Stack. greg@556: greg@556: Copyright (C): Edouard TISSERANT and Francis DUPIN greg@556: Copyright (C) Win32 Port Leonid Tochinski JaFojtik@697: Modified by: Jaroslav Fojtik greg@556: greg@556: See COPYING file for copyrights details. greg@556: greg@556: This library is free software; you can redistribute it and/or greg@556: modify it under the terms of the GNU Lesser General Public greg@556: License as published by the Free Software Foundation; either greg@556: version 2.1 of the License, or (at your option) any later version. greg@556: greg@556: This library is distributed in the hope that it will be useful, greg@556: but WITHOUT ANY WARRANTY; without even the implied warranty of greg@556: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU greg@556: Lesser General Public License for more details. greg@556: greg@556: You should have received a copy of the GNU Lesser General Public greg@556: License along with this library; if not, write to the Free Software greg@556: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA greg@556: */ greg@556: greg@556: /* greg@556: CAN driver interface. greg@556: */ greg@556: greg@556: #include greg@591: greg@591: #ifdef __cplusplus greg@591: extern "C" { greg@591: #endif greg@591: greg@556: #include "canfestival.h" Edouard@801: #include "timers.h" greg@556: #include "timers_driver.h" greg@591: greg@591: #ifdef __cplusplus greg@577: }; greg@591: #endif greg@591: greg@556: // GetProcAddress doesn't have an UNICODE version for NT greg@556: #ifdef UNDER_CE greg@556: #define myTEXT(str) TEXT(str) greg@556: #else greg@556: #define myTEXT(str) str greg@556: #endif greg@556: greg@556: #define MAX_NB_CAN_PORTS 16 greg@556: greg@556: typedef UNS8 (CALLBACK* CANRECEIVE_DRIVER_PROC)(void* inst, Message *m); greg@556: typedef UNS8 (CALLBACK* CANSEND_DRIVER_PROC)(void* inst, const Message *m); greg@556: typedef void* (CALLBACK* CANOPEN_DRIVER_PROC)(s_BOARD *board); greg@556: typedef int (CALLBACK* CANCLOSE_DRIVER_PROC)(void* inst); greg@556: typedef UNS8 (CALLBACK* CANCHANGEBAUDRATE_DRIVER_PROC)(void* fd, char* baud); greg@556: greg@556: CANRECEIVE_DRIVER_PROC m_canReceive; greg@556: CANSEND_DRIVER_PROC m_canSend; greg@556: CANOPEN_DRIVER_PROC m_canOpen; greg@556: CANCLOSE_DRIVER_PROC m_canClose; greg@556: CANCHANGEBAUDRATE_DRIVER_PROC m_canChangeBaudRate; greg@556: greg@556: /* CAN port structure */ greg@556: typedef struct greg@556: { greg@556: char used; /**< flag indicating CAN port usage, will be used to abort Receiver task*/ greg@556: CAN_HANDLE fd; /**< CAN port file descriptor*/ greg@556: TASK_HANDLE receiveTask; /**< CAN Receiver task*/ greg@556: CO_Data* d; /**< CAN object data*/ greg@556: }CANPort; greg@556: greg@556: CANPort canports[MAX_NB_CAN_PORTS] = {{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,}}; greg@556: greg@556: greg@556: /***************************************************************************/ greg@556: UNS8 UnLoadCanDriver(LIB_HANDLE handle) greg@556: { Christian@638: #ifndef NOT_USE_DYNAMIC_LOADING greg@556: if(handle != NULL) greg@556: { greg@556: FreeLibrary(handle); greg@556: handle=NULL; greg@556: return 0; greg@556: } greg@556: return -1; Christian@638: #else Christian@638: handle = NULL; Christian@638: return 0; Christian@638: #endif //NOT_USE_DYNAMIC_LOADING greg@556: } greg@556: greg@556: /***************************************************************************/ greg@556: /** greg@556: * Loads the dll and get funcs ptr greg@556: * greg@556: * @param driver_name String containing driver's dynamic library name greg@556: * @return Library handle greg@556: */ hacking@723: LIB_HANDLE LoadCanDriver(LPCSTR driver_name) greg@556: { Edouard@774: // driver module handle Edouard@774: LIB_HANDLE handle = NULL; greg@556: Christian@638: #ifndef NOT_USE_DYNAMIC_LOADING Edouard@774: handle = LoadLibrary(driver_name); Edouard@774: Edouard@774: if (!handle) Edouard@774: { Edouard@774: fprintf (stderr, "LoadLibrary error : %d\n", GetLastError()); Edouard@774: return NULL; Edouard@774: } Edouard@774: Edouard@774: m_canReceive = (CANRECEIVE_DRIVER_PROC)GetProcAddress(handle, myTEXT("canReceive_driver")); Edouard@774: m_canSend = (CANSEND_DRIVER_PROC)GetProcAddress(handle, myTEXT("canSend_driver")); Edouard@774: m_canOpen = (CANOPEN_DRIVER_PROC)GetProcAddress(handle, myTEXT("canOpen_driver")); Edouard@774: m_canClose = (CANCLOSE_DRIVER_PROC)GetProcAddress(handle, myTEXT("canClose_driver")); Edouard@774: m_canChangeBaudRate = (CANCHANGEBAUDRATE_DRIVER_PROC)GetProcAddress(handle, myTEXT("canChangeBaudRate_driver")); Edouard@774: Edouard@774: if(m_canReceive==NULL || m_canSend==NULL || m_canOpen==NULL || m_canClose==NULL || m_canChangeBaudRate==NULL) Edouard@774: { Edouard@774: m_canReceive = NULL; Edouard@774: m_canSend = NULL; Edouard@774: m_canOpen = NULL; Edouard@774: m_canClose = NULL; Edouard@774: m_canChangeBaudRate = NULL; Edouard@774: FreeLibrary(handle); Edouard@774: fprintf (stderr, "GetProc error : %d\n", GetLastError()); Edouard@774: return NULL; Edouard@774: } Christian@638: #else Edouard@774: //compiled in... Edouard@774: handle = 1; //TODO: remove this hack Edouard@774: Edouard@774: m_canReceive = canReceive_driver; Edouard@774: m_canSend = canSend_driver; Edouard@774: m_canOpen = canOpen_driver; Edouard@774: m_canClose = canClose_driver; Edouard@774: m_canChangeBaudRate = canChangeBaudRate_driver; Edouard@774: #endif Edouard@774: Edouard@774: Edouard@774: return handle; greg@556: } greg@556: greg@556: /***************************************************************************/ greg@556: UNS8 canSend(CAN_PORT port, Message *m) greg@556: { greg@556: if (port && (m_canSend != NULL)) greg@556: { Edouard@691: return m_canSend(((CANPort*)port)->fd, m); Edouard@691: } JaFojtik@696: return 1; /* NOT OK */ greg@556: } greg@556: greg@556: /***************************************************************************/ JaFojtik@697: DWORD canReceiveLoop(CAN_PORT port) greg@556: { greg@556: Message m; greg@556: while(((CANPort*)port)->used) greg@556: { Edouard@777: if(m_canReceive(((CANPort*)port)->fd, &m) != 0) Edouard@777: break; greg@556: EnterMutex(); greg@556: canDispatch(((CANPort*)port)->d, &m); greg@556: LeaveMutex(); greg@556: } JaFojtik@697: return 0; greg@556: } greg@556: greg@556: /***************************************************************************/ greg@556: CAN_HANDLE canOpen(s_BOARD *board, CO_Data * d) greg@556: { greg@556: int i; JaFojtik@697: CAN_HANDLE fd0; JaFojtik@697: JaFojtik@697: JaFojtik@697: /* Fix of multiple opening one data set, added by J.Fojtik. */ JaFojtik@697: if(d->canHandle) JaFojtik@697: { JaFojtik@697: canClose(d); JaFojtik@697: } greg@591: greg@556: for(i=0; i < MAX_NB_CAN_PORTS; i++) greg@556: { greg@556: if(!canports[i].used) greg@556: break; greg@556: } greg@556: greg@577: #ifndef NOT_USE_DYNAMIC_LOADING greg@556: if (m_canOpen == NULL) greg@556: { greg@556: fprintf(stderr,"CanOpen : Can Driver dll not loaded\n"); greg@556: return NULL; greg@556: } greg@556: #endif greg@577: greg@591: fd0 = m_canOpen(board); greg@556: if(fd0) greg@556: { greg@556: canports[i].used = 1; greg@556: canports[i].fd = fd0; greg@556: canports[i].d = d; greg@556: d->canHandle = (CAN_PORT)&canports[i]; greg@577: CreateReceiveTask(&(canports[i]), &canports[i].receiveTask, (void *)canReceiveLoop); greg@556: return (CAN_PORT)&canports[i]; greg@556: } greg@556: else greg@556: { hacking@687: MSG("CanOpen : Cannot open board {busname='%S',baudrate='%S'}\n",board->busname, board->baudrate); greg@556: return NULL; greg@556: } greg@556: } greg@556: greg@556: /***************************************************************************/ greg@556: int canClose(CO_Data * d) greg@556: { Edouard@777: int res = 0; Edouard@777: Edouard@777: CANPort* port = (CANPort*)d->canHandle; Edouard@777: if(port){ Edouard@777: ((CANPort*)d->canHandle)->used = 0; Edouard@777: Edouard@777: res = m_canClose(port->fd); Edouard@777: Edouard@777: WaitReceiveTaskEnd(&port->receiveTask); Edouard@777: Edouard@777: d->canHandle = NULL; Edouard@777: } Edouard@777: Edouard@777: return res; greg@556: } greg@556: greg@556: UNS8 canChangeBaudRate(CAN_PORT port, char* baud) greg@556: { greg@556: if(port){ greg@556: UNS8 res; greg@556: //LeaveMutex(); greg@556: res = m_canChangeBaudRate(((CANPort*)port)->fd, baud); greg@556: //EnterMutex(); greg@556: return res; // OK greg@577: } greg@556: return 1; // NOT OK greg@556: } greg@556: