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 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" greg@556: #include "timer.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: */ greg@556: LIB_HANDLE LoadCanDriver(LPCTSTR driver_name) greg@556: { greg@556: // driver module handle greg@556: LIB_HANDLE handle = NULL; greg@556: Christian@638: #ifndef NOT_USE_DYNAMIC_LOADING greg@556: if(handle == NULL) greg@556: { greg@556: handle = LoadLibrary(driver_name); greg@556: } greg@577: greg@577: if (!handle) greg@556: { gregory@600: fprintf (stderr, "%d\n", GetLastError()); greg@556: return NULL; greg@556: } greg@556: greg@556: m_canReceive = (CANRECEIVE_DRIVER_PROC)GetProcAddress(handle, myTEXT("canReceive_driver")); greg@556: m_canSend = (CANSEND_DRIVER_PROC)GetProcAddress(handle, myTEXT("canSend_driver")); greg@556: m_canOpen = (CANOPEN_DRIVER_PROC)GetProcAddress(handle, myTEXT("canOpen_driver")); greg@556: m_canClose = (CANCLOSE_DRIVER_PROC)GetProcAddress(handle, myTEXT("canClose_driver")); greg@556: m_canChangeBaudRate = (CANCHANGEBAUDRATE_DRIVER_PROC)GetProcAddress(handle, myTEXT("canChangeBaudRate_driver")); Christian@638: #else Christian@638: //compiled in... Christian@638: handle = 1; //TODO: remove this hack Christian@638: Christian@638: m_canReceive = canReceive_driver; Christian@638: m_canSend = canSend_driver; Christian@638: m_canOpen = canOpen_driver; Christian@638: m_canClose = canClose_driver; Christian@638: m_canChangeBaudRate = canChangeBaudRate_driver; Christian@638: #endif Christian@638: greg@577: greg@556: 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: } Edouard@691: return 1; greg@556: } greg@556: greg@556: /***************************************************************************/ greg@556: void canReceiveLoop(CAN_PORT port) greg@556: { greg@556: Message m; greg@556: while(((CANPort*)port)->used) greg@556: { greg@556: if(m_canReceive(((CANPort*)port)->fd, &m) != 0) break; greg@556: EnterMutex(); greg@556: canDispatch(((CANPort*)port)->d, &m); greg@556: LeaveMutex(); greg@556: } greg@556: } greg@556: greg@556: /***************************************************************************/ greg@556: CAN_HANDLE canOpen(s_BOARD *board, CO_Data * d) greg@556: { greg@556: int i; greg@591: CAN_HANDLE fd0; 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: { gregory@600: UNS8 res = 1; greg@591: CANPort* tmp; greg@591: greg@591: if((CANPort*)d->canHandle) greg@591: { greg@591: ((CANPort*)d->canHandle)->used = 0; greg@591: } greg@591: greg@591: tmp = (CANPort*)d->canHandle; greg@577: greg@591: if(tmp) greg@591: { edouard@629: // kill receiver task before port is closed and handle set to NULL edouard@629: WaitReceiveTaskEnd(&tmp->receiveTask); edouard@629: greg@591: // close CAN port greg@591: res = m_canClose(tmp->fd); edouard@629: } edouard@629: edouard@629: d->canHandle = NULL; edouard@629: greg@556: 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: