Skip to content

Commit 161c3b5

Browse files
authored
Merge pull request COVESA#29 from boschglobal/feat/CAN-FD-Rebased
Feat/can fd rebased
2 parents 3088820 + ab12471 commit 161c3b5

File tree

10 files changed

+243
-221
lines changed

10 files changed

+243
-221
lines changed

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,12 @@ target_include_directories(aaf-talker PRIVATE "examples" "include")
5353
target_link_libraries(aaf-talker open1722 open1722examples)
5454

5555
# CAN talker app
56-
add_executable(acf-can-talker "examples/acf-can/acf-can-talker.c")
56+
add_executable(acf-can-talker "examples/acf-can/acf-can-talker.c" "examples/acf-can/acf-can-common.c")
5757
target_include_directories(acf-can-talker PRIVATE "examples" "include")
5858
target_link_libraries(acf-can-talker open1722 open1722examples)
5959

6060
# CAN listener app
61-
add_executable(acf-can-listener "examples/acf-can/acf-can-listener.c")
61+
add_executable(acf-can-listener "examples/acf-can/acf-can-listener.c" "examples/acf-can/acf-can-common.c")
6262
target_include_directories(acf-can-listener PRIVATE "examples" "include")
6363
target_link_libraries(acf-can-listener open1722 open1722examples)
6464

examples/acf-can/acf-can-common.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright (c) 2024, COVESA
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions are met:
6+
*
7+
* * Redistributions of source code must retain the above copyright notice,
8+
* this list of conditions and the following disclaimer.
9+
* * Redistributions in binary form must reproduce the above copyright
10+
* notice, this list of conditions and the following disclaimer in the
11+
* documentation and/or other materials provided with the distribution.
12+
* * Neither the name of COVESA nor the names of its contributors may be
13+
* used to endorse or promote products derived from this software without
14+
* specific prior written permission.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26+
*
27+
* SPDX-License-Identifier: BSD-3-Clause
28+
*/
29+
30+
#include <linux/if.h>
31+
#include <linux/can.h>
32+
#include <linux/can/raw.h>
33+
#include <unistd.h>
34+
#include <sys/ioctl.h>
35+
#include <string.h>
36+
#include "acf-can-common.h"
37+
38+
int setup_can_socket(const char* can_ifname, Avtp_CanVariant_t can_variant) {
39+
40+
int can_socket, res;
41+
struct ifreq ifr;
42+
struct sockaddr_can can_addr;
43+
44+
can_socket = socket(PF_CAN, SOCK_RAW, CAN_RAW);
45+
if (can_socket < 0) return can_socket;
46+
47+
strcpy(ifr.ifr_name, can_ifname);
48+
ioctl(can_socket, SIOCGIFINDEX, &ifr);
49+
50+
memset(&can_addr, 0, sizeof(can_addr));
51+
can_addr.can_family = AF_CAN;
52+
can_addr.can_ifindex = ifr.ifr_ifindex;
53+
54+
if (can_variant == AVTP_CAN_FD) {
55+
int enable_canfx = 1;
56+
setsockopt(can_socket, SOL_CAN_RAW, CAN_RAW_FD_FRAMES,
57+
&enable_canfx, sizeof(enable_canfx));
58+
}
59+
60+
res = bind(can_socket, (struct sockaddr *)&can_addr, sizeof(can_addr));
61+
if (res < 0) {
62+
close(can_socket);
63+
return res;
64+
}
65+
66+
return can_socket;
67+
}

examples/acf-can/acf-can-common.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2024, COVESA
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions are met:
6+
*
7+
* * Redistributions of source code must retain the above copyright notice,
8+
* this list of conditions and the following disclaimer.
9+
* * Redistributions in binary form must reproduce the above copyright
10+
* notice, this list of conditions and the following disclaimer in the
11+
* documentation and/or other materials provided with the distribution.
12+
* * Neither the name of COVESA nor the names of its contributors may be
13+
* used to endorse or promote products derived from this software without
14+
* specific prior written permission.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26+
*
27+
* SPDX-License-Identifier: BSD-3-Clause
28+
*/
29+
30+
#include "avtp/acf/Can.h"
31+
32+
int setup_can_socket(const char* can_ifname, Avtp_CanVariant_t can_variant);

examples/acf-can/acf-can-listener.c

