43#include <sys/socket.h>
63#include <linux/net_tstamp.h>
64#include <linux/sockios.h>
67#include <linux/can/raw.h>
121#define READER_DEFAULT_PRIO 97
124#define WRITER_DEFAULT_PRIO 97
127#define MAX_WQ_MESSAGES 32
130#define MAX_QR_MESSAGES 32
171 unsigned char length;
172 unsigned char received_length;
179 struct timeval tv_request;
181 unsigned long tm_inhibit_us;
182 unsigned short urcnt;
185 unsigned short ircnt;
187 unsigned char w_echo;
203 pthread_mutex_t mutex;
210 char *interface_name;
212 int interface_index_valid;
214 unsigned int bitrate;
229static bool socan_use_rt_priority=
true;
230static bool socan_require_rt_priority=
false;
238static pthread_mutex_t global_semaphore;
241static unsigned char can_ports_no= 0;
243static int thread_count=0;
249static int errprintlevel= 1;
256static void errprint(
int level,
const char *function,
const int line,
263 if (level>errprintlevel)
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);
272#define ERRPRINT(lv, ...) errprint(lv, __func__, __LINE__, __VA_ARGS__)
274#define ERRPRINT_FUNC(lv, FUNC, ...) errprint(1, FUNC, __LINE__, __VA_ARGS__)
276#define ERRPRINT_ERRNO(syscall) \
277 errprint(1, __func__, __LINE__, \
278 syscall " failed, errno %d (%s)\n", errno, strerror(errno))
280#define ERRPRINT_RC(syscall, rc) \
281 errprint(1, __func__, __LINE__, \
282 syscall " failed, error %d (%s)\n", rc, strerror(rc))
284#define ERRPRINT_RC_FUNC(FUNC, syscall, rc) \
285 errprint(1, FUNC, __LINE__, \
286 syscall " failed, error %d (%s)\n", rc, strerror(rc))
296 errprintlevel= level;
297 return errprintlevel;
304static int tracelevel= 0;
310static void trace(
int level,
char *format, ...)
314 if (level>tracelevel)
316 va_start(args, format);
317 vprintf(format, args);
321static void trace_object(
int level,
326 const struct can_frame *frame_)
330 if (level>tracelevel)
335 snprintf(databuf, 30,
"CAN-LENGTH-OVERFLOW");
341 for (i = 0; i < frame_->can_dlc; i++)
345 sprintf(p,
"%02X", frame_->data[i]);
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);
370#define CCODE(x) if (rc==x) return(#x)
390 ERRPRINT(1,
"unexpected return code: %d\n", rc);
391 return(
"UNKNOWN ERROR CODE!");
432 ERRPRINT(1,
"unexpected return code: %d\n", rc);
445static bool check_len(
unsigned char len,
const char *func)
449 ERRPRINT_FUNC(2, func,
"len %d invalid", len);
455static bool check_cob(
unsigned short cob,
const char *func)
459 ERRPRINT_FUNC(2, func,
"cob %d invalid", cob);
465static socan_rc check_get_cob(
unsigned short cob,
const char *func,
472 ERRPRINT_FUNC(2, func,
"cob %d invalid", cob);
475 *obj= cob_dict_lookup(cp->dict, cob);
482 ERRPRINT_FUNC(2, func,
"can object for cob %d is not defined", cob);
486 if ((*obj)->hdl_s == NULL)
492 ERRPRINT_FUNC(2, func,
"can object for cob %d has no owner", cob);
499static bool check_get_port(
unsigned char port,
const char *func,
can_port **cp)
501 if (port>=can_ports_no)
503 ERRPRINT_FUNC(2, func,
"port %d invalid", port);
506 *cp= &(can_ports[port]);
514static void tv_to_str(
const struct timeval *tv,
char *buf,
int buflen)
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);
526static void us_to_tv(
unsigned long tv_us,
struct timeval *tv)
528 ldiv_t d= ldiv(tv_us, 1000000);
533static unsigned long tv_to_us(
const struct timeval *tv)
535 return tv->tv_sec * 1000000 + tv->tv_usec;
538static unsigned long tv_to_ms(
const struct timeval *tv)
540 return tv->tv_sec * 1000 + tv->tv_usec / 1000;
543static unsigned long tm_ms_now(
void)
549 gettimeofday(&now, NULL);
550 return tv_to_ms(&now);
553static unsigned long tm_us_now(
void)
557 gettimeofday(&now, NULL);
558 return tv_to_us(&now);
561static unsigned long tm_ms_diff_to_now(
const struct timeval *tv)
564 return tm_ms_now() - tv_to_ms(tv);
567static void tv_now(
struct timeval *tv)
569 gettimeofday(tv, NULL);
572static void calc_abs_timeout(
int timeout_ms,
struct timespec *ts)
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)
592 ts->tv_nsec-= 1000000000;
597static void mldelay(
long milliseconds)
600 {
struct timespec rq,rt;
603 if (milliseconds >= 1000L)
604 { rq.tv_sec = milliseconds / 1000L;
605 rq.tv_nsec= (milliseconds-1000L*rq.tv_sec) * 1000000L;
609 rq.tv_nsec= milliseconds * 1000000L;
611 nanosleep( &rq, &rt);
619#define THREAD_NAMELEN 16
621static char *thread_suffix(
bool is_reader,
int port)
623 static char buffer[THREAD_NAMELEN];
626 snprintf(buffer, THREAD_NAMELEN,
"-r%d", port);
628 snprintf(buffer, THREAD_NAMELEN,
"-w%d", port);
633static bool get_curr_prio(
int *policy,
int *min_prio,
int *max_prio,
643 struct sched_param param;
644 rc= pthread_getschedparam(pthread_self(), policy, ¶m);
647 ERRPRINT_RC(
"pthread_getschedparam", rc);
650 *max_prio= sched_get_priority_max(*policy);
651 *min_prio= sched_get_priority_min(*policy);
652 *curr_prio= param.sched_priority;
656static bool init_attr_p(pthread_attr_t *attr_p,
int stack,
int prio)
668 int curr_policy, min_prio, max_prio, curr_prio;
669 struct sched_param s_param;
671 rc= pthread_attr_init(attr_p);
674 ERRPRINT_RC(
"pthread_attr_init", rc);
678#ifndef PTHREAD_STACK_MIN
679#define PTHREAD_STACK_MIN 16384
681 rc= pthread_attr_setstacksize(attr_p,
682 (stack < PTHREAD_STACK_MIN) ? PTHREAD_STACK_MIN : stack);
685 ERRPRINT_RC(
"pthread_attr_setstacksize", rc);
690 if (!get_curr_prio(&curr_policy, &min_prio, &max_prio, &curr_prio))
695 rc= pthread_attr_setschedpolicy(attr_p, curr_policy);
698 ERRPRINT_RC(
"pthread_attr_setschedpolicy", rc);
701 rc = pthread_attr_setinheritsched(attr_p, PTHREAD_INHERIT_SCHED);
704 ERRPRINT_RC(
"pthread_attr_setinheritsched", rc);
707 s_param.sched_priority= curr_prio;
708 rc= pthread_attr_setschedparam(attr_p, &s_param);
711 ERRPRINT_RC(
"pthread_attr_setschedparam", rc);
717 rc= pthread_attr_setschedpolicy(attr_p, SCHED_FIFO);
720 ERRPRINT_RC(
"pthread_attr_setschedpolicy", rc);
727 rc = pthread_attr_setinheritsched(attr_p, PTHREAD_EXPLICIT_SCHED);
730 ERRPRINT_RC(
"pthread_attr_setinheritsched", rc);
733 s_param.sched_priority= prio;
734 rc= pthread_attr_setschedparam(attr_p, &s_param);
737 ERRPRINT_RC(
"pthread_attr_setschedparam", rc);
744static bool thread_start(
void *(*th)(
void*), pthread_t *pst,
753 char thread_name[THREAD_NAMELEN];
760 rc = pthread_getname_np(pthread_self(), thread_name, THREAD_NAMELEN);
763 ERRPRINT_RC(
"pthread_getname_np", rc);
767 l= strlen(thread_name);
769 if (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;
777 if (!socan_use_rt_priority)
780 if (!init_attr_p(&attr, stack, prio))
782 ERRPRINT(1,
"init_attr");
786 rc = pthread_create( pst, &attr, th, arg);
787 if ((rc==EPERM) && (prio>=0))
789 if (socan_require_rt_priority)
791 ERRPRINT(1,
"Error: creating thread %s with policy\n"
792 "\tSCHED_FIFO and priority %d failed.\n",
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",
801 socan_use_rt_priority=
false;
804 if (!init_attr_p(&attr, stack, -1))
807 rc = pthread_create( pst, &attr, th, arg);
811 ERRPRINT_RC(
"pthread_create", rc);
816 rc = pthread_setname_np(*pst, thread_name);
819 ERRPRINT_RC(
"pthread_setname_np", rc);
830static bool mutex_init(pthread_mutex_t *mutex)
835 pthread_mutexattr_t mutexattr;
837 rc= pthread_mutexattr_init(&mutexattr);
840 ERRPRINT_RC(
"pthread_mutexattr_init", rc);
843 rc= pthread_mutexattr_setprotocol(&mutexattr, PTHREAD_PRIO_INHERIT);
846 ERRPRINT_RC(
"pthread_mutexattr_setprotocol", rc);
849 rc= pthread_mutex_init(mutex, &mutexattr);
852 ERRPRINT_RC(
"pthread_mutex_init", rc);
858static bool mutex_delete(pthread_mutex_t *mutex)
862 rc= pthread_mutex_destroy(mutex);
865 ERRPRINT_RC(
"pthread_mutex_destroy", rc);
871static bool mutex_lock(pthread_mutex_t *mutex,
const char *func)
873 int rc= pthread_mutex_lock(mutex);
876 ERRPRINT_RC_FUNC(func,
"pthread_mutex_lock", rc);
880static bool mutex_unlock(pthread_mutex_t *mutex,
const char *func)
882 int rc= pthread_mutex_unlock(mutex);
885 ERRPRINT_RC_FUNC(func,
"pthread_mutex_unlock", rc);
889#define MUTEX_LOCK(mutex) mutex_lock(mutex, __func__)
891#define MUTEX_UNLOCK(mutex) mutex_unlock(mutex, __func__)
919static bool squeue_init(
squeue *q,
unsigned int elements)
926 if (!mutex_init(&(q->
qmutex)))
928 ERRPRINT(1,
"mutex_init failed\n");
931 if (sem_init(&(q->
qsem), 0, 0))
933 ERRPRINT_ERRNO(
"sem_init");
934 mutex_delete(&(q->
qmutex));
944static int squeue_inc(
const squeue *q,
int index)
953static bool squeue_delete(
squeue *q)
956 if (!mutex_delete(&(q->
qmutex)))
958 ERRPRINT(1,
"mutex_delete failed\n");
961 if (sem_destroy(&(q->
qsem)))
963 ERRPRINT_ERRNO(
"sem_destroy");
970static bool squeue_add(
squeue *q,
unsigned short cob,
unsigned char port)
982 MUTEX_UNLOCK(&(q->
qmutex));
990 if (sem_post(&(q->
qsem)))
991 ERRPRINT_ERRNO(
"sem_post");
992 MUTEX_UNLOCK(&(q->
qmutex));
996static void squeue_get(
squeue *q,
unsigned short *cob,
unsigned char *port)
1007 if (sem_wait(&(q->
qsem)))
1009 ERRPRINT_ERRNO(
"sem_wait");
1012 MUTEX_LOCK(&(q->
qmutex));
1017 MUTEX_UNLOCK(&(q->
qmutex));
1019 elm= &(q->
data[q->head]);
1021 *port= (
unsigned char)(elm->
port);
1022 q->head= squeue_inc(q, q->head);
1023 if (q->head == q->
tail)
1025 MUTEX_UNLOCK(&(q->
qmutex));
1032static bool interface_exists(
const char *device)
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)
1078static bool socan_is_virtual_interface(
const char *device)
1085 int rc= sscanf(device,
"vcan%d%c", &dummy, &dummy2);
1098 if (!check_get_port(port, __func__, &cp))
1113 cp->bitrate= *bitrate;
1118 if (cp->bitrate != 0)
1120 *bitrate= cp->bitrate;
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)
1130 sscanf(buf,
" bitrate %ud ", bitrate);
1136 cp->bitrate= *bitrate;
1158 ERRPRINT(1,
"socan is not initialized\n");
1161 MUTEX_LOCK(&global_semaphore);
1163 if (sem_init(&(t->thread_sem), 0, 1))
1165 ERRPRINT_ERRNO(
"sem_init");
1167 MUTEX_UNLOCK(&global_semaphore);
1170 rc= pthread_mutex_init(&(t->mutex), NULL);
1173 ERRPRINT_RC(
"pthread_mutex_init", rc);
1174 if (sem_destroy(&(t->thread_sem)))
1175 ERRPRINT_ERRNO(
"sem_destroy");
1177 MUTEX_UNLOCK(&global_semaphore);
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");
1188 MUTEX_UNLOCK(&global_semaphore);
1192 MUTEX_UNLOCK(&global_semaphore);
1204 h->is_active=
false;
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)))
1212 ERRPRINT_ERRNO(
"sem_destroy");
1215 for(port=0; port<can_ports_no; port++)
1217 cob_dict *dict= can_ports[port].dict;
1218 for(cob=0; cob<
COB_NO; cob++)
1220 obj= cob_dict_lookup(dict, cob);
1223 if (obj->hdl_s != h)
1229 MUTEX_UNLOCK(&global_semaphore);
1237 if (!check_get_port(port, __func__, &cp))
1239 *dev= cp->interface_name;
1247 if (sem_getvalue(&(h->thread_sem), &sval))
1249 ERRPRINT_ERRNO(
"sem_getvalue");
1254 if (sem_post(&(h->thread_sem)))
1256 ERRPRINT_ERRNO(
"sem_post");
1261static int socan_hdl_wait_tmo(
socan_hdl h,
struct timespec *ts)
1268 int rc= sem_timedwait(&(h->thread_sem), ts);
1272 if (errno==ETIMEDOUT)
1274 ERRPRINT_ERRNO(
"sem_timedwait");
1286 unsigned char length,
1287 unsigned int tmo_ms,
1290 if (!check_len(length, __func__))
1292 if (!check_cob(cob, __func__))
1299 obj->length= length;
1308 obj->tmo_ms= tmo_ms;
1314 obj->user_ptr= NULL;
1321 void *up= obj->user_ptr;
1323 obj->user_ptr= NULL;
1329static unsigned char *canobj_rtr_wbuf(
struct socan_obj_s *obj)
1331 if (obj->use_buffer2)
1332 return obj->buffer2;
1336static unsigned char *canobj_rtr_wbuf_other(
struct socan_obj_s *obj)
1338 if (obj->use_buffer2)
1340 return obj->buffer2;
1343static void canobj_rtr_switch(
struct socan_obj_s *obj)
1345 if (obj->use_buffer2)
1346 obj->use_buffer2=
false;
1348 obj->use_buffer2=
true;
1358 return calloc(1,
sizeof(
cob_dict));
1361void cob_dict_delete(
cob_dict *dict)
1368 if (!check_cob(cob, __func__))
1370 return (dict->objects)[cob];
1373static bool cob_dict_set(
cob_dict *dict,
unsigned short cob,
void *ptr)
1376 if (!check_cob(cob, __func__))
1378 (dict->objects)[cob]= ptr;
1382static bool cob_dict_remove(
cob_dict *dict,
unsigned short cob)
1385 if (!check_cob(cob, __func__))
1387 (dict->objects)[cob]= NULL;
1403 ERRPRINT(2,
"cannot add ports in INITIALIZED state\n");
1406 if (socan_state ==
ERROR)
1408 ERRPRINT(2,
"cannot add ports in ERROR state\n");
1414 ERRPRINT(2,
"too many ports\n");
1417 if (!interface_exists(devicename))
1419 ERRPRINT(2,
"interface '%s' doesn't exist\n", devicename);
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;
1429 cp->is_virtual= socan_is_virtual_interface(devicename);
1432 ERRPRINT(1,
"squeue_init failed\n");
1440static int can_port_interface_index(
can_port *cp,
int sock)
1445 if (!cp->interface_index_valid)
1447 MUTEX_LOCK(&global_semaphore);
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);
1455 i= cp->interface_index;
1460 unsigned short cob,
unsigned char length,
1466 if (!check_get_port(port, __func__, &cp))
1468 if (!check_cob(cob, __func__))
1470 if (!check_len(length, __func__))
1472 MUTEX_LOCK(&global_semaphore);
1473 obj= cob_dict_lookup(cp->dict, cob);
1476 if ((obj->hdl_s == hdl) && (obj->length == length) &&
1477 (obj->type == type) && (obj->tmo_ms == tmo_ms))
1481 MUTEX_UNLOCK(&global_semaphore);
1484 if ((obj->hdl_s !=NULL) && (obj->hdl_s != hdl))
1487 MUTEX_UNLOCK(&global_semaphore);
1491 ERRPRINT(2,
"CAN object cob %d port %d already exists\n",
1493 MUTEX_UNLOCK(&global_semaphore);
1496 obj= canobj_new(hdl, port, cob, length, tmo_ms, type);
1497 cob_dict_set(cp->dict, cob, obj);
1498 MUTEX_UNLOCK(&global_semaphore);
1507 if (!check_get_port(port, __func__, &cp))
1509 if (!check_cob(cob, __func__))
1511 MUTEX_LOCK(&global_semaphore);
1512 obj= cob_dict_lookup(cp->dict, cob);
1516 cob_dict_remove(cp->dict, cob);
1519 MUTEX_UNLOCK(&global_semaphore);
1524 unsigned char port,
unsigned short cob,
1525 unsigned char *length,
1526 unsigned int *tmo_ms,
1534 if (!check_get_port(port, __func__, &cp))
1536 if (!check_cob(cob, __func__))
1538 rc= check_get_cob(cob, __func__, cp, &obj,
false);
1541 if (obj->hdl_s != hdl)
1543 *length= obj->length;
1544 *tmo_ms= obj->tmo_ms;
1554 unsigned long us1, us2;
1557 if (!check_get_port(port, __func__, &cp))
1559 rc= check_get_cob(cob, __func__, cp, &obj,
true);
1565 us1= tv_to_us(&(obj->tv));
1566 us2= tv_to_us(&(obj->tv));
1567 }
while (us1 != us2);
1576 tv_to_str(&tv, buf, buflen);
1586 if (!check_get_port(port, __func__, &cp))
1588 rc= check_get_cob(cob, __func__, cp, &obj,
true);
1593 ERRPRINT(2,
"cob %d is not an ordinary write object\n", cob);
1596 obj->tm_inhibit_us= inhibit_time;
1607 if (!check_get_port(port, __func__, &cp))
1609 rc= check_get_cob(cob, __func__, cp, &obj,
true);
1614 ERRPRINT(2,
"cob %d is not a read or rtr-read object\n", cob);
1617 obj->use_queue=
true;
1630 if (!check_get_port(port, __func__, &cp))
1632 rc= check_get_cob(cob, __func__, cp, &obj,
true);
1635 if (obj->user_ptr != NULL)
1636 free(obj->user_ptr);
1637 obj->user_ptr= calloc(1, size);
1638 *area= obj->user_ptr;
1649 if (!check_get_port(port, __func__, &cp))
1651 rc= check_get_cob(cob, __func__, cp, &obj,
true);
1654 *area= obj->user_ptr;
1665 if (!check_get_port(port, __func__, &cp))
1667 rc= check_get_cob(cob, __func__, cp, &obj,
true);
1682 if (!check_get_port(port, __func__, &cp))
1684 rc= check_get_cob(cob, __func__, cp, &obj,
true);
1688 obj->user_ptr= NULL;
1717 if (!check_get_port(port, __func__, &cp))
1719 rc= check_get_cob(cob, __func__, cp, &obj,
true);
1724 ERRPRINT(2,
"cob %d is not a read object\n", cob);
1731 rlen= obj->received_length;
1732 memcpy(data, obj->buffer, obj->length);
1733 }
while (ircnt != obj->ircnt);
1736 if (obj->urcnt == ircnt)
1741 if (rlen != obj->length)
1746 if ((
unsigned short)(ircnt - obj->urcnt) > 1)
1778 if (!check_get_port(port, __func__, &cp))
1780 rc= check_get_cob(cob, __func__, cp, &obj,
true);
1787 obj->urcnt= obj->ircnt;
1788 calc_abs_timeout(obj->tmo_ms, &ts);
1789 if (!squeue_add(&(cp->writer_squeue), cob, port))
1791 ERRPRINT(3,
"squeue_add failed, queue full "
1792 "(size %d) port:%d cob:%d\n",
1793 cp->writer_squeue.
elements, port, cob);
1798 rc_i= socan_hdl_wait_tmo(hdl, &ts);
1806 if (obj->urcnt != obj->ircnt)
1811 if (obj->urcnt == obj->ircnt)
1813 calc_abs_timeout(obj->tmo_ms, &ts);
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))
1821 if (obj->urcnt != obj->ircnt)
1831 ERRPRINT(2,
"cob %d is not a read object\n", cob);
1840 rlen= obj->received_length;
1841 memcpy(data, obj->buffer, obj->length);
1842 }
while (ircnt != obj->ircnt);
1845 if (rlen != obj->length)
1850 if (obj->urcnt == ircnt)
1855 if ((
unsigned short)(ircnt - obj->urcnt) > 1)
1868 unsigned short *cob,
void *data)
1873 unsigned short cob_;
1874 unsigned char port_;
1880 squeue_get(&(hdl->qread_queue), &cob_, &port_);
1881 if (!check_get_port(port_, __func__, &cp))
1883 rc= check_get_cob(cob_, __func__, cp, &obj,
true);
1886 if (!obj->use_queue)
1888 ERRPRINT(2,
"not a qread object: %d port %d\n", cob_, port_);
1892 if (obj->urcnt == obj->ircnt)
1900 rlen= obj->received_length;
1901 memcpy(data, obj->buffer, obj->length);
1902 }
while (ircnt != obj->ircnt);
1905 trace(1,
" queue_read: port:%d cob:%d urcnt:%d ircnt:%d\n",
1906 port_, cob_, obj->urcnt, ircnt);
1909 if (rlen != obj->length)
1914 if ((
unsigned short)(ircnt - obj->urcnt) > 1)
1928 unsigned char port,
unsigned short cob,
const void *data)
1943 if (!check_get_port(port, __func__, &cp))
1945 rc= check_get_cob(cob, __func__, cp, &obj,
true);
1952 ERRPRINT(2,
"cob %d is not a write or RTR-read object\n", cob);
1959 tv_now(&(obj->tv_request));
1960 memcpy(canobj_rtr_wbuf_other(obj), data, obj->length);
1963 canobj_rtr_switch(obj);
1970 tv_now(&(obj->tv_request));
1972 trace(1,
"tm bef. write: %lu\n", tv_to_ms(&(obj->tv_request)));
1973 memcpy(obj->buffer, data, obj->length);
1976 if (!squeue_add(&(cp->writer_squeue), cob, port))
1978 ERRPRINT(3,
"squeue_add failed, queue full "
1979 "(size %d) port:%d cob:%d\n",
1980 cp->writer_squeue.
elements, port, cob);
1983 calc_abs_timeout(obj->tmo_ms, &ts);
1986 rc_i= socan_hdl_wait_tmo(hdl, &ts);
1987 if ((rc_i==1) || (rc_i==-1))
1992 trace(1,
"tm aft. write: %lu\n", tm_ms_now());
2001 unsigned char port,
unsigned short cob,
const void *data)
2019 if (!check_get_port(port, __func__, &cp))
2021 my_rc= check_get_cob(cob, __func__, cp, &obj,
true);
2028 ERRPRINT(2,
"cob %d is not a write or RTR-read object\n", cob);
2035 tv_now(&(obj->tv_request));
2036 memcpy(canobj_rtr_wbuf(obj), data, obj->length);
2039 canobj_rtr_switch(obj);
2048 unsigned long tdelta= tm_ms_diff_to_now(&(obj->tv_request));
2049 if (tdelta < obj->tmo_ms)
2057 tv_now(&(obj->tv_request));
2059 memcpy(obj->buffer, data, obj->length);
2062 if (!squeue_add(&(cp->writer_squeue), cob, port))
2064 ERRPRINT(3,
"squeue_add failed, queue full "
2065 "(size %d) port:%d cob:%d\n",
2066 cp->writer_squeue.
elements, port, cob);
2073 unsigned char port,
unsigned short cob,
2075 unsigned long *inhibit_time)
2089 unsigned long tm_us_next_write;
2090 unsigned long tm_us_now_;
2092 if (!check_get_port(port, __func__, &cp))
2094 my_rc= check_get_cob(cob, __func__, cp, &obj,
true);
2101 ERRPRINT(2,
"cob %d is not a write or RTR-read object\n", cob);
2109 tv_now(&(obj->tv_request));
2110 memcpy(canobj_rtr_wbuf(obj), data, obj->length);
2113 canobj_rtr_switch(obj);
2121 unsigned long tdelta= tm_ms_diff_to_now(&(obj->tv_request));
2122 if (tdelta < obj->tmo_ms)
2125 *inhibit_time= obj->tm_inhibit_us;
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)
2136 *inhibit_time= tm_us_next_write - tm_us_now_;
2141 tv_now(&(obj->tv_request));
2142 memcpy(obj->buffer, data, obj->length);
2145 if (!squeue_add(&(cp->writer_squeue), cob, port))
2147 ERRPRINT(3,
"squeue_add failed, queue full "
2148 "(size %d) port:%d cob:%d\n",
2149 cp->writer_squeue.
elements, port, cob);
2159static int init_can_socket(
can_port *cp,
int *sock)
2162 struct sockaddr_can addr;
2163 int interface_index;
2167 if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
2169 ERRPRINT_ERRNO(
"socket");
2172 sval= SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_TX_HARDWARE;
2173 if ((rc= setsockopt(s, SOL_SOCKET, SO_TIMESTAMPING, &sval,
sizeof(sval))))
2175 ERRPRINT_RC(
"setsockopt", rc);
2178 interface_index= can_port_interface_index(cp, s);
2179 if (interface_index==-1)
2181 ERRPRINT(1,
"can_port_interface_index failed\n");
2185 memset(&addr, 0,
sizeof(addr));
2186 addr.can_family = AF_CAN;
2187 addr.can_ifindex = interface_index;
2190 if (bind(s, (
struct sockaddr *) &addr,
sizeof(addr)) < 0)
2192 ERRPRINT_ERRNO(
"bind");
2199#define TASK "reader"
2200static void *reader(
void *arg)
2204 unsigned char port= ((
can_port *)arg)->port;
2207 struct can_frame frame;
2208 static int read_can_device_rc= 0;
2211 read_can_device_rc= init_can_socket(cp, &s);
2212 if (read_can_device_rc!=0)
2214 ERRPRINT(1,
"init_can_socket failed: %d\n", read_can_device_rc);
2218 MUTEX_LOCK(&global_semaphore);
2220 MUTEX_UNLOCK(&global_semaphore);
2224 int nbytes = read(s, &frame,
sizeof(
struct can_frame));
2230 ERRPRINT_ERRNO(
"read");
2234 cob= frame.can_id & CAN_SFF_MASK;
2235 is_rtr= (frame.can_id & CAN_RTR_FLAG) ? 1 : 0;
2236 rc= check_get_cob(cob, __func__, cp, &obj,
false);
2241 if (!obj->hdl_s->is_active)
2247 trace(2,
"(%s) ulock ! port:%d cob:0x%03X RTR:%1d",
2248 TASK, port, cob, is_rtr);
2253 ioctl(s, SIOCGSTAMP, &(obj->tv));
2260 ERRPRINT(3,
" (%s) RTR on SOCAN_READ "
2262 "port:%d cob:0x%03X RTR:%1d\n",
2263 TASK, port, cob, is_rtr);
2268 memcpy(obj->buffer, frame.data, frame.can_dlc);
2269 obj->received_length= frame.can_dlc;
2272 if (!squeue_add(&(obj->hdl_s->qread_queue), cob, port))
2274 ERRPRINT(3,
"(task %s) "
2275 "squeue_add failed, queue full "
2276 "(size %d) port:%d cob:%d RTR:%1d\n",
2278 cp->writer_squeue.
elements, port, cob, is_rtr);
2282 socan_hdl_give(obj->hdl_s);
2291 socan_hdl_give(obj->hdl_s);
2299 memcpy(obj->buffer, frame.data, frame.can_dlc);
2300 obj->received_length= frame.can_dlc;
2303 if (!squeue_add(&(obj->hdl_s->qread_queue), cob, port))
2305 ERRPRINT(3,
"(task %s) "
2306 "squeue_add failed, queue full "
2307 "(size %d) port:%d cob:%d RTR:%1d\n",
2314 socan_hdl_give(obj->hdl_s);
2320 ERRPRINT(3,
" (%s) non-RTR on SOCAN_WRITE_RTR "
2322 "port:%d cob:0x%03X RTR:%1d\n",
2323 TASK, port, cob, is_rtr);
2328 if (!squeue_add(&(cp->writer_squeue), cob, port))
2330 ERRPRINT(3,
"(task %s) "
2331 "squeue_add failed, queue full "
2332 "(size %d) port:%d cob:%d RTR:%1d\n",
2334 cp->writer_squeue.
elements, port, cob, is_rtr);
2337 trace(2,
" (%s) create reply on received "
2339 "port:%d cob:0x%03X RTR:%1d\n",
2340 TASK, port, cob, is_rtr);
2345 ERRPRINT(3,
" (%s) RTR on SOCAN_WRITE "
2347 "port:%d cob:0x%03X RTR:%1d\n",
2348 TASK, port, cob, is_rtr);
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);
2362 socan_hdl_give(obj->hdl_s);
2366 if (tracelevel >= 2)
2367 trace_object(2, TASK, obj, port, cob, &frame);
2372 ERRPRINT_ERRNO(
"close");
2373 read_can_device_rc= 5;
2379#define TASK "writer"
2380static void *writer(
void *arg)
2383 unsigned char writer_port= cp->port;
2385 static int write_can_device_rc= 0;
2386 struct can_frame frame;
2388 int can_frame_sz=
sizeof(
struct can_frame);
2392 memset(&frame, 0,
sizeof(
struct can_frame));
2394 write_can_device_rc= init_can_socket(cp, &s);
2396 if (write_can_device_rc!=0)
2398 ERRPRINT(1,
"init_can_socket failed: %d\n", write_can_device_rc);
2401 MUTEX_LOCK(&global_semaphore);
2403 MUTEX_UNLOCK(&global_semaphore);
2411 squeue_get(&(cp->writer_squeue), &cob, &port);
2412 if (writer_port != port)
2414 ERRPRINT(3,
"port %d != %d\n", port, writer_port);
2418 rc= check_get_cob(cob, __func__, cp, &obj,
true);
2423 if (!obj->hdl_s->is_active)
2431 memcpy(frame.data, canobj_rtr_wbuf(obj), obj->length);
2432 frame.can_dlc= obj->length;
2436 frame.can_id= cob | CAN_RTR_FLAG;
2437 memset(frame.data, 0, obj->length);
2438 frame.can_dlc= obj->length;
2449 memcpy(frame.data, obj->buffer, obj->length);
2450 frame.can_dlc= obj->length;
2454 trace(2,
"(%s) port:%d cob:0x%03X ", TASK, port, cob);
2456 for (i = 0; i < frame.can_dlc; i++)
2457 trace(2,
"%02X ", frame.data[i]);
2460 if (write(s, &frame, can_frame_sz) != can_frame_sz)
2462 ERRPRINT_ERRNO(
"write");
2473 bool require_rt_priority,
2474 int reader_priority,
2475 int writer_priority)
2484 int min_prio, max_prio;
2486 switch (socan_state)
2489 ERRPRINT(1,
"socan is in ERROR state, cannot setup realtime\n");
2492 ERRPRINT(1,
"socan is already initialized, "
2493 "cannot setup realtime\n");
2498 ERRPRINT(1,
"unknown internal state: %d\n", socan_state);
2502 if (use_rt_priority)
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))
2508 ERRPRINT(1,
"Error, reader priority %d out of range "
2510 reader_priority, min_prio, max_prio);
2513 if ((writer_priority < min_prio) || (writer_priority > max_prio))
2515 ERRPRINT(1,
"Error, writer priority %d out of range "
2517 writer_priority, min_prio, max_prio);
2522 socan_use_rt_priority= use_rt_priority;
2523 socan_require_rt_priority= require_rt_priority;
2524 if (use_rt_priority)
2526 socan_reader_priority= reader_priority;
2527 socan_writer_priority= writer_priority;
2536_Atomic
static int _lock= 0;
2548 if (socan_state ==
ERROR)
2550 if (can_ports_no==0)
2552 ERRPRINT(1,
"no ports are defined\n");
2564 if (socan_state ==
ERROR)
2569 if (!mutex_init(&global_semaphore))
2571 ERRPRINT(1,
"mutex_init failed\n");
2576 MUTEX_LOCK(&global_semaphore);
2578 for (p=0; p<can_ports_no; p++)
2581 if (!thread_start(reader, &(socan_read_threads[p]),
2582 thread_suffix(
true, p),
2584 socan_reader_priority,
2587 ERRPRINT(1,
"thread_start (reader) failed\n");
2589 MUTEX_UNLOCK(&global_semaphore);
2593 if (!thread_start(writer, &(socan_write_threads[p]),
2594 thread_suffix(
false, p),
2596 socan_writer_priority,
2599 ERRPRINT(1,
"thread_start (writer) failed\n");
2601 MUTEX_UNLOCK(&global_semaphore);
2607 MUTEX_UNLOCK(&global_semaphore);
2610 for(n=can_ports_no;n>0;n--)
2613 MUTEX_LOCK(&global_semaphore);
2614 if (thread_count >= can_ports_no*2)
2617 MUTEX_UNLOCK(&global_semaphore);
2620 MUTEX_UNLOCK(&global_semaphore);
2625 ERRPRINT(1,
"starting all threads took too long\n");
socan_rc socan_user_area(unsigned char port, unsigned short cob, void **area)
#define WRITER_DEFAULT_PRIO
absolute default priority of writer task
bool socan_close(socan_hdl h)
socan_rc socan_write_inhibit(socan_hdl hdl, unsigned char port, unsigned short cob, const void *data, unsigned long *inhibit_time)
socan_rc socan_set_user_area(unsigned char port, unsigned short cob, void *ptr)
char * socan_str_rc(socan_rc rc)
bool socan_realtime_setup(bool use_rt_priority, bool require_rt_priority, int reader_priority, int writer_priority)
socan_rc socan_port_bitrate(unsigned char port, unsigned int *bitrate)
#define MAX_WQ_MESSAGES
max. number of CAN objects in writer queue
socan_rc socan_del_obj(unsigned char port, unsigned short cob)
socan_rc socan_read(socan_hdl hdl, unsigned char port, unsigned short cob, void *data)
int socan_errprintlevel(int level)
#define MAX_QR_MESSAGES
max. number of CAN objects in reader queue
socan_rc socan_obj_ts(unsigned char port, unsigned short cob, unsigned long *ts)
socan_rc socan_use_queue(unsigned char port, unsigned short cob)
socan_rc socan_readnow(socan_hdl hdl, unsigned char port, unsigned short cob, void *data)
socan_rc socan_set_inhibit(unsigned char port, unsigned short cob, unsigned long inhibit_time)
#define READER_DEFAULT_PRIO
absolute default priority of reader task
socan_rc socan_write(socan_hdl hdl, unsigned char port, unsigned short cob, const void *data)
socan_rc socan_free_user_area(unsigned char port, unsigned short cob)
struct sq_elm sq_elm
type of a single element in the 'squeue' queue
int socan_add_port(const char *devicename)
bool socan_rc_is_error(socan_rc rc)
int socan_tracelevel(int level)
socan_hdl socan_open(void)
socan_rc socan_port_device(unsigned char port, char **dev)
socan_rc socan_queue_read(socan_hdl hdl, unsigned char *port, unsigned short *cob, void *data)
socan_rc socan_ts_to_str(unsigned long ts, char *buf, int buflen)
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)
socan_module_state
state of the socan module
socan_rc socan_writelater(socan_hdl hdl, unsigned char port, unsigned short cob, const void *data)
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)
socan_rc socan_new_user_area(unsigned char port, unsigned short cob, unsigned int size, void **area)
c header file for socan object layer library.
#define SOCAN_FRAME_LENGTH
type of a single element in the 'squeue' queue