26 #if !LELY_NO_STDIO && defined(__linux__)
46 #include <linux/can/raw.h>
47 #include <linux/sockios.h>
48 #include <sys/ioctl.h>
50 #include "../posix/fd.h"
55 #ifndef LELY_IO_CAN_RXLEN
56 #define LELY_IO_CAN_RXLEN 1024
62 struct can_frame frame;
64 struct canfd_frame frame;
70 static int io_can_fd_set_default(
int fd);
72 static int io_can_fd_read(
int fd,
struct can_frame *frame,
size_t *pnbytes,
73 int *pflags,
struct timespec *tp,
int timeout);
75 static int io_can_fd_read(
int fd,
struct canfd_frame *frame,
size_t *pnbytes,
76 int *pflags,
struct timespec *tp,
int timeout);
79 static int io_can_fd_write(
int fd,
const struct can_frame *frame,
size_t nbytes,
82 static int io_can_fd_write(
int fd,
const struct canfd_frame *frame,
83 size_t nbytes,
int timeout);
85 static int io_can_fd_write_msg(
int fd,
const struct can_msg *msg,
int timeout);
89 static size_t io_can_chan_impl_dev_cancel(
io_dev_t *dev,
struct ev_task *task);
90 static size_t io_can_chan_impl_dev_abort(
io_dev_t *dev,
struct ev_task *task);
93 static const struct io_dev_vtbl io_can_chan_impl_dev_vtbl = {
94 &io_can_chan_impl_dev_get_ctx,
95 &io_can_chan_impl_dev_get_exec,
96 &io_can_chan_impl_dev_cancel,
97 &io_can_chan_impl_dev_abort
102 static int io_can_chan_impl_get_flags(
const io_can_chan_t *chan);
104 struct can_err *err,
struct timespec *tp,
int timeout);
105 static void io_can_chan_impl_submit_read(
107 static int io_can_chan_impl_write(
109 static void io_can_chan_impl_submit_write(
114 &io_can_chan_impl_get_dev,
115 &io_can_chan_impl_get_flags,
116 &io_can_chan_impl_read,
117 &io_can_chan_impl_submit_read,
118 &io_can_chan_impl_write,
119 &io_can_chan_impl_submit_write
123 static void io_can_chan_impl_svc_shutdown(
struct io_svc *svc);
126 static const struct io_svc_vtbl io_can_chan_impl_svc_vtbl = {
128 &io_can_chan_impl_svc_shutdown
159 pthread_mutex_t
c_mtx;
197 static void io_can_chan_impl_watch_func(
199 static void io_can_chan_impl_rxbuf_task_func(
struct ev_task *task);
200 static void io_can_chan_impl_read_task_func(
struct ev_task *task);
201 static void io_can_chan_impl_write_task_func(
struct ev_task *task);
210 static void io_can_chan_impl_c_signal(
struct spscring *ring,
void *arg);
217 struct sllist *queue,
int *pwouldblock);
221 static size_t io_can_chan_impl_do_abort_tasks(
struct io_can_chan_impl *impl);
223 static int io_can_chan_impl_set_fd(
227 io_can_chan_alloc(
void)
239 io_can_chan_free(
void *ptr)
242 free(io_can_chan_impl_from_chan(ptr));
257 impl->
dev_vptr = &io_can_chan_impl_dev_vtbl;
258 impl->
chan_vptr = &io_can_chan_impl_vtbl;
268 &io_can_chan_impl_watch_func);
271 impl->
exec, &io_can_chan_impl_rxbuf_task_func);
273 impl->
exec, &io_can_chan_impl_read_task_func);
275 impl->
exec, &io_can_chan_impl_write_task_func);
278 if ((errsv = pthread_mutex_init(&impl->
c_mtx, NULL)))
279 goto error_init_c_mtx;
286 goto error_alloc_rxbuf;
290 if ((errsv = pthread_mutex_init(&impl->
mtx, NULL)))
320 pthread_mutex_destroy(&impl->
c_mtx);
335 io_can_chan_impl_svc_shutdown(&impl->
svc);
339 pthread_mutex_lock(&impl->
c_mtx);
341 pthread_mutex_unlock(&impl->
c_mtx);
344 pthread_mutex_lock(&impl->
mtx);
349 if (io_can_chan_impl_do_abort_tasks(impl))
351 pthread_mutex_unlock(&impl->
mtx);
355 "io_can_chan_fini() invoked with pending operations");
358 pthread_mutex_lock(&impl->
mtx);
360 pthread_mutex_unlock(&impl->
mtx);
364 if (impl->
fd != -1) {
371 pthread_mutex_destroy(&impl->
mtx);
377 pthread_mutex_destroy(&impl->
c_mtx);
402 io_can_chan_free((
void *)chan);
412 io_can_chan_fini(chan);
413 io_can_chan_free((
void *)chan);
423 pthread_mutex_lock((pthread_mutex_t *)&impl->
mtx);
427 pthread_mutex_unlock((pthread_mutex_t *)&impl->
mtx);
444 int fd = socket(AF_CAN, SOCK_RAW | SOCK_CLOEXEC, CAN_RAW);
450 struct sockaddr_can addr = { .can_family = AF_CAN,
453 if (bind(fd, (
struct sockaddr *)&addr,
sizeof(addr)) == -1) {
459 can_err_mask_t optval = CAN_ERR_MASK;
461 if (setsockopt(fd, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &optval,
462 sizeof(optval)) == -1) {
465 goto error_setsockopt;
473 if (setsockopt(fd, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &optval,
474 sizeof(optval)) == -1) {
477 goto error_setsockopt;
482 if (io_can_fd_set_default(fd) == -1) {
484 goto error_set_default;
487 fd = io_can_chan_impl_set_fd(impl, fd, flags);
507 struct sockaddr_can addr = { .can_family = AF_UNSPEC };
508 socklen_t addrlen =
sizeof(addr);
509 if (getsockname(fd, (
struct sockaddr *)&addr, &addrlen) == -1)
511 if (addrlen <
sizeof(addr) || addr.can_family != AF_CAN) {
515 unsigned int ifindex = addr.can_ifindex;
518 if (io_can_attr_get(&attr, ifindex) == -1)
520 int flags = attr.flags;
523 can_err_mask_t optval = 0;
524 socklen_t optlen =
sizeof(optval);
526 if (getsockopt(fd, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &optval,
530 if (optval & CAN_ERR_MASK)
540 socklen_t optlen =
sizeof(optval);
542 if (!getsockopt(fd, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &optval,
550 if (io_can_fd_set_default(fd) == -1)
553 fd = io_can_chan_impl_set_fd(impl, fd, flags);
565 return io_can_chan_impl_set_fd(impl, -1, 0);
578 return fd != -1 ? close(
fd) : 0;
582 io_can_fd_set_default(
int fd)
589 if (setsockopt(
fd, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &optval,
590 sizeof(optval)) == -1)
598 if (setsockopt(
fd, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &optval,
599 sizeof(optval)) == -1)
608 if (setsockopt(
fd, SOL_SOCKET, SO_SNDBUF, &optval,
sizeof(optval))
618 io_can_fd_read(
int fd,
struct can_frame *frame,
size_t *pnbytes,
int *pflags,
619 struct timespec *tp,
int timeout)
621 io_can_fd_read(
int fd,
struct canfd_frame *frame,
size_t *pnbytes,
int *pflags,
622 struct timespec *tp,
int timeout)
625 struct iovec iov = { .iov_base = (
void *)frame,
626 .iov_len =
sizeof(*frame) };
627 struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1 };
635 if (result == CAN_MTU)
637 if (result == CAN_MTU || result == CANFD_MTU)
648 *pflags = msg.msg_flags;
651 if (msg.msg_flags & MSG_CONFIRM) {
653 *tp = (
struct timespec){ 0, 0 };
655 struct timeval tv = { 0, 0 };
656 if (ioctl(fd, SIOCGSTAMP, &tv) == -1)
658 tp->tv_sec = tv.tv_sec;
659 tp->tv_nsec = tv.tv_usec * 1000;
668 io_can_fd_write(
int fd,
const struct can_frame *frame,
size_t nbytes,
671 io_can_fd_write(
int fd,
const struct canfd_frame *frame,
size_t nbytes,
675 struct iovec iov = { .iov_base = (
void *)frame, .iov_len = nbytes };
676 struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1 };
682 io_can_fd_write_msg(
int fd,
const struct can_msg *msg,
int timeout)
694 frame.nbytes = CANFD_MTU;
702 frame.nbytes = CAN_MTU;
707 return io_can_fd_write(fd, &frame.frame, frame.nbytes, timeout);
711 io_can_chan_impl_dev_get_ctx(
const io_dev_t *dev)
719 io_can_chan_impl_dev_get_exec(
const io_dev_t *dev)
733 struct sllist read_queue, write_queue, confirm_queue;
739 pthread_mutex_lock(&impl->
mtx);
741 io_can_chan_impl_do_pop(
742 impl, &read_queue, &write_queue, &confirm_queue, task);
749 pthread_mutex_unlock(&impl->
mtx);
752 size_t nread = io_can_chan_read_queue_post(&read_queue, -1, ECANCELED);
753 n = n < SIZE_MAX - nread ? n + nread : SIZE_MAX;
754 size_t nwrite = io_can_chan_write_queue_post(&write_queue, ECANCELED);
755 n = n < SIZE_MAX - nwrite ? n + nwrite : SIZE_MAX;
757 io_can_chan_write_queue_post(&confirm_queue, ECANCELED);
758 n = n < SIZE_MAX - nconfirm ? n + nconfirm : SIZE_MAX;
772 pthread_mutex_lock(&impl->
mtx);
774 io_can_chan_impl_do_pop(impl, &queue, &queue, &queue, task);
776 pthread_mutex_unlock(&impl->
mtx);
795 pthread_mutex_lock((pthread_mutex_t *)&impl->
mtx);
799 pthread_mutex_unlock((pthread_mutex_t *)&impl->
mtx);
806 struct can_err *err,
struct timespec *tp,
int timeout)
813 pthread_mutex_lock(&impl->
c_mtx);
821 frame = &impl->
rxbuf[i];
825 pthread_mutex_unlock(&impl->
c_mtx);
826 pthread_mutex_lock(&impl->
mtx);
831 pthread_mutex_unlock(&impl->
mtx);
835 if (io_can_fd_read(fd, &frame->frame, &frame->nbytes, &flags,
836 &frame->ts, timeout) < 0)
840 if (!(flags & MSG_CONFIRM))
843 void *src = &frame->frame;
846 if (frame->nbytes == CANFD_MTU)
855 pthread_mutex_lock(&impl->
mtx);
857 io_can_chan_impl_do_confirm(impl, &queue, &msg);
859 pthread_mutex_unlock(&impl->
mtx);
867 pthread_mutex_lock(&impl->
c_mtx);
871 void *data = &frame->frame;
872 int is_err = can_frame2can_err(data, err);
873 if (!is_err && msg) {
875 if (frame->nbytes == CANFD_MTU)
887 pthread_mutex_unlock(&impl->
c_mtx);
891 return is_err == -1 ? -1 : !is_err;
907 pthread_mutex_lock(&impl->
mtx);
911 pthread_mutex_unlock(&impl->
mtx);
913 io_can_chan_read_post(read, -1, ECANCELED);
921 pthread_mutex_unlock(&impl->
mtx);
930 io_can_chan_impl_write(
944 pthread_mutex_lock(&impl->
mtx);
949 pthread_mutex_unlock(&impl->
mtx);
957 pthread_mutex_unlock(&impl->
mtx);
960 return io_can_fd_write_msg(
fd, msg, timeout);
964 io_can_chan_impl_submit_write(
986 pthread_mutex_lock(&impl->
mtx);
990 pthread_mutex_unlock(&impl->
mtx);
992 io_can_chan_write_post(write, ECANCELED);
994 }
else if ((flags & impl->
flags) != flags) {
996 pthread_mutex_unlock(&impl->
mtx);
998 io_can_chan_write_post(write, EINVAL);
1006 #if !LELY_NO_THREADS
1007 pthread_mutex_unlock(&impl->
mtx);
1016 io_can_chan_impl_svc_shutdown(
struct io_svc *svc)
1021 #if !LELY_NO_THREADS
1022 pthread_mutex_lock(&impl->
mtx);
1036 io_can_chan_impl_do_abort_tasks(impl);
1038 #if !LELY_NO_THREADS
1039 pthread_mutex_unlock(&impl->
mtx);
1044 io_can_chan_impl_dev_cancel(dev, NULL);
1054 #if !LELY_NO_THREADS
1055 pthread_mutex_lock(&impl->
mtx);
1064 &impl->
watch) == -1) {
1087 #if !LELY_NO_THREADS
1088 pthread_mutex_unlock(&impl->
mtx);
1098 io_can_chan_impl_rxbuf_task_func(
struct ev_task *task)
1113 #if !LELY_NO_THREADS
1114 pthread_mutex_lock(&impl->
mtx);
1125 #if !LELY_NO_THREADS
1126 pthread_mutex_unlock(&impl->
mtx);
1135 frame = &impl->
rxbuf[i];
1139 result = io_can_fd_read(fd, &frame->frame, &frame->nbytes,
1142 errc = !result ? 0 : errno;
1143 wouldblock = errc == EAGAIN || errc == EWOULDBLOCK;
1148 if (!result && (
flags & MSG_CONFIRM)) {
1149 void *src = &frame->frame;
1151 if (frame->nbytes == CANFD_MTU)
1159 if (!result && !(
flags & MSG_CONFIRM))
1162 #if !LELY_NO_THREADS
1163 pthread_mutex_lock(&impl->
mtx);
1166 if (!result &&
flags & MSG_CONFIRM)
1167 io_can_chan_impl_do_confirm(impl, &queue, &msg);
1171 if (!impl->
poll || result < 0)
1175 if (result < 0 && !wouldblock) {
1176 io_can_chan_impl_do_read(impl, &queue, NULL);
1182 read->
r.
errc = errc;
1193 if (post_rxbuf && impl->
poll && wouldblock) {
1206 #if !LELY_NO_THREADS
1207 pthread_mutex_unlock(&impl->
mtx);
1219 io_can_chan_impl_read_task_func(
struct ev_task *
task)
1228 #if !LELY_NO_THREADS
1229 pthread_mutex_lock(&impl->
mtx);
1233 io_can_chan_impl_do_read(impl, &queue, &wouldblock);
1238 if (post_read && wouldblock) {
1239 #if !LELY_NO_THREADS
1240 pthread_mutex_lock(&impl->
c_mtx);
1245 io_can_chan_impl_c_signal, impl);
1246 #if !LELY_NO_THREADS
1247 pthread_mutex_unlock(&impl->
c_mtx);
1260 #if !LELY_NO_THREADS
1261 pthread_mutex_unlock(&impl->
mtx);
1275 io_can_chan_impl_write_task_func(
struct ev_task *task)
1285 #if !LELY_NO_THREADS
1286 pthread_mutex_lock(&impl->
mtx);
1293 #if !LELY_NO_THREADS
1294 pthread_mutex_unlock(&impl->
mtx);
1298 int result = io_can_fd_write_msg(fd, write->
msg,
1300 int errc = !result ? 0 : errno;
1301 wouldblock =
errc == EAGAIN ||
errc == EWOULDBLOCK;
1302 if (!wouldblock &&
errc)
1304 io_can_chan_write_post(write,
errc);
1305 #if !LELY_NO_THREADS
1306 pthread_mutex_lock(&impl->
mtx);
1323 if (!impl->
poll || wouldblock)
1339 if (post_write && impl->
poll && wouldblock) {
1352 #if !LELY_NO_THREADS
1353 pthread_mutex_unlock(&impl->
mtx);
1356 if (
task && wouldblock)
1359 io_can_chan_write_post(
1372 io_can_chan_impl_from_dev(
const io_dev_t *dev)
1388 io_can_chan_impl_from_svc(
const struct io_svc *
svc)
1396 io_can_chan_impl_c_signal(
struct spscring *ring,
void *arg)
1402 #if !LELY_NO_THREADS
1403 pthread_mutex_lock(&impl->
mtx);
1409 #if !LELY_NO_THREADS
1410 pthread_mutex_unlock(&impl->
mtx);
1457 #if !LELY_NO_THREADS
1458 pthread_mutex_lock(&impl->
c_mtx);
1465 #if !LELY_NO_THREADS
1466 pthread_mutex_unlock(&impl->
c_mtx);
1474 void *data = &frame->frame;
1475 int is_err = can_frame2can_err(data, read->
err);
1476 if (!is_err && read->
msg) {
1478 if (frame->nbytes == CANFD_MTU)
1485 *read->
tp = frame->ts;
1488 #if !LELY_NO_THREADS
1489 pthread_mutex_unlock(&impl->
c_mtx);
1500 *pwouldblock = wouldblock;
1533 if (&
task->_node == node) {
1583 assert(!(flags & ~IO_CAN_BUS_FLAG_MASK));
1585 struct sllist read_queue, write_queue, confirm_queue;
1590 #if !LELY_NO_THREADS
1591 pthread_mutex_lock(&impl->
mtx);
1600 #if !LELY_NO_THREADS
1601 pthread_mutex_lock(&impl->
c_mtx);
1605 size_t n = SIZE_MAX;
1609 #if !LELY_NO_THREADS
1610 pthread_mutex_unlock(&impl->
c_mtx);
1617 impl->
flags = flags;
1627 #if !LELY_NO_THREADS
1628 pthread_mutex_unlock(&impl->
mtx);
1631 io_can_chan_read_queue_post(&read_queue, -1, ECANCELED);
1632 io_can_chan_write_queue_post(&write_queue, ECANCELED);
1633 io_can_chan_write_queue_post(&confirm_queue, ECANCELED);
1638 #endif // !LELY_NO_STDIO && __linux__