canfdtest.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. /*
  2. * canfdtest.c - Full-duplex test program (DUT and host part)
  3. *
  4. * (C) 2009 by Vladislav Gribov, IXXAT Automation GmbH, <gribov@ixxat.de>
  5. * (C) 2009 Wolfgang Grandegger <wg@grandegger.com>
  6. *
  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
  10. * any later version.
  11. *
  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.
  16. *
  17. * Send feedback to <linux-can@vger.kernel.org>
  18. */
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <unistd.h>
  22. #include <string.h>
  23. #include <signal.h>
  24. #include <libgen.h>
  25. #include <getopt.h>
  26. #include <time.h>
  27. #include <sched.h>
  28. #include <limits.h>
  29. #include <errno.h>
  30. #include <sys/types.h>
  31. #include <sys/time.h>
  32. #include <sys/socket.h>
  33. #include <sys/ioctl.h>
  34. #include <net/if.h>
  35. #include <linux/can.h>
  36. #include <linux/can/raw.h>
  37. #define CAN_MSG_ID 0x77
  38. #define CAN_MSG_LEN 8
  39. #define CAN_MSG_COUNT 50
  40. #define CAN_MSG_WAIT 27
  41. static int running = 1;
  42. static int verbose;
  43. static int sockfd;
  44. static int test_loops;
  45. static void print_usage(char *prg)
  46. {
  47. fprintf(stderr,
  48. "Usage: %s [options] <can-interface>\n"
  49. "\n"
  50. "Options: -v (low verbosity)\n"
  51. " -vv (high verbosity)\n"
  52. " -g (generate messages)\n"
  53. " -l COUNT (test loop count)\n"
  54. "\n"
  55. "With the option '-g' CAN messages are generated and checked\n"
  56. "on <can-interface>, otherwise all messages received on the\n"
  57. "<can-interface> are sent back incrementing the CAN id and\n"
  58. "all data bytes. The program can be aborted with ^C.\n"
  59. "\n"
  60. "Example:\n"
  61. "\ton DUT : %s -v can0\n"
  62. "\ton Host: %s -g -v can2\n",
  63. prg, prg, prg);
  64. exit(1);
  65. }
  66. static void print_frame(struct can_frame *frame)
  67. {
  68. int i;
  69. printf("%04x: ", frame->can_id);
  70. if (frame->can_id & CAN_RTR_FLAG) {
  71. printf("remote request");
  72. } else {
  73. printf("[%d]", frame->can_dlc);
  74. for (i = 0; i < frame->can_dlc; i++)
  75. printf(" %02x", frame->data[i]);
  76. }
  77. printf("\n");
  78. }
  79. static void print_compare(struct can_frame *exp, struct can_frame *rec)
  80. {
  81. printf("expected: ");
  82. print_frame(exp);
  83. printf("received: ");
  84. print_frame(rec);
  85. }
  86. static void compare_frame(struct can_frame *exp, struct can_frame *rec)
  87. {
  88. int i;
  89. if (rec->can_id != exp->can_id) {
  90. printf("Message ID mismatch!\n");
  91. print_compare(exp, rec);
  92. running = 0;
  93. } else if (rec->can_dlc != exp->can_dlc) {
  94. printf("Message length mismatch!\n");
  95. print_compare(exp, rec);
  96. running = 0;
  97. } else {
  98. for (i = 0; i < rec->can_dlc; i++) {
  99. if (rec->data[i] != exp->data[i]) {
  100. printf("Databyte %x mismatch !\n", i);
  101. print_compare(exp,
  102. rec);
  103. running = 0;
  104. }
  105. }
  106. }
  107. }
  108. static void millisleep(int msecs)
  109. {
  110. struct timespec rqtp, rmtp;
  111. int err;
  112. /* sleep in ms */
  113. rqtp.tv_sec = msecs / 1000;
  114. rqtp.tv_nsec = msecs % 1000 * 1000000;
  115. do {
  116. err = clock_nanosleep(CLOCK_MONOTONIC, 0, &rqtp, &rmtp);
  117. if (err != 0 && err != EINTR) {
  118. printf("t\n");
  119. break;
  120. }
  121. rqtp = rmtp;
  122. } while (err != 0);
  123. }
  124. static void echo_progress(unsigned char data)
  125. {
  126. if (data == 0xff) {
  127. printf(".");
  128. fflush(stdout);
  129. }
  130. }
  131. static void signal_handler(int signo)
  132. {
  133. close(sockfd);
  134. running = 0;
  135. }
  136. static int recv_frame(struct can_frame *frame)
  137. {
  138. int ret;
  139. ret = recv(sockfd, frame, sizeof(*frame), 0);
  140. if (ret != sizeof(*frame)) {
  141. if (ret < 0)
  142. perror("recv failed");
  143. else
  144. fprintf(stderr, "recv returned %d", ret);
  145. return -1;
  146. }
  147. return 0;
  148. }
  149. static int send_frame(struct can_frame *frame)
  150. {
  151. int ret;
  152. while ((ret = send(sockfd, frame, sizeof(*frame), 0))
  153. != sizeof(*frame)) {
  154. if (ret < 0) {
  155. if (errno != ENOBUFS) {
  156. perror("send failed");
  157. return -1;
  158. } else {
  159. if (verbose) {
  160. printf("N");
  161. fflush(stdout);
  162. }
  163. }
  164. } else {
  165. fprintf(stderr, "send returned %d", ret);
  166. return -1;
  167. }
  168. }
  169. return 0;
  170. }
  171. static int can_echo_dut(void)
  172. {
  173. unsigned int frame_count = 0;
  174. struct can_frame frame;
  175. int i;
  176. while (running) {
  177. if (recv_frame(&frame))
  178. return -1;
  179. frame_count++;
  180. if (verbose == 1) {
  181. echo_progress(frame.data[0]);
  182. } else if (verbose > 1) {
  183. printf("%04x: ", frame.can_id);
  184. if (frame.can_id & CAN_RTR_FLAG) {
  185. printf("remote request");
  186. } else {
  187. printf("[%d]", frame.can_dlc);
  188. for (i = 0; i < frame.can_dlc; i++)
  189. printf(" %02x", frame.data[i]);
  190. }
  191. printf("\n");
  192. }
  193. frame.can_id++;
  194. for (i = 0; i < frame.can_dlc; i++)
  195. frame.data[i]++;
  196. if (send_frame(&frame))
  197. return -1;
  198. /*
  199. * to force a interlacing of the frames send by DUT and PC
  200. * test tool a waiting time is injected
  201. */
  202. if (frame_count == CAN_MSG_WAIT) {
  203. frame_count = 0;
  204. millisleep(3);
  205. }
  206. }
  207. return 0;
  208. }
  209. static int can_echo_gen(void)
  210. {
  211. struct can_frame tx_frames[CAN_MSG_COUNT];
  212. struct can_frame rx_frame;
  213. unsigned char counter = 0;
  214. int send_pos = 0, recv_pos = 0, unprocessed = 0, loops = 0;
  215. int i;
  216. while (running) {
  217. if (unprocessed < CAN_MSG_COUNT) {
  218. /* still send messages */
  219. tx_frames[send_pos].can_dlc = CAN_MSG_LEN;
  220. tx_frames[send_pos].can_id = CAN_MSG_ID;
  221. for (i = 0; i < CAN_MSG_LEN; i++)
  222. tx_frames[send_pos].data[i] = counter + i;
  223. if (send_frame(&tx_frames[send_pos]))
  224. return -1;
  225. /* increment to be equal to expected */
  226. tx_frames[send_pos].can_id++;
  227. for (i = 0; i < CAN_MSG_LEN; i++)
  228. tx_frames[send_pos].data[i]++;
  229. send_pos++;
  230. if (send_pos == CAN_MSG_COUNT)
  231. send_pos = 0;
  232. unprocessed++;
  233. if (verbose == 1)
  234. echo_progress(counter);
  235. counter++;
  236. if ((counter % 33) == 0)
  237. millisleep(3);
  238. else
  239. millisleep(1);
  240. } else {
  241. if (recv_frame(&rx_frame))
  242. return -1;
  243. if (verbose > 1)
  244. print_frame(&rx_frame);
  245. /* compare with expected */
  246. compare_frame(&tx_frames[recv_pos], &rx_frame);
  247. loops++;
  248. if (test_loops && loops >= test_loops)
  249. break;
  250. recv_pos++;
  251. if (recv_pos == CAN_MSG_COUNT)
  252. recv_pos = 0;
  253. unprocessed--;
  254. }
  255. }
  256. printf("\nTest messages sent and received: %d\n", loops);
  257. return 0;
  258. }
  259. int main(int argc, char *argv[])
  260. {
  261. struct sockaddr_can addr;
  262. char *intf_name;
  263. int family = PF_CAN, type = SOCK_RAW, proto = CAN_RAW;
  264. int echo_gen = 0;
  265. int opt, err;
  266. signal(SIGTERM, signal_handler);
  267. signal(SIGHUP, signal_handler);
  268. signal(SIGINT, signal_handler);
  269. while ((opt = getopt(argc, argv, "gl:v")) != -1) {
  270. switch (opt) {
  271. case 'v':
  272. verbose++;
  273. break;
  274. case 'l':
  275. test_loops = atoi(optarg);;
  276. break;
  277. case 'g':
  278. echo_gen = 1;
  279. break;
  280. default:
  281. print_usage(basename(argv[0]));
  282. break;
  283. }
  284. }
  285. if ((argc - optind) != 1)
  286. print_usage(basename(argv[0]));
  287. intf_name = argv[optind];
  288. printf("interface = %s, family = %d, type = %d, proto = %d\n",
  289. intf_name, family, type, proto);
  290. if ((sockfd = socket(family, type, proto)) < 0) {
  291. perror("socket");
  292. return 1;
  293. }
  294. addr.can_family = family;
  295. addr.can_ifindex = if_nametoindex(intf_name);
  296. if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
  297. perror("bind");
  298. close(sockfd);
  299. return 1;
  300. }
  301. if (echo_gen)
  302. err = can_echo_gen();
  303. else
  304. err = can_echo_dut();
  305. if (verbose)
  306. printf("Exiting...\n");
  307. close(sockfd);
  308. return err;
  309. }