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 
50 struct io_can_attr {
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
72 extern "C" {
73 #endif
74 
75 static int io_can_attr_get(struct io_can_attr *attr, unsigned int ifindex);
76 static int io_can_attr_parse(struct nlmsghdr *nlh, size_t len, void *arg);
77 
78 static inline int
79 io_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 
103 error_rtnl_recv_type:
104 error_rtnl_send_getlink_request:
105  rtnl_close(&rth);
106 error_rtnl_open:
107  errno = errsv;
108  return -1;
109 }
110 
111 static inline int
112 io_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_
rtnl.h
CAN_STATE_BUSOFF
@ CAN_STATE_BUSOFF
The bus off state (TX/RX error count >= 256).
Definition: err.h:34
CAN_STATE_ACTIVE
@ CAN_STATE_ACTIVE
The error active state (TX/RX error count < 128).
Definition: err.h:30
CAN_STATE_PASSIVE
@ CAN_STATE_PASSIVE
The error passive state (TX/RX error count < 256).
Definition: err.h:32
rtnl_handle
Definition: rtnl.h:47
IO_CAN_BUS_FLAG_FDF
@ IO_CAN_BUS_FLAG_FDF
FD Format (formerly Extended Data Length) support is enabled.
Definition: can.h:42
io.h
io_can_attr
Definition: can_attr.h:50
CAN_STATE_STOPPED
@ CAN_STATE_STOPPED
The device is stopped.
Definition: err.h:38
can.h
IO_CAN_BUS_FLAG_BRS
@ IO_CAN_BUS_FLAG_BRS
Bit Rate Switch support is enabled.
Definition: can.h:44
CAN_STATE_SLEEPING
@ CAN_STATE_SLEEPING
The device is in sleep mode.
Definition: err.h:36
can.h