26 #if !defined(LELY_NO_CAN) && defined(__linux__) && defined(HAVE_LINUX_CAN_H)
38 #if defined(__linux__) && defined(HAVE_LINUX_CAN_H)
40 #ifdef HAVE_LINUX_CAN_ERROR_H
41 #include <linux/can/error.h>
43 #ifdef HAVE_LINUX_CAN_NETLINK_H
44 #define can_state can_state_
45 #define CAN_STATE_STOPPED CAN_STATE_STOPPED_
46 #define CAN_STATE_SLEEPING CAN_STATE_SLEEPING_
47 #include <linux/can/netlink.h>
48 #undef CAN_STATE_SLEEPING
49 #undef CAN_STATE_STOPPED
52 #ifdef HAVE_LINUX_CAN_RAW_H
53 #include <linux/can/raw.h>
60 #if !defined(LELY_NO_CANFD) && defined(CANFD_MTU)
80 static void can_fini(
struct io_handle *handle);
82 static ssize_t can_read(
struct io_handle *handle,
void *buf,
size_t nbytes);
83 static ssize_t can_write(
84 struct io_handle *handle,
const void *buf,
size_t nbytes);
87 .size =
sizeof(
struct can),
91 .write = &can_write };
93 static int can_err(
struct can *
can,
const struct can_frame *frame);
95 #if defined(HAVE_LINUX_CAN_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H)
97 static int can_getattr(
int fd, __u32 seq, __u32 pid,
int ifi_index,
98 unsigned int *pifi_flags,
unsigned short type,
void *data,
99 unsigned short payload);
101 static int can_setattr(
int fd, __u32 seq, __u32 pid,
int ifi_index,
102 unsigned int ifi_flags,
unsigned short type,
const void *data,
103 unsigned short payload);
112 int s = socket(AF_CAN, SOCK_RAW | SOCK_CLOEXEC, CAN_RAW);
118 #if !defined(LELY_NO_CANFD) && defined(CANFD_MTU)
120 #ifdef HAVE_CAN_RAW_FD_FRAMES
123 if (!setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &(
int){ 1 },
132 #ifdef HAVE_LINUX_CAN_RAW_H
134 if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_ERR_FILTER,
135 &(can_err_mask_t){ CAN_ERR_MASK },
136 sizeof(can_err_mask_t)) == -1) {
139 goto error_setsockopt;
143 unsigned int ifindex = if_nametoindex(path);
146 goto error_if_nametoindex;
149 struct sockaddr_can addr = { .can_family = AF_CAN,
150 .can_ifindex = ifindex };
152 if (bind(s, (
struct sockaddr *)&addr,
sizeof(addr)) == -1) {
157 #ifdef HAVE_SYS_IOCTL_H
158 #if !defined(LELY_NO_CANFD) && defined(CANFD_MTU)
161 if_indextoname(ifindex, ifr.ifr_name);
162 if (ioctl(s, SIOCGIFMTU, &ifr) == -1) {
166 canfd = ifr.ifr_mtu == CANFD_MTU;
172 if_indextoname(ifindex, ifr.ifr_name);
173 if (ioctl(s, SIOCGIFFLAGS, &ifr) == -1) {
177 ifflags = ifr.ifr_flags;
183 goto error_alloc_handle;
187 #if !defined(LELY_NO_CANFD) && defined(CANFD_MTU)
188 ((
struct can *)handle)->canfd = canfd;
193 ((
struct can *)handle)->error = 0;
198 #ifdef HAVE_SYS_IOCTL_H
202 error_if_nametoindex:
203 #ifdef HAVE_LINUX_CAN_RAW_H
224 if (handle->
vtab != &can_vtab) {
230 #if !defined(LELY_NO_CANFD) && defined(CANFD_MTU)
231 if (((
struct can *)handle)->canfd) {
232 struct canfd_frame frame = { .can_id = 0 };
233 ssize_t nbytes = can_read(handle, &frame,
sizeof(frame));
237 if (nbytes == CANFD_MTU) {
238 if (frame.can_id & CAN_ERR_FLAG)
239 return can_err(
can, (
struct can_frame *)&frame);
243 }
else if (nbytes == CAN_MTU) {
244 if (frame.can_id & CAN_ERR_FLAG)
245 return can_err(
can, (
struct can_frame *)&frame);
256 struct can_frame frame = { .can_id = 0 };
257 ssize_t nbytes = can_read(handle, &frame,
sizeof(frame));
261 if (nbytes == CAN_MTU) {
262 if (frame.can_id & CAN_ERR_FLAG)
282 if (handle->
vtab != &can_vtab) {
287 #if !defined(LELY_NO_CANFD) && defined(CANFD_MTU)
288 if (msg->
flags & CAN_FLAG_EDL) {
289 if (!((
struct can *)handle)->canfd) {
294 struct canfd_frame frame;
297 ssize_t nbytes = can_write(handle, &frame,
sizeof(frame));
301 return nbytes == CANFD_MTU;
304 struct can_frame frame;
307 ssize_t nbytes = can_write(handle, &frame,
sizeof(frame));
311 return nbytes == CAN_MTU;
314 #endif // !LELY_NO_CAN
316 #if defined(HAVE_LINUX_CAN_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H)
326 if (handle->
vtab != &can_vtab) {
358 if (handle->
vtab != &can_vtab) {
382 #endif // HAVE_LINUX_CAN_NETLINK_H && HAVE_LINUX_RTNETLINK_H
392 if (handle->
vtab != &can_vtab) {
398 #if defined(HAVE_LINUX_CAN_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H)
408 &attr,
sizeof(attr)) < (
int)
sizeof(attr)) {
417 case CAN_STATE_ERROR_ACTIVE:
440 if (handle->
vtab != &can_vtab) {
446 *perror = ((
struct can *)handle)->error;
447 ((
struct can *)handle)->error = 0;
452 #if defined(HAVE_LINUX_CAN_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H)
462 if (handle->
vtab != &can_vtab) {
472 struct can_berr_counter attr = { 0 };
475 IFLA_CAN_BERR_COUNTER, &attr,
sizeof(attr))
476 < (
int)
sizeof(attr)) {
502 if (handle->
vtab != &can_vtab) {
512 struct can_bittiming attr = { 0 };
515 IFLA_CAN_BITTIMING, &attr,
sizeof(attr))
516 < (
int)
sizeof(attr)) {
527 *pbitrate = attr.bitrate;
543 if (handle->
vtab != &can_vtab) {
565 struct can_bittiming attr = { .bitrate = bitrate };
568 IFLA_CAN_BITTIMING, &attr,
sizeof(attr)) == -1) {
593 if (handle->
vtab != &can_vtab) {
606 &attr,
sizeof(attr)) < (
int)
sizeof(attr)) {
630 if (handle->
vtab != &can_vtab) {
643 &attr,
sizeof(attr)) == -1) {
654 #endif // HAVE_LINUX_CAN_NETLINK_H && HAVE_LINUX_RTNETLINK_H
666 can_flags(
struct io_handle *handle,
int flags)
670 int arg = fcntl(handle->
fd, F_GETFL, 0);
677 if (fcntl(handle->
fd, F_SETFL, arg | O_NONBLOCK) == -1) {
682 if (fcntl(handle->
fd, F_SETFL, arg & ~O_NONBLOCK) == -1) {
690 if (setsockopt(handle->
fd, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,
691 (
const char *)&optval,
sizeof(optval)) == -1) {
694 goto error_setsockopt;
700 fcntl(handle->
fd, F_SETFL, arg);
707 can_read(
struct io_handle *handle,
void *buf,
size_t nbytes)
715 result = read(handle->
fd, buf, nbytes);
716 }
while (result == -1 && errno == EINTR);
721 can_write(
struct io_handle *handle,
const void *buf,
size_t nbytes)
729 result = write(handle->
fd, buf, nbytes);
730 }
while (result == -1 && errno == EINTR);
739 assert(frame->can_id & CAN_ERR_FLAG);
741 #ifdef HAVE_LINUX_CAN_ERROR_H
742 if (frame->can_dlc != CAN_ERR_DLC)
749 #ifdef HAVE_LINUX_CAN_ERROR_H
750 if (frame->can_id & CAN_ERR_RESTARTED)
753 if (frame->can_id & CAN_ERR_CRTL) {
754 #ifdef CAN_ERR_CRTL_ACTIVE
755 if (frame->data[1] & CAN_ERR_CRTL_ACTIVE)
759 if (frame->data[1] & (CAN_ERR_CRTL_RX_PASSIVE
760 | CAN_ERR_CRTL_TX_PASSIVE))
765 if (frame->can_id & CAN_ERR_PROT) {
766 if (frame->data[2] & CAN_ERR_PROT_BIT)
768 if (frame->data[2] & CAN_ERR_PROT_FORM)
770 if (frame->data[2] & CAN_ERR_PROT_STUFF)
772 if (frame->data[3] & CAN_ERR_PROT_LOC_CRC_SEQ)
776 if (frame->can_id & CAN_ERR_ACK)
779 if (frame->can_id & CAN_ERR_BUSOFF)
794 #if defined(HAVE_LINUX_CAN_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H)
797 can_getattr(
int fd, __u32 seq, __u32 pid,
int ifi_index,
798 unsigned int *pifi_flags,
unsigned short type,
void *data,
799 unsigned short payload)
801 assert(data || !payload);
806 IFLA_LINKINFO, buf,
sizeof(buf));
811 io_rta_find((
struct rtattr *)buf, len, IFLA_INFO_DATA);
813 rta =
io_rta_find(RTA_DATA(rta), RTA_PAYLOAD(rta), type);
819 len = RTA_PAYLOAD(rta);
821 memcpy(data, RTA_DATA(rta),
MIN(payload, len));
826 can_setattr(
int fd, __u32 seq, __u32 pid,
int ifi_index,
unsigned int ifi_flags,
827 unsigned short type,
const void *data,
unsigned short payload)
829 assert(data || !payload);
834 const char *kind =
"can";
835 struct rtattr *info_kind = (
struct rtattr *)buf;
836 *info_kind = (
struct rtattr){ .rta_len = RTA_LENGTH(strlen(kind)),
837 .rta_type = IFLA_INFO_KIND };
838 memcpy(RTA_DATA(info_kind), kind, strlen(kind));
840 len += RTA_ALIGN(info_kind->rta_len);
842 struct rtattr *info_data =
RTA_TAIL(info_kind);
843 *info_data = (
struct rtattr){ .rta_len = RTA_LENGTH(0),
844 .rta_type = IFLA_INFO_DATA };
847 struct rtattr *rta = RTA_DATA(info_data);
848 *rta = (
struct rtattr){ .rta_len = RTA_LENGTH(payload),
850 memcpy(RTA_DATA(rta), data, payload);
852 info_data->rta_len += RTA_ALIGN(rta->rta_len);
855 len += RTA_ALIGN(info_data->rta_len);
858 IFLA_LINKINFO, buf, len);
861 #endif // HAVE_LINUX_CAN_NETLINK_H && HAVE_LINUX_RTNETLINK_H
863 #endif // __linux__ && HAVE_LINUX_CAN_H