1 /*
2  * CAN module object for Linux socketCAN.
3  *
4  * This file is a template for other microcontrollers.
5  *
6  * @ingroup     CO_driver
7  * @author      Janez Paternoster, Martin Wagner
8  * @copyright   2004 - 2015 Janez Paternoster, 2017 - 2020 Neuberger Gebaeudeautomation GmbH
9  *
10  *
11  * This file is part of CANopenNode, an opensource CANopen Stack.
12  * Project home page is <https://github.com/CANopenNode/CANopenNode>.
13  * For more information on CANopen see <http://www.can-cia.org/>.
14  *
15  * Licensed under the Apache License, Version 2.0 (the "License");
16  * you may not use this file except in compliance with the License.
17  * You may obtain a copy of the License at
18  *
19  *     http://www.apache.org/licenses/LICENSE-2.0
20  *
21  * Unless required by applicable law or agreed to in writing, software
22  * distributed under the License is distributed on an "AS IS" BASIS,
23  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24  * See the License for the specific language governing permissions and
25  * limitations under the License.
26  */
27 
28 #include <string.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <errno.h>
32 #include <linux/can/raw.h>
33 #include <linux/can/error.h>
34 #include <linux/net_tstamp.h>
35 #include <sys/socket.h>
36 #include <sys/epoll.h>
37 
38 #include "CO_driver.h"
39 
40 #if defined CO_DRIVER_ERROR_REPORTING
41   #if __has_include("syslog1/log.h")
42     #include "syslog/log.h"
43     #include "msgs.h"
44   #else
45     #include "CO_msgs.h"
46   #endif
47 #else
48   #define log_printf(macropar_prio, macropar_message, ...)
49 #endif
50 
51 #if __has_include("CO_Emergency.h")
52   #include "CO_Emergency.h"
53   #define USE_EMERGENCY_OBJECT
54 #endif
55 
56 pthread_mutex_t CO_EMCY_mutex = PTHREAD_MUTEX_INITIALIZER;
57 pthread_mutex_t CO_OD_mutex = PTHREAD_MUTEX_INITIALIZER;
58 
59 #ifndef CO_DRIVER_MULTI_INTERFACE
60 static CO_ReturnError_t CO_CANmodule_addInterface(CO_CANmodule_t *CANmodule, const void *CANdriverState);
61 #endif
62 
63 #ifdef CO_DRIVER_MULTI_INTERFACE
64 
65 static const uint32_t CO_INVALID_COB_ID = 0xffffffff;
66 
67 /******************************************************************************/
CO_CANsetIdentToIndex(uint32_t * lookup,uint32_t index,uint32_t identNew,uint32_t identCurrent)68 void CO_CANsetIdentToIndex(
69         uint32_t               *lookup,
70         uint32_t                index,
71         uint32_t                identNew,
72         uint32_t                identCurrent)
73 {
74     /* entry changed, remove old one */
75     if (identCurrent<CO_CAN_MSG_SFF_MAX_COB_ID && identNew!=identCurrent) {
76         lookup[identCurrent] = CO_INVALID_COB_ID;
77     }
78 
79     /* check if this COB ID is part of the table */
80     if (identNew > CO_CAN_MSG_SFF_MAX_COB_ID) {
81         return;
82     }
83 
84     /* Special case COB ID "0" -> valid value in *xArray[0] (CO_*CAN_NMT),
85      * "entry unconfigured" for all others */
86     if (identNew == 0) {
87         if (index == 0) {
88             lookup[0] = 0;
89         }
90     }
91     else {
92         lookup[identNew] = index;
93     }
94 }
95 
96 
97 /******************************************************************************/
CO_CANgetIndexFromIdent(uint32_t * lookup,uint32_t ident)98 static uint32_t CO_CANgetIndexFromIdent(
99         uint32_t               *lookup,
100         uint32_t                ident)
101 {
102     /* check if this COB ID is part of the table */
103     if (ident > CO_CAN_MSG_SFF_MAX_COB_ID) {
104         return CO_INVALID_COB_ID;
105     }
106 
107     return lookup[ident];
108 }
109 
110 #endif
111 
112 
113 /** Disable socketCAN rx *****************************************************/
disableRx(CO_CANmodule_t * CANmodule)114 static CO_ReturnError_t disableRx(CO_CANmodule_t *CANmodule)
115 {
116     int ret;
117     uint32_t i;
118     CO_ReturnError_t retval;
119 
120     /* insert a filter that doesn't match any messages */
121     retval = CO_ERROR_NO;
122     for (i = 0; i < CANmodule->CANinterfaceCount; i ++) {
123         ret = setsockopt(CANmodule->CANinterfaces[i].fd, SOL_CAN_RAW, CAN_RAW_FILTER,
124                          NULL, 0);
125         if(ret < 0){
126             log_printf(LOG_ERR, CAN_FILTER_FAILED,
127                        CANmodule->CANinterfaces[i].ifName);
128             log_printf(LOG_DEBUG, DBG_ERRNO, "setsockopt()");
129             retval = CO_ERROR_SYSCALL;
130         }
131     }
132 
133     return retval;
134 }
135 
136 /** Set up or update socketCAN rx filters *************************************/
setRxFilters(CO_CANmodule_t * CANmodule)137 static CO_ReturnError_t setRxFilters(CO_CANmodule_t *CANmodule)
138 {
139     int ret;
140     int i;
141     int count;
142     CO_ReturnError_t retval;
143 
144     struct can_filter rxFiltersCpy[CANmodule->rxSize];
145 
146     count = 0;
147     /* remove unused entries ( id == 0 and mask == 0 ) as they would act as
148      * "pass all" filter */
149     for (i = 0; i < CANmodule->rxSize; i ++) {
150         if ((CANmodule->rxFilter[i].can_id != 0) ||
151             (CANmodule->rxFilter[i].can_mask != 0)) {
152 
153             rxFiltersCpy[count] = CANmodule->rxFilter[i];
154 
155             count ++;
156         }
157     }
158 
159     if (count == 0) {
160         /* No filter is set, disable RX */
161         return disableRx(CANmodule);
162     }
163 
164     retval = CO_ERROR_NO;
165     for (i = 0; i < CANmodule->CANinterfaceCount; i ++) {
166       ret = setsockopt(CANmodule->CANinterfaces[i].fd, SOL_CAN_RAW, CAN_RAW_FILTER,
167                        rxFiltersCpy, sizeof(struct can_filter) * count);
168       if(ret < 0){
169           log_printf(LOG_ERR, CAN_FILTER_FAILED,
170                      CANmodule->CANinterfaces[i].ifName);
171           log_printf(LOG_DEBUG, DBG_ERRNO, "setsockopt()");
172           retval = CO_ERROR_SYSCALL;
173       }
174     }
175 
176     return retval;
177 }
178 
179 
180 /******************************************************************************/
CO_CANsetConfigurationMode(void * CANdriverState)181 void CO_CANsetConfigurationMode(void *CANdriverState)
182 {
183     /* Can't do anything because no reference to CANmodule_t is provided */
184 }
185 
186 
187 /******************************************************************************/
CO_CANsetNormalMode(CO_CANmodule_t * CANmodule)188 void CO_CANsetNormalMode(CO_CANmodule_t *CANmodule)
189 {
190     CO_ReturnError_t ret;
191 
192     CANmodule->CANnormal = false;
193 
194     if(CANmodule != NULL) {
195         ret = setRxFilters(CANmodule);
196         if (ret == CO_ERROR_NO) {
197             /* Put CAN module in normal mode */
198             CANmodule->CANnormal = true;
199         }
200     }
201 }
202 
203 
204 /******************************************************************************/
CO_CANmodule_init(CO_CANmodule_t * CANmodule,void * CANdriverState,CO_CANrx_t rxArray[],uint16_t rxSize,CO_CANtx_t txArray[],uint16_t txSize,uint16_t CANbitRate)205 CO_ReturnError_t CO_CANmodule_init(
206         CO_CANmodule_t         *CANmodule,
207         void                   *CANdriverState,
208         CO_CANrx_t              rxArray[],
209         uint16_t                rxSize,
210         CO_CANtx_t              txArray[],
211         uint16_t                txSize,
212         uint16_t                CANbitRate)
213 {
214     int32_t ret;
215     uint16_t i;
216     struct epoll_event ev;
217 
218     /* verify arguments */
219     if(CANmodule==NULL || rxArray==NULL || txArray==NULL){
220         return CO_ERROR_ILLEGAL_ARGUMENT;
221     }
222 
223     /* Create epoll FD */
224     CANmodule->fdEpoll = epoll_create(1);
225     if(CANmodule->fdEpoll < 0){
226         log_printf(LOG_DEBUG, DBG_ERRNO, "epoll_create()");
227         CO_CANmodule_disable(CANmodule);
228         return CO_ERROR_SYSCALL;
229     }
230 
231     /* Create notification pipe */
232     CANmodule->pipe = CO_NotifyPipeCreate();
233     if (CANmodule->pipe==NULL) {
234         log_printf(LOG_DEBUG, DBG_ERRNO, "pipe");
235         CO_CANmodule_disable(CANmodule);
236         return CO_ERROR_OUT_OF_MEMORY;
237     }
238     /* ...and add it to epoll */
239     ev.events = EPOLLIN;
240     ev.data.fd = CO_NotifyPipeGetFd(CANmodule->pipe);
241     ret = epoll_ctl(CANmodule->fdEpoll, EPOLL_CTL_ADD, ev.data.fd, &ev);
242     if(ret < 0){
243         log_printf(LOG_DEBUG, DBG_ERRNO, "epoll_ctl(pipe)");
244         CO_CANmodule_disable(CANmodule);
245         return CO_ERROR_SYSCALL;
246     }
247 
248     /* Configure object variables */
249     CANmodule->CANinterfaces = NULL;
250     CANmodule->CANinterfaceCount = 0;
251     CANmodule->rxArray = rxArray;
252     CANmodule->rxSize = rxSize;
253     CANmodule->txArray = txArray;
254     CANmodule->txSize = txSize;
255     CANmodule->CANnormal = false;
256     CANmodule->em = NULL; //this is set inside CO_Emergency.c init function!
257     CANmodule->fdTimerRead = -1;
258 #ifdef CO_DRIVER_MULTI_INTERFACE
259     for (i = 0; i < CO_CAN_MSG_SFF_MAX_COB_ID; i++) {
260         CANmodule->rxIdentToIndex[i] = CO_INVALID_COB_ID;
261         CANmodule->txIdentToIndex[i] = CO_INVALID_COB_ID;
262     }
263 #endif
264 
265     /* initialize socketCAN filters
266      * CAN module filters will be configured with CO_CANrxBufferInit()
267      * functions, called by separate CANopen init functions */
268     CANmodule->rxFilter = calloc(CANmodule->rxSize, sizeof(struct can_filter));
269     if(CANmodule->rxFilter == NULL){
270         log_printf(LOG_DEBUG, DBG_ERRNO, "malloc()");
271         return CO_ERROR_OUT_OF_MEMORY;
272     }
273 
274     for(i=0U; i<rxSize; i++){
275         rxArray[i].ident = 0U;
276         rxArray[i].mask = 0xFFFFFFFFU;
277         rxArray[i].object = NULL;
278         rxArray[i].pFunct = NULL;
279 #ifdef CO_DRIVER_MULTI_INTERFACE
280         rxArray[i].CANdriverState = NULL;
281         rxArray[i].timestamp.tv_sec = 0;
282         rxArray[i].timestamp.tv_nsec = 0;
283 #endif
284     }
285 
286 #ifndef CO_DRIVER_MULTI_INTERFACE
287     /* add one interface */
288     ret = CO_CANmodule_addInterface(CANmodule, CANdriverState);
289     if (ret != CO_ERROR_NO) {
290         CO_CANmodule_disable(CANmodule);
291     }
292 #else
293     ret = CO_ERROR_NO;
294 #endif
295     return ret;
296 }
297 
298 
299 /** enable socketCAN *********************************************************/
300 #ifndef CO_DRIVER_MULTI_INTERFACE
301 static
302 #endif
CO_CANmodule_addInterface(CO_CANmodule_t * CANmodule,const void * CANdriverState)303 CO_ReturnError_t CO_CANmodule_addInterface(
304         CO_CANmodule_t         *CANmodule,
305         const void             *CANdriverState)
306 {
307     int32_t ret;
308     int32_t tmp;
309     int32_t bytes;
310     char *ifName;
311     socklen_t sLen;
312     CO_CANinterface_t *interface;
313     struct sockaddr_can sockAddr;
314     struct epoll_event ev;
315 #ifdef CO_DRIVER_ERROR_REPORTING
316     can_err_mask_t err_mask;
317 #endif
318 
319     if (CANmodule->CANnormal != false) {
320         /* can't change config now! */
321         return CO_ERROR_INVALID_STATE;
322     }
323 
324     /* Add interface to interface list */
325     CANmodule->CANinterfaceCount ++;
326     CANmodule->CANinterfaces = realloc(CANmodule->CANinterfaces,
327         ((CANmodule->CANinterfaceCount) * sizeof(*CANmodule->CANinterfaces)));
328     if (CANmodule->CANinterfaces == NULL) {
329         log_printf(LOG_DEBUG, DBG_ERRNO, "malloc()");
330         return CO_ERROR_OUT_OF_MEMORY;
331     }
332     interface = &CANmodule->CANinterfaces[CANmodule->CANinterfaceCount - 1];
333 
334     interface->CANdriverState = CANdriverState;
335     ifName = if_indextoname((uintptr_t)interface->CANdriverState, interface->ifName);
336     if (ifName == NULL) {
337         log_printf(LOG_DEBUG, DBG_ERRNO, "if_indextoname()");
338         return CO_ERROR_ILLEGAL_ARGUMENT;
339     }
340 
341     /* Create socket */
342     interface->fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
343     if(interface->fd < 0){
344         log_printf(LOG_DEBUG, DBG_ERRNO, "socket(can)");
345         return CO_ERROR_SYSCALL;
346     }
347 
348     /* enable socket rx queue overflow detection */
349     tmp = 1;
350     ret = setsockopt(interface->fd, SOL_SOCKET, SO_RXQ_OVFL, &tmp, sizeof(tmp));
351     if(ret < 0){
352         log_printf(LOG_DEBUG, DBG_ERRNO, "setsockopt(ovfl)");
353         return CO_ERROR_SYSCALL;
354     }
355 #ifdef CO_DRIVER_MULTI_INTERFACE
356     /* enable software time stamp mode (hardware timestamps do not work properly
357      * on all devices)*/
358     tmp = (SOF_TIMESTAMPING_SOFTWARE |
359            SOF_TIMESTAMPING_RX_SOFTWARE);
360     ret = setsockopt(interface->fd, SOL_SOCKET, SO_TIMESTAMPING, &tmp, sizeof(tmp));
361     if (ret < 0) {
362         log_printf(LOG_DEBUG, DBG_ERRNO, "setsockopt(timestamping)");
363         return CO_ERROR_SYSCALL;
364     }
365 #endif
366 
367     //todo - modify rx buffer size? first one needs root
368     //ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, (void *)&bytes, sLen);
369     //ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void *)&bytes, sLen);
370 
371     /* print socket rx buffer size in bytes (In my experience, the kernel reserves
372      * around 450 bytes for each CAN message) */
373     sLen = sizeof(bytes);
374     getsockopt(interface->fd, SOL_SOCKET, SO_RCVBUF, (void *)&bytes, &sLen);
375     if (sLen == sizeof(bytes)) {
376         log_printf(LOG_INFO, CAN_SOCKET_BUF_SIZE, interface->ifName,
377                    bytes / 446, bytes);
378     }
379 
380     /* bind socket */
381     memset(&sockAddr, 0, sizeof(sockAddr));
382     sockAddr.can_family = AF_CAN;
383     sockAddr.can_ifindex = (uintptr_t)interface->CANdriverState;
384     ret = bind(interface->fd, (struct sockaddr*)&sockAddr, sizeof(sockAddr));
385     if(ret < 0){
386         log_printf(LOG_ERR, CAN_BINDING_FAILED, interface->ifName);
387         log_printf(LOG_DEBUG, DBG_ERRNO, "bind()");
388         return CO_ERROR_SYSCALL;
389     }
390 
391 #ifdef CO_DRIVER_ERROR_REPORTING
392     CO_CANerror_init(&interface->errorhandler, interface->fd, interface->ifName);
393     /* set up error frame generation. What actually is available depends on your
394      * CAN kernel driver */
395 #ifdef DEBUG
396     err_mask = CAN_ERR_MASK; //enable ALL error frames
397 #else
398     err_mask = CAN_ERR_ACK | CAN_ERR_CRTL | CAN_ERR_BUSOFF | CAN_ERR_BUSERROR;
399 #endif
400     ret = setsockopt(interface->fd, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &err_mask,
401                      sizeof(err_mask));
402     if(ret < 0){
403         log_printf(LOG_ERR, CAN_ERROR_FILTER_FAILED, interface->ifName);
404         log_printf(LOG_DEBUG, DBG_ERRNO, "setsockopt(can err)");
405         return CO_ERROR_SYSCALL;
406     }
407 #endif
408 
409     /* Add socket to epoll */
410     ev.events = EPOLLIN;
411     ev.data.fd = interface->fd;
412     ret = epoll_ctl(CANmodule->fdEpoll, EPOLL_CTL_ADD, ev.data.fd, &ev);
413     if(ret < 0){
414         log_printf(LOG_DEBUG, DBG_ERRNO, "epoll_ctl(can)");
415         return CO_ERROR_SYSCALL;
416     }
417 
418     /* rx is started by calling #CO_CANsetNormalMode() */
419     ret = disableRx(CANmodule);
420 
421     return ret;
422 }
423 
424 
425 /******************************************************************************/
CO_CANmodule_disable(CO_CANmodule_t * CANmodule)426 void CO_CANmodule_disable(CO_CANmodule_t *CANmodule)
427 {
428     uint32_t i;
429     struct timespec wait;
430 
431     if (CANmodule == NULL) {
432         return;
433     }
434 
435     /* clear interfaces */
436     for (i = 0; i < CANmodule->CANinterfaceCount; i++) {
437         CO_CANinterface_t *interface = &CANmodule->CANinterfaces[i];
438 
439 #ifdef CO_DRIVER_ERROR_REPORTING
440         CO_CANerror_disable(&interface->errorhandler);
441 #endif
442 
443         epoll_ctl(CANmodule->fdEpoll, EPOLL_CTL_DEL, interface->fd, NULL);
444         close(interface->fd);
445         interface->fd = -1;
446     }
447     if (CANmodule->CANinterfaces != NULL) {
448         free(CANmodule->CANinterfaces);
449     }
450     CANmodule->CANinterfaceCount = 0;
451 
452     /* cancel rx */
453     if (CANmodule->pipe != NULL) {
454         CO_NotifyPipeSend(CANmodule->pipe);
455         /* give some time for delivery */
456         wait.tv_sec = 0;
457         wait.tv_nsec = 50 /* ms */ * 1000000;
458         nanosleep(&wait, NULL);
459         CO_NotifyPipeFree(CANmodule->pipe);
460     }
461 
462     if (CANmodule->fdEpoll >= 0) {
463         close(CANmodule->fdEpoll);
464     }
465     CANmodule->fdEpoll = -1;
466 
467     if (CANmodule->rxFilter != NULL) {
468         free(CANmodule->rxFilter);
469     }
470     CANmodule->rxFilter = NULL;
471 }
472 
473 
474 /******************************************************************************/
CO_CANrxMsg_readIdent(const CO_CANrxMsg_t * rxMsg)475 uint16_t CO_CANrxMsg_readIdent(const CO_CANrxMsg_t *rxMsg)
476 {
477     /* remove socketCAN flags */
478     return (uint16_t) (rxMsg->ident & CAN_SFF_MASK);
479 }
480 
481 
482 /******************************************************************************/
CO_CANrxBufferInit(CO_CANmodule_t * CANmodule,uint16_t index,uint16_t ident,uint16_t mask,bool_t rtr,void * object,void (* pFunct)(void * object,const CO_CANrxMsg_t * message))483 CO_ReturnError_t CO_CANrxBufferInit(
484         CO_CANmodule_t         *CANmodule,
485         uint16_t                index,
486         uint16_t                ident,
487         uint16_t                mask,
488         bool_t                  rtr,
489         void                   *object,
490         void                  (*pFunct)(void *object, const CO_CANrxMsg_t *message))
491 {
492     CO_ReturnError_t ret = CO_ERROR_NO;
493 
494     if((CANmodule!=NULL) && (index < CANmodule->rxSize)){
495         uint16_t i;
496         CO_CANrx_t *buffer;
497 
498         /* check if COB ID is already used */
499         for (i = 0; i < CANmodule->rxSize; i ++) {
500             buffer = &CANmodule->rxArray[i];
501 
502             if (i!=index && ident>0 && ident==buffer->ident) {
503                 log_printf(LOG_DEBUG, DBG_CAN_RX_PARAM_FAILED, "duplicate entry");
504                 ret = CO_ERROR_ILLEGAL_ARGUMENT;
505             }
506         }
507 
508         if (ret == CO_ERROR_NO) {
509             /* buffer, which will be configured */
510             buffer = &CANmodule->rxArray[index];
511 
512 #ifdef CO_DRIVER_MULTI_INTERFACE
513             CO_CANsetIdentToIndex(CANmodule->rxIdentToIndex, index, ident,
514                                   buffer->ident);
515 #endif
516 
517             /* Configure object variables */
518             buffer->object = object;
519             buffer->pFunct = pFunct;
520 #ifdef CO_DRIVER_MULTI_INTERFACE
521             buffer->CANdriverState = NULL;
522             buffer->timestamp.tv_nsec = 0;
523             buffer->timestamp.tv_sec = 0;
524 #endif
525 
526             /* CAN identifier and CAN mask, bit aligned with CAN module */
527             buffer->ident = ident & CAN_SFF_MASK;
528             if(rtr){
529                 buffer->ident |= CAN_RTR_FLAG;
530             }
531             buffer->mask = (mask & CAN_SFF_MASK) | CAN_EFF_FLAG | CAN_RTR_FLAG;
532 
533             /* Set CAN hardware module filter and mask. */
534             CANmodule->rxFilter[index].can_id = buffer->ident;
535             CANmodule->rxFilter[index].can_mask = buffer->mask;
536             if(CANmodule->CANnormal){
537                 ret = setRxFilters(CANmodule);
538             }
539         }
540     }
541     else {
542         ret = CO_ERROR_ILLEGAL_ARGUMENT;
543     }
544 
545     return ret;
546 }
547 
548 #ifdef CO_DRIVER_MULTI_INTERFACE
549 
550 /******************************************************************************/
CO_CANrxBuffer_getInterface(CO_CANmodule_t * CANmodule,uint16_t ident,const void ** const CANdriverStateRx,struct timespec * timestamp)551 bool_t CO_CANrxBuffer_getInterface(
552         CO_CANmodule_t         *CANmodule,
553         uint16_t                ident,
554         const void            **const CANdriverStateRx,
555         struct timespec        *timestamp)
556 {
557     CO_CANrx_t *buffer;
558 
559     if (CANmodule == NULL){
560         return false;
561     }
562 
563     const uint32_t index = CO_CANgetIndexFromIdent(CANmodule->rxIdentToIndex, ident);
564     if ((index == CO_INVALID_COB_ID) || (index > CANmodule->rxSize)) {
565       return false;
566     }
567     buffer = &CANmodule->rxArray[index];
568 
569     /* return values */
570     if (CANdriverStateRx != NULL) {
571       *CANdriverStateRx = buffer->CANdriverState;
572     }
573     if (timestamp != NULL) {
574       *timestamp = buffer->timestamp;
575     }
576     if (buffer->CANdriverState != NULL) {
577       return true;
578     }
579     else {
580       return false;
581     }
582 }
583 
584 #endif
585 
586 
587 /******************************************************************************/
CO_CANtxBufferInit(CO_CANmodule_t * CANmodule,uint16_t index,uint16_t ident,bool_t rtr,uint8_t noOfBytes,bool_t syncFlag)588 CO_CANtx_t *CO_CANtxBufferInit(
589         CO_CANmodule_t         *CANmodule,
590         uint16_t                index,
591         uint16_t                ident,
592         bool_t                  rtr,
593         uint8_t                 noOfBytes,
594         bool_t                  syncFlag)
595 {
596     CO_CANtx_t *buffer = NULL;
597 
598     if((CANmodule != NULL) && (index < CANmodule->txSize)){
599         /* get specific buffer */
600         buffer = &CANmodule->txArray[index];
601 
602 #ifdef CO_DRIVER_MULTI_INTERFACE
603        CO_CANsetIdentToIndex(CANmodule->txIdentToIndex, index, ident, buffer->ident);
604 #endif
605 
606         buffer->CANdriverState = NULL;
607 
608         /* CAN identifier and rtr */
609         buffer->ident = ident & CAN_SFF_MASK;
610         if(rtr){
611             buffer->ident |= CAN_RTR_FLAG;
612         }
613         buffer->DLC = noOfBytes;
614         buffer->bufferFull = false;
615         buffer->syncFlag = syncFlag;
616     }
617 
618     return buffer;
619 }
620 
621 #ifdef CO_DRIVER_MULTI_INTERFACE
622 
623 /******************************************************************************/
CO_CANtxBuffer_setInterface(CO_CANmodule_t * CANmodule,uint16_t ident,const void * CANdriverStateTx)624 CO_ReturnError_t CO_CANtxBuffer_setInterface(
625         CO_CANmodule_t         *CANmodule,
626         uint16_t                ident,
627         const void             *CANdriverStateTx)
628 {
629     if (CANmodule != NULL) {
630         uint32_t index;
631 
632         index = CO_CANgetIndexFromIdent(CANmodule->txIdentToIndex, ident);
633         if ((index == CO_INVALID_COB_ID) || (index > CANmodule->txSize)) {
634             return CO_ERROR_PARAMETERS;
635         }
636         CANmodule->txArray[index].CANdriverState = CANdriverStateTx;
637 
638         return CO_ERROR_NO;
639     }
640     return CO_ERROR_PARAMETERS;
641 }
642 
643 #endif
644 
645 /******************************************************************************/
CO_CANCheckSendInterface(CO_CANmodule_t * CANmodule,CO_CANtx_t * buffer,CO_CANinterface_t * interface)646 static CO_ReturnError_t CO_CANCheckSendInterface(
647         CO_CANmodule_t         *CANmodule,
648         CO_CANtx_t             *buffer,
649         CO_CANinterface_t      *interface)
650 {
651     CO_ReturnError_t err = CO_ERROR_NO;
652 #ifdef CO_DRIVER_ERROR_REPORTING
653     CO_CANinterfaceState_t ifState;
654 #endif
655     ssize_t n;
656 
657     if (CANmodule==NULL || interface==NULL || interface->fd < 0) {
658         return CO_ERROR_PARAMETERS;
659     }
660 
661 #ifdef CO_DRIVER_ERROR_REPORTING
662     ifState = CO_CANerror_txMsg(&interface->errorhandler);
663     switch (ifState) {
664         case CO_INTERFACE_ACTIVE:
665             /* continue */
666             break;
667         case CO_INTERFACE_LISTEN_ONLY:
668             /* silently drop message */
669             return CO_ERROR_NO;
670         default:
671             return CO_ERROR_INVALID_STATE;
672     }
673 #endif
674 
675     do {
676         errno = 0;
677         n = send(interface->fd, buffer, CAN_MTU, MSG_DONTWAIT);
678         if (errno == EINTR) {
679             /* try again */
680             continue;
681         }
682         else if (errno == EAGAIN) {
683             /* socket queue full */
684             break;
685         }
686         else if (errno == ENOBUFS) {
687             /* socketCAN doesn't support blocking write. You can wait here for
688              * a few hundred us and then try again */
689             return CO_ERROR_TX_BUSY;
690         }
691         else if (n != CAN_MTU) {
692             break;
693         }
694     } while (errno != 0);
695 
696     if(n != CAN_MTU){
697 #ifdef USE_EMERGENCY_OBJECT
698         CO_errorReport((CO_EM_t*)CANmodule->em, CO_EM_CAN_TX_OVERFLOW, CO_EMC_CAN_OVERRUN, 0);
699 #endif
700         log_printf(LOG_ERR, DBG_CAN_TX_FAILED, buffer->ident, interface->ifName);
701         log_printf(LOG_DEBUG, DBG_ERRNO, "send()");
702         err = CO_ERROR_TX_OVERFLOW;
703     }
704 
705     return err;
706 }
707 
708 
709 /******************************************************************************/
CO_CANsend(CO_CANmodule_t * CANmodule,CO_CANtx_t * buffer)710 CO_ReturnError_t CO_CANsend(CO_CANmodule_t *CANmodule, CO_CANtx_t *buffer)
711 {
712     CO_ReturnError_t err;
713     err = CO_CANCheckSend(CANmodule, buffer);
714     if (err == CO_ERROR_TX_BUSY) {
715         /* send doesn't have "busy" */
716 #ifdef USE_EMERGENCY_OBJECT
717         CO_errorReport((CO_EM_t*)CANmodule->em, CO_EM_CAN_TX_OVERFLOW, CO_EMC_CAN_OVERRUN, 0);
718 #endif
719         log_printf(LOG_ERR, DBG_CAN_TX_FAILED, buffer->ident, "CANx");
720         log_printf(LOG_DEBUG, DBG_ERRNO, "send()");
721         err = CO_ERROR_TX_OVERFLOW;
722     }
723     return err;
724 }
725 
726 
727 /******************************************************************************/
CO_CANCheckSend(CO_CANmodule_t * CANmodule,CO_CANtx_t * buffer)728 CO_ReturnError_t CO_CANCheckSend(CO_CANmodule_t *CANmodule, CO_CANtx_t *buffer)
729 {
730     uint32_t i;
731     CO_ReturnError_t err = CO_ERROR_NO;
732 
733     /* check on which interfaces to send this messages */
734     for (i = 0; i < CANmodule->CANinterfaceCount; i++) {
735         CO_CANinterface_t *interface = &CANmodule->CANinterfaces[i];
736 
737         if ((buffer->CANdriverState == NULL) ||
738             buffer->CANdriverState == interface->CANdriverState) {
739 
740             CO_ReturnError_t tmp;
741 
742             /* match, use this one */
743             tmp = CO_CANCheckSendInterface(CANmodule, buffer, interface);
744             if (tmp) {
745                 /* only last error is returned to callee */
746                 err = tmp;
747             }
748         }
749     }
750 
751     return err;
752 }
753 
754 
755 /******************************************************************************/
CO_CANclearPendingSyncPDOs(CO_CANmodule_t * CANmodule)756 void CO_CANclearPendingSyncPDOs(CO_CANmodule_t *CANmodule)
757 {
758     /* Messages are either written to the socket queue or dropped */
759 }
760 
761 
762 /******************************************************************************/
CO_CANverifyErrors(CO_CANmodule_t * CANmodule)763 void CO_CANverifyErrors(CO_CANmodule_t *CANmodule)
764 {
765   /* socketCAN doesn't support microcontroller-like error counters. If an
766    * error has occured, a special can message is created by the driver and
767    * received by the application like a regular message.
768    * Therefore, error counter evaluation is included in rx function.*/
769 }
770 
771 /******************************************************************************/
CO_CANread(CO_CANmodule_t * CANmodule,CO_CANinterface_t * interface,struct can_frame * msg,struct timespec * timestamp)772 static CO_ReturnError_t CO_CANread(
773         CO_CANmodule_t         *CANmodule,
774         CO_CANinterface_t      *interface,
775         struct can_frame       *msg,
776         struct timespec        *timestamp)
777 {
778     int32_t n;
779     uint32_t dropped;
780     /* recvmsg - like read, but generates statistics about the socket
781      * example in berlios candump.c */
782     struct iovec iov;
783     struct msghdr msghdr;
784     char ctrlmsg[CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(sizeof(dropped))];
785     struct cmsghdr *cmsg;
786 
787     iov.iov_base = msg;
788     iov.iov_len = sizeof(*msg);
789 
790     msghdr.msg_name = NULL;
791     msghdr.msg_namelen = 0;
792     msghdr.msg_iov = &iov;
793     msghdr.msg_iovlen = 1;
794     msghdr.msg_control = &ctrlmsg;
795     msghdr.msg_controllen = sizeof(ctrlmsg);
796     msghdr.msg_flags = 0;
797 
798     n = recvmsg(interface->fd, &msghdr, 0);
799     if (n != CAN_MTU) {
800 #ifdef USE_EMERGENCY_OBJECT
801         CO_errorReport((CO_EM_t*)CANmodule->em, CO_EM_CAN_RXB_OVERFLOW,
802                        CO_EMC_CAN_OVERRUN, n);
803 #endif
804         log_printf(LOG_DEBUG, DBG_CAN_RX_FAILED, interface->ifName);
805         log_printf(LOG_DEBUG, DBG_ERRNO, "recvmsg()");
806         return CO_ERROR_SYSCALL;
807     }
808 
809     /* check for rx queue overflow, get rx time */
810     for (cmsg = CMSG_FIRSTHDR(&msghdr);
811          cmsg && (cmsg->cmsg_level == SOL_SOCKET);
812          cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
813         if (cmsg->cmsg_type == SO_TIMESTAMPING) {
814             /* this is system time, not monotonic time! */
815             *timestamp = ((struct timespec*)CMSG_DATA(cmsg))[0];
816         }
817         else if (cmsg->cmsg_type == SO_RXQ_OVFL) {
818             dropped = *(uint32_t*)CMSG_DATA(cmsg);
819             if (dropped > CANmodule->rxDropCount) {
820 #ifdef USE_EMERGENCY_OBJECT
821                 CO_errorReport((CO_EM_t*)CANmodule->em, CO_EM_CAN_RXB_OVERFLOW,
822                                CO_EMC_COMMUNICATION, 0);
823 #endif
824                 log_printf(LOG_ERR, CAN_RX_SOCKET_QUEUE_OVERFLOW,
825                            interface->ifName, dropped);
826             }
827             CANmodule->rxDropCount = dropped;
828             //todo use this info!
829         }
830     }
831 
832     return CO_ERROR_NO;
833 }
834 
CO_CANrxMsg(CO_CANmodule_t * CANmodule,struct can_frame * msg,CO_CANrxMsg_t * buffer)835 static int32_t CO_CANrxMsg(
836         CO_CANmodule_t        *CANmodule,
837         struct can_frame      *msg,
838         CO_CANrxMsg_t         *buffer)
839 {
840     int32_t retval;
841     const CO_CANrxMsg_t *rcvMsg;  /* pointer to received message in CAN module */
842     uint16_t index;               /* index of received message */
843     CO_CANrx_t *rcvMsgObj = NULL; /* receive message object from CO_CANmodule_t object. */
844     bool_t msgMatched = false;
845 
846     /* CANopenNode can message is binary compatible to the socketCAN one, except
847      * for extension flags */
848     msg->can_id &= CAN_EFF_MASK;
849     rcvMsg = (CO_CANrxMsg_t *)msg;
850 
851     /* Message has been received. Search rxArray from CANmodule for the
852      * same CAN-ID. */
853     rcvMsgObj = &CANmodule->rxArray[0];
854     for (index = 0; index < CANmodule->rxSize; index ++) {
855         if(((rcvMsg->ident ^ rcvMsgObj->ident) & rcvMsgObj->mask) == 0U){
856             msgMatched = true;
857             break;
858         }
859         rcvMsgObj++;
860     }
861     if(msgMatched) {
862         /* Call specific function, which will process the message */
863         if ((rcvMsgObj != NULL) && (rcvMsgObj->pFunct != NULL)){
864             rcvMsgObj->pFunct(rcvMsgObj->object, rcvMsg);
865         }
866         /* return message */
867         if (buffer != NULL) {
868             memcpy(buffer, rcvMsg, sizeof(*buffer));
869         }
870         retval = index;
871     }
872     else {
873         retval = -1;
874     }
875 
876     return retval;
877 }
878 
879 /******************************************************************************/
CO_CANrxWait(CO_CANmodule_t * CANmodule,int fdTimer,CO_CANrxMsg_t * buffer)880 int32_t CO_CANrxWait(CO_CANmodule_t *CANmodule, int fdTimer, CO_CANrxMsg_t *buffer)
881 {
882     int32_t retval;
883     int32_t ret;
884 #ifdef CO_DRIVER_MULTI_INTERFACE
885     const void *CANdriverState;
886 #endif
887     CO_ReturnError_t err;
888     CO_CANinterface_t *interface = NULL;
889     struct epoll_event ev[1];
890     struct can_frame msg;
891     struct timespec timestamp;
892 
893     if (CANmodule==NULL || CANmodule->CANinterfaceCount==0) {
894         return -1;
895     }
896 
897     if (fdTimer>=0 && fdTimer!=CANmodule->fdTimerRead) {
898         /* new timer, timer changed */
899         epoll_ctl(CANmodule->fdEpoll, EPOLL_CTL_DEL, CANmodule->fdTimerRead, NULL);
900         ev[0].events = EPOLLIN;
901         ev[0].data.fd = fdTimer;
902         ret = epoll_ctl(CANmodule->fdEpoll, EPOLL_CTL_ADD, ev[0].data.fd, &ev[0]);
903         if(ret < 0){
904             return -1;
905         }
906         CANmodule->fdTimerRead = fdTimer;
907     }
908 
909     /*
910      * blocking read using epoll
911      */
912     do {
913         errno = 0;
914         ret = epoll_wait(CANmodule->fdEpoll, ev, sizeof(ev) / sizeof(ev[0]), -1);
915         if (errno == EINTR) {
916             /* try again */
917             continue;
918         }
919         else if (ret < 0) {
920             /* epoll failed */
921             return -1;
922         }
923         else if ((ev[0].events & (EPOLLERR | EPOLLHUP)) != 0) {
924             /* epoll detected close/error on socket. Try to pull event */
925             errno = 0;
926             recv(ev[0].data.fd, &msg, sizeof(msg), MSG_DONTWAIT);
927             log_printf(LOG_DEBUG, DBG_CAN_RX_EPOLL, ev[0].events, strerror(errno));
928             continue;
929         }
930         else if ((ev[0].events & EPOLLIN) != 0) {
931             /* one of the sockets is ready */
932             if ((ev[0].data.fd == CO_NotifyPipeGetFd(CANmodule->pipe)) ||
933                 (ev[0].data.fd == fdTimer)) {
934                 /* timer/pipe socket */
935                 return -1;
936             }
937             else {
938                 /* CAN socket */
939                 uint32_t i;
940 
941                 for (i = 0; i < CANmodule->CANinterfaceCount; i ++) {
942                     interface = &CANmodule->CANinterfaces[i];
943 
944                     if (ev[0].data.fd == interface->fd) {
945 #ifdef CO_DRIVER_MULTI_INTERFACE
946                         /* get interface handle */
947                         CANdriverState = interface->CANdriverState;
948 #endif
949                         /* get message */
950                         err = CO_CANread(CANmodule, interface, &msg, &timestamp);
951                         if (err != CO_ERROR_NO) {
952                             return -1;
953                         }
954                         /* no need to continue search */
955                         break;
956                     }
957                 }
958             }
959         }
960     } while (errno != 0);
961 
962     /*
963      * evaluate Rx
964      */
965     retval = -1;
966     if(CANmodule->CANnormal){
967 
968         if (msg.can_id & CAN_ERR_FLAG) {
969             /* error msg */
970 #ifdef CO_DRIVER_ERROR_REPORTING
971             CO_CANerror_rxMsgError(&interface->errorhandler, &msg);
972 #endif
973         }
974         else {
975             /* data msg */
976             int32_t msgIndex;
977 
978 #ifdef CO_DRIVER_ERROR_REPORTING
979             CO_CANerror_rxMsg(&interface->errorhandler);
980 #endif
981 
982             msgIndex = CO_CANrxMsg(CANmodule, &msg, buffer);
983             if (msgIndex > -1) {
984 #ifdef CO_DRIVER_MULTI_INTERFACE
985                 /* Store message info */
986                 CANmodule->rxArray[msgIndex].timestamp = timestamp;
987                 CANmodule->rxArray[msgIndex].CANdriverState = CANdriverState;
988 #endif
989             }
990             retval = msgIndex;
991         }
992     }
993     return retval;
994 }
995