Lines changed: 56 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,17 @@
4848
#include "avtp/acf/Common.h"
4949
#include "avtp/acf/Can.h"
5050
#include "avtp/CommonHeader.h"
51+
#include "acf-can-common.h"
5152

5253
#define MAX_PDU_SIZE 1500
54+
#define ARGPARSE_CAN_FD_OPTION 500
5355

5456
static char ifname[IFNAMSIZ];
5557
static uint8_t macaddr[ETH_ALEN];
5658
static uint8_t use_udp;
5759
static uint32_t udp_port = 17220;
58-
static char can_ifname[IFNAMSIZ] = "STDOUT\0";
60+
static Avtp_CanVariant_t can_variant = AVTP_CAN_CLASSIC;
61+
static char can_ifname[IFNAMSIZ];
5962

6063
static char doc[] = "\nacf-can-listener -- a program designed to receive CAN messages from \
6164
a remote CAN bus over Ethernet using Open1722 \
@@ -72,6 +75,7 @@ static char args_doc[] = "[ifname] dst-mac-address [can ifname]";
7275
static struct argp_option options[] = {
7376
{"port", 'p', "UDP_PORT", 0, "UDP Port to listen on if UDP enabled"},
7477
{"udp", 'u', 0, 0, "Use UDP"},
78+
{"fd", ARGPARSE_CAN_FD_OPTION, 0, 0, "Use CAN-FD"},
7579
{"can ifname", 0, 0, OPTION_DOC, "CAN interface (set to STDOUT by default)"},
7680
{"dst-mac-address", 0, 0, OPTION_DOC, "Stream destination MAC address (If Ethernet)"},
7781
{"ifname", 0, 0, OPTION_DOC, "Network interface (If Ethernet)" },
@@ -89,6 +93,8 @@ static error_t parser(int key, char *arg, struct argp_state *state)
8993
case 'u':
9094
use_udp = 1;
9195
break;
96+
case ARGPARSE_CAN_FD_OPTION:
97+
can_variant = AVTP_CAN_FD;
9298

9399
case ARGP_KEY_NO_ARGS:
94100
break;
@@ -100,7 +106,6 @@ static error_t parser(int key, char *arg, struct argp_state *state)
100106
}
101107

