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#include <linux/can/netlink.h>
48#ifdef HAVE_LINUX_CAN_RAW_H
49#include <linux/can/raw.h>
56#if !defined(LELY_NO_CANFD) && defined(CANFD_MTU)
76static void can_fini(
struct io_handle *handle);
80 struct io_handle *handle,
const void *buf,
size_t nbytes);
83 .size =
sizeof(
struct can),
87 .write = &can_write };
89static int can_err(
struct can *
can,
const struct can_frame *frame);
91#if defined(HAVE_LINUX_CAN_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H)
93static int can_getattr(
int fd, __u32 seq, __u32 pid,
int ifi_index,
94 unsigned int *pifi_flags,
unsigned short type,
void *data,
95 unsigned short payload);
97static int can_setattr(
int fd, __u32 seq, __u32 pid,
int ifi_index,
98 unsigned int ifi_flags,
unsigned short type,
const void *data,
99 unsigned short payload);
108 int s = socket(AF_CAN, SOCK_RAW | SOCK_CLOEXEC, CAN_RAW);
114#if !defined(LELY_NO_CANFD) && defined(CANFD_MTU)
116#ifdef HAVE_CAN_RAW_FD_FRAMES
119 if (
__likely(!setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &(
int){ 1 },
128#ifdef HAVE_LINUX_CAN_RAW_H
130 if (
__unlikely(setsockopt(s, SOL_CAN_RAW, CAN_RAW_ERR_FILTER,
131 &(can_err_mask_t){ CAN_ERR_MASK },
132 sizeof(can_err_mask_t)) == -1)) {
135 goto error_setsockopt;
139 unsigned int ifindex = if_nametoindex(path);
142 goto error_if_nametoindex;
145 struct sockaddr_can addr = { .can_family = AF_CAN,
146 .can_ifindex = ifindex };
148 if (
__unlikely(bind(s, (
struct sockaddr *)&addr,
sizeof(addr)) == -1)) {
153#ifdef HAVE_SYS_IOCTL_H
154#if !defined(LELY_NO_CANFD) && defined(CANFD_MTU)
157 if_indextoname(ifindex, ifr.ifr_name);
158 if (
__unlikely(ioctl(s, SIOCGIFMTU, &ifr) == -1)) {
162 canfd = ifr.ifr_mtu == CANFD_MTU;
168 if_indextoname(ifindex, ifr.ifr_name);
169 if (
__unlikely(ioctl(s, SIOCGIFFLAGS, &ifr) == -1)) {
173 ifflags = ifr.ifr_flags;
179 goto error_alloc_handle;
183#if !defined(LELY_NO_CANFD) && defined(CANFD_MTU)
184 ((
struct can *)handle)->canfd = canfd;
189 ((
struct can *)handle)->error = 0;
194#ifdef HAVE_SYS_IOCTL_H
199#ifdef HAVE_LINUX_CAN_RAW_H
226#if !defined(LELY_NO_CANFD) && defined(CANFD_MTU)
227 if (((
struct can *)handle)->canfd) {
228 struct canfd_frame frame;
229 ssize_t nbytes = can_read(handle, &frame,
sizeof(frame));
233 if (nbytes == CANFD_MTU) {
235 return can_err(
can, (
struct can_frame *)&frame);
239 }
else if (nbytes == CAN_MTU) {
241 return can_err(
can, (
struct can_frame *)&frame);
244 (
struct can_frame *)&frame, msg) == -1))
254 struct can_frame frame;
255 ssize_t nbytes = can_read(handle, &frame,
sizeof(frame));
259 if (nbytes == CAN_MTU) {
261 return can_err(
can, &frame);
285#if !defined(LELY_NO_CANFD) && defined(CANFD_MTU)
292 struct canfd_frame frame;
295 ssize_t nbytes = can_write(handle, &frame,
sizeof(frame));
299 return nbytes == CANFD_MTU;
302 struct can_frame frame;
305 ssize_t nbytes = can_write(handle, &frame,
sizeof(frame));
309 return nbytes == CAN_MTU;
314#if defined(HAVE_LINUX_CAN_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H)
396#if defined(HAVE_LINUX_CAN_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H)
406 IFLA_CAN_STATE, &attr,
sizeof(attr))
407 < (
int)
sizeof(attr))) {
416 case CAN_STATE_ERROR_ACTIVE:
445 *perror = ((
struct can *)handle)->error;
446 ((
struct can *)handle)->error = 0;
451#if defined(HAVE_LINUX_CAN_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H)
471 struct can_berr_counter attr = { 0 };
474 IFLA_CAN_BERR_COUNTER, &attr,
sizeof(attr))
475 < (
int)
sizeof(attr))) {
511 struct can_bittiming attr = { 0 };
514 IFLA_CAN_BITTIMING, &attr,
sizeof(attr))
515 < (
int)
sizeof(attr))) {
526 *pbitrate = attr.bitrate;
564 struct can_bittiming attr = { .bitrate = bitrate };
567 IFLA_CAN_BITTIMING, &attr,
sizeof(attr)) == -1)) {
605 IFLA_TXQLEN, &attr,
sizeof(attr))
606 < (
int)
sizeof(attr))) {
643 IFLA_TXQLEN, &attr,
sizeof(attr)) == -1)) {
666can_flags(
struct io_handle *handle,
int flags)
670 int arg = fcntl(handle->
fd, F_GETFL, 0);
678 if (
__unlikely(fcntl(handle->
fd, F_SETFL, arg | O_NONBLOCK)
686 if (
__unlikely(fcntl(handle->
fd, F_SETFL, arg & ~O_NONBLOCK)
697 CAN_RAW_RECV_OWN_MSGS, (
const char *)&optval,
698 sizeof(optval)) == -1)) {
701 goto error_setsockopt;
707 fcntl(handle->
fd, F_SETFL, arg);
714can_read(
struct io_handle *handle,
void *buf,
size_t nbytes)
722 result = read(handle->
fd, buf, nbytes);
723 }
while (
__unlikely(result == -1 && errno == EINTR));
728can_write(
struct io_handle *handle,
const void *buf,
size_t nbytes)
736 result = write(handle->
fd, buf, nbytes);
737 }
while (
__unlikely(result == -1 && errno == EINTR));
742can_err(
struct can *
can,
const struct can_frame *frame)
746 assert(frame->can_id & CAN_ERR_FLAG);
748#ifdef HAVE_LINUX_CAN_ERROR_H
749 if (
__unlikely(frame->can_dlc != CAN_ERR_DLC))
756#ifdef HAVE_LINUX_CAN_ERROR_H
757 if (frame->can_id & CAN_ERR_RESTARTED)
760 if (frame->can_id & CAN_ERR_CRTL) {
761#ifdef CAN_ERR_CRTL_ACTIVE
762 if (frame->data[1] & CAN_ERR_CRTL_ACTIVE)
766 if (frame->data[1] & (CAN_ERR_CRTL_RX_PASSIVE
767 | CAN_ERR_CRTL_TX_PASSIVE))
772 if (frame->can_id & CAN_ERR_PROT) {
773 if (frame->data[2] & CAN_ERR_PROT_BIT)
774 error |= CAN_ERROR_BIT;
775 if (frame->data[2] & CAN_ERR_PROT_FORM)
776 error |= CAN_ERROR_FORM;
777 if (frame->data[2] & CAN_ERR_PROT_STUFF)
778 error |= CAN_ERROR_STUFF;
779 if (frame->data[3] & CAN_ERR_PROT_LOC_CRC_SEQ)
780 error |= CAN_ERROR_CRC;
783 if (frame->can_id & CAN_ERR_ACK)
784 error |= CAN_ERROR_ACK;
786 if (frame->can_id & CAN_ERR_BUSOFF)
801#if defined(HAVE_LINUX_CAN_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H)
804can_getattr(
int fd, __u32 seq, __u32 pid,
int ifi_index,
805 unsigned int *pifi_flags,
unsigned short type,
void *data,
806 unsigned short payload)
808 assert(data || !payload);
813 IFLA_LINKINFO, buf,
sizeof(buf));
818 io_rta_find((
struct rtattr *)buf, len, IFLA_INFO_DATA);
820 rta =
io_rta_find(RTA_DATA(rta), RTA_PAYLOAD(rta), type);
826 len = RTA_PAYLOAD(rta);
828 memcpy(data, RTA_DATA(rta),
MIN(payload, len));
833can_setattr(
int fd, __u32 seq, __u32 pid,
int ifi_index,
unsigned int ifi_flags,
834 unsigned short type,
const void *data,
unsigned short payload)
836 assert(data || !payload);
841 const char *kind =
"can";
842 struct rtattr *info_kind = (
struct rtattr *)buf;
843 *info_kind = (
struct rtattr){ .rta_len = RTA_LENGTH(strlen(kind)),
844 .rta_type = IFLA_INFO_KIND };
845 memcpy(RTA_DATA(info_kind), kind, strlen(kind));
847 len += RTA_ALIGN(info_kind->rta_len);
849 struct rtattr *info_data =
RTA_TAIL(info_kind);
850 *info_data = (
struct rtattr){ .rta_len = RTA_LENGTH(0),
851 .rta_type = IFLA_INFO_DATA };
854 struct rtattr *rta = RTA_DATA(info_data);
855 *rta = (
struct rtattr){ .rta_len = RTA_LENGTH(payload),
857 memcpy(RTA_DATA(rta), data, payload);
859 info_data->rta_len += RTA_ALIGN(rta->rta_len);
862 len += RTA_ALIGN(info_data->rta_len);
865 IFLA_LINKINFO, buf, len);
int io_can_get_error(io_handle_t handle, int *perror)
Obtains and clears the current error number of a CAN device, and stores the value (any combination of...
int io_can_set_txqlen(io_handle_t handle, size_t txqlen)
Sets the length of the transmission queue (in number of CAN frames) of a CAN device.
int io_can_stop(io_handle_t handle)
Stops transmission and reception on a CAN device.
int io_can_write(io_handle_t handle, const struct can_msg *msg)
Writes a single CAN or CAN FD frame.
int io_can_get_txqlen(io_handle_t handle, size_t *ptxqlen)
Obtains the length of the transmission queue (in number of CAN frames) of a CAN device and stores the...
io_handle_t io_open_can(const char *path)
Opens a CAN device.
int io_can_read(io_handle_t handle, struct can_msg *msg)
Reads a single CAN or CAN FD frame.
int io_can_get_ec(io_handle_t handle, uint16_t *ptxec, uint16_t *prxec)
Obtains the transmit and/or receive error count of a CAN device and stores the value in *ptxec and/or...
int io_can_start(io_handle_t handle)
Starts transmission and reception on a CAN device.
int io_can_set_bitrate(io_handle_t handle, uint32_t bitrate)
Sets the bitrate (in bit/s) of a CAN device.
int io_can_get_state(io_handle_t handle)
Obtains the state of a CAN device.
int io_can_get_bitrate(io_handle_t handle, uint32_t *pbitrate)
Obtains the bitrate (in bit/s) of a CAN device and stores the value in *pbitrate.
This header file is part of the utilities library; it contains the native and platform-independent er...
#define __unlikely(x)
Indicates to the compiler that the expression is most-likely false.
#define __likely(x)
Indicates to the compiler that the expression is most-likely true.
struct io_handle * io_handle_alloc(const struct io_handle_vtab *vtab)
Allocates a new I/O device handle from a virtual table.
This is the internal header file of the I/O handle declarations.
@ CAN_STATE_BUSOFF
The bus off state (TX/RX error count >= 256).
@ CAN_STATE_PASSIVE
The error passive state (TX/RX error count < 256).
@ CAN_STATE_ACTIVE
The error active state (TX/RX error count < 128).
This header file is part of the I/O library; it contains the Controller Area Network (CAN) declaratio...
@ IO_TYPE_CAN
A CAN device.
io_handle_t io_handle_acquire(io_handle_t handle)
Increments the reference count of an I/O device handle.
#define IO_HANDLE_ERROR
The value of an invalid I/O device handle.
@ IO_FLAG_NONBLOCK
Perform I/O operations in non-blocking mode.
@ IO_FLAG_LOOPBACK
Receive own messages (i.e., sent by the same device).
@ IO_FLAG_NO_CLOSE
Do not close the native file descriptor when closing an I/O device.
#define MIN(a, b)
Returns the minimum of a and b.
#define CAN_FLAG_EDL
The Extended Data Length (EDL) flag.
int io_rtnl_getattr(int fd, __u32 seq, __u32 pid, int ifi_index, unsigned int *pifi_flags, unsigned short type, void *data, unsigned short payload)
Invokes io_rtnl_getlink() and retrieves a single attribute of the specified network interface.
int io_rtnl_socket(__u32 pid, __u32 groups)
Opens an rtnetlink socket.
int io_rtnl_newlink(int fd, __u32 seq, __u32 pid, int ifi_index, unsigned int ifi_flags, struct rtattr *rta, unsigned short rtalen)
Sends an RTM_NEWLINK request and waits until the acknowledgment is received.
int io_rtnl_setattr(int fd, __u32 seq, __u32 pid, int ifi_index, unsigned int ifi_flags, unsigned short type, const void *data, unsigned short payload)
Invokes io_rtnl_newlink() to set at most one attribute of the specified network interface.
This is the internal header file of the rtnetlink declarations.
#define RTA_TAIL(rta)
Returns the address of the next attribute.
static struct rtattr * io_rta_find(struct rtattr *rta, unsigned short len, unsigned short type)
Finds an attribute in a list of attributes.
This header file is part of the CAN library; it contains the SocketCAN interface declarations.
int can_frame2can_msg(const struct can_frame *src, struct can_msg *dst)
Converts a SocketCAN CAN frame to a can_msg frame.
int can_msg2canfd_frame(const struct can_msg *src, struct canfd_frame *dst)
Converts a can_msg frame to a SocketCAN CAN FD frame.
int canfd_frame2can_msg(const struct canfd_frame *src, struct can_msg *dst)
Converts a SocketCAN CAN FD frame to a can_msg frame.
int can_msg2can_frame(const struct can_msg *src, struct can_frame *dst)
Converts a can_msg frame to a SocketCAN CAN frame.
This is the internal header file of the I/O library.
This header file is part of the C11 and POSIX compatibility library; it includes <string....
A CAN or CAN FD format frame.
uint_least8_t flags
The flags (any combination of CAN_FLAG_IDE, CAN_FLAG_RTR, CAN_FLAG_EDL, CAN_FLAG_BRS and CAN_FLAG_ESI...
struct io_handle base
The I/O device base handle.
int error
The last error (any combination of CAN_ERROR_BIT, CAN_ERROR_STUFF, CAN_ERROR_CRC, CAN_ERROR_FORM and ...
int state
The state of the CAN controller (one of CAN_STATE_ACTIVE, CAN_STATE_PASSIVE or CAN_STATE_BUSOFF).
unsigned int ifflags
The active flag word of the device.
unsigned int ifindex
The interface index.
The virtual table of an I/O device handle.
int type
The type of the device (one of IO_TYPE_CAN, IO_TYPE_FILE, IO_TYPE_PIPE, IO_TYPE_SERIAL or IO_TYPE_SOC...
int fd
The native file descriptor.
int flags
The I/O device flags (any combination of IO_FLAG_NO_CLOSE and IO_FLAG_NONBLOCK).
const struct io_handle_vtab * vtab
A pointer to the virtual table.
ptrdiff_t ssize_t
Used for a count of bytes or an error indication.