int main(int argc, char **argv) { int s; /* can raw socket */ int nbytes; struct sockaddr_can addr; struct can_frame rframe; struct ifreq ifr; /* check command line options */ if (argc != 2) { fprintf(stderr, "Usage: %s <device>.\n", argv[0]); return 1; } /* open socket */ if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) { perror("socket"); return 1; } strcpy(ifr.ifr_name, argv[1]); ioctl(s, SIOCGIFINDEX, &ifr); addr.can_family = AF_CAN; addr.can_ifindex = ifr.ifr_ifindex; /* ifr.ifr_ifru.ifru_ivalue = 1000000/2; ioctl(s, SIOCSCANBAUDRATE, &ifr); */ if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("bind"); return 1; } while(1) { if ((nbytes = read(s, &rframe, sizeof(rframe))) < 0) { perror("rx frame read"); return 0; /* quit */ } printf("\nread %d bytes\n", nbytes); fprint_long_canframe(stdout, &rframe, "\n", 0); } close(s); return 0; }
int main(int argc, char **argv) { fd_set rdfs; int s[MAXSOCK]; int bridge = 0; unsigned char timestamp = 0; unsigned char dropmonitor = 0; unsigned char silent = SILENT_INI; unsigned char silentani = 0; unsigned char color = 0; unsigned char view = 0; unsigned char log = 0; unsigned char logfrmt = 0; int count = 0; int rcvbuf_size = 0; int opt, ret; int currmax, numfilter; char *ptr, *nptr; struct sockaddr_can addr; char ctrlmsg[CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(sizeof(__u32))]; struct iovec iov; struct msghdr msg; struct cmsghdr *cmsg; struct can_filter *rfilter; can_err_mask_t err_mask; struct can_frame frame; int nbytes, i; struct ifreq ifr; struct timeval tv, last_tv; FILE *logfile = NULL; signal(SIGTERM, sigterm); signal(SIGHUP, sigterm); signal(SIGINT, sigterm); last_tv.tv_sec = 0; last_tv.tv_usec = 0; while ((opt = getopt(argc, argv, "t:ciaSs:b:B:ldLn:r:h?")) != -1) { switch (opt) { case 't': timestamp = optarg[0]; if ((timestamp != 'a') && (timestamp != 'A') && (timestamp != 'd') && (timestamp != 'z')) { fprintf(stderr, "%s: unknown timestamp mode '%c' - ignored\n", basename(argv[0]), optarg[0]); timestamp = 0; } break; case 'c': color++; break; case 'i': view |= CANLIB_VIEW_BINARY; break; case 'a': view |= CANLIB_VIEW_ASCII; break; case 'S': view |= CANLIB_VIEW_SWAP; break; case 's': silent = atoi(optarg); if (silent > SILENT_ON) { print_usage(basename(argv[0])); exit(1); } break; case 'b': case 'B': if (strlen(optarg) >= IFNAMSIZ) { fprintf(stderr, "Name of CAN device '%s' is too long!\n\n", optarg); return 1; } else { bridge = socket(PF_CAN, SOCK_RAW, CAN_RAW); if (bridge < 0) { perror("bridge socket"); return 1; } addr.can_family = AF_CAN; strcpy(ifr.ifr_name, optarg); if (ioctl(bridge, SIOCGIFINDEX, &ifr) < 0) perror("SIOCGIFINDEX"); addr.can_ifindex = ifr.ifr_ifindex; if (!addr.can_ifindex) { perror("invalid bridge interface"); return 1; } /* disable default receive filter on this write-only RAW socket */ setsockopt(bridge, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0); if (opt == 'B') { const int loopback = 0; setsockopt(bridge, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback, sizeof(loopback)); } if (bind(bridge, (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("bridge bind"); return 1; } } break; case 'l': log = 1; break; case 'd': dropmonitor = 1; break; case 'L': logfrmt = 1; break; case 'n': count = atoi(optarg); if (count < 1) { print_usage(basename(argv[0])); exit(1); } break; case 'r': rcvbuf_size = atoi(optarg); if (rcvbuf_size < 1) { print_usage(basename(argv[0])); exit(1); } break; default: print_usage(basename(argv[0])); exit(1); break; } } if (optind == argc) { print_usage(basename(argv[0])); exit(0); } if (logfrmt && view) { fprintf(stderr, "Log file format selected: Please disable ASCII/BINARY/SWAP options!\n"); exit(0); } if (silent == SILENT_INI) { if (log) { fprintf(stderr, "Disabled standard output while logging.\n"); silent = SILENT_ON; /* disable output on stdout */ } else silent = SILENT_OFF; /* default output */ } currmax = argc - optind; /* find real number of CAN devices */ if (currmax > MAXSOCK) { fprintf(stderr, "More than %d CAN devices given on commandline!\n", MAXSOCK); return 1; } for (i=0; i < currmax; i++) { ptr = argv[optind+i]; nptr = strchr(ptr, ','); #ifdef DEBUG printf("open %d '%s'.\n", i, ptr); #endif s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW); if (s[i] < 0) { perror("socket"); return 1; } cmdlinename[i] = ptr; /* save pointer to cmdline name of this socket */ if (nptr) nbytes = nptr - ptr; /* interface name is up the first ',' */ else nbytes = strlen(ptr); /* no ',' found => no filter definitions */ if (nbytes >= IFNAMSIZ) { fprintf(stderr, "name of CAN device '%s' is too long!\n", ptr); return 1; } if (nbytes > max_devname_len) max_devname_len = nbytes; /* for nice printing */ addr.can_family = AF_CAN; memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name)); strncpy(ifr.ifr_name, ptr, nbytes); #ifdef DEBUG printf("using interface name '%s'.\n", ifr.ifr_name); #endif if (strcmp(ANYDEV, ifr.ifr_name)) { if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) { perror("SIOCGIFINDEX"); exit(1); } addr.can_ifindex = ifr.ifr_ifindex; } else addr.can_ifindex = 0; /* any can interface */ if (nptr) { /* found a ',' after the interface name => check for filters */ /* determine number of filters to alloc the filter space */ numfilter = 0; ptr = nptr; while (ptr) { numfilter++; ptr++; /* hop behind the ',' */ ptr = strchr(ptr, ','); /* exit condition */ } rfilter = malloc(sizeof(struct can_filter) * numfilter); if (!rfilter) { fprintf(stderr, "Failed to create filter space!\n"); return 1; } numfilter = 0; err_mask = 0; while (nptr) { ptr = nptr+1; /* hop behind the ',' */ nptr = strchr(ptr, ','); /* update exit condition */ if (sscanf(ptr, "%x:%x", &rfilter[numfilter].can_id, &rfilter[numfilter].can_mask) == 2) { rfilter[numfilter].can_mask &= ~CAN_ERR_FLAG; numfilter++; } else if (sscanf(ptr, "%x~%x", &rfilter[numfilter].can_id, &rfilter[numfilter].can_mask) == 2) { rfilter[numfilter].can_id |= CAN_INV_FILTER; rfilter[numfilter].can_mask &= ~CAN_ERR_FLAG; numfilter++; } else if (sscanf(ptr, "#%x", &err_mask) != 1) { fprintf(stderr, "Error in filter option parsing: '%s'\n", ptr); return 1; } } if (err_mask) setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &err_mask, sizeof(err_mask)); if (numfilter) setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FILTER, rfilter, numfilter * sizeof(struct can_filter)); free(rfilter); } /* if (nptr) */ if (rcvbuf_size) { int curr_rcvbuf_size; socklen_t curr_rcvbuf_size_len = sizeof(curr_rcvbuf_size); /* try SO_RCVBUFFORCE first, if we run with CAP_NET_ADMIN */ if (setsockopt(s[i], SOL_SOCKET, SO_RCVBUFFORCE, &rcvbuf_size, sizeof(rcvbuf_size)) < 0) { #ifdef DEBUG printf("SO_RCVBUFFORCE failed so try SO_RCVBUF ...\n"); #endif if (setsockopt(s[i], SOL_SOCKET, SO_RCVBUF, &rcvbuf_size, sizeof(rcvbuf_size)) < 0) { perror("setsockopt SO_RCVBUF"); return 1; } if (getsockopt(s[i], SOL_SOCKET, SO_RCVBUF, &curr_rcvbuf_size, &curr_rcvbuf_size_len) < 0) { perror("getsockopt SO_RCVBUF"); return 1; } /* Only print a warning the first time we detect the adjustment */ /* n.b.: The wanted size is doubled in Linux in net/sore/sock.c */ if (!i && curr_rcvbuf_size < rcvbuf_size*2) fprintf(stderr, "The socket receive buffer size was " "adjusted due to /proc/sys/net/core/rmem_max.\n"); } } if (timestamp || log || logfrmt) { const int timestamp_on = 1; if (setsockopt(s[i], SOL_SOCKET, SO_TIMESTAMP, ×tamp_on, sizeof(timestamp_on)) < 0) { perror("setsockopt SO_TIMESTAMP"); return 1; } } if (dropmonitor) { const int dropmonitor_on = 1; if (setsockopt(s[i], SOL_SOCKET, SO_RXQ_OVFL, &dropmonitor_on, sizeof(dropmonitor_on)) < 0) { perror("setsockopt SO_RXQ_OVFL not supported by your Linux Kernel"); return 1; } } if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("bind"); return 1; } } if (log) { time_t currtime; struct tm now; char fname[sizeof("candump-2006-11-20_202026.log")+1]; if (time(&currtime) == (time_t)-1) { perror("time"); return 1; } localtime_r(&currtime, &now); sprintf(fname, "candump-%04d-%02d-%02d_%02d%02d%02d.log", now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec); if (silent != SILENT_ON) printf("\nWarning: console output active while logging!"); fprintf(stderr, "\nEnabling Logfile '%s'\n\n", fname); logfile = fopen(fname, "w"); if (!logfile) { perror("logfile"); return 1; } } /* these settings are static and can be held out of the hot path */ iov.iov_base = &frame; msg.msg_name = &addr; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = &ctrlmsg; while (running) { FD_ZERO(&rdfs); for (i=0; i<currmax; i++) FD_SET(s[i], &rdfs); if ((ret = select(s[currmax-1]+1, &rdfs, NULL, NULL, NULL)) < 0) { //perror("select"); running = 0; continue; } for (i=0; i<currmax; i++) { /* check all CAN RAW sockets */ if (FD_ISSET(s[i], &rdfs)) { int idx; /* these settings may be modified by recvmsg() */ iov.iov_len = sizeof(frame); msg.msg_namelen = sizeof(addr); msg.msg_controllen = sizeof(ctrlmsg); msg.msg_flags = 0; nbytes = recvmsg(s[i], &msg, 0); if (nbytes < 0) { perror("read"); return 1; } if (nbytes < sizeof(struct can_frame)) { fprintf(stderr, "read: incomplete CAN frame\n"); return 1; } if (count && (--count == 0)) running = 0; if (bridge) { nbytes = write(bridge, &frame, sizeof(struct can_frame)); if (nbytes < 0) { perror("bridge write"); return 1; } else if (nbytes < sizeof(struct can_frame)) { fprintf(stderr,"bridge write: incomplete CAN frame\n"); return 1; } } for (cmsg = CMSG_FIRSTHDR(&msg); cmsg && (cmsg->cmsg_level == SOL_SOCKET); cmsg = CMSG_NXTHDR(&msg,cmsg)) { if (cmsg->cmsg_type == SO_TIMESTAMP) tv = *(struct timeval *)CMSG_DATA(cmsg); else if (cmsg->cmsg_type == SO_RXQ_OVFL) dropcnt[i] = *(__u32 *)CMSG_DATA(cmsg); } /* check for (unlikely) dropped frames on this specific socket */ if (dropcnt[i] != last_dropcnt[i]) { __u32 frames; if (dropcnt[i] > last_dropcnt[i]) frames = dropcnt[i] - last_dropcnt[i]; else frames = 4294967295U - last_dropcnt[i] + dropcnt[i]; /* 4294967295U == UINT32_MAX */ if (silent != SILENT_ON) printf("DROPCOUNT: dropped %d CAN frame%s on '%s' socket (total drops %d)\n", frames, (frames > 1)?"s":"", cmdlinename[i], dropcnt[i]); if (log) fprintf(logfile, "DROPCOUNT: dropped %d CAN frame%s on '%s' socket (total drops %d)\n", frames, (frames > 1)?"s":"", cmdlinename[i], dropcnt[i]); last_dropcnt[i] = dropcnt[i]; } idx = idx2dindex(addr.can_ifindex, s[i]); if (log) { /* log CAN frame with absolute timestamp & device */ fprintf(logfile, "(%ld.%06ld) ", tv.tv_sec, tv.tv_usec); fprintf(logfile, "%*s ", max_devname_len, devname[idx]); /* without seperator as logfile use-case is parsing */ fprint_canframe(logfile, &frame, "\n", 0); } if (logfrmt) { /* print CAN frame in log file style to stdout */ printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec); printf("%*s ", max_devname_len, devname[idx]); fprint_canframe(stdout, &frame, "\n", 0); goto out_fflush; /* no other output to stdout */ } if (silent != SILENT_OFF){ if (silent == SILENT_ANI) { printf("%c\b", anichar[silentani%=MAXANI]); silentani++; } goto out_fflush; /* no other output to stdout */ } printf(" %s", (color>2)?col_on[idx%MAXCOL]:""); switch (timestamp) { case 'a': /* absolute with timestamp */ printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec); break; case 'A': /* absolute with date */ { struct tm tm; char timestring[25]; tm = *localtime(&tv.tv_sec); strftime(timestring, 24, "%Y-%m-%d %H:%M:%S", &tm); printf("(%s.%06ld) ", timestring, tv.tv_usec); } break; case 'd': /* delta */ case 'z': /* starting with zero */ { struct timeval diff; if (last_tv.tv_sec == 0) /* first init */ last_tv = tv; diff.tv_sec = tv.tv_sec - last_tv.tv_sec; diff.tv_usec = tv.tv_usec - last_tv.tv_usec; if (diff.tv_usec < 0) diff.tv_sec--, diff.tv_usec += 1000000; if (diff.tv_sec < 0) diff.tv_sec = diff.tv_usec = 0; printf("(%ld.%06ld) ", diff.tv_sec, diff.tv_usec); if (timestamp == 'd') last_tv = tv; /* update for delta calculation */ } break; default: /* no timestamp output */ break; } printf(" %s", (color && (color<3))?col_on[idx%MAXCOL]:""); printf("%*s", max_devname_len, devname[idx]); printf("%s ", (color==1)?col_off:""); fprint_long_canframe(stdout, &frame, NULL, view); printf("%s", (color>1)?col_off:""); printf("\n"); } out_fflush: fflush(stdout); } } for (i=0; i<currmax; i++) close(s[i]); if (bridge) close(bridge); if (log) fclose(logfile); return 0; }
int main(int argc, char **argv) { unsigned long gap = DEFAULT_GAP; unsigned char extended = 0; unsigned char fix_id = 0; unsigned char fix_data = 0; unsigned char fix_dlc = 0; unsigned char default_frame = 1; unsigned char verbose = 0; int opt; int s; /* socket */ struct sockaddr_can addr; static struct can_frame frame; int nbytes; struct ifreq ifr; struct timespec ts; signal(SIGTERM, sigterm); signal(SIGHUP, sigterm); signal(SIGINT, sigterm); while ((opt = getopt(argc, argv, "g:eIDLf:v")) != -1) { switch (opt) { case 'g': gap = strtoul(optarg, NULL, 10); break; case 'e': extended = 1; break; case 'I': fix_id = 1; break; case 'D': fix_data = 1; break; case 'L': fix_dlc = 1; break; case 'f': default_frame = 0; if (parse_canframe(optarg, &frame)) { fprintf(stderr, "'%s' is a wrong CAN frame format.\n", optarg); exit(1); } break; case 'v': verbose = 1; break; default: print_usage(basename(argv[0])); exit(1); break; } } if (optind == argc) { print_usage(basename(argv[0])); exit(0); } ts.tv_sec = gap / 1000; ts.tv_nsec = (gap % 1000) * 1000000; if (default_frame) { if (extended) frame.can_id = 0x12345678 | CAN_EFF_FLAG; else frame.can_id = 0x123; frame.can_dlc = 8; frame.data[0] = 0x01; frame.data[1] = 0x23; frame.data[2] = 0x45; frame.data[3] = 0x67; frame.data[4] = 0x89; frame.data[5] = 0xAB; frame.data[6] = 0xCD; frame.data[7] = 0xEF; } if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) { perror("socket"); return 1; } addr.can_family = AF_CAN; strcpy(ifr.ifr_name, argv[optind]); if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) perror("SIOCGIFINDEX"); addr.can_ifindex = ifr.ifr_ifindex; /* disable default receive filter on this RAW socket */ /* This is obsolete as we do not read from the socket at all, but for */ /* this reason we can remove the receive list in the Kernel to save a */ /* little (really a very little!) CPU usage. */ setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0); if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("bind"); return 1; } while (running) { if (!fix_id) { frame.can_id = random(); if (extended) { frame.can_id &= CAN_EFF_MASK; frame.can_id |= CAN_EFF_FLAG; } else frame.can_id &= CAN_SFF_MASK; } if (!fix_dlc) { frame.can_dlc = random() & 0xF; if (frame.can_dlc & 8) frame.can_dlc = 8; /* for about 50% of the frames */ } if (!fix_data) { /* that's what the 64 bit alignment of data[] is for ... :) */ *(unsigned long*)(&frame.data[0]) = random(); *(unsigned long*)(&frame.data[4]) = random(); } if ((nbytes = write(s, &frame, sizeof(struct can_frame))) < 0) { perror("write"); return 1; } else if (nbytes < sizeof(struct can_frame)) { fprintf(stderr, "write: incomplete CAN frame\n"); return 1; } if (gap) /* gap == 0 => performance test :-] */ if (nanosleep(&ts, NULL)) return 1; if (verbose) #if 0 fprint_long_canframe(stdout, &frame, "\n", 1); #else fprint_canframe(stdout, &frame, "\n", 1); #endif } close(s); return 0; }
int main(int argc, char **argv) { static char buf[BUFSZ], device[BUFSZ], ascframe[BUFSZ]; struct sockaddr_can addr; static struct canfd_frame frame; static struct timeval today_tv, log_tv, last_log_tv, diff_tv; struct timespec sleep_ts; int s; /* CAN_RAW socket */ FILE *infile = stdin; unsigned long gap = DEFAULT_GAP; int use_timestamps = 1; static int verbose, opt, delay_loops; static unsigned long skipgap; static int loopback_disable = 0; static int infinite_loops = 0; static int loops = DEFAULT_LOOPS; int assignments; /* assignments defined on the commandline */ int txidx; /* sendto() interface index */ int eof, txmtu, i, j; char *fret; while ((opt = getopt(argc, argv, "I:l:tg:s:xv?")) != -1) { switch (opt) { case 'I': infile = fopen(optarg, "r"); if (!infile) { perror("infile"); return 1; } break; case 'l': if (optarg[0] == 'i') infinite_loops = 1; else if (!(loops = atoi(optarg))) { fprintf(stderr, "Invalid argument for option -l !\n"); return 1; } break; case 't': use_timestamps = 0; break; case 'g': gap = strtoul(optarg, NULL, 10); break; case 's': skipgap = strtoul(optarg, NULL, 10); if (skipgap < 1) { fprintf(stderr, "Invalid argument for option -s !\n"); return 1; } break; case 'x': loopback_disable = 1; break; case 'v': verbose++; break; case '?': default: print_usage(basename(argv[0])); return 1; break; } } assignments = argc - optind; /* find real number of user assignments */ if (infile == stdin) { /* no jokes with stdin */ infinite_loops = 0; loops = 1; } if (verbose > 1) { /* use -v -v to see this */ if (infinite_loops) printf("infinite_loops\n"); else printf("%d loops\n", loops); } sleep_ts.tv_sec = gap / 1000; sleep_ts.tv_nsec = (gap % 1000) * 1000000; /* open socket */ if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) { perror("socket"); return 1; } addr.can_family = AF_CAN; addr.can_ifindex = 0; /* disable unneeded default receive filter on this RAW socket */ setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0); /* try to switch the socket into CAN FD mode */ setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &canfd_on, sizeof(canfd_on)); if (loopback_disable) { int loopback = 0; setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback, sizeof(loopback)); } if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("bind"); return 1; } if (assignments) { /* add & check user assginments from commandline */ for (i=0; i<assignments; i++) { if (strlen(argv[optind+i]) >= BUFSZ) { fprintf(stderr, "Assignment too long!\n"); print_usage(basename(argv[0])); return 1; } strcpy(buf, argv[optind+i]); for (j=0; j<BUFSZ; j++) { /* find '=' in assignment */ if (buf[j] == '=') break; } if ((j == BUFSZ) || (buf[j] != '=')) { fprintf(stderr, "'=' missing in assignment!\n"); print_usage(basename(argv[0])); return 1; } buf[j] = 0; /* cut string in two pieces */ if (add_assignment("user", s, &buf[0], &buf[j+1], verbose)) return 1; } } while (infinite_loops || loops--) { if (infile != stdin) rewind(infile); /* for each loop */ if (verbose > 1) /* use -v -v to see this */ printf (">>>>>>>>> start reading file. remaining loops = %d\n", loops); /* read first non-comment frame from logfile */ while ((fret = fgets(buf, BUFSZ-1, infile)) != NULL && buf[0] != '(') { if (strlen(buf) >= BUFSZ-2) { fprintf(stderr, "comment line too long for input buffer\n"); return 1; } } if (!fret) goto out; /* nothing to read */ eof = 0; if (sscanf(buf, "(%ld.%ld) %s %s", &log_tv.tv_sec, &log_tv.tv_usec, device, ascframe) != 4) { fprintf(stderr, "incorrect line format in logfile\n"); return 1; } if (use_timestamps) { /* throttle sending due to logfile timestamps */ gettimeofday(&today_tv, NULL); create_diff_tv(&today_tv, &diff_tv, &log_tv); last_log_tv = log_tv; } while (!eof) { while ((!use_timestamps) || (frames_to_send(&today_tv, &diff_tv, &log_tv) < 0)) { /* log_tv/device/ascframe are valid here */ if (strlen(device) >= IFNAMSIZ) { fprintf(stderr, "log interface name '%s' too long!", device); return 1; } txidx = get_txidx(device); /* get ifindex for sending the frame */ if ((!txidx) && (!assignments)) { /* ifindex not found and no user assignments */ /* => assign this device automatically */ if (add_assignment("auto", s, device, device, verbose)) return 1; txidx = get_txidx(device); } if (txidx == STDOUTIDX) { /* hook to print logfile lines on stdout */ printf("%s", buf); /* print the line AS-IS without extra \n */ fflush(stdout); } else if (txidx > 0) { /* only send to valid CAN devices */ txmtu = parse_canframe(ascframe, &frame); if (!txmtu) { fprintf(stderr, "wrong CAN frame format: '%s'!", ascframe); return 1; } addr.can_family = AF_CAN; addr.can_ifindex = txidx; /* send via this interface */ if (sendto(s, &frame, txmtu, 0, (struct sockaddr*)&addr, sizeof(addr)) != txmtu) { perror("sendto"); return 1; } if (verbose) { printf("%s (%s) ", get_txname(device), device); if (txmtu == CAN_MTU) fprint_long_canframe(stdout, &frame, "\n", CANLIB_VIEW_INDENT_SFF, CAN_MAX_DLEN); else fprint_long_canframe(stdout, &frame, "\n", CANLIB_VIEW_INDENT_SFF, CANFD_MAX_DLEN); } } /* read next non-comment frame from logfile */ while ((fret = fgets(buf, BUFSZ-1, infile)) != NULL && buf[0] != '(') { if (strlen(buf) >= BUFSZ-2) { fprintf(stderr, "comment line too long for input buffer\n"); return 1; } } if (!fret) { eof = 1; /* this file is completely processed */ break; } if (sscanf(buf, "(%ld.%ld) %s %s", &log_tv.tv_sec, &log_tv.tv_usec, device, ascframe) != 4) { fprintf(stderr, "incorrect line format in logfile\n"); return 1; } if (use_timestamps) { gettimeofday(&today_tv, NULL); /* test for logfile timestamps jumping backwards OR */ /* if the user likes to skip long gaps in the timestamps */ if ((last_log_tv.tv_sec > log_tv.tv_sec) || (skipgap && labs(last_log_tv.tv_sec - log_tv.tv_sec) > skipgap)) create_diff_tv(&today_tv, &diff_tv, &log_tv); last_log_tv = log_tv; } } /* while frames_to_send ... */ if (nanosleep(&sleep_ts, NULL)) return 1; delay_loops++; /* private statistics */ gettimeofday(&today_tv, NULL); } /* while (!eof) */ } /* while (infinite_loops || loops--) */ out: close(s); fclose(infile); if (verbose > 1) /* use -v -v to see this */ printf("%d delay_loops\n", delay_loops); return 0; }
int main(int argc, char **argv) { int s; /* can raw socket */ int nbytes, ret; struct sockaddr_can addr; struct can_frame frame, rframe; struct ifreq ifr; int i; /* check command line options */ if ((argc != 2) && (argc != 3)) { fprintf(stderr, "Usage: send frame: %s <device>.\n", argv[0]); fprintf(stderr, "Usage: receive frame: %s <device> <can_frame>.\n", argv[0]); return 1; } /* open socket */ if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) { perror("socket"); return 1; } strcpy(ifr.ifr_name, argv[1]); ioctl(s, SIOCGIFINDEX, &ifr); addr.can_family = AF_CAN; addr.can_ifindex = ifr.ifr_ifindex; #ifdef TOLTO_GEA ifr.ifr_ifru.ifru_ivalue = 1000000/2; ret = ioctl(s, SIOCSCANBAUDRATE, &ifr); if (ret) { printf("Err: cantest failed to set up baud rate for can port %s\n", argv[1]); printf(" Please check the settings of system clock.\n"); exit(1); } #endif if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("bind"); return 1; } if (argc ==3) { printf("writing to CAN\n"); /* parse CAN frame */ if (parse_canframe(argv[2], &frame)){ fprintf(stderr, "\nWrong CAN-frame format!\n\n"); fprintf(stderr, "Try: <can_id>#{R|data}\n"); fprintf(stderr, "can_id can have 3 (SFF) or 8 (EFF) hex chars\n"); fprintf(stderr, "data has 0 to 8 hex-values that can (optionally)"); fprintf(stderr, " be seperated by '.'\n\n"); fprintf(stderr, "e.g. 5A1#11.2233.44556677.88 / 123#DEADBEEF / "); fprintf(stderr, "5AA# /\n 1F334455#1122334455667788 / 123#R "); fprintf(stderr, "for remote transmission request.\n\n"); return 1; } if ((nbytes = write(s, &frame, sizeof(frame))) != sizeof(frame)) { perror("write"); return 1; } } else if (argc == 2) { printf("reading from CAN\n"); if ((nbytes = read(s, &rframe, sizeof(rframe))) < 0) { perror("rx frame read"); return 0; } printf("\nread %d bytes\n", nbytes); fprint_long_canframe(stdout, &rframe, "\n", 0); } close(s); return 0; }