Lely core libraries 2.3.4
can_attr.h
Go to the documentation of this file.
1
22#ifndef LELY_IO2_INTERN_LINUX_CAN_ATTR_H_
23#define LELY_IO2_INTERN_LINUX_CAN_ATTR_H_
24
25#include "io.h"
26
27#ifdef __linux__
28
29#include <lely/io2/can.h>
30
31#include <errno.h>
32
33#include <net/if.h>
34
35#include <linux/can.h>
36#if !LELY_NO_CANFD && !defined(CANFD_MTU)
37#error CAN FD not supported.
38#endif
39#define can_state can_state_
40#define CAN_STATE_STOPPED CAN_STATE_STOPPED_
41#define CAN_STATE_SLEEPING CAN_STATE_SLEEPING_
42#include <linux/can/netlink.h>
43#undef CAN_STATE_SLEEPING
44#undef CAN_STATE_STOPPED
45#undef can_state
46#include <linux/if_arp.h>
47
48#include "rtnl.h"
49
51 int state;
52 int flags;
53 int nominal;
54#if !LELY_NO_CANFD
55 int data;
56#endif
57};
58
59#if LELY_NO_CANFD
60#define IO_CAN_ATTR_INIT \
61 { \
62 CAN_STATE_ACTIVE, 0, 0 \
63 }
64#else
65#define IO_CAN_ATTR_INIT \
66 { \
67 CAN_STATE_ACTIVE, 0, 0, 0 \
68 }
69#endif
70
71#ifdef __cplusplus
72extern "C" {
73#endif
74
75static int io_can_attr_get(struct io_can_attr *attr, unsigned int ifindex);
76static int io_can_attr_parse(struct nlmsghdr *nlh, size_t len, void *arg);
77
78static inline int
79io_can_attr_get(struct io_can_attr *attr, unsigned int ifindex)
80{
81 int errsv = 0;
82
83 struct rtnl_handle rth = { -1, 0, 0 };
84 if (rtnl_open(&rth) == -1) {
85 errsv = errno;
86 goto error_rtnl_open;
87 }
88
89 if (rtnl_send_getlink_request(&rth, AF_UNSPEC, ARPHRD_CAN, ifindex)
90 == -1) {
91 errsv = errno;
92 goto error_rtnl_send_getlink_request;
93 }
94
95 if (rtnl_recv_type(&rth, RTM_NEWLINK, &io_can_attr_parse, attr) == -1) {
96 errsv = errno;
97 goto error_rtnl_recv_type;
98 }
99
100 rtnl_close(&rth);
101 return 0;
102
103error_rtnl_recv_type:
104error_rtnl_send_getlink_request:
105 rtnl_close(&rth);
106error_rtnl_open:
107 errno = errsv;
108 return -1;
109}
110
111static inline int
112io_can_attr_parse(struct nlmsghdr *nlh, size_t len, void *arg)
113{
114 assert(nlh);
115 assert(NLMSG_OK(nlh, len));
116 assert(nlh->nlmsg_type == RTM_NEWLINK);
117 (void)len;
118 struct io_can_attr *attr = arg;
119 assert(attr);
120
121 struct ifinfomsg *ifi = NLMSG_DATA(nlh);
122 if (ifi->ifi_type != ARPHRD_CAN) {
123 errno = ENODEV;
124 return -1;
125 }
126
127#if !LELY_NO_CANFD
128 struct rtattr *mtu =
129 rta_find(IFLA_RTA(ifi), IFLA_PAYLOAD(nlh), IFLA_MTU);
130 if (mtu && RTA_PAYLOAD(mtu) >= sizeof(unsigned int)) {
131 unsigned int *data = RTA_DATA(mtu);
132 if (*data == CANFD_MTU)
133 attr->flags |= IO_CAN_BUS_FLAG_FDF;
134 else
135 attr->flags &= ~IO_CAN_BUS_FLAG_FDF;
136 }
137#endif
138
139 struct rtattr *linkinfo = rta_find(
140 IFLA_RTA(ifi), IFLA_PAYLOAD(nlh), IFLA_LINKINFO);
141 if (!linkinfo) {
142 errno = EOPNOTSUPP;
143 return -1;
144 }
145
146 struct rtattr *info_data = rta_find(RTA_DATA(linkinfo),
147 RTA_PAYLOAD(linkinfo), IFLA_INFO_DATA);
148 if (info_data) {
149 struct rtattr *rta;
150
151 rta = rta_find(RTA_DATA(info_data), RTA_PAYLOAD(info_data),
152 IFLA_CAN_STATE);
153 if (rta && RTA_PAYLOAD(rta) >= sizeof(int)) {
154 int *data = RTA_DATA(rta);
155 switch (*data) {
156 case CAN_STATE_ERROR_ACTIVE:
157 case CAN_STATE_ERROR_WARNING:
158 attr->state = CAN_STATE_ACTIVE;
159 break;
160 case CAN_STATE_ERROR_PASSIVE:
161 attr->state = CAN_STATE_PASSIVE;
162 break;
163 case CAN_STATE_BUS_OFF:
164 attr->state = CAN_STATE_BUSOFF;
165 break;
166 case CAN_STATE_STOPPED_:
167 attr->state = CAN_STATE_STOPPED;
168 break;
169 case CAN_STATE_SLEEPING_:
170 attr->state = CAN_STATE_SLEEPING;
171 break;
172 }
173 }
174
175#if !LELY_NO_CANFD
176 rta = rta_find(RTA_DATA(info_data), RTA_PAYLOAD(info_data),
177 IFLA_CAN_CTRLMODE);
178 if (rta && RTA_PAYLOAD(rta) >= sizeof(struct can_ctrlmode)) {
179 struct can_ctrlmode *data = RTA_DATA(rta);
180 if (data->flags & CAN_CTRLMODE_FD)
181 attr->flags |= IO_CAN_BUS_FLAG_BRS;
182 else
183 attr->flags &= ~IO_CAN_BUS_FLAG_BRS;
184 }
185#endif
186
187 rta = rta_find(RTA_DATA(info_data), RTA_PAYLOAD(info_data),
188 IFLA_CAN_BITTIMING);
189 if (rta && RTA_PAYLOAD(rta) >= sizeof(struct can_bittiming)) {
190 struct can_bittiming *data = RTA_DATA(rta);
191 attr->nominal = data->bitrate;
192 }
193
194#if !LELY_NO_CANFD
195 rta = rta_find(RTA_DATA(info_data), RTA_PAYLOAD(info_data),
196 IFLA_CAN_DATA_BITTIMING);
197 if (rta && RTA_PAYLOAD(rta) >= sizeof(struct can_bittiming)) {
198 struct can_bittiming *data = RTA_DATA(rta);
199 attr->data = data->bitrate;
200 }
201#endif
202 }
203
204 return 0;
205}
206
207#ifdef __cplusplus
208}
209#endif
210
211#endif // __linux__
212
213#endif // !LELY_IO2_INTERN_LINUX_CAN_ATTR_H_
@ CAN_STATE_BUSOFF
The bus off state (TX/RX error count >= 256).
Definition: err.h:34
@ CAN_STATE_SLEEPING
The device is in sleep mode.
Definition: err.h:36
@ CAN_STATE_PASSIVE
The error passive state (TX/RX error count < 256).
Definition: err.h:32
@ CAN_STATE_STOPPED
The device is stopped.
Definition: err.h:38
@ CAN_STATE_ACTIVE
The error active state (TX/RX error count < 128).
Definition: err.h:30
This header file is part of the I/O library; it contains the abstract CAN bus interface.
@ IO_CAN_BUS_FLAG_BRS
Bit Rate Switch support is enabled.
Definition: can.h:44
@ IO_CAN_BUS_FLAG_FDF
FD Format (formerly Extended Data Length) support is enabled.
Definition: can.h:42
This header file is part of the I/O library; it contains the CAN bus declarations for Linux.
This is the internal header file of the rtnetlink functions.
This is the internal header file of the Windows-specific I/O declarations.