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 nico@215: 00006 See COPYING file for copyrights details. nico@215: 00007 nico@215: 00008 This library is free software; you can redistribute it and/or nico@215: 00009 modify it under the terms of the GNU Lesser General Public nico@215: 00010 License as published by the Free Software Foundation; either nico@215: 00011 version 2.1 of the License, or (at your option) any later version. nico@215: 00012 nico@215: 00013 This library is distributed in the hope that it will be useful, nico@215: 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of nico@215: 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU nico@215: 00016 Lesser General Public License for more details. nico@215: 00017 nico@215: 00018 You should have received a copy of the GNU Lesser General Public nico@215: 00019 License along with this library; if not, write to the Free Software nico@215: 00020 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA nico@215: 00021 */ nico@215: 00022 #include <unistd.h> nico@215: 00023 #include <stdio.h> nico@215: 00024 #include <stdlib.h> nico@215: 00025 nico@215: 00026 #ifndef NOT_USE_DYNAMIC_LOADING etisserant@240: 00027 #define DLL_CALL(funcname) (* funcname##_driver) etisserant@240: 00028 #define FCT_PTR_INIT =NULL nico@215: 00029 etisserant@240: 00030 #define DLSYM(name)\ nico@215: 00031 *(void **) (&name##_driver) = dlsym(handle, #name"_driver");\ nico@215: 00032 if ((error = dlerror()) != NULL) {\ nico@215: 00033 fprintf (stderr, "%s\n", error);\ nico@215: 00034 UnLoadCanDriver(handle);\ nico@215: 00035 return NULL;\ nico@215: 00036 } nico@215: 00037 nico@215: 00038 #else /*NOT_USE_DYNAMIC_LOADING*/ nico@215: 00039 nico@215: 00040 /*Function call is direct*/ nico@215: 00041 #define DLL_CALL(funcname) funcname##_driver nico@215: 00042 nico@215: 00043 #endif /*NOT_USE_DYNAMIC_LOADING*/ nico@215: 00044 nico@215: 00045 #include "data.h" nico@215: 00046 #include "canfestival.h" nico@215: 00047 #include "timers_driver.h" nico@215: 00048 etisserant@240: 00049 #define MAX_NB_CAN_PORTS 16 nico@215: 00050 nico@215: 00051 typedef struct { etisserant@240: 00052 char used; etisserant@240: 00053 CAN_HANDLE fd; etisserant@240: 00054 TASK_HANDLE receiveTask; etisserant@240: 00055 CO_Data* d; nico@215: 00056 } CANPort; nico@215: 00057 nico@215: 00058 #include "can_driver.h" nico@215: 00059 nico@215: 00060 /*Declares the funtion pointers for dll binding or simple protos*/ nico@215: 00061 /*UNS8 DLL_CALL(canReceive)(CAN_HANDLE, Message *); nico@215: 00062 UNS8 DLL_CALL(canSend)(CAN_HANDLE, Message *); nico@215: 00063 CAN_HANDLE DLL_CALL(canOpen)(s_BOARD *); nico@215: 00064 int DLL_CALL(canClose)(CAN_HANDLE); nico@215: 00065 */ etisserant@240: 00066 CANPort canports[MAX_NB_CAN_PORTS] = {{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,}}; nico@215: 00067 nico@215: 00068 #ifndef NOT_USE_DYNAMIC_LOADING nico@215: 00069 nico@215: 00070 /*UnLoads the dll*/ etisserant@240: 00071 UNS8 UnLoadCanDriver(LIB_HANDLE handle) nico@215: 00072 { nico@215: 00073 if(handle!=NULL) nico@215: 00074 { nico@215: 00075 dlclose(handle); nico@215: 00076 nico@215: 00077 handle=NULL; nico@215: 00078 return 0; nico@215: 00079 } nico@215: 00080 return -1; nico@215: 00081 } nico@215: 00082 nico@215: 00083 /*Loads the dll and get funcs ptr*/ etisserant@240: 00084 LIB_HANDLE LoadCanDriver(char* driver_name) nico@215: 00085 { etisserant@240: 00086 LIB_HANDLE handle = NULL; nico@215: 00087 char *error; nico@215: 00088 nico@215: 00089 nico@215: 00090 if(handle==NULL) nico@215: 00091 { nico@215: 00092 handle = dlopen(driver_name, RTLD_LAZY); nico@215: 00093 } nico@215: 00094 nico@215: 00095 if (!handle) { nico@215: 00096 fprintf (stderr, "%s\n", dlerror()); nico@215: 00097 return NULL; nico@215: 00098 } nico@215: 00099 nico@215: 00100 /*Get function ptr*/ etisserant@240: 00101 DLSYM(canReceive) etisserant@240: 00102 DLSYM(canSend) etisserant@240: 00103 DLSYM(canOpen) etisserant@240: 00104 DLSYM(canClose) nico@215: 00105 nico@215: 00106 return handle; nico@215: 00107 } nico@215: 00108 nico@215: 00109 #endif nico@215: 00110 nico@215: 00111 nico@215: 00112 nico@215: 00113 /*Not needed -- canReceiveLoop calls _canReceive directly *//* nico@215: 00114 UNS8 canReceive(CAN_PORT port, Message *m) nico@215: 00115 { nico@215: 00116 return DLL_CALL(canReceive)(port->fd, Message *m); nico@215: 00117 } nico@215: 00118 */ nico@215: 00119 etisserant@240: 00120 UNS8 canSend(CAN_PORT port, Message *m) nico@215: 00121 { nico@215: 00122 if(port){ etisserant@240: 00123 UNS8 res; nico@215: 00124 //LeaveMutex(); etisserant@240: 00125 res = DLL_CALL(canSend)(((CANPort*)port)->fd, m); nico@215: 00126 //EnterMutex(); nico@215: 00127 return res; nico@215: 00128 } nico@215: 00129 return -1; nico@215: 00130 } nico@215: 00131 etisserant@240: 00132 void canReceiveLoop(CAN_PORT port) nico@215: 00133 { nico@215: 00134 Message m; nico@215: 00135 nico@215: 00136 while (1) { etisserant@240: 00137 if (DLL_CALL(canReceive)(((CANPort*)port)->fd, &m) != 0) nico@215: 00138 break; nico@215: 00139 etisserant@240: 00140 EnterMutex(); etisserant@240: 00141 canDispatch(((CANPort*)port)->d, &m); etisserant@240: 00142 LeaveMutex(); nico@215: 00143 } nico@215: 00144 } etisserant@240: 00145 CAN_PORT canOpen(s_BOARD *board, CO_Data * d) nico@215: 00146 { nico@215: 00147 int i; etisserant@240: 00148 for(i=0; i < MAX_NB_CAN_PORTS; i++) nico@215: 00149 { etisserant@240: 00150 if(!canports[i].used) nico@215: 00151 break; nico@215: 00152 } nico@215: 00153 nico@215: 00154 #ifndef NOT_USE_DYNAMIC_LOADING etisserant@240: 00155 if (&DLL_CALL(canOpen)==NULL) { nico@215: 00156 fprintf(stderr,"CanOpen : Can Driver dll not loaded\n"); nico@215: 00157 return NULL; nico@215: 00158 } nico@215: 00159 #endif etisserant@240: 00160 CAN_HANDLE fd0 = DLL_CALL(canOpen)(board); nico@215: 00161 if(fd0){ etisserant@240: 00162 canports[i].used = 1; etisserant@240: 00163 canports[i].fd = fd0; etisserant@240: 00164 canports[i].d = d; nico@215: 00165 etisserant@240: 00166 CreateReceiveTask(&(canports[i]), &canports[i].receiveTask, &canReceiveLoop); nico@215: 00167 etisserant@240: 00168 EnterMutex(); etisserant@240: 00169 d->canHandle = (CAN_PORT)&canports[i]; etisserant@240: 00170 LeaveMutex(); etisserant@240: 00171 return (CAN_PORT)&canports[i]; nico@215: 00172 }else{ etisserant@240: 00173 fprintf(stderr,"CanOpen : Cannot open board {busname='%s',baudrate='%s'}\n",board->busname, board->baudrate); nico@215: 00174 return NULL; nico@215: 00175 } nico@215: 00176 } nico@215: 00177 etisserant@240: 00178 int canClose(CO_Data * d) nico@215: 00179 { etisserant@240: 00180 EnterMutex(); etisserant@240: 00181 ((CANPort*)d->canHandle)->used = 0; etisserant@240: 00182 CANPort* tmp = (CANPort*)d->canHandle; etisserant@240: 00183 d->canHandle = NULL; etisserant@240: 00184 LeaveMutex(); nico@215: 00185 etisserant@240: 00186 int res = DLL_CALL(canClose)(tmp->fd); nico@215: 00187 etisserant@240: 00188 WaitReceiveTaskEnd(tmp->receiveTask); nico@215: 00189 return res; nico@215: 00190 } etisserant@240: