Lely core libraries 1.9.2
socket.c
Go to the documentation of this file.
1
24#include "can.h"
25
26#ifdef LELY_HAVE_SOCKET_CAN
27
28#include <lely/can/socket.h>
29#include <lely/util/errnum.h>
30#include <lely/util/util.h>
31
32#include <assert.h>
33#include <string.h>
34
35#ifdef HAVE_LINUX_CAN_H
36#include <linux/can.h>
37#endif
38#ifdef HAVE_LINUX_CAN_ERROR_H
39#include <linux/can/error.h>
40#endif
41
42int
43can_frame_is_error(const struct can_frame *frame, enum can_state *pstate,
44 enum can_error *perror)
45{
46 assert(frame);
47
48 if (!(frame->can_id & CAN_ERR_FLAG))
49 return 0;
50
51 enum can_state state = pstate ? *pstate : CAN_STATE_ACTIVE;
52 enum can_error error = perror ? *perror : 0;
53
54#ifdef HAVE_LINUX_CAN_ERROR_H
55 if (frame->can_dlc != CAN_ERR_DLC) {
57 return -1;
58 }
59
60 if (frame->can_id & CAN_ERR_RESTARTED)
61 state = CAN_STATE_ACTIVE;
62
63 if (frame->can_id & CAN_ERR_TX_TIMEOUT)
64 error |= CAN_ERROR_OTHER;
65
66 if (frame->can_id & CAN_ERR_CRTL) {
67#ifdef CAN_ERR_CRTL_ACTIVE
68 if (frame->data[1] & CAN_ERR_CRTL_ACTIVE)
69 state = CAN_STATE_ACTIVE;
70#endif
71 // clang-format off
72 if (frame->data[1] & (CAN_ERR_CRTL_RX_PASSIVE
73 | CAN_ERR_CRTL_TX_PASSIVE))
74 // clang-format on
75 state = CAN_STATE_PASSIVE;
76 }
77
78 if (frame->can_id & CAN_ERR_PROT) {
79 if (frame->data[2] & CAN_ERR_PROT_BIT)
80 error |= CAN_ERROR_BIT;
81 if (frame->data[2] & CAN_ERR_PROT_FORM)
82 error |= CAN_ERROR_FORM;
83 if (frame->data[2] & CAN_ERR_PROT_STUFF)
84 error |= CAN_ERROR_STUFF;
85 // clang-format off
86 if (frame->data[2] & (CAN_ERR_PROT_BIT0 | CAN_ERR_PROT_BIT1
87 | CAN_ERR_PROT_OVERLOAD))
88 // clang-format on
89 error |= CAN_ERROR_OTHER;
90 if (frame->data[2] & CAN_ERR_PROT_ACTIVE)
91 state = CAN_STATE_ACTIVE;
92 if (frame->data[3] & CAN_ERR_PROT_LOC_CRC_SEQ)
93 error |= CAN_ERROR_CRC;
94 }
95
96 if ((frame->can_id & CAN_ERR_TRX) && frame->data[4])
97 error |= CAN_ERROR_OTHER;
98
99 if (frame->can_id & CAN_ERR_ACK)
100 error |= CAN_ERROR_ACK;
101
102 if (frame->can_id & CAN_ERR_BUSOFF)
103 state = CAN_STATE_BUSOFF;
104#endif // HAVE_LINUX_CAN_ERROR_H
105
106 if (pstate)
107 *pstate = state;
108
109 if (perror)
110 *perror = error;
111
112 return 1;
113}
114
115int
116can_frame2can_msg(const struct can_frame *src, struct can_msg *dst)
117{
118 assert(src);
119 assert(dst);
120
121 if (src->can_id & CAN_ERR_FLAG) {
123 return -1;
124 }
125
126 memset(dst, 0, sizeof(*dst));
127 dst->flags = 0;
128 if (src->can_id & CAN_EFF_FLAG) {
129 dst->id = src->can_id & CAN_EFF_MASK;
130 dst->flags |= CAN_FLAG_IDE;
131 } else {
132 dst->id = src->can_id & CAN_SFF_MASK;
133 }
134 if (src->can_id & CAN_RTR_FLAG)
135 dst->flags |= CAN_FLAG_RTR;
136 dst->len = MIN(src->can_dlc, CAN_MAX_LEN);
137 if (!(dst->flags & CAN_FLAG_RTR))
138 memcpy(dst->data, src->data, dst->len);
139
140 return 0;
141}
142
143int
144can_msg2can_frame(const struct can_msg *src, struct can_frame *dst)
145{
146 assert(src);
147 assert(dst);
148
149#ifndef LELY_NO_CANFD
150 if (src->flags & CAN_FLAG_EDL) {
152 return -1;
153 }
154#endif
155
156 memset(dst, 0, sizeof(*dst));
157 dst->can_id = src->id;
158 if (src->flags & CAN_FLAG_IDE) {
159 dst->can_id &= CAN_EFF_MASK;
160 dst->can_id |= CAN_EFF_FLAG;
161 } else {
162 dst->can_id &= CAN_SFF_MASK;
163 }
164 dst->can_dlc = MIN(src->len, CAN_MAX_LEN);
165 if (src->flags & CAN_FLAG_RTR)
166 dst->can_id |= CAN_RTR_FLAG;
167 else
168 memcpy(dst->data, src->data, dst->can_dlc);
169
170 return 0;
171}
172
173#if !defined(LELY_NO_CANFD) && defined(CANFD_MTU)
174
175int
176canfd_frame2can_msg(const struct canfd_frame *src, struct can_msg *dst)
177{
178 assert(src);
179 assert(dst);
180
181 if (src->can_id & CAN_ERR_FLAG) {
183 return -1;
184 }
185
186 memset(dst, 0, sizeof(*dst));
187 dst->flags = CAN_FLAG_EDL;
188 if (src->can_id & CAN_EFF_FLAG) {
189 dst->id = src->can_id & CAN_EFF_MASK;
190 dst->flags |= CAN_FLAG_IDE;
191 } else {
192 dst->id = src->can_id & CAN_SFF_MASK;
193 }
194 if (src->flags & CANFD_BRS)
195 dst->flags |= CAN_FLAG_BRS;
196 if (src->flags & CANFD_ESI)
197 dst->flags |= CAN_FLAG_ESI;
198 dst->len = MIN(src->len, CANFD_MAX_LEN);
199 memcpy(dst->data, src->data, dst->len);
200
201 return 0;
202}
203
204int
205can_msg2canfd_frame(const struct can_msg *src, struct canfd_frame *dst)
206{
207 assert(src);
208 assert(dst);
209
210 if (!(src->flags & CAN_FLAG_EDL)) {
212 return -1;
213 }
214
215 memset(dst, 0, sizeof(*dst));
216 dst->can_id = src->id;
217 if (src->flags & CAN_FLAG_IDE) {
218 dst->can_id &= CAN_EFF_MASK;
219 dst->can_id |= CAN_EFF_FLAG;
220 } else {
221 dst->can_id &= CAN_SFF_MASK;
222 }
223 dst->flags = 0;
224 if (src->flags & CAN_FLAG_BRS)
225 dst->flags |= CANFD_BRS;
226 if (src->flags & CAN_FLAG_ESI)
227 dst->flags |= CANFD_ESI;
228 dst->len = MIN(src->len, CANFD_MAX_LEN);
229 memcpy(dst->data, src->data, dst->len);
230
231 return 0;
232}
233
234#endif // !LELY_NO_CANFD && CANFD_MTU
235
236#endif // LELY_HAVE_SOCKET_CAN
This header file is part of the utilities library; it contains the native and platform-independent er...
@ ERRNUM_INVAL
Invalid argument.
Definition: errnum.h:129
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
Definition: errnum.h:375
can_error
The error flags of a CAN bus, which are not mutually exclusive.
Definition: can.h:37
can_state
The states of a CAN node, depending on the TX/RX error count.
Definition: can.h:27
@ CAN_STATE_BUSOFF
The bus off state (TX/RX error count >= 256).
Definition: can.h:33
@ CAN_STATE_PASSIVE
The error passive state (TX/RX error count < 256).
Definition: can.h:31
@ CAN_STATE_ACTIVE
The error active state (TX/RX error count < 128).
Definition: can.h:29
This is the public header file of the utilities library.
#define MIN(a, b)
Returns the minimum of a and b.
Definition: util.h:57
#define CAN_FLAG_RTR
The Remote Transmission Request (RTR) flag (unavailable in CAN FD format frames).
Definition: msg.h:47
#define CAN_FLAG_BRS
The Bit Rate Switch (BRS) flag (only available in CAN FD format frames).
Definition: msg.h:62
#define CAN_MAX_LEN
The maximum number of bytes in the payload of a CAN format frame.
Definition: msg.h:73
#define CAN_FLAG_ESI
The Error State Indicator (ESI) flag (only available in CAN FD format frames).
Definition: msg.h:68
#define CAN_FLAG_IDE
The Identifier Extension (IDE) flag.
Definition: msg.h:41
#define CANFD_MAX_LEN
The maximum number of bytes in the payload of a CAN FD format frame.
Definition: msg.h:77
#define CAN_FLAG_EDL
The Extended Data Length (EDL) flag.
Definition: msg.h:55
int can_frame2can_msg(const struct can_frame *src, struct can_msg *dst)
Converts a SocketCAN CAN frame to a can_msg frame.
Definition: socket.c:116
int can_frame_is_error(const struct can_frame *frame, enum can_state *pstate, enum can_error *perror)
Checks if a SocketCAN CAN frame is an error frame and parses the bus state and error flags if it is.
Definition: socket.c:43
int can_msg2can_frame(const struct can_msg *src, struct can_frame *dst)
Converts a can_msg frame to a SocketCAN CAN frame.
Definition: socket.c:144
This header file is part of the CAN library; it contains the SocketCAN interface declarations.
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.
This is the internal header file of the CAN library.
This header file is part of the C11 and POSIX compatibility library; it includes <string....
A CAN or CAN FD format frame.
Definition: msg.h:88
uint_least8_t data[CAN_MSG_MAX_LEN]
The frame payload (in case of a data frame).
Definition: msg.h:103
uint_least32_t id
The identifier (11 or 29 bits, depending on the CAN_FLAG_IDE flag).
Definition: msg.h:90
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...
Definition: msg.h:95
uint_least8_t len
The number of bytes in data (or the requested number of bytes in case of a remote frame).
Definition: msg.h:101