102108
if(!use_udp){
103-
104109
strncpy(ifname, arg, sizeof(ifname) - 1);
105110

106111
if(state->next < state->argc)
@@ -154,7 +159,7 @@ void print_can_acf(uint8_t* acf_pdu)
154159

155160
Avtp_Can_t *pdu = (Avtp_Can_t*) acf_pdu;
156161

157-
Avtp_Can_GetField(pdu, AVTP_ACF_FIELD_ACF_MSG_LENGTH, &acf_msg_len);
162+
Avtp_Can_GetField(pdu, AVTP_CAN_FIELD_ACF_MSG_LENGTH, &acf_msg_len);
158163
Avtp_Can_GetField(pdu, AVTP_CAN_FIELD_CAN_BUS_ID, &can_bus_id);
159164
Avtp_Can_GetField(pdu, AVTP_CAN_FIELD_MESSAGE_TIMESTAMP, &timestamp);
160165
Avtp_Can_GetField(pdu, AVTP_CAN_FIELD_CAN_IDENTIFIER, &can_identifier);
@@ -172,17 +177,13 @@ static int new_packet(int sk_fd, int can_socket) {
172177

173178
int res;
174179
uint64_t msg_length, proc_bytes = 0, msg_proc_bytes = 0;
175-
uint64_t can_frame_id, udp_seq_num = 0, subtype;
180+
uint64_t can_frame_id, udp_seq_num, subtype, flag;
176181
uint16_t payload_length, pdu_length;
177-
uint8_t *can_payload, i;
178-
uint8_t pdu[MAX_PDU_SIZE];
179-
uint8_t* cf_pdu;
180-
uint8_t* acf_pdu;
181-
Avtp_Udp_t *udp_pdu;
182-
char stdout_string[1000] = "\0";
183-
struct can_frame frame;
184-
uint64_t eff;
182+
uint8_t pdu[MAX_PDU_SIZE], i;
183+
uint8_t *cf_pdu, *acf_pdu, *udp_pdu, *can_payload;
184+
struct canfd_frame frame;
185185

186+
memset(&frame, 0, sizeof(struct canfd_frame));
186187
res = recv(sk_fd, pdu, MAX_PDU_SIZE, 0);
187188

188189
if (res < 0 || res > MAX_PDU_SIZE) {
@@ -191,8 +192,8 @@ static int new_packet(int sk_fd, int can_socket) {
191192
}
192193

193194
if (use_udp) {
194-
udp_pdu = (Avtp_Udp_t *) pdu;
195-
Avtp_Udp_GetField(udp_pdu, AVTP_UDP_FIELD_ENCAPSULATION_SEQ_NO, &udp_seq_num);
195+
udp_pdu = pdu;
196+
Avtp_Udp_GetField((Avtp_Udp_t *)udp_pdu, AVTP_UDP_FIELD_ENCAPSULATION_SEQ_NO, &udp_seq_num);
196197
cf_pdu = pdu + AVTP_UDP_HEADER_LEN;
197198
proc_bytes += AVTP_UDP_HEADER_LEN;
198199
} else {
@@ -214,15 +215,10 @@ static int new_packet(int sk_fd, int can_socket) {
214215

215216
if(subtype == AVTP_SUBTYPE_TSCF){
216217
proc_bytes += AVTP_TSCF_HEADER_LEN;
217-
res = Avtp_Tscf_GetField((Avtp_Tscf_t*)cf_pdu, AVTP_TSCF_FIELD_STREAM_DATA_LENGTH, (uint64_t *) &msg_length);
218+
Avtp_Tscf_GetField((Avtp_Tscf_t*)cf_pdu, AVTP_TSCF_FIELD_STREAM_DATA_LENGTH, (uint64_t *) &msg_length);
218219
}else{
219220
proc_bytes += AVTP_NTSCF_HEADER_LEN;
220-
res = Avtp_Ntscf_GetField((Avtp_Ntscf_t*)cf_pdu, AVTP_NTSCF_FIELD_NTSCF_DATA_LENGTH, (uint64_t *) &msg_length);
221-
}
222-
223-
if (res < 0) {
224-
fprintf(stderr, "Failed to get message length: %d\n", res);
225-
return -1;
221+
Avtp_Ntscf_GetField((Avtp_Ntscf_t*)cf_pdu, AVTP_NTSCF_FIELD_NTSCF_DATA_LENGTH, (uint64_t *) &msg_length);
226222
}
227223

228224
while (msg_proc_bytes < msg_length) {
@@ -234,56 +230,50 @@ static int new_packet(int sk_fd, int can_socket) {
234230
return -1;
235231
}
236232

237-
res = Avtp_Can_GetField((Avtp_Can_t*)acf_pdu, AVTP_CAN_FIELD_CAN_IDENTIFIER,
238-
&can_frame_id);
239-
if (res < 0) {
240-
fprintf(stderr, "Error: Getting CAN frame ID\n");
241-
return -1;
242-
}
233+
Avtp_Can_GetField((Avtp_Can_t*)acf_pdu, AVTP_CAN_FIELD_CAN_IDENTIFIER,
234+
&(can_frame_id));
235+
frame.can_id = can_frame_id;
243236

244237
can_payload = Avtp_Can_GetPayload((Avtp_Can_t*)acf_pdu, &payload_length, &pdu_length);
245238
msg_proc_bytes += pdu_length*4;
246239

247-
res = Avtp_Can_GetField((Avtp_Can_t*)acf_pdu, AVTP_CAN_FIELD_EFF, &eff);
248-
if (res < 0) {
249-
fprintf(stderr, "Failed to get eff field: %d\n", res);
250-
return -1;
251-
}
252-
253-
if (can_frame_id > 0x7FF && !eff) {
240+
// Handle EFF Flag
241+
Avtp_Can_GetField((Avtp_Can_t*)acf_pdu, AVTP_CAN_FIELD_EFF, &flag);
242+
if (frame.can_id > 0x7FF && !flag) {
254243
fprintf(stderr, "Error: CAN ID is > 0x7FF but the EFF bit is not set.\n");
255244
return -1;
256245
}
246+
if (flag) frame.can_id |= CAN_EFF_FLAG;
257247

258-
if (can_socket == 0) {
259-
for (i = 0; i < payload_length; i++) {
260-
sprintf(stdout_string+(2*i), "%02x", can_payload[i]);
261-
}
248+
// Handle RTR Flag
249+
Avtp_Can_GetField((Avtp_Can_t*)acf_pdu, AVTP_CAN_FIELD_RTR, &flag);
250+
if (flag) frame.can_id |= CAN_RTR_FLAG;
262251

263-
if (eff) {
264-
fprintf(stdout, "(000000.000000) elmcan 0000%03lx#%s\n", can_frame_id, stdout_string);
265-
} else {
266-
fprintf(stdout, "(000000.000000) elmcan %03lx#%s\n", can_frame_id, stdout_string);
267-
}
268-
fflush(stdout);
269-
} else {
270-
frame.can_id = (canid_t) can_frame_id;
271-
if (eff) {
272-
frame.can_id |= CAN_EFF_FLAG;
273-
}
274-
frame.can_dlc = payload_length;
275-
memcpy(frame.data, can_payload, payload_length);
276-
if (write(can_socket, &frame, sizeof(struct can_frame)) != sizeof(struct can_frame)) {
277-
return 1;
278-
}
252+
if (can_variant == AVTP_CAN_FD) {
253+
Avtp_Can_GetField((Avtp_Can_t*)acf_pdu, AVTP_CAN_FIELD_BRS, &flag);
254+
if (flag) frame.flags |= CANFD_BRS;
255+
256+
Avtp_Can_GetField((Avtp_Can_t*)acf_pdu, AVTP_CAN_FIELD_FDF, &flag);
257+
if (flag) frame.flags |= CANFD_FDF;
258+
259+
Avtp_Can_GetField((Avtp_Can_t*)acf_pdu, AVTP_CAN_FIELD_ESI, &flag);
260+
if (flag) frame.flags |= CANFD_ESI;
261+
}
262+
263+
frame.len = payload_length;
264+
memcpy(frame.data, can_payload, payload_length);
265+
res = write(can_socket, &frame, sizeof(struct canfd_frame)) != sizeof(struct canfd_frame);
266+
if (res < 0) {
267+
return res;
279268
}
269+
280270
}
281271
return 1;
282272
}
283273

284274
int main(int argc, char *argv[])
285275
{
286-
int sk_fd, res;
276+
int fd, res;
287277
struct pollfd fds;
288278

289279
int can_socket = 0;
@@ -292,33 +282,22 @@ int main(int argc, char *argv[])
292282

293283
argp_parse(&argp, argc, argv, 0, NULL, NULL);
294284

295-
// Open a CAN socket for reading frames if required
296-
if (strcmp(can_ifname, "STDOUT\0")) {
297-
can_socket = socket(PF_CAN, SOCK_RAW, CAN_RAW);
298-
if (can_socket < 0)
299-
return 1;
300-
301-
strcpy(ifr.ifr_name, can_ifname);
302-
ioctl(can_socket, SIOCGIFINDEX, &ifr);
303-
304-
memset(&can_addr, 0, sizeof(can_addr));
305-
can_addr.can_family = AF_CAN;
306-
can_addr.can_ifindex = ifr.ifr_ifindex;
307-
if (bind(can_socket, (struct sockaddr *)&can_addr, sizeof(can_addr)) < 0)
308-
return 1;
309-
}
310-
285+
// Configure an appropriate socket: UDP or Ethernet Raw
311286
if (use_udp) {
312-
sk_fd = create_listener_socket_udp(udp_port);
287+
fd = create_listener_socket_udp(udp_port);
313288
} else {
314-
sk_fd = create_listener_socket(ifname, macaddr, ETH_P_TSN);
289+
fd = create_listener_socket(ifname, macaddr, ETH_P_TSN);
315290
}
316-
fds.fd = sk_fd;
291+
fds.fd = fd;
317292
fds.events = POLLIN;
318293

319-
if (sk_fd < 0)
294+
if (fd < 0)
320295
return 1;
321296

297+
// Open a CAN socket for reading frames
298+
can_socket = setup_can_socket(can_ifname, can_variant);
299+
if (!can_socket) goto err;
300+
322301
while (1) {
323302

324303
res = poll(&fds, 1, -1);
@@ -328,7 +307,7 @@ int main(int argc, char *argv[])
328307
}
329308

330309
if (fds.revents & POLLIN) {
331-
res = new_packet(sk_fd, can_socket);
310+
res = new_packet(fd, can_socket);
332311
if (res < 0)
333312
goto err;
334313
}
@@ -338,7 +317,7 @@ int main(int argc, char *argv[])
338317
return 0;
339318

340319
err:
341-
close(sk_fd);
320+
close(fd);
342321
return 1;
343322

344323
}

0 commit comments

Comments
 (0)