socan 1.2.1
Linux SocketCAN higher level library
Loading...
Searching...
No Matches
socan.c
Go to the documentation of this file.
1
30#include <assert.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#include <unistd.h>
35#include <stdarg.h>
36
37#include <stdbool.h>
38
39#include <errno.h>
40
41#include <net/if.h>
42#include <sys/ioctl.h>
43#include <sys/socket.h>
44
45/* for gettimeofday: */
46#include <sys/time.h>
47
48/* nanosleep: */
49#include <time.h>
50
51/* header for semaphores: */
52#include <semaphore.h>
53
54/* __USE_GNU must be defined in order to use pthread_setname_np and
55 * pthread_getname_np: */
56#define __USE_GNU
57/* threads, mutexes: */
58#include <pthread.h>
59
60/* message queues */
61#include <mqueue.h>
62
63#include <linux/net_tstamp.h>
64#include <linux/sockios.h>
65
66#include <linux/can.h>
67#include <linux/can/raw.h>
68
69/*
70 * virtual CAN interface, see:
71 * https://www.pragmaticlinux.com/2021/10/how-to-create-a-virtual-can-interface-on-linux/
72
73
74 Load the vcan kernel module:
75 $ sudo modprobe vcan
76 Create the virtual CAN interface:
77 $ sudo ip link add dev vcan0 type vcan
78 Bring the virtual CAN interface online:
79 $ sudo ip link set up vcan0
80
81 Afterwards, you can run the
82 $ ip addr | grep "can"
83 command to verify that the virtual CAN interface is available and online on your Linux system:
84
85 * couple two virtual interfaces:
86 * https://stackoverflow.com/questions/54296852/how-to-connect-two-vcan-ports-in-linux
87
88 sudo modprobe can-gw
89 sudo cangw -A -s vcan0 -d vcan1 -e
90 sudo cangw -A -s vcan1 -d vcan0 -e
91
92 test this program with:
93 terminal 1:
94 $ ./socantest
95 terminal 2:
96 $ cansend vcan0 '190#DEADBEEF'
97 */
98
99/* PEAK PCAN-PCI Express FD
100
101make and install driver
102
103 $ sudo modprobe pcan
104
105 $ sudo ip link set can0 type can bitrate 1000000
106 $ sudo ip link set up can0
107 $ sudo ip link set can0 txqueuelen 1000
108 $ sudo ip link set can1 type can bitrate 1000000
109 $ sudo ip link set up can1
110 $ sudo ip link set can1 txqueuelen 1000
111
112*/
113
114#include <socan.h>
115
116/* ----------------------------------------------
117 * constants
118 * ---------------------------------------------- */
119
121#define READER_DEFAULT_PRIO 97
122
124#define WRITER_DEFAULT_PRIO 97
125
127#define MAX_WQ_MESSAGES 32
128
130#define MAX_QR_MESSAGES 32
131
132/* ----------------------------------------------
133 * types
134 * ---------------------------------------------- */
135
143
145typedef struct sq_elm
146 {
147 unsigned short cob;
148 unsigned short port;
150
157typedef struct
158 {
160 int head, tail;
162 pthread_mutex_t qmutex;
163 sem_t qsem;
164 bool empty;
165 } squeue;
166
168 {
169 unsigned char port;
170 unsigned short cob;
171 unsigned char length;
172 unsigned char received_length;
173 unsigned char buffer[SOCAN_FRAME_LENGTH];
174 unsigned char buffer2[SOCAN_FRAME_LENGTH]; /* only for RTR */
175 bool use_buffer2; /* only for RTR */
176 bool use_queue; /* for queue read */
177 socan_obj_type type;
178 struct timeval tv;
179 struct timeval tv_request;
180 unsigned int tmo_ms;
181 unsigned long tm_inhibit_us; /* inhibit time in microseconds */
182 unsigned short urcnt; /* Made equal to ircnt at the end of all read
183 functions. So urcnt==ircnt means no new
184 unread data is in the CAN object buffer. */
185 unsigned short ircnt; /* Incremented each time the reader task receives
186 data for a CAN object. */
187 unsigned char w_echo; /* set to 0 when something should be written to
188 the CAN bus, set to 1 when the echo was received. */
189 unsigned char ulock; /* 1 if the user task is currently changing the
190 structure */
191 void *user_ptr;
192 struct socan_hdl_s *hdl_s;
193 };
194
195typedef struct
196 {
197 struct socan_obj_s *objects[COB_NO];
198 } cob_dict;
199
201 {
202 sem_t thread_sem;
203 pthread_mutex_t mutex;
204 bool is_active;
205 squeue qread_queue;
206 };
207
208typedef struct
209 {
210 char *interface_name;
211 int interface_index;
212 int interface_index_valid;
213 unsigned char port; /* port number, starts with 0 */
214 unsigned int bitrate; /* Bitrate in bit/s, initially 0.
215 Used to buffer the bitrate, if requested with
216 socan_interface_bitrate */
217 bool is_virtual; /* true for virtual CAN bus interfaces like
218 "vcan0", "vcan1" ... */
219 squeue writer_squeue;
220 cob_dict *dict;
221 } can_port;
222
223/* ----------------------------------------------
224 * variables
225 * ---------------------------------------------- */
226
227static socan_module_state socan_state= UNINITIALIZED;
228
229static bool socan_use_rt_priority= true;
230static bool socan_require_rt_priority= false;
231
232static int socan_reader_priority= READER_DEFAULT_PRIO;
233static int socan_writer_priority= WRITER_DEFAULT_PRIO;
234
235static pthread_t socan_read_threads[SOCAN_MAX_PORTS];
236static pthread_t socan_write_threads[SOCAN_MAX_PORTS];
237
238static pthread_mutex_t global_semaphore;
239
240static can_port can_ports[SOCAN_MAX_PORTS];
241static unsigned char can_ports_no= 0;
242
243static int thread_count=0;
244
245/* ----------------------------------------------
246 * errprint module
247 * ---------------------------------------------- */
248
249static int errprintlevel= 1;
250/* 0: no output
251 * 1: output of severe errors, system calls that failed
252 * 2: output of usage errors, invalid parameters
253 * 3: output of run-time errors (e.g. congestion)
254 */
255
256static void errprint(int level, const char *function, const int line,
257 char *format, ...)
258 {
259 va_list args;
260 char mypre[80];
261 char mymsg[240];
262
263 if (level>errprintlevel)
264 return;
265 va_start(args, format);
266 snprintf(mypre, 80, "socan error in %s (line %d): ", function, line);
267 vsnprintf(mymsg, 240, format, args);
268 fprintf(stderr, "%s%s", mypre, mymsg);
269 va_end(args);
270 }
271
272#define ERRPRINT(lv, ...) errprint(lv, __func__, __LINE__, __VA_ARGS__)
273
274#define ERRPRINT_FUNC(lv, FUNC, ...) errprint(1, FUNC, __LINE__, __VA_ARGS__)
275
276#define ERRPRINT_ERRNO(syscall) \
277 errprint(1, __func__, __LINE__, \
278 syscall " failed, errno %d (%s)\n", errno, strerror(errno))
279
280#define ERRPRINT_RC(syscall, rc) \
281 errprint(1, __func__, __LINE__, \
282 syscall " failed, error %d (%s)\n", rc, strerror(rc))
283
284#define ERRPRINT_RC_FUNC(FUNC, syscall, rc) \
285 errprint(1, FUNC, __LINE__, \
286 syscall " failed, error %d (%s)\n", rc, strerror(rc))
287
289 /* get/set errprintlevel,
290 * level>=0: set this level
291 * level<0 : do not change level
292 * returns: the current or changed errprintlevel
293 */
294 {
295 if (level>=0)
296 errprintlevel= level;
297 return errprintlevel;
298 }
299
300/* ----------------------------------------------
301 * trace module
302 * ---------------------------------------------- */
303
304static int tracelevel= 0;
305/* 0: no traces
306 * 1: traces in user functions
307 * 2: traces in reader/writer
308 */
309
310static void trace(int level, char *format, ...)
311 {
312 va_list args;
313
314 if (level>tracelevel)
315 return;
316 va_start(args, format);
317 vprintf(format, args);
318 va_end(args);
319 }
320
321static void trace_object(int level,
322 const char *TASK,
323 const struct socan_obj_s *obj,
324 unsigned char port,
325 unsigned short cob,
326 const struct can_frame *frame_)
327 {
328 char databuf[30];
329
330 if (level>tracelevel)
331 return;
332
333 if (frame_->can_dlc > SOCAN_FRAME_LENGTH)
334 {
335 snprintf(databuf, 30, "CAN-LENGTH-OVERFLOW");
336 }
337 else
338 {
339 int i;
340 char *p= databuf;
341 for (i = 0; i < frame_->can_dlc; i++)
342 {
343 if (i!=0)
344 *(p++)= ' ';
345 sprintf(p, "%02X", frame_->data[i]);
346 p+= 2;
347 }
348 *p= 0;
349 }
350 printf("(%s) port:%d t:%ld.%06ld cob:0x%03X data: %s\n",
351 TASK, port, obj->tv.tv_sec, obj->tv.tv_usec, cob, databuf);
352 }
353
354int socan_tracelevel(int level)
355 /* get/set tracelevel,
356 * level>=0: set this level
357 * level<0 : do not change level
358 * returns: the current or changed tracelevel
359 */
360 {
361 if (level>=0)
362 tracelevel= level;
363 return tracelevel;
364 }
365
366/* ----------------------------------------------
367 * socan_rc
368 * ---------------------------------------------- */
369
370#define CCODE(x) if (rc==x) return(#x)
371/*@EX*/
373 {
374 CCODE(SOCAN_OK);
375 CCODE(SOCAN_TIMEOUT);
376 CCODE(SOCAN_OLD);
377 CCODE(SOCAN_LOST);
378 CCODE(SOCAN_WAIT);
379 CCODE(SOCAN_EXISTS);
380 CCODE(SOCAN_LENGTH_ERR);
381 CCODE(SOCAN_PORT_ERR);
382 CCODE(SOCAN_COB_ERR);
383 CCODE(SOCAN_NOT_RO_ERR);
384 CCODE(SOCAN_NOT_WO_ERR);
385 CCODE(SOCAN_TYPE_ERR);
387 CCODE(SOCAN_NOT_OWNED_ERR);
388 CCODE(SOCAN_EXISTS_ERR);
389 CCODE(SOCAN_ERROR);
390 ERRPRINT(1, "unexpected return code: %d\n", rc);
391 return("UNKNOWN ERROR CODE!");
392 }
393#undef CCODE
394
396 {
397 switch (rc)
398 {
399 case SOCAN_OK:
400 return false;
401 case SOCAN_TIMEOUT:
402 return false;
403 case SOCAN_OLD:
404 return false;
405 case SOCAN_LOST:
406 return false;
407 case SOCAN_WAIT:
408 return false;
409 case SOCAN_EXISTS:
410 return false;
411 case SOCAN_LENGTH_ERR:
412 return true;
413 case SOCAN_PORT_ERR:
414 return true;
415 case SOCAN_COB_ERR:
416 return true;
417 case SOCAN_NOT_RO_ERR:
418 return true;
419 case SOCAN_NOT_WO_ERR:
420 return true;
421 case SOCAN_TYPE_ERR:
422 return true;
424 return true;
426 return true;
427 case SOCAN_EXISTS_ERR:
428 return true;
429 case SOCAN_ERROR:
430 return true;
431 default:
432 ERRPRINT(1, "unexpected return code: %d\n", rc);
433 return true;
434 }
435 }
436
437
438/* ----------------------------------------------
439 * check module
440 * ---------------------------------------------- */
441
442/* forward declaration: */
443static struct socan_obj_s *cob_dict_lookup(cob_dict *dict, unsigned short cob);
444
445static bool check_len(unsigned char len, const char *func)
446 {
447 if (len>SOCAN_FRAME_LENGTH)
448 {
449 ERRPRINT_FUNC(2, func, "len %d invalid", len);
450 return false;
451 }
452 return true;
453 }
454
455static bool check_cob(unsigned short cob, const char *func)
456 {
457 if (cob>=COB_NO)
458 {
459 ERRPRINT_FUNC(2, func, "cob %d invalid", cob);
460 return false;
461 }
462 return true;
463 }
464
465static socan_rc check_get_cob(unsigned short cob, const char *func,
466 can_port *cp,
467 struct socan_obj_s **obj,
468 bool in_user_task)
469 {
470 if (cob>=COB_NO)
471 {
472 ERRPRINT_FUNC(2, func, "cob %d invalid", cob);
473 return SOCAN_COB_ERR;
474 }
475 *obj= cob_dict_lookup(cp->dict, cob);
476 if (*obj == NULL)
477 {
478 if (in_user_task)
479 {
480 /* note: it would be better to have the port number in this error
481 * message */
482 ERRPRINT_FUNC(2, func, "can object for cob %d is not defined", cob);
483 }
485 }
486 if ((*obj)->hdl_s == NULL)
487 {
488 if (in_user_task)
489 {
490 /* note: it would be better to have the port number in this error
491 * message */
492 ERRPRINT_FUNC(2, func, "can object for cob %d has no owner", cob);
493 }
494 return SOCAN_NOT_OWNED_ERR;
495 }
496 return SOCAN_OK;
497 }
498
499static bool check_get_port(unsigned char port, const char *func, can_port **cp)
500 {
501 if (port>=can_ports_no)
502 {
503 ERRPRINT_FUNC(2, func, "port %d invalid", port);
504 return false;
505 }
506 *cp= &(can_ports[port]);
507 return true;
508 }
509
510/* ----------------------------------------------
511 * time module
512 * ---------------------------------------------- */
513
514static void tv_to_str(const struct timeval *tv, char *buf, int buflen)
515 {
516 time_t nowtime;
517 struct tm nowtm;
518 int len;
519
520 nowtime = tv->tv_sec;
521 localtime_r(&nowtime, &nowtm);
522 len= strftime(buf, buflen, "%Y-%m-%d %H:%M:%S", &nowtm);
523 snprintf(buf+len, buflen-len, ".%06ld", tv->tv_usec);
524 }
525
526static void us_to_tv(unsigned long tv_us, struct timeval *tv)
527 {
528 ldiv_t d= ldiv(tv_us, 1000000);
529 tv->tv_sec= d.quot;
530 tv->tv_usec= d.rem;
531 }
532
533static unsigned long tv_to_us(const struct timeval *tv)
534 { /* convert timeval to microseconds */
535 return tv->tv_sec * 1000000 + tv->tv_usec;
536 }
537
538static unsigned long tv_to_ms(const struct timeval *tv)
539 { /* convert timeval to microseconds */
540 return tv->tv_sec * 1000 + tv->tv_usec / 1000;
541 }
542
543static unsigned long tm_ms_now(void)
544 /* calculate an absolute timeout in a timespec structure from
545 * a relative timeout given in milliseconds.
546 */
547 {
548 struct timeval now;
549 gettimeofday(&now, NULL);
550 return tv_to_ms(&now);
551 }
552
553static unsigned long tm_us_now(void)
554 /* get current time in microseconds */
555 {
556 struct timeval now;
557 gettimeofday(&now, NULL);
558 return tv_to_us(&now);
559 }
560
561static unsigned long tm_ms_diff_to_now(const struct timeval *tv)
562 /* returns now - tv1 in milliseconds */
563 {
564 return tm_ms_now() - tv_to_ms(tv);
565 }
566
567static void tv_now(struct timeval *tv)
568 {
569 gettimeofday(tv, NULL);
570 }
571
572static void calc_abs_timeout(int timeout_ms, struct timespec *ts)
573 /* calculate an absolute timeout in a timespec structure from
574 * a relative timeout given in milliseconds.
575 */
576 {
577 int s =0;
578 int ms= timeout_ms;
579
580 if (ms >= 1000)
581 {
582 s= ms / 1000;
583 ms-= s * 1000;
584 }
585
586 struct timeval now;
587 gettimeofday(&now, NULL);
588 ts->tv_sec= now.tv_sec + s;
589 ts->tv_nsec= now.tv_usec * 1000 + ms * 1000000;
590 if (ts->tv_nsec >= 1000000000)
591 {
592 ts->tv_nsec-= 1000000000;
593 ts->tv_sec++;
594 }
595 }
596
597static void mldelay(long milliseconds)
598/* millisecond-delay, works without "dirty tricks"
599 warning: the actual resolution may be smaller, e.g 1/60th of a second*/
600 { struct timespec rq,rt;
601
602 /* POSIX-conform wait */
603 if (milliseconds >= 1000L)
604 { rq.tv_sec = milliseconds / 1000L;
605 rq.tv_nsec= (milliseconds-1000L*rq.tv_sec) * 1000000L;
606 }
607 else
608 { rq.tv_sec = 0;
609 rq.tv_nsec= milliseconds * 1000000L;
610 };
611 nanosleep( &rq, &rt);
612 }
613
614/* ----------------------------------------------
615 * thread module
616 * ---------------------------------------------- */
617
618/* max. thread name length according to pthread_setname_np man page: */
619#define THREAD_NAMELEN 16
620
621static char *thread_suffix(bool is_reader, int port)
622 {
623 static char buffer[THREAD_NAMELEN];
624
625 if (is_reader)
626 snprintf(buffer, THREAD_NAMELEN, "-r%d", port);
627 else
628 snprintf(buffer, THREAD_NAMELEN, "-w%d", port);
629 return buffer;
630 }
631
632
633static bool get_curr_prio(int *policy, int *min_prio, int *max_prio,
634 int *curr_prio)
635 /* Note: usually this returns:
636 * *policy= SCHED_OTHER
637 * *min_prio= 0
638 * *max_prio= 0
639 * *curr_prio= 0
640 */
641 {
642 int rc;
643 struct sched_param param;
644 rc= pthread_getschedparam(pthread_self(), policy, &param);
645 if (rc!=0)
646 {
647 ERRPRINT_RC("pthread_getschedparam", rc);
648 return false;
649 }
650 *max_prio= sched_get_priority_max(*policy);
651 *min_prio= sched_get_priority_min(*policy);
652 *curr_prio= param.sched_priority;
653 return true;
654 }
655
656static bool init_attr_p(pthread_attr_t *attr_p, int stack, int prio)
657 /* prio<0: take standard priority and scheduling policy */
658 /* Setting the policy to SCHED_FIFO is only allowed for user "root". If the
659 application has not the permissions to to this, the thread is created with
660 regular priority.
661
662 To have real time priorities you should instead start your CAN bus
663 application with:
664 $ sudo PROGRAM
665 */
666 {
667 int rc;
668 int curr_policy, min_prio, max_prio, curr_prio;
669 struct sched_param s_param;
670
671 rc= pthread_attr_init(attr_p);
672 if (rc!=0)
673 {
674 ERRPRINT_RC("pthread_attr_init", rc);
675 return false;
676 }
677 /* On debian 12 (bullseye) PTHREAD_STACK_MIN doesn't seem to be defined: */
678#ifndef PTHREAD_STACK_MIN
679#define PTHREAD_STACK_MIN 16384
680#endif
681 rc= pthread_attr_setstacksize(attr_p,
682 (stack < PTHREAD_STACK_MIN) ? PTHREAD_STACK_MIN : stack);
683 if (rc!=0)
684 {
685 ERRPRINT_RC("pthread_attr_setstacksize", rc);
686 return false;
687 }
688 /* Get scheduling policy, minimum and maximum priority for this policy and
689 * the current priority of the parent (this) thread: */
690 if (!get_curr_prio(&curr_policy, &min_prio, &max_prio, &curr_prio))
691 return false;
692
693 if (prio<0)
694 { /* standard policy and priority */
695 rc= pthread_attr_setschedpolicy(attr_p, curr_policy);
696 if (rc!=0)
697 {
698 ERRPRINT_RC("pthread_attr_setschedpolicy", rc);
699 return false;
700 }
701 rc = pthread_attr_setinheritsched(attr_p, PTHREAD_INHERIT_SCHED);
702 if (rc!=0)
703 {
704 ERRPRINT_RC("pthread_attr_setinheritsched", rc);
705 return false;
706 }
707 s_param.sched_priority= curr_prio;
708 rc= pthread_attr_setschedparam(attr_p, &s_param);
709 if (rc!=0)
710 {
711 ERRPRINT_RC("pthread_attr_setschedparam", rc);
712 return false;
713 }
714 }
715 else
716 { /* read-time policy and priority */
717 rc= pthread_attr_setschedpolicy(attr_p, SCHED_FIFO);
718 if (rc!=0)
719 {
720 ERRPRINT_RC("pthread_attr_setschedpolicy", rc);
721 return false;
722 }
723 /* we must set PTHREAD_EXPLICIT_SCHED, PTHREAD_INHERIT_SCHED is
724 * the default, which means as a default new threads inherit the
725 * scheduling policy AND priority from their parents regardless of the
726 * settings in attr_p. */
727 rc = pthread_attr_setinheritsched(attr_p, PTHREAD_EXPLICIT_SCHED);
728 if (rc!=0)
729 {
730 ERRPRINT_RC("pthread_attr_setinheritsched", rc);
731 return false;
732 }
733 s_param.sched_priority= prio;
734 rc= pthread_attr_setschedparam(attr_p, &s_param);
735 if (rc!=0)
736 {
737 ERRPRINT_RC("pthread_attr_setschedparam", rc);
738 return false;
739 }
740 }
741 return true;
742 }
743
744static bool thread_start(void *(*th)(void*), pthread_t *pst,
745 char *suffix,
746 int stack,
747 int prio,
748 void *arg)
749/* stack may be 0 or prio may be -1 in order to use default-values */
750 {
751 int rc;
752 pthread_attr_t attr;
753 char thread_name[THREAD_NAMELEN];
754
755 if (suffix != NULL)
756 {
757 int l, m;
758
759 /* Get name of parent thread: */
760 rc = pthread_getname_np(pthread_self(), thread_name, THREAD_NAMELEN);
761 if (rc!=0)
762 {
763 ERRPRINT_RC("pthread_getname_np", rc);
764 return false;
765 }
766 /* combine parent thread name and suffix: */
767 l= strlen(thread_name);
768 m= strlen(suffix);
769 if (m>THREAD_NAMELEN-1)
770 m= THREAD_NAMELEN-1;
771 if (l+m > THREAD_NAMELEN-1)
772 l= THREAD_NAMELEN-1 - m;
773 strncpy(thread_name+l, suffix, m);
774 thread_name[THREAD_NAMELEN-1]= 0;
775 }
776
777 if (!socan_use_rt_priority)
778 prio= -1;
779
780 if (!init_attr_p(&attr, stack, prio))
781 {
782 ERRPRINT(1, "init_attr");
783 return false;
784 }
785
786 rc = pthread_create( pst, &attr, th, arg);
787 if ((rc==EPERM) && (prio>=0)) /* operation not permitted */
788 {
789 if (socan_require_rt_priority)
790 {
791 ERRPRINT(1, "Error: creating thread %s with policy\n"
792 "\tSCHED_FIFO and priority %d failed.\n",
793 thread_name, prio);
794 return false;
795 }
796 ERRPRINT(1, "Warning: creating thread with policy\n"
797 "\tSCHED_FIFO and priority %d failed.\n"
798 "\tUsing SCHED_OTHER and priority 0 from now on.\n",
799 prio);
800 /* do not try again to use real time priorities */
801 socan_use_rt_priority= false;
802
803 /* try with standard priority */
804 if (!init_attr_p(&attr, stack, -1))
805 return false;
806 /* now try again */
807 rc = pthread_create( pst, &attr, th, arg);
808 }
809 if (rc!=0)
810 {
811 ERRPRINT_RC("pthread_create", rc);
812 return false;
813 }
814 if (suffix!=NULL)
815 {
816 rc = pthread_setname_np(*pst, thread_name);
817 if (rc!=0)
818 {
819 ERRPRINT_RC("pthread_setname_np", rc);
820 return false;
821 }
822 }
823 return true;
824 }
825
826/* ----------------------------------------------
827 * mutex module
828 * ---------------------------------------------- */
829
830static bool mutex_init(pthread_mutex_t *mutex)
831 /* initialize mutex with PTHREAD_PRIO_INHERIT */
832 {
833 int rc;
834
835 pthread_mutexattr_t mutexattr;
836
837 rc= pthread_mutexattr_init(&mutexattr);
838 if (rc!=0)
839 {
840 ERRPRINT_RC("pthread_mutexattr_init", rc);
841 return false;
842 }
843 rc= pthread_mutexattr_setprotocol(&mutexattr, PTHREAD_PRIO_INHERIT);
844 if (rc!=0)
845 {
846 ERRPRINT_RC("pthread_mutexattr_setprotocol", rc);
847 return false;
848 }
849 rc= pthread_mutex_init(mutex, &mutexattr);
850 if (rc!=0)
851 {
852 ERRPRINT_RC("pthread_mutex_init", rc);
853 return false;
854 }
855 return true;
856 }
857
858static bool mutex_delete(pthread_mutex_t *mutex)
859 {
860 int rc;
861
862 rc= pthread_mutex_destroy(mutex);
863 if (rc!=0)
864 {
865 ERRPRINT_RC("pthread_mutex_destroy", rc);
866 return false;
867 }
868 return true;
869 }
870
871static bool mutex_lock(pthread_mutex_t *mutex, const char *func)
872 {
873 int rc= pthread_mutex_lock(mutex);
874 if (!rc)
875 return true;
876 ERRPRINT_RC_FUNC(func, "pthread_mutex_lock", rc);
877 return false;
878 }
879
880static bool mutex_unlock(pthread_mutex_t *mutex, const char *func)
881 {
882 int rc= pthread_mutex_unlock(mutex);
883 if (!rc)
884 return true;
885 ERRPRINT_RC_FUNC(func, "pthread_mutex_unlock", rc);
886 return false;
887 }
888
889#define MUTEX_LOCK(mutex) mutex_lock(mutex, __func__)
890
891#define MUTEX_UNLOCK(mutex) mutex_unlock(mutex, __func__)
892
893/* ----------------------------------------------
894 * message queue module
895 * ---------------------------------------------- */
896
897/*
898 x 1 elm
899 0 1 2 3 4 5
900 H T
901
902 x x x 3 elm
903 0 1 2 3 4 5
904 H T
905
906 x x x 3 elm
907 0 1 2 3 4 5
908 T H
909
910 x x x x x x 5 elm, full !!
911 0 1 2 3 4 5
912 HT
913
914
915 0 1 2 3 4 5 empty, empty flag set
916 HT
917*/
918
919static bool squeue_init(squeue *q, unsigned int elements)
920 {
921 q->data= NULL;
922 q->elements= 0;
923 q->head= 0;
924 q->tail= 0;
925
926 if (!mutex_init(&(q->qmutex)))
927 {
928 ERRPRINT(1, "mutex_init failed\n");
929 return false;
930 }
931 if (sem_init(&(q->qsem), 0, 0)) /* initially taken */
932 {
933 ERRPRINT_ERRNO("sem_init");
934 mutex_delete(&(q->qmutex));
935 return false;
936 }
937
938 q->data= calloc(elements, sizeof(sq_elm));
939 q->elements= elements;
940 q->empty= true;
941 return true;
942 }
943
944static int squeue_inc(const squeue *q, int index)
945 { /* increment index */
946 index++;
947 if (index >= q->elements)
948 index= 0;
949 return index;
950 }
951
952#if 0
953static bool squeue_delete(squeue *q)
954 {
955 free(q->data);
956 if (!mutex_delete(&(q->qmutex)))
957 {
958 ERRPRINT(1, "mutex_delete failed\n");
959 return false;
960 }
961 if (sem_destroy(&(q->qsem)))
962 {
963 ERRPRINT_ERRNO("sem_destroy");
964 return false;
965 }
966 return true;
967 }
968#endif
969
970static bool squeue_add(squeue *q, unsigned short cob, unsigned char port)
971 /* add element to squeue (at "tail") */
972 {
973 sq_elm elm;
974
975 elm.cob= cob;
976 elm.port= port;
977
978 MUTEX_LOCK(&(q->qmutex));
979
980 if ((q->tail == q->head) && (!q->empty))
981 { /* squeue is actually full */
982 MUTEX_UNLOCK(&(q->qmutex));
983 return false;
984 }
985
986 /* squeue is currently empty */
987 q->data[q->tail]= elm;
988 q->tail= squeue_inc(q, q->tail);
989 q->empty= false;
990 if (sem_post(&(q->qsem)))
991 ERRPRINT_ERRNO("sem_post");
992 MUTEX_UNLOCK(&(q->qmutex));
993 return true;
994 }
995
996static void squeue_get(squeue *q, unsigned short *cob, unsigned char *port)
997 /* remove element from squeue (at "head") */
998 /* this is called in a real-time task, it may interrupt
999 * squeue_add at *any* time
1000 * blocks until qmutex is given
1001 */
1002 {
1003 sq_elm *elm;
1004
1005 for(;;)
1006 {
1007 if (sem_wait(&(q->qsem)))
1008 {
1009 ERRPRINT_ERRNO("sem_wait");
1010 continue;
1011 }
1012 MUTEX_LOCK(&(q->qmutex));
1013 if (!q->empty)
1014 { /* squeue is not empty */
1015 break;
1016 }
1017 MUTEX_UNLOCK(&(q->qmutex));
1018 }
1019 elm= &(q->data[q->head]);
1020 *cob= elm->cob;
1021 *port= (unsigned char)(elm->port);
1022 q->head= squeue_inc(q, q->head);
1023 if (q->head == q->tail)
1024 q->empty= true;
1025 MUTEX_UNLOCK(&(q->qmutex));
1026 }
1027
1028/* ----------------------------------------------
1029 * "ip" utility calls
1030 * ---------------------------------------------- */
1031
1032static bool interface_exists(const char *device)
1033 /* returns -1 when interface doesn't exist */
1034 {
1035 FILE *cmd;
1036 char buf[120];
1037 int rc;
1038
1039 /* check for CAN interface by calling
1040 * ip link show DEVICE
1041 */
1042 snprintf(buf, sizeof(buf), "ip link show %s 2>&1", device);
1043 cmd=popen(buf, "r");
1044 while (fgets(buf, sizeof(buf), cmd) !=NULL)
1045 {
1046 /* printf("^%s\n", buf); */
1047 }
1048 rc= pclose(cmd);
1049 /* rc: return code of command */
1050 return (rc==0);
1051 }
1052
1053/* ----------------------------------------------
1054 * socan bitrate module
1055 * ---------------------------------------------- */
1056
1057/* Note:
1058
1059 typical output of ip -details link show vcan0:
1060
1061 4: vcan0: <NOARP,UP,LOWER_UP> mtu 72 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
1062 link/can promiscuity 0 allmulti 0 minmtu 0 maxmtu 0
1063 vcan numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 tso_max_size 65536 tso_max_segs 65535 gro_max_size 65536 gso_ipv4_max_size 65536 gro_ipv4_max_size 65536
1064
1065 typical output of ip -details link show can0:
1066
1067 9: can0: <NOARP,UP,LOWER_UP> mtu 16 qdisc pfifo_fast state UP mode DEFAULT group default qlen 10
1068 link/can promiscuity 0 allmulti 0 minmtu 0 maxmtu 0
1069 can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0
1070 bitrate 1000000 sample-point 0.750
1071 tq 12 prop-seg 29 phase-seg1 30 phase-seg2 20 sjw 10 brp 1
1072 pcan: tseg1 1..256 tseg2 1..128 sjw 1..128 brp 1..1024 brp_inc 1
1073 pcan: dtseg1 1..32 dtseg2 1..16 dsjw 1..16 dbrp 1..1024 dbrp_inc 1
1074 clock 80000000 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 tso_max_size 65536 tso_max_segs 65535 gro_max_size 65536 gso_ipv4_max_size 65536 gro_ipv4_max_size 65536
1075
1076*/
1077
1078static bool socan_is_virtual_interface(const char *device)
1079 /* return true when the device name is (written here as regexp):
1080 * ^vcan[0-9]+$
1081 */
1082 {
1083 int dummy;
1084 char dummy2;
1085 int rc= sscanf(device, "vcan%d%c", &dummy, &dummy2);
1086 return (rc==1);
1087 }
1088
1089socan_rc socan_port_bitrate(unsigned char port, unsigned int *bitrate)
1090 /* returns the bitrate in bits/sec.
1091 * returns -1 when bitrate could not be determined */
1092 {
1093 FILE *cmd;
1094 char buf[120];
1095 int rc;
1096 can_port *cp;
1097
1098 if (!check_get_port(port, __func__, &cp))
1099 return SOCAN_PORT_ERR;
1100
1101 /* get CAN interface bitrate by calling
1102 * ip -details link show DEVICE
1103 */
1104
1105 /* if DEVICE has a name like vcanNUMBER e.g. "vcan0" we assume that this is
1106 * a virtual CAN interface that has no bitrate. In this case we pretend
1107 * that it has a bitrate of 1000000 (1MBit). */
1108 if (cp->is_virtual)
1109 {
1110 /* return 1MBit */
1111 *bitrate= 1000000;
1112 /* cache this value: */
1113 cp->bitrate= *bitrate;
1114 return SOCAN_OK;
1115 }
1116
1117 /* see if bitrate is already known: */
1118 if (cp->bitrate != 0)
1119 {
1120 *bitrate= cp->bitrate;
1121 return SOCAN_OK;
1122 }
1123
1124 snprintf(buf, sizeof(buf), "ip -details link show %s",
1125 cp->interface_name);
1126 cmd=popen(buf, "r");
1127 while (fgets(buf, sizeof(buf), cmd) !=NULL)
1128 {
1129 /*printf("^%s\n", buf);*/
1130 sscanf(buf, " bitrate %ud ", bitrate);
1131 }
1132 rc= pclose(cmd);
1133 if (rc==0)
1134 {
1135 /* cache this value: */
1136 cp->bitrate= *bitrate;
1137 return SOCAN_OK;
1138 }
1139 /* error case here */
1140 *bitrate= 0;
1141 return SOCAN_ERROR;
1142 }
1143
1144/* ----------------------------------------------
1145 * socan_hdl module
1146 * ---------------------------------------------- */
1147
1148/* forward declaration: */
1149static void canobj_delete(socan_obj_h obj);
1150
1152 {
1153 int rc;
1154 struct socan_hdl_s *t;
1155
1156 if (socan_state != INITIALIZED)
1157 {
1158 ERRPRINT(1, "socan is not initialized\n");
1159 return NULL;
1160 }
1161 MUTEX_LOCK(&global_semaphore);
1162 t= calloc(1, sizeof(struct socan_hdl_s));
1163 if (sem_init(&(t->thread_sem), 0, 1)) /* initially not taken */
1164 {
1165 ERRPRINT_ERRNO("sem_init");
1166 free(t);
1167 MUTEX_UNLOCK(&global_semaphore);
1168 return NULL;
1169 }
1170 rc= pthread_mutex_init(&(t->mutex), NULL);
1171 if (rc!=0)
1172 {
1173 ERRPRINT_RC("pthread_mutex_init", rc);
1174 if (sem_destroy(&(t->thread_sem)))
1175 ERRPRINT_ERRNO("sem_destroy");
1176 free(t);
1177 MUTEX_UNLOCK(&global_semaphore);
1178 return NULL;
1179 }
1180 if (!squeue_init(&(t->qread_queue), MAX_QR_MESSAGES))
1181 {
1182 ERRPRINT(1, "squeue_init failed\n");
1183 if (sem_destroy(&(t->thread_sem)))
1184 ERRPRINT_ERRNO("sem_destroy");
1185 if (!mutex_delete(&(t->mutex)))
1186 ERRPRINT(1, "mutex_delete failed\n");
1187 free(t);
1188 MUTEX_UNLOCK(&global_semaphore);
1189 return NULL;
1190 }
1191 t->is_active= true;
1192 MUTEX_UNLOCK(&global_semaphore);
1193 return t;
1194 }
1195
1197 {
1198 /* free all resources */
1199 unsigned char port;
1200 struct socan_obj_s *obj;
1201 unsigned short cob;
1202 int rc=0;
1203
1204 h->is_active= false; /* stop reader/writer from using this */
1205 /* now iterate over all ports and delete all objects */
1206
1207 MUTEX_LOCK(&global_semaphore);
1208 if ((rc= pthread_mutex_destroy(&(h->mutex))))
1209 ERRPRINT_RC("pthread_mutex_destroy", rc);
1210 if (sem_destroy(&(h->thread_sem)))
1211 {
1212 ERRPRINT_ERRNO("sem_destroy");
1213 rc=1;
1214 }
1215 for(port=0; port<can_ports_no; port++)
1216 {
1217 cob_dict *dict= can_ports[port].dict;
1218 for(cob=0; cob<COB_NO; cob++)
1219 {
1220 obj= cob_dict_lookup(dict, cob);
1221 if (obj==NULL)
1222 continue;
1223 if (obj->hdl_s != h)
1224 continue;
1225 canobj_delete(obj);
1226 }
1227 }
1228 free(h);
1229 MUTEX_UNLOCK(&global_semaphore);
1230 return (rc==0);
1231 }
1232
1233socan_rc socan_port_device(unsigned char port, char **dev)
1234 /* return device name */
1235 {
1236 can_port *cp;
1237 if (!check_get_port(port, __func__, &cp))
1238 return SOCAN_PORT_ERR;
1239 *dev= cp->interface_name;
1240 return SOCAN_OK;
1241 }
1242
1243static void socan_hdl_give(socan_hdl h)
1244 {
1245 int sval;
1246
1247 if (sem_getvalue(&(h->thread_sem), &sval))
1248 {
1249 ERRPRINT_ERRNO("sem_getvalue");
1250 return;
1251 }
1252 if (sval>0)
1253 return;
1254 if (sem_post(&(h->thread_sem)))
1255 {
1256 ERRPRINT_ERRNO("sem_post");
1257 return;
1258 }
1259 }
1260
1261static int socan_hdl_wait_tmo(socan_hdl h, struct timespec *ts)
1262 /* returns:
1263 0: ok
1264 1: timeout
1265 -1: error
1266 */
1267 {
1268 int rc= sem_timedwait(&(h->thread_sem), ts);
1269
1270 if (rc==0)
1271 return 0;
1272 if (errno==ETIMEDOUT)
1273 return 1;
1274 ERRPRINT_ERRNO("sem_timedwait");
1275 return -1;
1276 }
1277
1278/* ----------------------------------------------
1279 * socan_obj module
1280 * ---------------------------------------------- */
1281
1282
1283static socan_obj_h canobj_new(socan_hdl hdl,
1284 unsigned char port,
1285 unsigned short cob,
1286 unsigned char length,
1287 unsigned int tmo_ms,
1288 socan_obj_type type)
1289 {
1290 if (!check_len(length, __func__))
1291 return NULL;
1292 if (!check_cob(cob, __func__))
1293 return NULL;
1294 /* calloc initializes the structure with 0 bytes, so various fields are
1295 * initialized with 0 which is indicated by a comment here. */
1296 struct socan_obj_s *obj= calloc(1, sizeof(struct socan_obj_s));
1297 obj->port= port;
1298 obj->cob= cob;
1299 obj->length= length;
1300 /* received_length==0 */
1301 /* buffer[] filled with 0 */
1302 /* buffer2[] filled with 0 */
1303 /* use_buffer2==false */
1304 /* use_queue==false */
1305 obj->type= type;
1306 /* tv is 0 */
1307 /* tv_request is 0 */
1308 obj->tmo_ms= tmo_ms;
1309 /* tm_inhibit_us == 0 */
1310 obj->ircnt= 0;
1311 obj->urcnt= 0;
1312 obj->w_echo= 1;
1313 /* ulock==0 */
1314 obj->user_ptr= NULL;
1315 obj->hdl_s= hdl;
1316 return obj;
1317 }
1318
1319static void canobj_delete(socan_obj_h obj)
1320 {
1321 void *up= obj->user_ptr;
1322
1323 obj->user_ptr= NULL;
1324 if (up != NULL)
1325 free(up);
1326 free(obj);
1327 }
1328
1329static unsigned char *canobj_rtr_wbuf(struct socan_obj_s *obj)
1330 {
1331 if (obj->use_buffer2)
1332 return obj->buffer2;
1333 return obj->buffer;
1334 }
1335
1336static unsigned char *canobj_rtr_wbuf_other(struct socan_obj_s *obj)
1337 {
1338 if (obj->use_buffer2)
1339 return obj->buffer;
1340 return obj->buffer2;
1341 }
1342
1343static void canobj_rtr_switch(struct socan_obj_s *obj)
1344 {
1345 if (obj->use_buffer2)
1346 obj->use_buffer2= false;
1347 else
1348 obj->use_buffer2= true;
1349 }
1350
1351/* ----------------------------------------------
1352 * cob_dict module
1353 * ---------------------------------------------- */
1354
1355
1356cob_dict *cob_dict_new(void)
1357 {
1358 return calloc(1, sizeof(cob_dict));
1359 }
1360
1361void cob_dict_delete(cob_dict *dict)
1362 {
1363 return free(dict);
1364 }
1365
1366static struct socan_obj_s *cob_dict_lookup(cob_dict *dict, unsigned short cob)
1367 {
1368 if (!check_cob(cob, __func__))
1369 return NULL;
1370 return (dict->objects)[cob];
1371 }
1372
1373static bool cob_dict_set(cob_dict *dict, unsigned short cob, void *ptr)
1374 /* returns false on error */
1375 {
1376 if (!check_cob(cob, __func__))
1377 return false;
1378 (dict->objects)[cob]= ptr;
1379 return true;
1380 }
1381
1382static bool cob_dict_remove(cob_dict *dict, unsigned short cob)
1383 /* returns 0 on error */
1384 {
1385 if (!check_cob(cob, __func__))
1386 return false;
1387 (dict->objects)[cob]= NULL;
1388 return true;
1389 }
1390
1391/* ----------------------------------------------
1392 * can_port module
1393 * ---------------------------------------------- */
1394
1395int socan_add_port(const char *devicename)
1396 /* returns -1 on error, otherwise the port number */
1397 {
1398 can_port *cp;
1399 int idx;
1400
1401 if (socan_state == INITIALIZED)
1402 {
1403 ERRPRINT(2, "cannot add ports in INITIALIZED state\n");
1404 return -1;
1405 };
1406 if (socan_state == ERROR)
1407 {
1408 ERRPRINT(2, "cannot add ports in ERROR state\n");
1409 return -1;
1410 };
1411
1412 if (can_ports_no >= SOCAN_MAX_PORTS)
1413 {
1414 ERRPRINT(2, "too many ports\n");
1415 return -1;
1416 };
1417 if (!interface_exists(devicename))
1418 {
1419 ERRPRINT(2, "interface '%s' doesn't exist\n", devicename);
1420 return -1;
1421 };
1422 cp= &(can_ports[can_ports_no]);
1423 cp->interface_name= strdup(devicename);
1424 cp->interface_index_valid= 0;
1425 cp->interface_index= 0;
1426 cp->dict= cob_dict_new();
1427 cp->port= can_ports_no;
1428 cp->bitrate= 0;
1429 cp->is_virtual= socan_is_virtual_interface(devicename);
1430 if (!squeue_init(&(cp->writer_squeue), MAX_WQ_MESSAGES))
1431 {
1432 ERRPRINT(1, "squeue_init failed\n");
1433 return -1;
1434 }
1435 idx= can_ports_no;
1436 can_ports_no++;
1437 return idx;
1438 }
1439
1440static int can_port_interface_index(can_port *cp, int sock)
1441 /* returns interface index, -1 on error */
1442 {
1443 int i;
1444
1445 if (!cp->interface_index_valid)
1446 {
1447 MUTEX_LOCK(&global_semaphore);
1448 struct ifreq ifr;
1449 strcpy(ifr.ifr_name, cp->interface_name);
1450 ioctl(sock, SIOCGIFINDEX, &ifr);
1451 cp->interface_index= ifr.ifr_ifindex;
1452 cp->interface_index_valid= 1;
1453 MUTEX_UNLOCK(&global_semaphore);
1454 }
1455 i= cp->interface_index;
1456 return i;
1457 }
1458
1459socan_rc socan_add_obj(socan_hdl hdl, unsigned char port,
1460 unsigned short cob, unsigned char length,
1461 unsigned int tmo_ms, socan_obj_type type)
1462 {
1463 struct socan_obj_s *obj;
1464 can_port *cp;
1465
1466 if (!check_get_port(port, __func__, &cp))
1467 return SOCAN_PORT_ERR;
1468 if (!check_cob(cob, __func__))
1469 return SOCAN_COB_ERR;
1470 if (!check_len(length, __func__))
1471 return SOCAN_LENGTH_ERR;
1472 MUTEX_LOCK(&global_semaphore);
1473 obj= cob_dict_lookup(cp->dict, cob);
1474 if (obj != NULL)
1475 {
1476 if ((obj->hdl_s == hdl) && (obj->length == length) &&
1477 (obj->type == type) && (obj->tmo_ms == tmo_ms))
1478 /* can object already exists with exactly the same parameters */
1479 /* this is not neccesarily an error */
1480 {
1481 MUTEX_UNLOCK(&global_semaphore);
1482 return SOCAN_EXISTS;
1483 }
1484 if ((obj->hdl_s !=NULL) && (obj->hdl_s != hdl))
1485 /* object is not owned by *this* thread */
1486 {
1487 MUTEX_UNLOCK(&global_semaphore);
1488 return SOCAN_NOT_OWNED_ERR;
1489 }
1490 /* object is owned by this thread but with different parameters */
1491 ERRPRINT(2, "CAN object cob %d port %d already exists\n",
1492 port, cob);
1493 MUTEX_UNLOCK(&global_semaphore);
1494 return SOCAN_EXISTS_ERR;
1495 }
1496 obj= canobj_new(hdl, port, cob, length, tmo_ms, type);
1497 cob_dict_set(cp->dict, cob, obj);
1498 MUTEX_UNLOCK(&global_semaphore);
1499 return SOCAN_OK;
1500 }
1501
1502socan_rc socan_del_obj(unsigned char port, unsigned short cob)
1503 {
1504 struct socan_obj_s *obj;
1505 can_port *cp;
1506
1507 if (!check_get_port(port, __func__, &cp))
1508 return SOCAN_PORT_ERR;
1509 if (!check_cob(cob, __func__))
1510 return SOCAN_COB_ERR;
1511 MUTEX_LOCK(&global_semaphore);
1512 obj= cob_dict_lookup(cp->dict, cob);
1513 /* we do not treat it as an error when the can object is not defined: */
1514 if (obj != NULL)
1515 {
1516 cob_dict_remove(cp->dict, cob);
1517 canobj_delete(obj);
1518 }
1519 MUTEX_UNLOCK(&global_semaphore);
1520 return SOCAN_OK;
1521 }
1522
1524 unsigned char port, unsigned short cob,
1525 unsigned char *length,
1526 unsigned int *tmo_ms,
1527 socan_obj_type *type)
1528 /* object info */
1529 {
1530 struct socan_obj_s *obj;
1531 can_port *cp;
1532 socan_rc rc;
1533
1534 if (!check_get_port(port, __func__, &cp))
1535 return SOCAN_PORT_ERR;
1536 if (!check_cob(cob, __func__))
1537 return SOCAN_COB_ERR;
1538 rc= check_get_cob(cob, __func__, cp, &obj, false);
1539 if (rc!=SOCAN_OK)
1540 return rc;
1541 if (obj->hdl_s != hdl)
1542 return SOCAN_NOT_OWNED_ERR;
1543 *length= obj->length;
1544 *tmo_ms= obj->tmo_ms;
1545 *type = obj->type;
1546 return SOCAN_OK;
1547 }
1548
1549socan_rc socan_obj_ts(unsigned char port, unsigned short cob, unsigned long *ts)
1550 /* microsecond timestamp */
1551 {
1552 struct socan_obj_s *obj;
1553 can_port *cp;
1554 unsigned long us1, us2;
1555 socan_rc rc;
1556
1557 if (!check_get_port(port, __func__, &cp))
1558 return SOCAN_PORT_ERR;
1559 rc= check_get_cob(cob, __func__, cp, &obj, true);
1560 if (rc!=SOCAN_OK)
1561 return rc;
1562 /* read timestamp again until we know we were not interrupted by the reader
1563 * thread: */
1564 do {
1565 us1= tv_to_us(&(obj->tv));
1566 us2= tv_to_us(&(obj->tv));
1567 } while (us1 != us2);
1568 *ts= us1;
1569 return SOCAN_OK;
1570 }
1571
1572socan_rc socan_ts_to_str(unsigned long ts, char *buf, int buflen)
1573 {
1574 struct timeval tv;
1575 us_to_tv(ts, &tv);
1576 tv_to_str(&tv, buf, buflen);
1577 return SOCAN_OK;
1578 }
1579
1580socan_rc socan_set_inhibit(unsigned char port, unsigned short cob, unsigned long inhibit_time)
1581 {
1582 can_port *cp;
1583 struct socan_obj_s *obj;
1584 socan_rc rc;
1585
1586 if (!check_get_port(port, __func__, &cp))
1587 return SOCAN_PORT_ERR;
1588 rc= check_get_cob(cob, __func__, cp, &obj, true);
1589 if (rc!=SOCAN_OK)
1590 return rc;
1591 if (obj->type != SOCAN_WRITE)
1592 { /* doesn't exist */
1593 ERRPRINT(2, "cob %d is not an ordinary write object\n", cob);
1594 return SOCAN_NOT_WO_ERR;
1595 }
1596 obj->tm_inhibit_us= inhibit_time;
1597 return SOCAN_OK;
1598 }
1599
1600socan_rc socan_use_queue(unsigned char port, unsigned short cob)
1601 /* prepare for queue-read usage */
1602 {
1603 can_port *cp;
1604 struct socan_obj_s *obj;
1605 socan_rc rc;
1606
1607 if (!check_get_port(port, __func__, &cp))
1608 return SOCAN_PORT_ERR;
1609 rc= check_get_cob(cob, __func__, cp, &obj, true);
1610 if (rc!=SOCAN_OK)
1611 return rc;
1612 if ((obj->type != SOCAN_READ) && (obj->type != SOCAN_READ_RTR))
1613 { /* wrong type */
1614 ERRPRINT(2, "cob %d is not a read or rtr-read object\n", cob);
1615 return SOCAN_NOT_RO_ERR;
1616 }
1617 obj->use_queue= true;
1618 return SOCAN_OK;
1619 }
1620
1621socan_rc socan_new_user_area(unsigned char port, unsigned short cob,
1622 unsigned int size,
1623 void **area)
1624 /* allocate space for user data area */
1625 {
1626 can_port *cp;
1627 struct socan_obj_s *obj;
1628 socan_rc rc;
1629
1630 if (!check_get_port(port, __func__, &cp))
1631 return SOCAN_PORT_ERR;
1632 rc= check_get_cob(cob, __func__, cp, &obj, true);
1633 if (rc!=SOCAN_OK)
1634 return rc;
1635 if (obj->user_ptr != NULL)
1636 free(obj->user_ptr);
1637 obj->user_ptr= calloc(1, size);
1638 *area= obj->user_ptr;
1639 return SOCAN_OK;
1640 }
1641
1642socan_rc socan_user_area(unsigned char port, unsigned short cob, void **area)
1643 /* return user data area */
1644 {
1645 can_port *cp;
1646 struct socan_obj_s *obj;
1647 socan_rc rc;
1648
1649 if (!check_get_port(port, __func__, &cp))
1650 return SOCAN_PORT_ERR;
1651 rc= check_get_cob(cob, __func__, cp, &obj, true);
1652 if (rc!=SOCAN_OK)
1653 return rc;
1654 *area= obj->user_ptr;
1655 return SOCAN_OK;
1656 }
1657
1658socan_rc socan_set_user_area(unsigned char port, unsigned short cob, void *ptr)
1659 /* directly set the user data area */
1660 {
1661 can_port *cp;
1662 struct socan_obj_s *obj;
1663 socan_rc rc;
1664
1665 if (!check_get_port(port, __func__, &cp))
1666 return SOCAN_PORT_ERR;
1667 rc= check_get_cob(cob, __func__, cp, &obj, true);
1668 if (rc!=SOCAN_OK)
1669 return rc;
1670 obj->user_ptr= ptr;
1671 return SOCAN_OK;
1672 }
1673
1674socan_rc socan_free_user_area(unsigned char port, unsigned short cob)
1675 /* free user data area */
1676 {
1677 can_port *cp;
1678 struct socan_obj_s *obj;
1679 void *up;
1680 socan_rc rc;
1681
1682 if (!check_get_port(port, __func__, &cp))
1683 return SOCAN_PORT_ERR;
1684 rc= check_get_cob(cob, __func__, cp, &obj, true);
1685 if (rc!=SOCAN_OK)
1686 return rc;
1687 up= obj->user_ptr;
1688 obj->user_ptr= NULL;
1689 if (up!=NULL)
1690 free(up);
1691 return SOCAN_OK;
1692 }
1693
1694/* ----------------------------------------------
1695 * read and write functions
1696 * ---------------------------------------------- */
1697
1698socan_rc socan_readnow(socan_hdl hdl, unsigned char port, unsigned short cob, void *data)
1699 /* Non blocking read :
1700 * This only reads the local buffer for SOCAN_READ and SOCAN_READ_RTR
1701 * objects. In case of SOCAN_READ_RTR it *does not* send an rtr frame.
1702 *
1703 * may return:
1704 * SOCAN_ERROR : generic error
1705 * SOCAN_LENGTH_ERR : data with wrong length arrived
1706 * SOCAN_OK : data was read
1707 * SOCAN_OLD : old data was read again
1708 * SOCAN_LOST : some data was lost
1709 */
1710 {
1711 can_port *cp;
1712 struct socan_obj_s *obj;
1713 int ircnt;
1714 unsigned char rlen;
1715 socan_rc rc;
1716
1717 if (!check_get_port(port, __func__, &cp))
1718 return SOCAN_PORT_ERR;
1719 rc= check_get_cob(cob, __func__, cp, &obj, true);
1720 if (rc!=SOCAN_OK)
1721 return rc;
1722 if ((obj->type != SOCAN_READ) && (obj->type != SOCAN_READ_RTR))
1723 { /* doesn't exist */
1724 ERRPRINT(2, "cob %d is not a read object\n", cob);
1725 return SOCAN_NOT_RO_ERR;
1726 }
1727 /* read until ircnt hasn't changed, only then
1728 * we know we have consistent data */
1729 do {
1730 ircnt= obj->ircnt;
1731 rlen= obj->received_length;
1732 memcpy(data, obj->buffer, obj->length);
1733 } while (ircnt != obj->ircnt);
1734 for(;;)
1735 {
1736 if (obj->urcnt == ircnt)
1737 {
1738 rc= SOCAN_OLD;
1739 break;
1740 }
1741 if (rlen != obj->length)
1742 {
1743 rc= SOCAN_LENGTH_ERR;
1744 break;
1745 }
1746 if ((unsigned short)(ircnt - obj->urcnt) > 1)
1747 {
1748 rc= SOCAN_LOST;
1749 break;
1750 }
1751 rc= SOCAN_OK;
1752 break;
1753 }
1754 obj->urcnt= ircnt;
1755 return rc;
1756 }
1757
1758socan_rc socan_read(socan_hdl hdl, unsigned char port, unsigned short cob, void *data)
1759 {
1760 /* Blocking read with timeout for SOCAN_READ and SOCAN_READ_RTR objects. For
1761 * SOCAN_READ_RTR objects, it sends an RTR frame.
1762 *
1763 * may return:
1764 * SOCAN_ERROR : generic error
1765 * SOCAN_LENGTH_ERR : data with wrong length arrived
1766 * SOCAN_OK : data was read
1767 * SOCAN_OLD : old data was read again (shouldn't happen)
1768 * SOCAN_TIMEOUT : timeout, no data read
1769 * SOCAN_LOST : some data was lost
1770 */
1771 can_port *cp;
1772 struct socan_obj_s *obj;
1773 struct timespec ts;
1774 int ircnt, rc_i;
1775 unsigned char rlen;
1776 socan_rc rc;
1777
1778 if (!check_get_port(port, __func__, &cp))
1779 return SOCAN_PORT_ERR;
1780 rc= check_get_cob(cob, __func__, cp, &obj, true);
1781 if (rc!=SOCAN_OK)
1782 return rc;
1783
1784 switch(obj->type)
1785 {
1786 case SOCAN_READ_RTR:
1787 obj->urcnt= obj->ircnt;
1788 calc_abs_timeout(obj->tmo_ms, &ts);
1789 if (!squeue_add(&(cp->writer_squeue), cob, port))
1790 {
1791 ERRPRINT(3, "squeue_add failed, queue full "
1792 "(size %d) port:%d cob:%d\n",
1793 cp->writer_squeue.elements, port, cob);
1794 return SOCAN_ERROR;
1795 }
1796 for(;;)
1797 {
1798 rc_i= socan_hdl_wait_tmo(hdl, &ts);
1799 switch (rc_i)
1800 { case 1: return SOCAN_TIMEOUT;
1801 case -1: return SOCAN_ERROR;
1802 }
1803 /* socan_hdl_wait_tmo also returns when the RTR frame was sent.
1804 * We simply ignore this here and wait again. Only when a reply
1805 * to the RTR frame arrived, obj->ircnt will change. */
1806 if (obj->urcnt != obj->ircnt)
1807 break; /* data has arrived */
1808 }
1809 break;
1810 case SOCAN_READ:
1811 if (obj->urcnt == obj->ircnt)
1812 { /* no data, must wait */
1813 calc_abs_timeout(obj->tmo_ms, &ts);
1814 for(;;)
1815 {
1816 trace(1, " read: wait on semaphore\n");
1817 rc_i= socan_hdl_wait_tmo(hdl, &ts);
1818 trace(1, " read: semaphore wait returned: %d\n", rc_i);
1819 if ((rc_i==1) || (rc_i==-1)) /* timeout or error */
1820 break;
1821 if (obj->urcnt != obj->ircnt)
1822 break;
1823 }
1824 switch (rc_i)
1825 { case 1: return SOCAN_TIMEOUT;
1826 case -1: return SOCAN_ERROR;
1827 }
1828 }
1829 break;
1830 default:
1831 ERRPRINT(2, "cob %d is not a read object\n", cob);
1832 return SOCAN_NOT_RO_ERR;
1833 }
1834
1835 /* from here we know that urcnt != ircnt : */
1836 /* read until ircnt hasn't changed, only then
1837 * we know we have consistent data */
1838 do {
1839 ircnt= obj->ircnt;
1840 rlen= obj->received_length;
1841 memcpy(data, obj->buffer, obj->length);
1842 } while (ircnt != obj->ircnt);
1843 for(;;)
1844 {
1845 if (rlen != obj->length)
1846 {
1847 rc= SOCAN_LENGTH_ERR;
1848 break;
1849 }
1850 if (obj->urcnt == ircnt)
1851 {
1852 rc= SOCAN_OLD;
1853 break;
1854 }
1855 if ((unsigned short)(ircnt - obj->urcnt) > 1)
1856 {
1857 rc= SOCAN_LOST;
1858 break;
1859 }
1860 rc= SOCAN_OK;
1861 break;
1862 }
1863 obj->urcnt= ircnt;
1864 return rc;
1865 }
1866
1867socan_rc socan_queue_read(socan_hdl hdl, unsigned char *port,
1868 unsigned short *cob, void *data)
1869 {
1870 int ircnt;
1871 unsigned char rlen;
1872 struct socan_obj_s *obj= NULL;
1873 unsigned short cob_;
1874 unsigned char port_;
1875 can_port *cp;
1876 socan_rc rc;
1877
1878 for(;;)
1879 {
1880 squeue_get(&(hdl->qread_queue), &cob_, &port_);
1881 if (!check_get_port(port_, __func__, &cp))
1882 continue;
1883 rc= check_get_cob(cob_, __func__, cp, &obj, true);
1884 if (rc!=SOCAN_OK)
1885 return rc;
1886 if (!obj->use_queue)
1887 {
1888 ERRPRINT(2, "not a qread object: %d port %d\n", cob_, port_);
1889 continue;
1890 }
1891
1892 if (obj->urcnt == obj->ircnt)
1893 /* no new data in this object */
1894 continue;
1895 /* from here we know that urcnt != ircnt : */
1896 /* read until ircnt hasn't changed, only then
1897 * we know we have consistent data */
1898 do {
1899 ircnt= obj->ircnt;
1900 rlen= obj->received_length;
1901 memcpy(data, obj->buffer, obj->length);
1902 } while (ircnt != obj->ircnt);
1903 *port= port_;
1904 *cob= cob_;
1905 trace(1, " queue_read: port:%d cob:%d urcnt:%d ircnt:%d\n",
1906 port_, cob_, obj->urcnt, ircnt);
1907 for(;;)
1908 {
1909 if (rlen != obj->length)
1910 {
1911 rc= SOCAN_LENGTH_ERR;
1912 break;
1913 }
1914 if ((unsigned short)(ircnt - obj->urcnt) > 1)
1915 {
1916 rc= SOCAN_LOST;
1917 break;
1918 }
1919 rc= SOCAN_OK;
1920 break;
1921 }
1922 obj->urcnt= ircnt;
1923 return rc;
1924 }
1925 }
1926
1928 unsigned char port, unsigned short cob, const void *data)
1929 /* this function may also be used to write data that will be fetched by some
1930 * other CAN-device by a rtr-request
1931 * may return:
1932 * SOCAN_ERROR : generic error
1933 * SOCAN_OK : data was read
1934 * SOCAN_TIMEOUT : timeout, no data was sent
1935 */
1936 {
1937 can_port *cp;
1938 struct socan_obj_s *obj;
1939 int rc_i;
1940 struct timespec ts;
1941 socan_rc rc;
1942
1943 if (!check_get_port(port, __func__, &cp))
1944 return SOCAN_PORT_ERR;
1945 rc= check_get_cob(cob, __func__, cp, &obj, true);
1946 if (rc!=SOCAN_OK)
1947 return rc;
1948
1949 if ((obj->type != SOCAN_WRITE) && (obj->type != SOCAN_WRITE_RTR) &&
1950 (obj->type != SOCAN_READ_RTR))
1951 { /* neither SOCAN_WRITE nor SOCAN_WRITE_RTR object */
1952 ERRPRINT(2, "cob %d is not a write or RTR-read object\n", cob);
1953 return SOCAN_TYPE_ERR;
1954 }
1955
1956 if (obj->type == SOCAN_WRITE_RTR)
1957 { /* special handling of writing to a SOCAN_WRITE_RTR object:
1958 we only write to the local buffer in this case. */
1959 tv_now(&(obj->tv_request));
1960 memcpy(canobj_rtr_wbuf_other(obj), data, obj->length);
1961 /* switch between two buffers to avoid race condition with the writer
1962 * task : */
1963 canobj_rtr_switch(obj);
1964 return SOCAN_OK;
1965 }
1966
1967 /* the following code also handles writing an RTR request frame when the
1968 * object type is SOCAN_READ_RTR. */
1969
1970 tv_now(&(obj->tv_request));
1971 obj->ulock= 1; /* mark that we are writing */
1972 trace(1, "tm bef. write: %lu\n", tv_to_ms(&(obj->tv_request)));
1973 memcpy(obj->buffer, data, obj->length);
1974 obj->w_echo= 0;
1975 obj->ulock= 0; /* mark that we are finished with writing */
1976 if (!squeue_add(&(cp->writer_squeue), cob, port))
1977 {
1978 ERRPRINT(3, "squeue_add failed, queue full "
1979 "(size %d) port:%d cob:%d\n",
1980 cp->writer_squeue.elements, port, cob);
1981 return SOCAN_ERROR;
1982 }
1983 calc_abs_timeout(obj->tmo_ms, &ts);
1984 for(;;)
1985 {
1986 rc_i= socan_hdl_wait_tmo(hdl, &ts);
1987 if ((rc_i==1) || (rc_i==-1)) /* timeout or error */
1988 break;
1989 if (obj->w_echo)
1990 break;
1991 }
1992 trace(1, "tm aft. write: %lu\n", tm_ms_now());
1993 switch (rc_i)
1994 { case 1: return SOCAN_TIMEOUT;
1995 case -1: return SOCAN_ERROR;
1996 default: return SOCAN_OK;
1997 }
1998 }
1999
2001 unsigned char port, unsigned short cob, const void *data)
2002 /* Write a message on the can bus, do not wait for a result,
2003 * This function may also be used to create an RTR request frame by writing
2004 * to an SOCAN_READ_RTR object.
2005 *
2006 * other CAN-device by a rtr-request
2007 * may return:
2008 * SOCAN_ERROR : generic error
2009 * SOCAN_WAIT : previous write hasn't happened yet, write rejected
2010 * SOCAN_OK : data was writen
2011 * SOCAN_TIMEOUT : previous write had a timeout
2012 * SOCAN_TYPE_ERR : wrong type of CAN object
2013 */
2014 {
2015 can_port *cp;
2016 struct socan_obj_s *obj;
2017 socan_rc my_rc= SOCAN_OK;
2018
2019 if (!check_get_port(port, __func__, &cp))
2020 return SOCAN_PORT_ERR;
2021 my_rc= check_get_cob(cob, __func__, cp, &obj, true);
2022 if (my_rc!=SOCAN_OK)
2023 return my_rc;
2024
2025 if ((obj->type != SOCAN_WRITE) && (obj->type != SOCAN_WRITE_RTR) &&
2026 (obj->type != SOCAN_READ_RTR))
2027 { /* not SOCAN_WRITE, SOCAN_WRITE_RTR or SOCAN_WRITE_RTR object */
2028 ERRPRINT(2, "cob %d is not a write or RTR-read object\n", cob);
2029 return SOCAN_TYPE_ERR;
2030 }
2031
2032 if (obj->type == SOCAN_WRITE_RTR)
2033 { /* special handling of writing to a SOCAN_WRITE_RTR object:
2034 we only write to the local buffer in this case. */
2035 tv_now(&(obj->tv_request));
2036 memcpy(canobj_rtr_wbuf(obj), data, obj->length);
2037 /* switch between two buffers to avoid race condition with the writer
2038 * task : */
2039 canobj_rtr_switch(obj);
2040 return SOCAN_OK;
2041 }
2042
2043 /* the following code also handles writing an RTR request frame when the
2044 * object type is SOCAN_READ_RTR. */
2045
2046 if (!obj->w_echo)
2047 { /* old request still running */
2048 unsigned long tdelta= tm_ms_diff_to_now(&(obj->tv_request));
2049 if (tdelta < obj->tmo_ms)
2050 { /* old request still running, no timeout yet */
2051 return SOCAN_WAIT;
2052 }
2053 /* from here: previous write must have had timeout */
2054 my_rc= SOCAN_TIMEOUT;
2055 }
2056
2057 tv_now(&(obj->tv_request));
2058 obj->ulock= 1; /* mark that we are writing */
2059 memcpy(obj->buffer, data, obj->length);
2060 obj->w_echo= 0;
2061 obj->ulock= 0; /* mark that we are finished with writing */
2062 if (!squeue_add(&(cp->writer_squeue), cob, port))
2063 {
2064 ERRPRINT(3, "squeue_add failed, queue full "
2065 "(size %d) port:%d cob:%d\n",
2066 cp->writer_squeue.elements, port, cob);
2067 return SOCAN_ERROR;
2068 }
2069 return my_rc;
2070 }
2071
2073 unsigned char port, unsigned short cob,
2074 const void *data,
2075 unsigned long *inhibit_time)
2076 /* write a message on the can bus, do not wait for a result,
2077 * this function may also be used to write data that will be fetched by some
2078 * other CAN-device by a rtr-request
2079 * may return:
2080 * SOCAN_ERROR : generic error
2081 * SOCAN_WAIT : previous write hasn't happened yet, write rejected
2082 * SOCAN_OK : data was writen
2083 * SOCAN_TIMEOUT : previous write had a timeout
2084 */
2085 {
2086 can_port *cp;
2087 struct socan_obj_s *obj;
2088 socan_rc my_rc= SOCAN_OK;
2089 unsigned long tm_us_next_write;
2090 unsigned long tm_us_now_;
2091
2092 if (!check_get_port(port, __func__, &cp))
2093 return SOCAN_PORT_ERR;
2094 my_rc= check_get_cob(cob, __func__, cp, &obj, true);
2095 if (my_rc!=SOCAN_OK)
2096 return my_rc;
2097
2098 if ((obj->type != SOCAN_WRITE) && (obj->type != SOCAN_WRITE_RTR) &&
2099 (obj->type != SOCAN_READ_RTR))
2100 { /* not SOCAN_WRITE, SOCAN_WRITE_RTR or SOCAN_WRITE_RTR object */
2101 ERRPRINT(2, "cob %d is not a write or RTR-read object\n", cob);
2102 return SOCAN_TYPE_ERR;
2103 }
2104
2105 /* initialize inhibit_time with 0: */
2106 *inhibit_time= 0;
2107 if (obj->type == SOCAN_WRITE_RTR)
2108 { /* special handling of RTR write */
2109 tv_now(&(obj->tv_request));
2110 memcpy(canobj_rtr_wbuf(obj), data, obj->length);
2111 /* switch between two buffers to avoid race condition with the writer
2112 * task : */
2113 canobj_rtr_switch(obj);
2114 return SOCAN_OK;
2115 }
2116
2117 /* the following code also handles writing an RTR request frame when the
2118 * object type is SOCAN_READ_RTR. */
2119 if (!obj->w_echo)
2120 { /* old request still running */
2121 unsigned long tdelta= tm_ms_diff_to_now(&(obj->tv_request));
2122 if (tdelta < obj->tmo_ms)
2123 { /* old request still running, no timeout yet */
2124 /* must wait (at least) the full inhibit time: */
2125 *inhibit_time= obj->tm_inhibit_us;
2126 return SOCAN_WAIT;
2127 }
2128 /* from here: previous write had timeout */
2129 my_rc= SOCAN_TIMEOUT;
2130 }
2131 /* wait-time= timestamp+inhibit-now */
2132 tm_us_next_write= tv_to_us(&(obj->tv)) + obj->tm_inhibit_us;
2133 tm_us_now_= tm_us_now();
2134 if (tm_us_now_ < tm_us_next_write)
2135 { /* must wait */
2136 *inhibit_time= tm_us_next_write - tm_us_now_;
2137 return SOCAN_WAIT; /* hides possible SOCAN_TIMEOUT */
2138 }
2139 /* we can continue here: */
2140 obj->ulock= 1; /* mark that we are writing */
2141 tv_now(&(obj->tv_request));
2142 memcpy(obj->buffer, data, obj->length);
2143 obj->w_echo= 0;
2144 obj->ulock= 0; /* mark that we are finished with writing */
2145 if (!squeue_add(&(cp->writer_squeue), cob, port))
2146 {
2147 ERRPRINT(3, "squeue_add failed, queue full "
2148 "(size %d) port:%d cob:%d\n",
2149 cp->writer_squeue.elements, port, cob);
2150 return SOCAN_ERROR;
2151 }
2152 return my_rc;
2153 }
2154
2155/* ----------------------------------------------
2156 * reader and writer threads
2157 * ---------------------------------------------- */
2158
2159static int init_can_socket(can_port *cp, int *sock)
2160 {
2161 int rc, s;
2162 struct sockaddr_can addr;
2163 int interface_index;
2164 int sval;
2165
2166 *sock= 0;
2167 if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
2168 {
2169 ERRPRINT_ERRNO("socket");
2170 return 1;
2171 }
2172 sval= SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_TX_HARDWARE;
2173 if ((rc= setsockopt(s, SOL_SOCKET, SO_TIMESTAMPING, &sval, sizeof(sval))))
2174 {
2175 ERRPRINT_RC("setsockopt", rc);
2176 return 2;
2177 }
2178 interface_index= can_port_interface_index(cp, s);
2179 if (interface_index==-1)
2180 {
2181 ERRPRINT(1, "can_port_interface_index failed\n");
2182 return 20;
2183 }
2184
2185 memset(&addr, 0, sizeof(addr));
2186 addr.can_family = AF_CAN;
2187 addr.can_ifindex = interface_index;
2188 /* printf("ifr_index: %d\n", interface_index); */
2189
2190 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0)
2191 {
2192 ERRPRINT_ERRNO("bind");
2193 return 3;
2194 }
2195 *sock= s;
2196 return 0;
2197 }
2198
2199#define TASK "reader"
2200static void *reader(void *arg)
2201 /* return code !=0 on error */
2202 {
2203 can_port *cp= (can_port *)arg;
2204 unsigned char port= ((can_port *)arg)->port;
2205 int s;
2206 int is_rtr;
2207 struct can_frame frame;
2208 static int read_can_device_rc= 0;
2209 socan_rc rc;
2210
2211 read_can_device_rc= init_can_socket(cp, &s);
2212 if (read_can_device_rc!=0)
2213 {
2214 ERRPRINT(1, "init_can_socket failed: %d\n", read_can_device_rc);
2215 pthread_exit(NULL);
2216 }
2217
2218 MUTEX_LOCK(&global_semaphore);
2219 thread_count++;
2220 MUTEX_UNLOCK(&global_semaphore);
2221
2222 for(;;)
2223 {
2224 int nbytes = read(s, &frame, sizeof(struct can_frame));
2225 unsigned short cob;
2226 struct socan_obj_s *obj;
2227
2228 if (nbytes < 0)
2229 {
2230 ERRPRINT_ERRNO("read");
2231 /* continue in spite of error */
2232 continue;
2233 }
2234 cob= frame.can_id & CAN_SFF_MASK; /* mask out special bits */
2235 is_rtr= (frame.can_id & CAN_RTR_FLAG) ? 1 : 0;
2236 rc= check_get_cob(cob, __func__, cp, &obj, false);
2237 if (rc!=SOCAN_OK)
2238 continue;
2239
2240 /* do nothing when handle is not active: */
2241 if (!obj->hdl_s->is_active)
2242 continue;
2243
2244 if (obj->ulock)
2245 { /* user task is writing (write, but no RTR write) to the object
2246 right now, we skip everything here */
2247 trace(2, "(%s) ulock ! port:%d cob:0x%03X RTR:%1d",
2248 TASK, port, cob, is_rtr);
2249 continue;
2250 };
2251
2252 /* get timestamp: */
2253 ioctl(s, SIOCGSTAMP, &(obj->tv));
2254
2255 switch(obj->type)
2256 {
2257 case SOCAN_READ:
2258 if (is_rtr)
2259 {
2260 ERRPRINT(3, " (%s) RTR on SOCAN_READ "
2261 "object received "
2262 "port:%d cob:0x%03X RTR:%1d\n",
2263 TASK, port, cob, is_rtr);
2264 continue;
2265 }
2266 /* mark changes: */
2267 (obj->ircnt)++;
2268 memcpy(obj->buffer, frame.data, frame.can_dlc);
2269 obj->received_length= frame.can_dlc;
2270 if (obj->use_queue)
2271 {
2272 if (!squeue_add(&(obj->hdl_s->qread_queue), cob, port))
2273 {
2274 ERRPRINT(3, "(task %s) "
2275 "squeue_add failed, queue full "
2276 "(size %d) port:%d cob:%d RTR:%1d\n",
2277 TASK,
2278 cp->writer_squeue.elements, port, cob, is_rtr);
2279 break;
2280 }
2281 }
2282 socan_hdl_give(obj->hdl_s);
2283 break;
2284 case SOCAN_READ_RTR:
2285 if (is_rtr)
2286 { /* echo of RTR frame sent by this host,
2287 mark changes: */
2288 if (!obj->ulock)
2289 {
2290 obj->w_echo= 1;
2291 socan_hdl_give(obj->hdl_s);
2292 }
2293 }
2294 else
2295 {
2296 /* data arrived as reply to an RTR request,
2297 mark changes: */
2298 (obj->ircnt)++;
2299 memcpy(obj->buffer, frame.data, frame.can_dlc);
2300 obj->received_length= frame.can_dlc;
2301 if (obj->use_queue)
2302 {
2303 if (!squeue_add(&(obj->hdl_s->qread_queue), cob, port))
2304 {
2305 ERRPRINT(3, "(task %s) "
2306 "squeue_add failed, queue full "
2307 "(size %d) port:%d cob:%d RTR:%1d\n",
2308 TASK,
2309 cp->writer_squeue.elements,
2310 port, cob, is_rtr);
2311 break;
2312 }
2313 }
2314 socan_hdl_give(obj->hdl_s);
2315 }
2316 break;
2317 case SOCAN_WRITE_RTR:
2318 if (!is_rtr)
2319 {
2320 ERRPRINT(3, " (%s) non-RTR on SOCAN_WRITE_RTR "
2321 "object received "
2322 "port:%d cob:0x%03X RTR:%1d\n",
2323 TASK, port, cob, is_rtr);
2324 continue;
2325 }
2326 /* an RTR request was received by another host, create an
2327 answer by enqueuing a send request for writer task: */
2328 if (!squeue_add(&(cp->writer_squeue), cob, port))
2329 {
2330 ERRPRINT(3, "(task %s) "
2331 "squeue_add failed, queue full "
2332 "(size %d) port:%d cob:%d RTR:%1d\n",
2333 TASK,
2334 cp->writer_squeue.elements, port, cob, is_rtr);
2335 continue;
2336 }
2337 trace(2, " (%s) create reply on received "
2338 "RTR request "
2339 "port:%d cob:0x%03X RTR:%1d\n",
2340 TASK, port, cob, is_rtr);
2341 continue;
2342 case SOCAN_WRITE:
2343 if (is_rtr)
2344 {
2345 ERRPRINT(3, " (%s) RTR on SOCAN_WRITE "
2346 "object received "
2347 "port:%d cob:0x%03X RTR:%1d\n",
2348 TASK, port, cob, is_rtr);
2349 continue;
2350 }
2351 /* we got the data of a "write" on the local host via
2352 loopback, set w_echo and give the semaphore in case
2353 "write" is waiting on it:
2354 */
2355 trace(2, " (%s) local echo of CAN write received "
2356 "port:%d cob:0x%03X RTR:%1d\n",
2357 TASK, port, cob, is_rtr);
2358 /* change w_echo only when ulock is not set: */
2359 if (!obj->ulock)
2360 {
2361 obj->w_echo= 1;
2362 socan_hdl_give(obj->hdl_s);
2363 }
2364 continue;
2365 }
2366 if (tracelevel >= 2)
2367 trace_object(2, TASK, obj, port, cob, &frame);
2368 }
2369
2370 if (close(s) < 0)
2371 {
2372 ERRPRINT_ERRNO("close");
2373 read_can_device_rc= 5;
2374 }
2375 pthread_exit(NULL);
2376 }
2377#undef TASK
2378
2379#define TASK "writer"
2380static void *writer(void *arg)
2381 {
2382 can_port *cp= (can_port *)arg;
2383 unsigned char writer_port= cp->port;
2384 int s;
2385 static int write_can_device_rc= 0;
2386 struct can_frame frame;
2387 int i;
2388 int can_frame_sz= sizeof(struct can_frame);
2389 socan_rc rc;
2390
2391 /* initialize frame variable with 0 bytes: */
2392 memset(&frame, 0, sizeof(struct can_frame));
2393
2394 write_can_device_rc= init_can_socket(cp, &s);
2395
2396 if (write_can_device_rc!=0)
2397 {
2398 ERRPRINT(1, "init_can_socket failed: %d\n", write_can_device_rc);
2399 pthread_exit(NULL);
2400 }
2401 MUTEX_LOCK(&global_semaphore);
2402 thread_count++;
2403 MUTEX_UNLOCK(&global_semaphore);
2404
2405 for(;;)
2406 {
2407 unsigned short cob;
2408 unsigned char port;
2409 struct socan_obj_s *obj;
2410
2411 squeue_get(&(cp->writer_squeue), &cob, &port);
2412 if (writer_port != port)
2413 {
2414 ERRPRINT(3, "port %d != %d\n", port, writer_port);
2415 continue;
2416 }
2417
2418 rc= check_get_cob(cob, __func__, cp, &obj, true);
2419 if (rc!=SOCAN_OK)
2420 continue;
2421
2422 /* do nothing when handle is not active: */
2423 if (!obj->hdl_s->is_active)
2424 continue;
2425
2426 switch(obj->type)
2427 {
2428 case SOCAN_WRITE_RTR:
2429 /* must answer RTR request */
2430 frame.can_id= cob;
2431 memcpy(frame.data, canobj_rtr_wbuf(obj), obj->length);
2432 frame.can_dlc= obj->length;
2433 break;
2434 case SOCAN_READ_RTR:
2435 /* must send RTR request */
2436 frame.can_id= cob | CAN_RTR_FLAG;
2437 memset(frame.data, 0, obj->length);
2438 frame.can_dlc= obj->length;
2439 break;
2440 default:
2441 if (obj->ulock)
2442 { /* User task is currently writing to the data field. It may
2443 contain inconsistent data so we discard *this* write
2444 request */
2445 continue;
2446 };
2447
2448 frame.can_id= cob;
2449 memcpy(frame.data, obj->buffer, obj->length);
2450 frame.can_dlc= obj->length;
2451 break;
2452 }
2453
2454 trace(2, "(%s) port:%d cob:0x%03X ", TASK, port, cob);
2455 trace(2, "data: ");
2456 for (i = 0; i < frame.can_dlc; i++)
2457 trace(2, "%02X ", frame.data[i]);
2458 trace(2, "\n");
2459
2460 if (write(s, &frame, can_frame_sz) != can_frame_sz)
2461 {
2462 ERRPRINT_ERRNO("write");
2463 }
2464 }
2465 }
2466#undef TASK
2467
2468/* ----------------------------------------------
2469 * setup module
2470 * ---------------------------------------------- */
2471
2472bool socan_realtime_setup(bool use_rt_priority,
2473 bool require_rt_priority,
2474 int reader_priority,
2475 int writer_priority)
2476 /* Set up of some defaults. If used, must be called before socan_init().
2477 *
2478 * writer_priority and reader_priority are only used when real time
2479 * scheduling is used (use_rt_priority==true).
2480 *
2481 * Note: socan_realtime_setup is not strictly thread safe, if socan_init() is
2482 * started at the same time as this function, this may cause problems. */
2483 {
2484 int min_prio, max_prio;
2485
2486 switch (socan_state)
2487 {
2488 case ERROR:
2489 ERRPRINT(1, "socan is in ERROR state, cannot setup realtime\n");
2490 return false;
2491 case INITIALIZED:
2492 ERRPRINT(1, "socan is already initialized, "
2493 "cannot setup realtime\n");
2494 return false;
2495 case UNINITIALIZED:
2496 break;
2497 default:
2498 ERRPRINT(1, "unknown internal state: %d\n", socan_state);
2499 return false;
2500 }
2501
2502 if (use_rt_priority)
2503 {
2504 min_prio= sched_get_priority_min(SCHED_FIFO);
2505 max_prio= sched_get_priority_max(SCHED_FIFO);
2506 if ((reader_priority < min_prio) || (reader_priority > max_prio))
2507 {
2508 ERRPRINT(1, "Error, reader priority %d out of range "
2509 "%d .. %d\n",
2510 reader_priority, min_prio, max_prio);
2511 return false;
2512 }
2513 if ((writer_priority < min_prio) || (writer_priority > max_prio))
2514 {
2515 ERRPRINT(1, "Error, writer priority %d out of range "
2516 "%d .. %d\n",
2517 writer_priority, min_prio, max_prio);
2518 return false;
2519 }
2520 }
2521
2522 socan_use_rt_priority= use_rt_priority;
2523 socan_require_rt_priority= require_rt_priority;
2524 if (use_rt_priority)
2525 {
2526 socan_reader_priority= reader_priority;
2527 socan_writer_priority= writer_priority;
2528 }
2529 return true;
2530 }
2531
2532/* ----------------------------------------------
2533 * init module
2534 * ---------------------------------------------- */
2535
2536_Atomic static int _lock= 0;
2537
2538bool socan_init(void)
2539 /* generic initialization */
2540 {
2541 bool ok;
2542 int p, n;
2543
2544 /* note: socan_init is not strictly thread safe, if started at the same
2545 * time from two threads this may cause problems. */
2546 if (socan_state == INITIALIZED)
2547 return true;
2548 if (socan_state == ERROR)
2549 return false;
2550 if (can_ports_no==0)
2551 {
2552 ERRPRINT(1, "no ports are defined\n");
2553 return false;
2554 }
2555 /* reading and writing to _lock is atomic: */
2556 if (_lock++)
2557 {
2558 /* some other thread is initializing, check every 10ms if it is
2559 * finished */
2560 while (socan_state==UNINITIALIZED)
2561 mldelay(10);
2562 if (socan_state == INITIALIZED)
2563 return true;
2564 if (socan_state == ERROR)
2565 return false;
2566 }
2567
2568 /* *this* thread is now exclusively initializing: */
2569 if (!mutex_init(&global_semaphore))
2570 {
2571 ERRPRINT(1, "mutex_init failed\n");
2572 return false;
2573 }
2574
2575 /* initialize: */
2576 MUTEX_LOCK(&global_semaphore);
2577
2578 for (p=0; p<can_ports_no; p++)
2579 {
2580 /* read thread: */
2581 if (!thread_start(reader, &(socan_read_threads[p]),
2582 thread_suffix(true, p),
2583 8192, /* stack */
2584 socan_reader_priority, /* prio */
2585 &(can_ports[p]))) /* arg */
2586 {
2587 ERRPRINT(1, "thread_start (reader) failed\n");
2588 socan_state= ERROR;
2589 MUTEX_UNLOCK(&global_semaphore);
2590 return false;
2591 }
2592 /* write thread: */
2593 if (!thread_start(writer, &(socan_write_threads[p]),
2594 thread_suffix(false, p),
2595 8192, /* stack */
2596 socan_writer_priority, /* prio */
2597 &(can_ports[p]))) /* arg */
2598 {
2599 ERRPRINT(1, "thread_start (writer) failed\n");
2600 socan_state= ERROR;
2601 MUTEX_UNLOCK(&global_semaphore);
2602 return false;
2603 }
2604 }
2605 /* must wait for all threads to start : */
2606 socan_state= INITIALIZED;
2607 MUTEX_UNLOCK(&global_semaphore);
2608 ok= false;
2609 mldelay(50); /* initial sleep of 50 ms */
2610 for(n=can_ports_no;n>0;n--) /* 100ms for each port to initialize */
2611 {
2612 mldelay(100); /* sleep 100 ms */
2613 MUTEX_LOCK(&global_semaphore);
2614 if (thread_count >= can_ports_no*2)
2615 {
2616 ok= true;
2617 MUTEX_UNLOCK(&global_semaphore);
2618 break;
2619 }
2620 MUTEX_UNLOCK(&global_semaphore);
2621 }
2622 if (!ok)
2623 {
2624 socan_state= ERROR;
2625 ERRPRINT(1, "starting all threads took too long\n");
2626 }
2627 return ok;
2628 }
2629
socan_rc socan_user_area(unsigned char port, unsigned short cob, void **area)
Definition socan.c:1642
#define WRITER_DEFAULT_PRIO
absolute default priority of writer task
Definition socan.c:124
bool socan_close(socan_hdl h)
Definition socan.c:1196
socan_rc socan_write_inhibit(socan_hdl hdl, unsigned char port, unsigned short cob, const void *data, unsigned long *inhibit_time)
Definition socan.c:2072
socan_rc socan_set_user_area(unsigned char port, unsigned short cob, void *ptr)
Definition socan.c:1658
char * socan_str_rc(socan_rc rc)
Definition socan.c:372
bool socan_realtime_setup(bool use_rt_priority, bool require_rt_priority, int reader_priority, int writer_priority)
Definition socan.c:2472
socan_rc socan_port_bitrate(unsigned char port, unsigned int *bitrate)
Definition socan.c:1089
#define MAX_WQ_MESSAGES
max. number of CAN objects in writer queue
Definition socan.c:127
socan_rc socan_del_obj(unsigned char port, unsigned short cob)
Definition socan.c:1502
socan_rc socan_read(socan_hdl hdl, unsigned char port, unsigned short cob, void *data)
Definition socan.c:1758
int socan_errprintlevel(int level)
Definition socan.c:288
#define MAX_QR_MESSAGES
max. number of CAN objects in reader queue
Definition socan.c:130
socan_rc socan_obj_ts(unsigned char port, unsigned short cob, unsigned long *ts)
Definition socan.c:1549
socan_rc socan_use_queue(unsigned char port, unsigned short cob)
Definition socan.c:1600
socan_rc socan_readnow(socan_hdl hdl, unsigned char port, unsigned short cob, void *data)
Definition socan.c:1698
socan_rc socan_set_inhibit(unsigned char port, unsigned short cob, unsigned long inhibit_time)
Definition socan.c:1580
#define READER_DEFAULT_PRIO
absolute default priority of reader task
Definition socan.c:121
socan_rc socan_write(socan_hdl hdl, unsigned char port, unsigned short cob, const void *data)
Definition socan.c:1927
socan_rc socan_free_user_area(unsigned char port, unsigned short cob)
Definition socan.c:1674
struct sq_elm sq_elm
type of a single element in the 'squeue' queue
int socan_add_port(const char *devicename)
Definition socan.c:1395
bool socan_rc_is_error(socan_rc rc)
Definition socan.c:395
int socan_tracelevel(int level)
Definition socan.c:354
bool socan_init(void)
Definition socan.c:2538
socan_hdl socan_open(void)
Definition socan.c:1151
socan_rc socan_port_device(unsigned char port, char **dev)
Definition socan.c:1233
socan_rc socan_queue_read(socan_hdl hdl, unsigned char *port, unsigned short *cob, void *data)
Definition socan.c:1867
socan_rc socan_ts_to_str(unsigned long ts, char *buf, int buflen)
Definition socan.c:1572
socan_rc socan_add_obj(socan_hdl hdl, unsigned char port, unsigned short cob, unsigned char length, unsigned int tmo_ms, socan_obj_type type)
Definition socan.c:1459
socan_module_state
state of the socan module
Definition socan.c:138
@ ERROR
Definition socan.c:140
@ INITIALIZED
Definition socan.c:141
@ UNINITIALIZED
Definition socan.c:139
socan_rc socan_writelater(socan_hdl hdl, unsigned char port, unsigned short cob, const void *data)
Definition socan.c:2000
socan_rc socan_obj_info(socan_hdl hdl, unsigned char port, unsigned short cob, unsigned char *length, unsigned int *tmo_ms, socan_obj_type *type)
Definition socan.c:1523
socan_rc socan_new_user_area(unsigned char port, unsigned short cob, unsigned int size, void **area)
Definition socan.c:1621
c header file for socan object layer library.
socan_rc
Definition socan.h:176
@ SOCAN_NOT_OWNED_ERR
Definition socan.h:194
@ SOCAN_ERROR
Definition socan.h:198
@ SOCAN_LOST
Definition socan.h:181
@ SOCAN_LENGTH_ERR
Definition socan.h:186
@ SOCAN_EXISTS
Definition socan.h:185
@ SOCAN_TYPE_ERR
Definition socan.h:191
@ SOCAN_TIMEOUT
Definition socan.h:178
@ SOCAN_COB_ERR
Definition socan.h:188
@ SOCAN_EXISTS_ERR
Definition socan.h:196
@ SOCAN_OLD
Definition socan.h:179
@ SOCAN_NOT_WO_ERR
Definition socan.h:190
@ SOCAN_WAIT
Definition socan.h:183
@ SOCAN_OK
Definition socan.h:177
@ SOCAN_PORT_ERR
Definition socan.h:187
@ SOCAN_NOT_RO_ERR
Definition socan.h:189
@ SOCAN_NOT_EXISTS_ERR
Definition socan.h:192
socan_obj_type
Definition socan.h:162
@ SOCAN_WRITE
Definition socan.h:164
@ SOCAN_WRITE_RTR
Definition socan.h:166
@ SOCAN_READ
Definition socan.h:163
@ SOCAN_READ_RTR
Definition socan.h:165
#define SOCAN_FRAME_LENGTH
Definition socan.h:137
#define COB_NO
Definition socan.h:146
#define SOCAN_MAX_PORTS
Definition socan.h:130
type of a single element in the 'squeue' queue
Definition socan.c:146
unsigned short port
Definition socan.c:148
unsigned short cob
Definition socan.c:147
queue for CAN objects.
Definition socan.c:158
int elements
Definition socan.c:159
sem_t qsem
Definition socan.c:163
sq_elm * data
Definition socan.c:161
bool empty
Definition socan.c:164
int tail
Definition socan.c:160
pthread_mutex_t qmutex
Definition socan.c:162