2 * canfdtest.c - Full-duplex test program (DUT and host part)
4 * (C) 2009 by Vladislav Gribov, IXXAT Automation GmbH, <gribov@ixxat.de>
5 * (C) 2009 Wolfgang Grandegger <wg@grandegger.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * Send feedback to <linux-can@vger.kernel.org>
32 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <sys/ioctl.h>
38 #include <linux/can.h>
39 #include <linux/can/raw.h>
41 #define CAN_MSG_ID 0x77
43 #define CAN_MSG_COUNT 50
44 #define CAN_MSG_WAIT 27
46 static int running = 1;
49 static int test_loops;
51 static void print_usage(char *prg)
54 "Usage: %s [options] <can-interface>\n"
56 "Options: -v (low verbosity)\n"
57 " -vv (high verbosity)\n"
58 " -g (generate messages)\n"
59 " -l COUNT (test loop count)\n"
61 "With the option '-g' CAN messages are generated and checked\n"
62 "on <can-interface>, otherwise all messages received on the\n"
63 "<can-interface> are sent back incrementing the CAN id and\n"
64 "all data bytes. The program can be aborted with ^C.\n"
67 "\ton DUT : %s -v can0\n"
68 "\ton Host: %s -g -v can2\n",
74 static void print_frame(struct can_frame *frame)
78 printf("%04x: ", frame->can_id);
79 if (frame->can_id & CAN_RTR_FLAG) {
80 printf("remote request");
82 printf("[%d]", frame->can_dlc);
83 for (i = 0; i < frame->can_dlc; i++)
84 printf(" %02x", frame->data[i]);
89 static void print_compare(struct can_frame *exp, struct can_frame *rec)
97 static void compare_frame(struct can_frame *exp, struct can_frame *rec)
101 if (rec->can_id != exp->can_id) {
102 printf("Message ID mismatch!\n");
103 print_compare(exp, rec);
105 } else if (rec->can_dlc != exp->can_dlc) {
106 printf("Message length mismatch!\n");
107 print_compare(exp, rec);
110 for (i = 0; i < rec->can_dlc; i++) {
111 if (rec->data[i] != exp->data[i]) {
112 printf("Databyte %x mismatch !\n", i);
121 static void millisleep(int msecs)
126 struct timespec rqtp, rmtp;
129 rqtp.tv_sec = msecs / 1000;
130 rqtp.tv_nsec = (msecs % 1000) * 1000000;
131 while (nanosleep(&rqtp, &rmtp)) {
132 if (errno != EINTR) {
141 static void echo_progress(unsigned char data)
149 static void signal_handler(int signo)
155 static int recv_frame(struct can_frame *frame)
159 ret = recv(sockfd, frame, sizeof(*frame), 0);
160 if (ret != sizeof(*frame)) {
162 perror("recv failed");
164 fprintf(stderr, "recv returned %d", ret);
170 static int send_frame(struct can_frame *frame)
174 while ((ret = send(sockfd, frame, sizeof(*frame), 0))
177 if (errno != ENOBUFS) {
178 perror("send failed");
187 fprintf(stderr, "send returned %d", ret);
194 static int can_echo_dut(void)
196 unsigned int frame_count = 0;
197 struct timeval tvn, tv_stop;
198 struct can_frame frame;
202 if (recv_frame(&frame))
206 echo_progress(frame.data[0]);
207 } else if (verbose > 1) {
208 printf("%04x: ", frame.can_id);
209 if (frame.can_id & CAN_RTR_FLAG) {
210 printf("remote request");
212 printf("[%d]", frame.can_dlc);
213 for (i = 0; i < frame.can_dlc; i++)
214 printf(" %02x", frame.data[i]);
219 for (i = 0; i < frame.can_dlc; i++)
221 if (send_frame(&frame))
225 * to force a interlacing of the frames send by DUT and PC
226 * test tool a waiting time is injected
228 if (frame_count == CAN_MSG_WAIT) {
230 if (gettimeofday(&tv_stop, NULL)) {
231 perror("gettimeofday failed\n");
234 tv_stop.tv_usec += 3000;
235 if (tv_stop.tv_usec > 999999) {
238 tv_stop.tv_usec % 1000000;
240 gettimeofday(&tvn, NULL);
241 while ((tv_stop.tv_sec > tvn.tv_sec) ||
242 ((tv_stop.tv_sec = tvn.tv_sec) &&
243 (tv_stop.tv_usec >= tvn.tv_usec)))
244 gettimeofday(&tvn, NULL);
252 static int can_echo_gen(void)
254 struct can_frame tx_frames[CAN_MSG_COUNT];
255 struct can_frame rx_frame;
256 unsigned char counter = 0;
257 int send_pos = 0, recv_pos = 0, unprocessed = 0, loops = 0;
261 if (unprocessed < CAN_MSG_COUNT) {
262 /* still send messages */
263 tx_frames[send_pos].can_dlc = CAN_MSG_LEN;
264 tx_frames[send_pos].can_id = CAN_MSG_ID;
265 for (i = 0; i < CAN_MSG_LEN; i++)
266 tx_frames[send_pos].data[i] = counter + i;
267 if (send_frame(&tx_frames[send_pos]))
270 /* increment to be equal to expected */
271 tx_frames[send_pos].can_id++;
272 for (i = 0; i < CAN_MSG_LEN; i++)
273 tx_frames[send_pos].data[i]++;
276 if (send_pos == CAN_MSG_COUNT)
280 echo_progress(counter);
283 if ((counter % 33) == 0)
288 if (recv_frame(&rx_frame))
292 print_frame(&rx_frame);
294 /* compare with expected */
295 compare_frame(&tx_frames[recv_pos], &rx_frame);
298 if (test_loops && loops >= test_loops)
302 if (recv_pos == CAN_MSG_COUNT)
308 printf("\nTest messages sent and received: %d\n", loops);
313 int main(int argc, char *argv[])
316 struct sockaddr_can addr;
318 int family = PF_CAN, type = SOCK_RAW, proto = CAN_RAW;
322 signal(SIGTERM, signal_handler);
323 signal(SIGHUP, signal_handler);
324 signal(SIGINT, signal_handler);
326 while ((opt = getopt(argc, argv, "gl:v")) != -1) {
333 test_loops = atoi(optarg);;
341 print_usage(basename(argv[0]));
346 if ((argc - optind) != 1)
347 print_usage(basename(argv[0]));
348 intf_name = argv[optind];
350 printf("interface = %s, family = %d, type = %d, proto = %d\n",
351 intf_name, family, type, proto);
353 if ((sockfd = socket(family, type, proto)) < 0) {
358 addr.can_family = family;
359 strcpy(ifr.ifr_name, intf_name);
360 ioctl(sockfd, SIOCGIFINDEX, &ifr);
361 addr.can_ifindex = ifr.ifr_ifindex;
363 if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
370 err = can_echo_gen();
372 err = can_echo_dut();
375 printf("Exiting...\n");