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: 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: #include etisserant@145: #include etisserant@145: #include etisserant@145: etisserant@145: #ifndef NOT_USE_DYNAMIC_LOADING etisserant@145: #define DLL_CALL(funcname) (* funcname##_driver) etisserant@145: #define FCT_PTR_INIT =NULL etisserant@145: etisserant@145: #define DLSYM(name)\ etisserant@145: *(void **) (&name##_driver) = dlsym(handle, #name"_driver");\ etisserant@145: if ((error = dlerror()) != NULL) {\ etisserant@145: fprintf (stderr, "%s\n", error);\ etisserant@145: UnLoadCanDriver(handle);\ etisserant@145: return NULL;\ etisserant@145: } etisserant@145: etisserant@145: #else /*NOT_USE_DYNAMIC_LOADING*/ etisserant@145: etisserant@145: /*Function call is direct*/ etisserant@145: #define DLL_CALL(funcname) funcname##_driver etisserant@145: etisserant@145: #endif /*NOT_USE_DYNAMIC_LOADING*/ etisserant@145: etisserant@145: #include "data.h" etisserant@145: #include "canfestival.h" etisserant@145: #include "timers_driver.h" etisserant@145: etisserant@145: #define MAX_NB_CAN_PORTS 16 etisserant@145: etisserant@145: typedef struct { etisserant@145: char used; etisserant@145: CAN_HANDLE fd; etisserant@145: TASK_HANDLE receiveTask; etisserant@145: CO_Data* d; etisserant@145: } CANPort; etisserant@145: etisserant@145: #include "can_driver.h" etisserant@145: etisserant@145: /*Declares the funtion pointers for dll binding or simple protos*/ etisserant@145: /*UNS8 DLL_CALL(canReceive)(CAN_HANDLE, Message *); etisserant@145: UNS8 DLL_CALL(canSend)(CAN_HANDLE, Message *); etisserant@145: CAN_HANDLE DLL_CALL(canOpen)(s_BOARD *); etisserant@145: int DLL_CALL(canClose)(CAN_HANDLE); etisserant@145: */ etisserant@145: CANPort canports[MAX_NB_CAN_PORTS] = {{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,}}; etisserant@145: etisserant@145: #ifndef NOT_USE_DYNAMIC_LOADING etisserant@145: etisserant@145: /*UnLoads the dll*/ etisserant@145: UNS8 UnLoadCanDriver(LIB_HANDLE handle) etisserant@145: { etisserant@145: if(handle!=NULL) etisserant@145: { etisserant@145: dlclose(handle); etisserant@151: etisserant@145: handle=NULL; etisserant@145: return 0; etisserant@145: } etisserant@145: return -1; etisserant@145: } etisserant@145: etisserant@145: /*Loads the dll and get funcs ptr*/ etisserant@145: LIB_HANDLE LoadCanDriver(char* driver_name) etisserant@145: { etisserant@145: LIB_HANDLE handle = NULL; etisserant@145: char *error; etisserant@145: etisserant@145: etisserant@145: if(handle==NULL) etisserant@145: { etisserant@145: handle = dlopen(driver_name, RTLD_LAZY); etisserant@145: } etisserant@145: etisserant@145: if (!handle) { etisserant@145: fprintf (stderr, "%s\n", dlerror()); etisserant@145: return NULL; etisserant@145: } etisserant@145: etisserant@145: /*Get function ptr*/ etisserant@145: DLSYM(canReceive) etisserant@145: DLSYM(canSend) etisserant@145: DLSYM(canOpen) groke6@384: DLSYM(canChangeBaudRate) etisserant@145: DLSYM(canClose) etisserant@145: etisserant@197: return handle; etisserant@145: } etisserant@145: etisserant@145: #endif etisserant@145: etisserant@145: etisserant@145: etisserant@145: /*Not needed -- canReceiveLoop calls _canReceive directly *//* etisserant@145: UNS8 canReceive(CAN_PORT port, Message *m) etisserant@145: { etisserant@145: return DLL_CALL(canReceive)(port->fd, Message *m); etisserant@145: } etisserant@145: */ etisserant@145: etisserant@145: UNS8 canSend(CAN_PORT port, Message *m) etisserant@145: { etisserant@149: if(port){ etisserant@149: UNS8 res; etisserant@155: //LeaveMutex(); etisserant@149: res = DLL_CALL(canSend)(((CANPort*)port)->fd, m); etisserant@155: //EnterMutex(); greg@267: return res; // OK etisserant@149: } greg@267: return 1; // NOT OK etisserant@145: } etisserant@145: etisserant@145: void canReceiveLoop(CAN_PORT port) etisserant@145: { etisserant@145: Message m; etisserant@145: etisserant@145: while (1) { etisserant@145: if (DLL_CALL(canReceive)(((CANPort*)port)->fd, &m) != 0) etisserant@145: break; etisserant@145: etisserant@145: EnterMutex(); etisserant@145: canDispatch(((CANPort*)port)->d, &m); etisserant@145: LeaveMutex(); etisserant@145: } etisserant@145: } etisserant@145: CAN_PORT canOpen(s_BOARD *board, CO_Data * d) etisserant@145: { etisserant@145: int i; etisserant@145: for(i=0; i < MAX_NB_CAN_PORTS; i++) etisserant@145: { etisserant@145: if(!canports[i].used) etisserant@145: break; etisserant@145: } etisserant@145: etisserant@145: #ifndef NOT_USE_DYNAMIC_LOADING etisserant@145: if (&DLL_CALL(canOpen)==NULL) { etisserant@145: fprintf(stderr,"CanOpen : Can Driver dll not loaded\n"); etisserant@145: return NULL; etisserant@145: } etisserant@145: #endif etisserant@145: CAN_HANDLE fd0 = DLL_CALL(canOpen)(board); etisserant@162: if(fd0){ etisserant@162: canports[i].used = 1; etisserant@162: canports[i].fd = fd0; etisserant@162: canports[i].d = d; etisserant@149: etisserant@162: CreateReceiveTask(&(canports[i]), &canports[i].receiveTask, &canReceiveLoop); etisserant@162: etisserant@162: EnterMutex(); etisserant@162: d->canHandle = (CAN_PORT)&canports[i]; etisserant@162: LeaveMutex(); etisserant@162: return (CAN_PORT)&canports[i]; etisserant@162: }else{ etisserant@162: fprintf(stderr,"CanOpen : Cannot open board {busname='%s',baudrate='%s'}\n",board->busname, board->baudrate); etisserant@162: return NULL; etisserant@162: } etisserant@145: } etisserant@145: etisserant@149: int canClose(CO_Data * d) etisserant@149: { etisserant@149: EnterMutex(); etisserant@149: ((CANPort*)d->canHandle)->used = 0; etisserant@149: CANPort* tmp = (CANPort*)d->canHandle; etisserant@149: d->canHandle = NULL; etisserant@149: LeaveMutex(); etisserant@149: etisserant@149: int res = DLL_CALL(canClose)(tmp->fd); etisserant@149: etisserant@149: WaitReceiveTaskEnd(tmp->receiveTask); etisserant@145: return res; etisserant@145: } groke6@384: groke6@384: groke6@384: UNS8 canChangeBaudRate(CAN_PORT port, char* baud) groke6@384: { groke6@384: if(port){ groke6@384: UNS8 res; groke6@384: //LeaveMutex(); groke6@384: res = DLL_CALL(canChangeBaudRate)(((CANPort*)port)->fd, baud); groke6@384: //EnterMutex(); groke6@384: return res; // OK groke6@384: } groke6@384: return 1; // NOT OK groke6@384: }