]> rtime.felk.cvut.cz Git - CanFestival-3.git/blob - drivers/unix/unix.c
7678874086e5edb4947a552c0b5153c1ec927d8c
[CanFestival-3.git] / drivers / unix / unix.c
1 /*
2 This file is part of CanFestival, a library implementing CanOpen Stack. 
3
4 Copyright (C): Edouard TISSERANT and Francis DUPIN
5
6 See COPYING file for copyrights details.
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 */
22 #ifndef __KERNEL__
23 #include <unistd.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #else
27 #include <linux/module.h>
28 #endif
29
30 #ifndef NOT_USE_DYNAMIC_LOADING
31 #define DLL_CALL(funcname) (* funcname##_driver)
32 #define FCT_PTR_INIT =NULL
33
34 #define DLSYM(name)\
35         *(void **) (&name##_driver) = dlsym(handle, #name"_driver");\
36         if ((error = dlerror()) != NULL)  {\
37                 fprintf (stderr, "%s\n", error);\
38                 UnLoadCanDriver(handle);\
39                 return NULL;\
40         }
41
42 #else /*NOT_USE_DYNAMIC_LOADING*/
43
44 /*Function call is direct*/
45 #define DLL_CALL(funcname) funcname##_driver
46
47 #endif /*NOT_USE_DYNAMIC_LOADING*/
48
49 #include "data.h"
50 #include "canfestival.h"
51 #include "timers_driver.h"
52
53 #define MAX_NB_CAN_PORTS 16
54
55 /** CAN port structure */
56 typedef struct {
57   char used;  /**< flag indicating CAN port usage, will be used to abort Receiver task*/
58   CAN_HANDLE fd; /**< CAN port file descriptor*/
59   TASK_HANDLE receiveTask; /**< CAN Receiver task*/
60   CO_Data* d; /**< CAN object data*/
61 } CANPort;
62
63 #include "can_driver.h"
64
65 /*Declares the funtion pointers for dll binding or simple protos*/
66 /*UNS8 DLL_CALL(canReceive)(CAN_HANDLE, Message *);
67 UNS8 DLL_CALL(canSend)(CAN_HANDLE, Message *);
68 CAN_HANDLE DLL_CALL(canOpen)(s_BOARD *);
69 int DLL_CALL(canClose)(CAN_HANDLE);
70 */
71 CANPort canports[MAX_NB_CAN_PORTS] = {{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,}};
72
73 #ifndef NOT_USE_DYNAMIC_LOADING
74
75 /*UnLoads the dll*/
76 UNS8 UnLoadCanDriver(LIB_HANDLE handle)
77 {
78         if(handle!=NULL)
79         {
80                 dlclose(handle);
81
82                 handle=NULL;
83                 return 0;
84         }
85         return -1;
86 }
87
88 /**
89  * Loads the dll and get funcs ptr
90  *
91  * @param driver_name String containing driver's dynamic library name
92  * @return Library handle
93  */
94 LIB_HANDLE LoadCanDriver(char* driver_name)
95 {
96         LIB_HANDLE handle = NULL;
97         char *error;
98         
99
100         if(handle==NULL)
101         {
102                 handle = dlopen(driver_name, RTLD_LAZY);
103         }
104
105         if (!handle) {
106                 fprintf (stderr, "%s\n", dlerror());
107                 return NULL;
108         }
109  
110         /*Get function ptr*/
111         DLSYM(canReceive)
112         DLSYM(canSend)
113         DLSYM(canOpen)
114         DLSYM(canChangeBaudRate)
115         DLSYM(canClose)
116
117         return handle;
118 }
119
120 #endif
121
122
123
124 /*Not needed -- canReceiveLoop calls _canReceive directly *//*
125 UNS8 canReceive(CAN_PORT port, Message *m)
126 {
127         return DLL_CALL(canReceive)(port->fd, Message *m);
128 }
129 */
130
131 /**
132  * CAN send routine
133  * @param port CAN port
134  * @param m CAN message
135  * @return success or error
136  */
137 UNS8 canSend(CAN_PORT port, Message *m)
138 {
139         if(port){
140                 UNS8 res;
141                 //LeaveMutex();
142                 res = DLL_CALL(canSend)(((CANPort*)port)->fd, m);
143                 //EnterMutex();
144                 return res; // OK
145         }               
146         return 1; // NOT OK
147 }
148
149 /**
150  * CAN Receiver Task
151  * @param port CAN port
152  */
153 void canReceiveLoop(CAN_PORT port)
154 {
155        Message m;
156
157        while (((CANPort*)port)->used) {
158                if (DLL_CALL(canReceive)(((CANPort*)port)->fd, &m) != 0)
159                        break;
160
161                EnterMutex();
162                canDispatch(((CANPort*)port)->d, &m);
163                LeaveMutex();
164        }
165 }
166
167 /**
168  * CAN open routine
169  * @param board device name and baudrate
170  * @param d CAN object data
171  * @return valid CAN_PORT pointer or NULL
172  */
173 CAN_PORT canOpen(s_BOARD *board, CO_Data * d)
174 {
175         int i;
176         for(i=0; i < MAX_NB_CAN_PORTS; i++)
177         {
178                 if(!canports[i].used)
179                 break;
180         }
181         
182 #ifndef NOT_USE_DYNAMIC_LOADING
183         if (&DLL_CALL(canOpen)==NULL) {
184                 fprintf(stderr,"CanOpen : Can Driver dll not loaded\n");
185                 return NULL;
186         }
187 #endif  
188         CAN_HANDLE fd0 = DLL_CALL(canOpen)(board);
189         if(fd0){
190                 canports[i].used = 1;
191                 canports[i].fd = fd0;
192                 canports[i].d = d;
193                 d->canHandle = (CAN_PORT)&canports[i];          
194                 CreateReceiveTask(&(canports[i]), &canports[i].receiveTask, &canReceiveLoop);
195                 return (CAN_PORT)&canports[i];
196         }else{
197                 MSG("CanOpen : Cannot open board {busname='%s',baudrate='%s'}\n",board->busname, board->baudrate);
198                 return NULL;
199         }
200 }
201
202 /**
203  * CAN close routine
204  * @param d CAN object data
205  * @return success or error
206  */
207 int canClose(CO_Data * d)
208 {
209         UNS8 res;
210         
211         ((CANPort*)d->canHandle)->used = 0;
212         CANPort* tmp = (CANPort*)d->canHandle;
213         d->canHandle = NULL;
214         
215         // close CAN port
216         res = DLL_CALL(canClose)(tmp->fd);
217
218         // kill receiver task
219         WaitReceiveTaskEnd(&tmp->receiveTask);
220         
221         return res;
222 }
223
224
225 /**
226  * CAN change baudrate routine
227  * @param port CAN port
228  * @param baud baudrate
229  * @return success or error
230  */
231 UNS8 canChangeBaudRate(CAN_PORT port, char* baud)
232 {
233    if(port){
234                 UNS8 res;
235                 //LeaveMutex();
236                 res = DLL_CALL(canChangeBaudRate)(((CANPort*)port)->fd, baud);
237                 //EnterMutex();
238                 return res; // OK
239         }               
240         return 1; // NOT OK
241 }
242
243
244 #ifdef __KERNEL__
245 EXPORT_SYMBOL (canOpen);
246 EXPORT_SYMBOL (canClose);
247 EXPORT_SYMBOL (canSend);
248 EXPORT_SYMBOL (canChangeBaudRate);
249 #endif