mirror of
https://github.com/linux-can/can-utils.git
synced 2026-09-21 15:29:56 +02:00
Compare commits
40
Commits
f7779a8f1d
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cbbad5eede | ||
|
|
95aae6bf83 | ||
|
|
bf5fe736c3 | ||
|
|
14245b7c79 | ||
|
|
90383a0cca | ||
|
|
d5cb91c8ea | ||
|
|
9743a2ffcf | ||
|
|
d5ed23583c | ||
|
|
60301896d1 | ||
|
|
99ab67143a | ||
|
|
a0aeaed234 | ||
|
|
3cae8a449b | ||
|
|
44e6eb45e3 | ||
|
|
9e444073b1 | ||
|
|
9d4f3c82a2 | ||
|
|
7e8e247b2f | ||
|
|
3fe1c42bbf | ||
|
|
1520ab5b98 | ||
|
|
aa902ae2af | ||
|
|
a0b592178e | ||
|
|
4f2fdecfba | ||
|
|
cbbe4b41ea | ||
|
|
2da0c7e95e | ||
|
|
1f038b3cd8 | ||
|
|
392ccc970b | ||
|
|
7939678070 | ||
|
|
88a0417a6b | ||
|
|
65e715d56d | ||
|
|
374fecde09 | ||
|
|
bfbf0c851f | ||
|
|
ed7822c9a2 | ||
|
|
e9ea9d1168 | ||
|
|
2d793d38d2 | ||
|
|
340a3b8c92 | ||
|
|
8838ce80fc | ||
|
|
d6c57240ed | ||
|
|
3e0e6ae3a4 | ||
|
|
8bf5f8873f | ||
|
|
0094905376 | ||
|
|
987bc8aac2 |
@@ -75,7 +75,6 @@ jobs:
|
||||
gcc \
|
||||
gcc-aarch64-linux-gnu \
|
||||
gcc-arm-linux-gnueabihf \
|
||||
gcc-mips-linux-gnu \
|
||||
libgps-dev \
|
||||
make
|
||||
|
||||
@@ -139,13 +138,6 @@ jobs:
|
||||
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=cmake/${toolchain}.cmake -DENABLE_WERROR=ON -DENABLE_GPS=${gps} -B build-${toolchain}
|
||||
podman exec -i stable cmake --build build-${toolchain}
|
||||
|
||||
- name: Configure & Build with mips-linux-gnu-gcc
|
||||
env:
|
||||
toolchain: mips-linux-gnu-gcc
|
||||
run: |
|
||||
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=cmake/${toolchain}.cmake -DENABLE_WERROR=ON -B build-${toolchain}
|
||||
podman exec -i stable cmake --build build-${toolchain}
|
||||
|
||||
- name: Configure & Build with gcc (Makefile)
|
||||
env:
|
||||
cc: gcc
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
cmake_minimum_required(VERSION 3.5...3.10)
|
||||
|
||||
project(can-utils LANGUAGES C)
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ static void print_usage(char *prg)
|
||||
}
|
||||
|
||||
static void prframe(FILE *file, struct timeval *tv, int dev,
|
||||
cu_t *cf, char dir)
|
||||
union cfu *cf, char dir)
|
||||
{
|
||||
static char abuf[BUFLEN];
|
||||
|
||||
@@ -177,7 +177,7 @@ static void eval_can(char* buf, struct timeval *date_tvp, char timestamps,
|
||||
cf.len = CAN_ERR_DLC;
|
||||
|
||||
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
||||
prframe(outfile, &tv, interface, (cu_t *)&cf, NO_DIR);
|
||||
prframe(outfile, &tv, interface, (union cfu *)&cf, NO_DIR);
|
||||
fflush(outfile);
|
||||
return;
|
||||
}
|
||||
@@ -249,7 +249,7 @@ static void eval_can(char* buf, struct timeval *date_tvp, char timestamps,
|
||||
cf.data[i] = data[i] & 0xFFU;
|
||||
|
||||
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
||||
prframe(outfile, &tv, interface, (cu_t *)&cf, dir[0]);
|
||||
prframe(outfile, &tv, interface, (union cfu *)&cf, dir[0]);
|
||||
fflush(outfile);
|
||||
}
|
||||
}
|
||||
@@ -374,7 +374,7 @@ static void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps,
|
||||
}
|
||||
|
||||
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
||||
prframe(outfile, &tv, interface, (cu_t *)&cf, dir[0]);
|
||||
prframe(outfile, &tv, interface, (union cfu *)&cf, dir[0]);
|
||||
fflush(outfile);
|
||||
|
||||
/* No support for really strange CANFD ErrorFrames format m( */
|
||||
@@ -487,7 +487,7 @@ static void eval_canxl_cc(char* buf, struct timeval *date_tvp, char timestamps,
|
||||
cf.len8_dlc = dlc;
|
||||
|
||||
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
||||
prframe(outfile, &tv, interface, (cu_t *)&cf, dir[0]);
|
||||
prframe(outfile, &tv, interface, (union cfu *)&cf, dir[0]);
|
||||
fflush(outfile);
|
||||
}
|
||||
|
||||
@@ -584,7 +584,7 @@ static void eval_canxl_fd(char* buf, struct timeval *date_tvp, char timestamps,
|
||||
return;
|
||||
|
||||
if (!(flags & ASC_F_FDF))
|
||||
return;
|
||||
return;
|
||||
|
||||
cf.flags = CANFD_FDF;
|
||||
|
||||
@@ -594,7 +594,7 @@ static void eval_canxl_fd(char* buf, struct timeval *date_tvp, char timestamps,
|
||||
cf.flags |= CANFD_ESI;
|
||||
|
||||
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
||||
prframe(outfile, &tv, interface, (cu_t *)&cf, dir[0]);
|
||||
prframe(outfile, &tv, interface, (union cfu *)&cf, dir[0]);
|
||||
fflush(outfile);
|
||||
}
|
||||
|
||||
@@ -723,7 +723,7 @@ static void eval_canxl_xl(char* buf, struct timeval *date_tvp, char timestamps,
|
||||
cf.flags |= CANXL_RRS;
|
||||
|
||||
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
||||
prframe(outfile, &tv, interface, (cu_t *)&cf, dir[0]);
|
||||
prframe(outfile, &tv, interface, (union cfu *)&cf, dir[0]);
|
||||
fflush(outfile);
|
||||
|
||||
/* No support for CAN XL ErrorFrames */
|
||||
|
||||
+29
-9
@@ -153,7 +153,7 @@ int main(void)
|
||||
|
||||
char buf[MAXLEN];
|
||||
char format[FORMATSZ];
|
||||
char rxmsg[50];
|
||||
char rxmsg[64];
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpragmas"
|
||||
@@ -234,7 +234,7 @@ int main(void)
|
||||
}
|
||||
|
||||
while (1) {
|
||||
|
||||
again:
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(sc, &readfds);
|
||||
FD_SET(sa, &readfds);
|
||||
@@ -242,6 +242,8 @@ int main(void)
|
||||
select((sc > sa)?sc+1:sa+1, &readfds, NULL, NULL, NULL);
|
||||
|
||||
if (FD_ISSET(sc, &readfds)) {
|
||||
size_t size = sizeof(rxmsg);
|
||||
int len = 0, res;
|
||||
|
||||
recvfrom(sc, &msg, sizeof(msg), 0,
|
||||
(struct sockaddr*)&caddr, &caddrlen);
|
||||
@@ -249,17 +251,35 @@ int main(void)
|
||||
ifr.ifr_ifindex = caddr.can_ifindex;
|
||||
ioctl(sc, SIOCGIFNAME, &ifr);
|
||||
|
||||
sprintf(rxmsg, "< %s %03X %d ", ifr.ifr_name,
|
||||
msg.msg_head.can_id, msg.frame.can_dlc);
|
||||
res = snprintf(rxmsg, size, "< %s %03X %d ", ifr.ifr_name,
|
||||
msg.msg_head.can_id, msg.frame.can_dlc);
|
||||
if (res < 0 || (size_t)res >= size) {
|
||||
printf("Error: rxmsg buffer (size %zu) too small for data.\n", size);
|
||||
continue;
|
||||
}
|
||||
|
||||
for ( i = 0; i < msg.frame.can_dlc; i++)
|
||||
sprintf(rxmsg + strlen(rxmsg), "%02X ",
|
||||
msg.frame.data[i]);
|
||||
len += res;
|
||||
|
||||
for (i = 0; i < msg.frame.can_dlc; i++) {
|
||||
res = snprintf(rxmsg + len, size - len, "%02X ", msg.frame.data[i]);
|
||||
if (res < 0 || (size_t)res >= (size - len)) {
|
||||
printf("Error: rxmsg buffer (size %zu) too small for data.\n", size);
|
||||
goto again;
|
||||
}
|
||||
|
||||
len += res;
|
||||
}
|
||||
|
||||
/* delimiter '\0' for Adobe(TM) Flash(TM) XML sockets */
|
||||
strcat(rxmsg, ">\0");
|
||||
res = snprintf(rxmsg + len, size - len, ">");
|
||||
if (res < 0 || (size_t)res >= (size - len)) {
|
||||
printf("Error: rxmsg buffer (size %zu) too small for data.\n", size);
|
||||
continue;
|
||||
}
|
||||
|
||||
send(sa, rxmsg, strlen(rxmsg) + 1, 0);
|
||||
len += res;
|
||||
|
||||
send(sa, rxmsg, len + 1, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -72,6 +72,9 @@
|
||||
#ifndef SO_TIMESTAMPING
|
||||
#define SO_TIMESTAMPING 37
|
||||
#endif
|
||||
#ifndef SCM_TIMESTAMPING
|
||||
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
||||
#endif
|
||||
|
||||
#define TIMESTAMPSZ 50 /* string 'absolute with date' requires max 49 bytes */
|
||||
|
||||
@@ -113,7 +116,8 @@ static const int canfx_on = 1;
|
||||
|
||||
#define MAXANI 4
|
||||
static const char anichar[MAXANI] = { '|', '/', '-', '\\' };
|
||||
static const char extra_m_info[4][4] = { "- -", "B -", "- E", "B E" };
|
||||
static const char extra_fd_info[4][4] = { "- -", "B -", "- E", "B E" };
|
||||
static const char extra_xl_info[4][4] = { "- -", "S -", "- R", "S R" };
|
||||
|
||||
extern int optind, opterr, optopt;
|
||||
|
||||
@@ -128,6 +132,7 @@ static void print_usage(void)
|
||||
fprintf(stderr, "Options:\n");
|
||||
fprintf(stderr, " -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n");
|
||||
fprintf(stderr, " -H (read hardware timestamps instead of system timestamps)\n");
|
||||
fprintf(stderr, " -N (log nanosecond timestamps instead of microseconds)\n");
|
||||
fprintf(stderr, " -c (increment color mode level)\n");
|
||||
fprintf(stderr, " -i (binary output - may exceed 80 chars/line)\n");
|
||||
fprintf(stderr, " -a (enable additional ASCII output)\n");
|
||||
@@ -142,7 +147,7 @@ static void print_usage(void)
|
||||
fprintf(stderr, " -d (monitor dropped CAN frames)\n");
|
||||
fprintf(stderr, " -e (dump CAN error frames in human-readable format)\n");
|
||||
fprintf(stderr, " -8 (display raw DLC values in {} for Classical CAN)\n");
|
||||
fprintf(stderr, " -x (print extra message infos, rx/tx brs esi)\n");
|
||||
fprintf(stderr, " -x (print extra message infos, rx/tx [brs esi|sec rrs])\n");
|
||||
fprintf(stderr, " -T <msecs> (terminate after <msecs> if no frames were received)\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "Up to %d CAN interfaces with optional filter sets can be specified\n", MAXSOCK);
|
||||
@@ -220,16 +225,22 @@ static int idx2dindex(int ifidx, int socket)
|
||||
return i;
|
||||
}
|
||||
|
||||
static int sprint_timestamp(char *ts_buffer, const char timestamp,
|
||||
const struct timeval *tv, struct timeval *const last_tv)
|
||||
static int sprint_timestamp(char *ts_buffer, const char timestamp, const char use_ns,
|
||||
const struct timespec *ts, struct timespec *const last_ts)
|
||||
{
|
||||
int numchars = 0;
|
||||
|
||||
switch (timestamp) {
|
||||
case 'a': /* absolute with timestamp */
|
||||
numchars = sprintf(ts_buffer, "(%010llu.%06llu) ",
|
||||
(unsigned long long)tv->tv_sec,
|
||||
(unsigned long long)tv->tv_usec);
|
||||
if (use_ns) {
|
||||
numchars = sprintf(ts_buffer, "(%010llu.%09llu) ",
|
||||
(unsigned long long)ts->tv_sec,
|
||||
(unsigned long long)ts->tv_nsec);
|
||||
} else {
|
||||
numchars = sprintf(ts_buffer, "(%010llu.%06llu) ",
|
||||
(unsigned long long)ts->tv_sec,
|
||||
(unsigned long long)ts->tv_nsec / 1000);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'A': /* absolute with date */
|
||||
@@ -237,32 +248,43 @@ static int sprint_timestamp(char *ts_buffer, const char timestamp,
|
||||
struct tm tm;
|
||||
char timestring[25];
|
||||
|
||||
tm = *localtime(&tv->tv_sec);
|
||||
tm = *localtime(&ts->tv_sec);
|
||||
strftime(timestring, 24, "%Y-%m-%d %H:%M:%S", &tm);
|
||||
numchars = sprintf(ts_buffer, "(%s.%06llu) ", timestring,
|
||||
(unsigned long long)tv->tv_usec);
|
||||
if (use_ns) {
|
||||
numchars = sprintf(ts_buffer, "(%s.%09llu) ", timestring,
|
||||
(unsigned long long)ts->tv_nsec);
|
||||
} else {
|
||||
numchars = sprintf(ts_buffer, "(%s.%06llu) ", timestring,
|
||||
(unsigned long long)ts->tv_nsec / 1000);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'd': /* delta */
|
||||
case 'z': /* starting with zero */
|
||||
{
|
||||
struct timeval diff;
|
||||
struct timespec 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 (last_ts->tv_sec == 0) /* first init */
|
||||
*last_ts = *ts;
|
||||
diff.tv_sec = ts->tv_sec - last_ts->tv_sec;
|
||||
diff.tv_nsec = ts->tv_nsec - last_ts->tv_nsec;
|
||||
if (diff.tv_nsec < 0)
|
||||
diff.tv_sec--, diff.tv_nsec += 1000000000;
|
||||
if (diff.tv_sec < 0)
|
||||
diff.tv_sec = diff.tv_usec = 0;
|
||||
numchars = sprintf(ts_buffer, "(%03llu.%06llu) ",
|
||||
(unsigned long long)diff.tv_sec,
|
||||
(unsigned long long)diff.tv_usec);
|
||||
diff.tv_sec = diff.tv_nsec = 0;
|
||||
if (use_ns) {
|
||||
numchars = sprintf(ts_buffer, "(%03llu.%09llu) ",
|
||||
(unsigned long long)diff.tv_sec,
|
||||
(unsigned long long)diff.tv_nsec);
|
||||
} else {
|
||||
numchars = sprintf(ts_buffer, "(%03llu.%06llu) ",
|
||||
(unsigned long long)diff.tv_sec,
|
||||
(unsigned long long)diff.tv_nsec / 1000);
|
||||
}
|
||||
|
||||
if (timestamp == 'd')
|
||||
*last_tv = *tv; /* update for delta calculation */
|
||||
*last_ts = *ts; /* update for delta calculation */
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -288,6 +310,7 @@ int main(int argc, char **argv)
|
||||
unsigned char timestamp = 0;
|
||||
unsigned char logtimestamp = 'a';
|
||||
unsigned char hwtimestamp = 0;
|
||||
unsigned char use_ns = 0;
|
||||
unsigned char down_causes_exit = 1;
|
||||
unsigned char dropmonitor = 0;
|
||||
unsigned char extra_msg_info = 0;
|
||||
@@ -319,10 +342,10 @@ int main(int argc, char **argv)
|
||||
struct cmsghdr *cmsg;
|
||||
struct can_filter *rfilter;
|
||||
can_err_mask_t err_mask;
|
||||
static cu_t cu; /* union for CAN CC/FD/XL frames */
|
||||
static union cfu cu; /* union for CAN CC/FD/XL frames */
|
||||
int nbytes, i;
|
||||
struct ifreq ifr;
|
||||
struct timeval tv, last_tv;
|
||||
struct timespec ts, last_ts;
|
||||
int timeout_ms = -1; /* default to no timeout */
|
||||
FILE *logfile = NULL;
|
||||
char fname[83]; /* suggested by -Wformat-overflow= */
|
||||
@@ -334,12 +357,12 @@ int main(int argc, char **argv)
|
||||
signal(SIGHUP, sigterm);
|
||||
signal(SIGINT, sigterm);
|
||||
|
||||
last_tv.tv_sec = 0;
|
||||
last_tv.tv_usec = 0;
|
||||
last_ts.tv_sec = 0;
|
||||
last_ts.tv_nsec = 0;
|
||||
|
||||
progname = basename(argv[0]);
|
||||
|
||||
while ((opt = getopt(argc, argv, "t:HciaSs:lf:Ln:r:Dde8xT:h?")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "t:HNciaSs:lf:Ln:r:Dde8xT:h?")) != -1) {
|
||||
switch (opt) {
|
||||
case 't':
|
||||
timestamp = optarg[0];
|
||||
@@ -359,6 +382,10 @@ int main(int argc, char **argv)
|
||||
hwtimestamp = 1;
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
use_ns = 1;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
color++;
|
||||
break;
|
||||
@@ -688,12 +715,12 @@ int main(int argc, char **argv)
|
||||
localtime_r(&currtime, &now);
|
||||
|
||||
snprintf(fname, sizeof(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);
|
||||
now.tm_year + 1900,
|
||||
now.tm_mon + 1,
|
||||
now.tm_mday,
|
||||
now.tm_hour,
|
||||
now.tm_min,
|
||||
now.tm_sec);
|
||||
|
||||
logname = fname;
|
||||
}
|
||||
@@ -783,9 +810,13 @@ int main(int argc, char **argv)
|
||||
for (cmsg = CMSG_FIRSTHDR(&msg);
|
||||
cmsg && (cmsg->cmsg_level == SOL_SOCKET);
|
||||
cmsg = CMSG_NXTHDR(&msg,cmsg)) {
|
||||
if (cmsg->cmsg_type == SO_TIMESTAMP) {
|
||||
if (cmsg->cmsg_type == SCM_TIMESTAMP) {
|
||||
struct timeval tv;
|
||||
memcpy(&tv, CMSG_DATA(cmsg), sizeof(tv));
|
||||
} else if (cmsg->cmsg_type == SO_TIMESTAMPING) {
|
||||
ts.tv_sec = tv.tv_sec;
|
||||
ts.tv_nsec = tv.tv_usec;
|
||||
ts.tv_nsec *= 1000;
|
||||
} else if (cmsg->cmsg_type == SCM_TIMESTAMPING) {
|
||||
struct timespec *stamp = (struct timespec *)CMSG_DATA(cmsg);
|
||||
|
||||
/*
|
||||
@@ -795,8 +826,7 @@ int main(int argc, char **argv)
|
||||
* See chapter 2.1.2 Receive timestamps in
|
||||
* linux/Documentation/networking/timestamping.txt
|
||||
*/
|
||||
tv.tv_sec = stamp[2].tv_sec;
|
||||
tv.tv_usec = stamp[2].tv_nsec / 1000;
|
||||
ts = stamp[2];
|
||||
} else if (cmsg->cmsg_type == SO_RXQ_OVFL) {
|
||||
memcpy(&obj->dropcnt, CMSG_DATA(cmsg), sizeof(__u32));
|
||||
}
|
||||
@@ -831,11 +861,9 @@ int main(int argc, char **argv)
|
||||
/* build common log format output */
|
||||
if ((log) || ((logfrmt) && (silent == SILENT_OFF))) {
|
||||
|
||||
alen = sprint_timestamp(afrbuf, logtimestamp,
|
||||
&tv, &last_tv);
|
||||
alen = sprint_timestamp(afrbuf, logtimestamp, use_ns, &ts, &last_ts);
|
||||
|
||||
alen += sprintf(afrbuf + alen, "%*s ",
|
||||
max_devname_len, devname[idx]);
|
||||
alen += sprintf(afrbuf + alen, "%*s ", max_devname_len, devname[idx]);
|
||||
|
||||
alen += snprintf_canframe(afrbuf + alen, sizeof(afrbuf) - alen, &cu, 0);
|
||||
}
|
||||
@@ -861,18 +889,23 @@ int main(int argc, char **argv)
|
||||
|
||||
/* print (colored) long CAN frame style to stdout */
|
||||
alen = sprintf(afrbuf, " %s", (color > 2) ? col_on[idx % MAXCOL] : "");
|
||||
alen += sprint_timestamp(afrbuf + alen, timestamp, &tv, &last_tv);
|
||||
alen += sprint_timestamp(afrbuf + alen, timestamp, use_ns, &ts, &last_ts);
|
||||
alen += sprintf(afrbuf + alen, " %s%*s",
|
||||
(color && (color < 3)) ? col_on[idx % MAXCOL] : "",
|
||||
max_devname_len, devname[idx]);
|
||||
(color && (color < 3)) ? col_on[idx % MAXCOL] : "",
|
||||
max_devname_len, devname[idx]);
|
||||
|
||||
if (extra_msg_info) {
|
||||
if (msg.msg_flags & MSG_DONTROUTE)
|
||||
alen += sprintf(afrbuf + alen, " TX %s",
|
||||
extra_m_info[cu.fd.flags & 3]);
|
||||
alen += sprintf(afrbuf + alen, " TX");
|
||||
else
|
||||
alen += sprintf(afrbuf + alen, " RX %s",
|
||||
extra_m_info[cu.fd.flags & 3]);
|
||||
alen += sprintf(afrbuf + alen, " RX");
|
||||
|
||||
if (cu.xl.flags & CANXL_XLF)
|
||||
alen += sprintf(afrbuf + alen, " %s",
|
||||
extra_xl_info[cu.xl.flags & 3]);
|
||||
else
|
||||
alen += sprintf(afrbuf + alen, " %s",
|
||||
extra_fd_info[cu.fd.flags & 3]);
|
||||
}
|
||||
|
||||
alen += sprintf(afrbuf + alen, "%s ", (color == 1) ? col_off : "");
|
||||
|
||||
+18
-19
@@ -25,6 +25,7 @@
|
||||
#include <linux/can/error.h>
|
||||
#include <linux/can/raw.h>
|
||||
#include <net/if.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
@@ -122,27 +123,25 @@ void show_help_and_exit()
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
void err_exit(const char *msg)
|
||||
void __attribute__((format (printf, 1, 2))) err_exit(const char *format, ...)
|
||||
{
|
||||
printf("%s", msg);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
va_list ap;
|
||||
|
||||
void show_custom_format_and_exit(const char *param, const char *format)
|
||||
{
|
||||
char str_buf[80];
|
||||
sprintf(str_buf, format, param);
|
||||
err_exit(str_buf);
|
||||
va_start(ap, format);
|
||||
vfprintf(stdout, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void show_invalid_option(const char *option)
|
||||
{
|
||||
show_custom_format_and_exit(option, "Error: Invalid option %s\n");
|
||||
err_exit("Error: Invalid option %s\n", option);
|
||||
}
|
||||
|
||||
void show_err_and_exit(const char *err_type)
|
||||
{
|
||||
show_custom_format_and_exit(err_type, "Error: You can only have one %s parameter!\n");
|
||||
err_exit("Error: You can only have one %s parameter!\n", err_type);
|
||||
}
|
||||
|
||||
void show_loc_err_and_exit()
|
||||
@@ -176,7 +175,6 @@ int main(int argc, char *argv[])
|
||||
struct ifreq ifr;
|
||||
struct can_frame frame;
|
||||
bool show_bits = false, location_processed = false, transceiver_processed = false, arbitration_processed = false;
|
||||
char tmp_str[256];
|
||||
|
||||
printf("CAN Sockets Error Messages Simulator\n");
|
||||
if (argc < 3)
|
||||
@@ -537,24 +535,25 @@ int main(int argc, char *argv[])
|
||||
|
||||
// create socket
|
||||
if ((sock = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
|
||||
err_exit("Error while opening socket");
|
||||
err_exit("Error while opening socket\n");
|
||||
|
||||
// set interface name
|
||||
if (strlen(argv[1]) >= IFNAMSIZ)
|
||||
err_exit("Name of CAN device '%s' is too long!\n\n", argv[1]);
|
||||
|
||||
strcpy(ifr.ifr_name, argv[1]); // can0, vcan0...
|
||||
if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
|
||||
sprintf(tmp_str, "Error setting CAN interface name %s", argv[1]);
|
||||
err_exit(tmp_str);
|
||||
}
|
||||
if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0)
|
||||
err_exit("Error setting CAN interface name %s\n", argv[1]);
|
||||
|
||||
// bind socket to the CAN interface
|
||||
addr.can_family = AF_CAN;
|
||||
addr.can_ifindex = ifr.ifr_ifindex;
|
||||
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
|
||||
err_exit("Error in socket bind");
|
||||
err_exit("Error in socket bind\n");
|
||||
|
||||
// Send CAN error frame
|
||||
if (write(sock, &frame, sizeof(frame)) < 0)
|
||||
err_exit("Error writing to socket");
|
||||
err_exit("Error writing to socket\n");
|
||||
else
|
||||
printf("CAN error frame sent\n");
|
||||
|
||||
|
||||
@@ -180,7 +180,7 @@ static void print_usage(char *prg)
|
||||
fprintf(stderr, " -X (generate CAN XL CAN frames)\n");
|
||||
fprintf(stderr, " -R (generate RTR frames)\n");
|
||||
fprintf(stderr, " -8 (allow DLC values greater then 8 for Classic CAN frames)\n");
|
||||
fprintf(stderr, " -m (mix -e -f -b -E -R -X frames)\n");
|
||||
fprintf(stderr, " -m (mix CC [-e -R] FD [-f -b -E] XL [-X] on capable devices)\n");
|
||||
fprintf(stderr, " -I <mode> (CAN ID generation mode - see below)\n");
|
||||
fprintf(stderr, " -L <mode> (CAN data length code (dlc) generation mode - see below)\n");
|
||||
fprintf(stderr, " -D <mode> (CAN data (payload) generation mode - see below)\n");
|
||||
@@ -299,7 +299,7 @@ static int setsockopt_txtime(int fd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_send_one(int fd, cu_t *cu, size_t len, int timeout)
|
||||
static int do_send_one(int fd, union cfu *cu, size_t len, int timeout)
|
||||
{
|
||||
uint8_t control[CMSG_SPACE(sizeof(uint64_t))] = { 0 };
|
||||
struct iovec iov = {
|
||||
@@ -339,10 +339,9 @@ resend:
|
||||
nbytes = sendmsg(fd, &msg, 0);
|
||||
if (nbytes < 0) {
|
||||
ret = -errno;
|
||||
if (ret != -ENOBUFS) {
|
||||
perror("write");
|
||||
if (ret != -ENOBUFS)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!ignore_enobufs && !timeout) {
|
||||
perror("write");
|
||||
return ret;
|
||||
@@ -455,6 +454,9 @@ int main(int argc, char **argv)
|
||||
unsigned char extended = 0;
|
||||
unsigned char canfd = 0;
|
||||
unsigned char canxl = 0;
|
||||
unsigned char mixcc = 1; /* mix default */
|
||||
unsigned char mixfd = 1; /* mix default */
|
||||
unsigned char mixxl = 1; /* mix default */
|
||||
unsigned char brs = 0;
|
||||
unsigned char esi = 0;
|
||||
unsigned char mix = 0;
|
||||
@@ -492,7 +494,7 @@ int main(int argc, char **argv)
|
||||
struct can_raw_vcid_options vcid_opts = {
|
||||
.flags = CAN_RAW_XL_VCID_TX_PASS,
|
||||
};
|
||||
static cu_t cu;
|
||||
static union cfu cu;
|
||||
int i;
|
||||
struct ifreq ifr = { 0 };
|
||||
const int enable_canfx = 1;
|
||||
@@ -574,7 +576,6 @@ int main(int argc, char **argv)
|
||||
|
||||
case 'm':
|
||||
mix = 1;
|
||||
canfd = 1; /* to switch the socket into CAN FD mode */
|
||||
view |= CANLIB_VIEW_INDENT_SFF;
|
||||
break;
|
||||
|
||||
@@ -777,14 +778,58 @@ int main(int argc, char **argv)
|
||||
&loopback, sizeof(loopback));
|
||||
}
|
||||
|
||||
if (canfd || canxl) {
|
||||
/* get CAN netdevice MTU for frame type capabilities */
|
||||
if (ioctl(s, SIOCGIFMTU, &ifr) < 0) {
|
||||
perror("SIOCGIFMTU");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* check if the frame fits into the CAN netdevice */
|
||||
if (ioctl(s, SIOCGIFMTU, &ifr) < 0) {
|
||||
perror("SIOCGIFMTU");
|
||||
/* check CAN XL support */
|
||||
if (ifr.ifr_mtu < (int)CANXL_MIN_MTU) {
|
||||
mixxl = 0;
|
||||
if (canxl) {
|
||||
printf("CAN interface not CAN XL capable - sorry.\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* check CAN FD support */
|
||||
if (ifr.ifr_mtu < (int)CANFD_MTU) {
|
||||
mixfd = 0;
|
||||
if (canfd) {
|
||||
printf("CAN interface not CAN FD capable - sorry.\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* enable CAN FD on the socket */
|
||||
if (mixfd) {
|
||||
/* interface is ok - try to switch the socket into CAN FD mode */
|
||||
if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES,
|
||||
&enable_canfx, sizeof(enable_canfx))){
|
||||
printf("error when enabling CAN FD support\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* enable CAN XL on the socket */
|
||||
if (mixxl) {
|
||||
/* interface is ok - try to switch the socket into CAN XL mode */
|
||||
if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_XL_FRAMES,
|
||||
&enable_canfx, sizeof(enable_canfx))){
|
||||
printf("error when enabling CAN XL support\n");
|
||||
return 1;
|
||||
}
|
||||
/* try to enable the CAN XL VCID pass through mode */
|
||||
if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_XL_VCID_OPTS,
|
||||
&vcid_opts, sizeof(vcid_opts))) {
|
||||
printf("error when enabling CAN XL VCID pass through\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* sanitize given values */
|
||||
if (canfd || canxl) {
|
||||
if (canfd) {
|
||||
/* ensure discrete CAN FD length values 0..8, 12, 16, 20, 24, 32, 64 */
|
||||
cu.fd.len = can_fd_dlc2len(can_fd_len2dlc(cu.fd.len));
|
||||
@@ -793,41 +838,6 @@ int main(int argc, char **argv)
|
||||
if (cu.fd.len > CANFD_MAX_DLEN)
|
||||
cu.fd.len = CANFD_MAX_DLEN;
|
||||
}
|
||||
|
||||
if (canxl && (ifr.ifr_mtu < (int)CANXL_MIN_MTU)) {
|
||||
printf("CAN interface not CAN XL capable - sorry.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (canfd && (ifr.ifr_mtu < (int)CANFD_MTU)) {
|
||||
printf("CAN interface not CAN FD capable - sorry.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ifr.ifr_mtu == (int)CANFD_MTU) {
|
||||
/* interface is ok - try to switch the socket into CAN FD mode */
|
||||
if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES,
|
||||
&enable_canfx, sizeof(enable_canfx))){
|
||||
printf("error when enabling CAN FD support\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ifr.ifr_mtu >= (int)CANXL_MIN_MTU) {
|
||||
/* interface is ok - try to switch the socket into CAN XL mode */
|
||||
if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_XL_FRAMES,
|
||||
&enable_canfx, sizeof(enable_canfx))){
|
||||
printf("error when enabling CAN XL support\n");
|
||||
return 1;
|
||||
}
|
||||
/* try to enable the CAN XL VCID pass through mode */
|
||||
if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_XL_VCID_OPTS,
|
||||
&vcid_opts, sizeof(vcid_opts))) {
|
||||
printf("error when enabling CAN XL VCID pass through\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
/* sanitize Classical CAN 2.0 frame length */
|
||||
if (len8_dlc) {
|
||||
@@ -1040,8 +1050,31 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
ret = do_send_one(s, &cu, mtu, polltimeout);
|
||||
if (ret)
|
||||
if ((ret == -EINVAL) && mix) {
|
||||
/* mix mode: disable unsupported CAN frame type */
|
||||
switch (mtu) {
|
||||
case CAN_MTU:
|
||||
mixcc = 0;
|
||||
break;
|
||||
case CANFD_MTU:
|
||||
mixfd = 0;
|
||||
break;
|
||||
case CANXL_MTU:
|
||||
mixxl = 0;
|
||||
break;
|
||||
default:
|
||||
printf ("mix mode: unknown MTU");
|
||||
return 1;
|
||||
}
|
||||
if (!mixcc && !mixfd && !mixxl) {
|
||||
printf ("mix mode: no valid CAN frame types\n");
|
||||
return 1;
|
||||
}
|
||||
} else if (ret) {
|
||||
/* other error than -ENOBUFS and -EINVAL */
|
||||
perror("write");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (burst_sent_count >= burst_count)
|
||||
burst_sent_count = 0;
|
||||
@@ -1082,18 +1115,41 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (mix) {
|
||||
canfd = 0;
|
||||
canxl = 0;
|
||||
i = random();
|
||||
extended = i & 1;
|
||||
canfd = i & 2;
|
||||
if (canfd) {
|
||||
brs = i & 4;
|
||||
esi = i & 8;
|
||||
if (mixfd) {
|
||||
canfd = i & 2;
|
||||
if (canfd) {
|
||||
brs = i & 4;
|
||||
esi = i & 8;
|
||||
}
|
||||
}
|
||||
if (mixxl) {
|
||||
if (mixfd)
|
||||
canxl = ((i & 96) == 96); /* 1/4 */
|
||||
else
|
||||
canxl = ((i & 32) == 32); /* 1/2 */
|
||||
}
|
||||
if (mixcc) {
|
||||
rtr_frame = ((i & 24) == 24); /* reduce RTR to 1/4 */
|
||||
} else {
|
||||
/* no CC frames allowed - CAN XL-only mode? */
|
||||
if (!canxl && !canfd) {
|
||||
/* force XL or FD frames */
|
||||
if (mixxl)
|
||||
canxl = 1;
|
||||
else if (mixfd) {
|
||||
canfd = 1;
|
||||
brs = i & 4;
|
||||
esi = i & 8;
|
||||
} else {
|
||||
printf ("mix mode: no valid CAN frame types\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* generate CAN XL traffic if the interface is capable */
|
||||
if (ifr.ifr_mtu >= (int)CANXL_MIN_MTU)
|
||||
canxl = ((i & 96) == 96);
|
||||
|
||||
rtr_frame = ((i & 24) == 24); /* reduce RTR frames to 1/4 */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+28
-6
@@ -177,7 +177,8 @@ int main(int argc, char **argv)
|
||||
sigset_t sigset;
|
||||
fd_set rdfs;
|
||||
int s[MAXDEV];
|
||||
int socki, accsocket;
|
||||
int socki;
|
||||
int accsocket = -1;
|
||||
canid_t mask[MAXDEV] = {0};
|
||||
canid_t value[MAXDEV] = {0};
|
||||
int inv_filter[MAXDEV] = {0};
|
||||
@@ -191,7 +192,7 @@ int main(int argc, char **argv)
|
||||
.rx_vcid_mask = 0,
|
||||
};
|
||||
struct can_filter rfilter;
|
||||
static cu_t cu; /* union for CAN CC/FD/XL frames */
|
||||
static union cfu cu; /* union for CAN CC/FD/XL frames */
|
||||
const int canfx_on = 1;
|
||||
int nbytes, i, j;
|
||||
struct ifreq ifr;
|
||||
@@ -286,7 +287,7 @@ int main(int argc, char **argv)
|
||||
inaddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
inaddr.sin_port = htons(port);
|
||||
|
||||
while(bind(socki, (struct sockaddr*)&inaddr, sizeof(inaddr)) < 0) {
|
||||
while(running && bind(socki, (struct sockaddr*)&inaddr, sizeof(inaddr)) < 0) {
|
||||
struct timespec f = {
|
||||
.tv_nsec = 100 * 1000 * 1000,
|
||||
};
|
||||
@@ -295,18 +296,28 @@ int main(int argc, char **argv)
|
||||
nanosleep(&f, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if loop exited due to signal (during nanosleep) rather than
|
||||
* successful bind.
|
||||
*/
|
||||
if (!running) {
|
||||
close(socki);
|
||||
return 128 + signal_num;
|
||||
}
|
||||
|
||||
if (listen(socki, 3) != 0) {
|
||||
perror("listen");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while(1) {
|
||||
while(running) {
|
||||
accsocket = accept(socki, (struct sockaddr*)&clientaddr, &sin_size);
|
||||
if (accsocket > 0) {
|
||||
//printf("accepted\n");
|
||||
if (!fork())
|
||||
break;
|
||||
close(accsocket);
|
||||
accsocket = -1;
|
||||
}
|
||||
else if (errno != EINTR) {
|
||||
perror("accept");
|
||||
@@ -314,11 +325,22 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if loop exited due to signal (accept returned EINTR) rather
|
||||
* than successful fork
|
||||
*/
|
||||
if (!running) {
|
||||
if (accsocket > 0)
|
||||
close(accsocket);
|
||||
close(socki);
|
||||
return 128 + signal_num;
|
||||
}
|
||||
|
||||
for (i=0; i<currmax; i++) {
|
||||
|
||||
pr_debug("open %d '%s' m%08X v%08X i%d e%d.\n",
|
||||
i, argv[optind+i], mask[i], value[i],
|
||||
inv_filter[i], err_mask[i]);
|
||||
i, argv[optind+i], mask[i], value[i],
|
||||
inv_filter[i], err_mask[i]);
|
||||
|
||||
if ((s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
|
||||
perror("socket");
|
||||
|
||||
+23
-11
@@ -68,7 +68,7 @@
|
||||
#endif
|
||||
|
||||
#define DEVSZ 22 /* IFNAMSZ + 6 */
|
||||
#define TIMESZ sizeof("(1345212884.318850) ")
|
||||
#define TIMESZ sizeof("(1345212884.318850123) ")
|
||||
#define BUFSZ (TIMESZ + DEVSZ + AFRSZ)
|
||||
|
||||
/* adapt sscanf() functions below on error */
|
||||
@@ -261,7 +261,7 @@ int main(int argc, char **argv)
|
||||
struct can_raw_vcid_options vcid_opts = {
|
||||
.flags = CAN_RAW_XL_VCID_TX_PASS,
|
||||
};
|
||||
static cu_t cu;
|
||||
static union cfu cu;
|
||||
static struct timeval today_tv, log_tv, last_log_tv, diff_tv;
|
||||
struct timespec sleep_ts;
|
||||
int s; /* CAN_RAW socket */
|
||||
@@ -452,14 +452,20 @@ int main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
log_tv.tv_sec = sec;
|
||||
log_tv.tv_usec = usec;
|
||||
|
||||
/*
|
||||
* ensure the fractions of seconds are 6 decimal places long to catch
|
||||
* ensure the fractions of seconds are 6 or 9 decimal places long to catch
|
||||
* 3rd party or handcrafted logfiles that treat the timestamp as float
|
||||
*/
|
||||
if (strchr(buf, ')') - strchr(buf, '.') != 7) {
|
||||
fprintf(stderr, "timestamp format in logfile requires 6 decimal places\n");
|
||||
switch (strchr(buf, ')') - strchr(buf, '.')) {
|
||||
case 7: //6
|
||||
log_tv.tv_usec = usec;
|
||||
break;
|
||||
case 10: //9
|
||||
log_tv.tv_usec = usec / 1000;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "timestamp format in logfile requires 6 or 9 decimal places\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -541,19 +547,25 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
}
|
||||
|
||||
if (sscanf(buf, "(%llu.%llu) %s %s", &sec, &usec, device, afrbuf) != 4) {
|
||||
if (sscanf(buf, "(%llu.%llu) %21s %6299s", &sec, &usec, device, afrbuf) != 4) {
|
||||
fprintf(stderr, "incorrect line format in logfile\n");
|
||||
return 1;
|
||||
}
|
||||
log_tv.tv_sec = sec;
|
||||
log_tv.tv_usec = usec;
|
||||
|
||||
/*
|
||||
* ensure the fractions of seconds are 6 decimal places long to catch
|
||||
* ensure the fractions of seconds are 6 or 9 decimal places long to catch
|
||||
* 3rd party or handcrafted logfiles that treat the timestamp as float
|
||||
*/
|
||||
if (strchr(buf, ')') - strchr(buf, '.') != 7) {
|
||||
fprintf(stderr, "timestamp format in logfile requires 6 decimal places\n");
|
||||
switch (strchr(buf, ')') - strchr(buf, '.')) {
|
||||
case 7: //6
|
||||
log_tv.tv_usec = usec;
|
||||
break;
|
||||
case 10: //9
|
||||
log_tv.tv_usec = usec / 1000;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "timestamp format in logfile requires 6 or 9 decimal places\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,10 @@ static void print_usage(char *prg)
|
||||
"_{dlc}:\n"
|
||||
" an optional 9..F data length code value when payload length is 8\n"
|
||||
"<flags>:\n"
|
||||
" a single ASCII Hex value (0 .. F) which defines canfd_frame.flags\n"
|
||||
" a single ASCII Hex value (0 .. F) which defines canfd_frame.flags:\n"
|
||||
" %x CANFD_BRS\n"
|
||||
" %x CANFD_ESI\n"
|
||||
" %x CANFD_FDF\n"
|
||||
"\n"
|
||||
"<vcid>:\n"
|
||||
" 2 hex chars - virtual CAN network identifier (00 .. FF)\n"
|
||||
@@ -100,7 +103,8 @@ static void print_usage(char *prg)
|
||||
" 1F334455#1122334455667788_B / 123#R / 00000123#R3 / 333#R8_E /\n"
|
||||
" 45123#81:00:12345678#11223344.556677 / 00242#81:07:40000123#112233\n"
|
||||
"\n",
|
||||
prg, prg);
|
||||
prg, prg,
|
||||
CANFD_BRS, CANFD_ESI, CANFD_FDF);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
@@ -113,7 +117,7 @@ int main(int argc, char **argv)
|
||||
struct can_raw_vcid_options vcid_opts = {
|
||||
.flags = CAN_RAW_XL_VCID_TX_PASS,
|
||||
};
|
||||
static cu_t cu;
|
||||
static union cfu cu;
|
||||
struct ifreq ifr;
|
||||
|
||||
/* check command line options */
|
||||
|
||||
+11
-11
@@ -161,15 +161,15 @@ void switchvdl(char *delim)
|
||||
|
||||
int comp(const void *elem1, const void *elem2)
|
||||
{
|
||||
unsigned long f = ((struct snif*)elem1)->current.can_id;
|
||||
unsigned long s = ((struct snif*)elem2)->current.can_id;
|
||||
unsigned long f = ((struct snif*)elem1)->current.can_id;
|
||||
unsigned long s = ((struct snif*)elem2)->current.can_id;
|
||||
|
||||
if (f > s)
|
||||
return 1;
|
||||
if (f < s)
|
||||
return -1;
|
||||
if (f > s)
|
||||
return 1;
|
||||
if (f < s)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void print_usage(char *prg)
|
||||
@@ -741,10 +741,10 @@ int handle_timeo(long currcms)
|
||||
do_clr(i, UPDATE);
|
||||
}
|
||||
else if ((sniftab[i].hold) && (sniftab[i].hold < currcms)) {
|
||||
memset(&sniftab[i].marker.data, 0, max_dlen);
|
||||
print_snifline(i);
|
||||
sniftab[i].hold = 0; /* disable update by hold */
|
||||
}
|
||||
memset(&sniftab[i].marker.data, 0, max_dlen);
|
||||
print_snifline(i);
|
||||
sniftab[i].hold = 0; /* disable update by hold */
|
||||
}
|
||||
else
|
||||
printf("%s", CSR_DOWN); /* skip my line */
|
||||
|
||||
|
||||
+88
-88
@@ -426,112 +426,112 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (frame.can_id & CAN_EFF_FLAG)
|
||||
printf(" %s %8X", argv[optind], frame.can_id & CAN_EFF_MASK);
|
||||
else
|
||||
printf(" %s %3X", argv[optind], frame.can_id & CAN_SFF_MASK);
|
||||
if (frame.can_id & CAN_EFF_FLAG)
|
||||
printf(" %s %8X", argv[optind], frame.can_id & CAN_EFF_MASK);
|
||||
else
|
||||
printf(" %s %3X", argv[optind], frame.can_id & CAN_SFF_MASK);
|
||||
|
||||
if (ext)
|
||||
printf("{%02X}", frame.data[0]);
|
||||
if (ext)
|
||||
printf("{%02X}", frame.data[0]);
|
||||
|
||||
if (nbytes == CAN_MTU)
|
||||
printf(" [%d] ", frame.len);
|
||||
else
|
||||
printf(" [%02d] ", frame.len);
|
||||
if (nbytes == CAN_MTU)
|
||||
printf(" [%d] ", frame.len);
|
||||
else
|
||||
printf(" [%02d] ", frame.len);
|
||||
|
||||
datidx = 0;
|
||||
n_pci = frame.data[ext];
|
||||
datidx = 0;
|
||||
n_pci = frame.data[ext];
|
||||
|
||||
switch (n_pci & 0xF0) {
|
||||
case 0x00:
|
||||
is_ff = 1;
|
||||
if (n_pci & 0xF) {
|
||||
printf("[SF] ln: %-4d data:", n_pci & 0xF);
|
||||
datidx = ext+1;
|
||||
} else {
|
||||
printf("[SF] ln: %-4d data:", frame.data[ext + 1]);
|
||||
datidx = ext+2;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
is_ff = 1;
|
||||
fflen = ((n_pci & 0x0F)<<8) + frame.data[ext+1];
|
||||
if (fflen)
|
||||
datidx = ext+2;
|
||||
else {
|
||||
fflen = (frame.data[ext+2]<<24) +
|
||||
(frame.data[ext+3]<<16) +
|
||||
(frame.data[ext+4]<<8) +
|
||||
frame.data[ext+5];
|
||||
datidx = ext+6;
|
||||
}
|
||||
printf("[FF] ln: %-4lu data:", fflen);
|
||||
break;
|
||||
|
||||
case 0x20:
|
||||
printf("[CF] sn: %X data:", n_pci & 0x0F);
|
||||
switch (n_pci & 0xF0) {
|
||||
case 0x00:
|
||||
is_ff = 1;
|
||||
if (n_pci & 0xF) {
|
||||
printf("[SF] ln: %-4d data:", n_pci & 0xF);
|
||||
datidx = ext+1;
|
||||
break;
|
||||
} else {
|
||||
printf("[SF] ln: %-4d data:", frame.data[ext + 1]);
|
||||
datidx = ext+2;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x30:
|
||||
n_pci &= 0x0F;
|
||||
printf("[FC] FC: %d ", n_pci);
|
||||
case 0x10:
|
||||
is_ff = 1;
|
||||
fflen = ((n_pci & 0x0F)<<8) + frame.data[ext+1];
|
||||
if (fflen)
|
||||
datidx = ext+2;
|
||||
else {
|
||||
fflen = (frame.data[ext+2]<<24) +
|
||||
(frame.data[ext+3]<<16) +
|
||||
(frame.data[ext+4]<<8) +
|
||||
frame.data[ext+5];
|
||||
datidx = ext+6;
|
||||
}
|
||||
printf("[FF] ln: %-4lu data:", fflen);
|
||||
break;
|
||||
|
||||
if (n_pci > 3)
|
||||
n_pci = 3;
|
||||
case 0x20:
|
||||
printf("[CF] sn: %X data:", n_pci & 0x0F);
|
||||
datidx = ext+1;
|
||||
break;
|
||||
|
||||
printf("= %s # ", fc_info[n_pci]);
|
||||
case 0x30:
|
||||
n_pci &= 0x0F;
|
||||
printf("[FC] FC: %d ", n_pci);
|
||||
|
||||
printf("BS: %d %s# ", frame.data[ext+1],
|
||||
(frame.data[ext+1])? "":"= off ");
|
||||
if (n_pci > 3)
|
||||
n_pci = 3;
|
||||
|
||||
i = frame.data[ext+2];
|
||||
printf("STmin: 0x%02X = ", i);
|
||||
printf("= %s # ", fc_info[n_pci]);
|
||||
|
||||
if (i < 0x80)
|
||||
printf("%d ms", i);
|
||||
else if (i > 0xF0 && i < 0xFA)
|
||||
printf("%d us", (i & 0x0F) * 100);
|
||||
else
|
||||
printf("reserved");
|
||||
break;
|
||||
printf("BS: %d %s# ", frame.data[ext+1],
|
||||
(frame.data[ext+1])? "":"= off ");
|
||||
|
||||
default:
|
||||
printf("[??]");
|
||||
i = frame.data[ext+2];
|
||||
printf("STmin: 0x%02X = ", i);
|
||||
|
||||
if (i < 0x80)
|
||||
printf("%d ms", i);
|
||||
else if (i > 0xF0 && i < 0xFA)
|
||||
printf("%d us", (i & 0x0F) * 100);
|
||||
else
|
||||
printf("reserved");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("[??]");
|
||||
}
|
||||
|
||||
if (datidx && frame.len > datidx) {
|
||||
printf(" ");
|
||||
for (i = datidx; i < frame.len; i++) {
|
||||
printf("%02X ", frame.data[i]);
|
||||
}
|
||||
|
||||
if (datidx && frame.len > datidx) {
|
||||
printf(" ");
|
||||
if (asc) {
|
||||
printf("%*s", ((7-ext) - (frame.len-datidx))*3 + 5 ,
|
||||
"- '");
|
||||
for (i = datidx; i < frame.len; i++) {
|
||||
printf("%02X ", frame.data[i]);
|
||||
}
|
||||
|
||||
if (asc) {
|
||||
printf("%*s", ((7-ext) - (frame.len-datidx))*3 + 5 ,
|
||||
"- '");
|
||||
for (i = datidx; i < frame.len; i++) {
|
||||
printf("%c",((frame.data[i] > 0x1F) &&
|
||||
(frame.data[i] < 0x7F))?
|
||||
frame.data[i] : '.');
|
||||
}
|
||||
printf("'");
|
||||
}
|
||||
if (uds_output && is_ff) {
|
||||
int offset = 3;
|
||||
if (asc)
|
||||
offset = 1;
|
||||
printf("%*s", ((7-ext) - (frame.len-datidx))*offset + 3,
|
||||
" - ");
|
||||
print_uds_message(frame.data[datidx], frame.data[datidx+2]);
|
||||
is_ff = 0;
|
||||
printf("%c",((frame.data[i] > 0x1F) &&
|
||||
(frame.data[i] < 0x7F))?
|
||||
frame.data[i] : '.');
|
||||
}
|
||||
printf("'");
|
||||
}
|
||||
if (uds_output && is_ff) {
|
||||
int offset = 3;
|
||||
if (asc)
|
||||
offset = 1;
|
||||
printf("%*s", ((7-ext) - (frame.len-datidx))*offset + 3,
|
||||
" - ");
|
||||
print_uds_message(frame.data[datidx], frame.data[datidx+2]);
|
||||
is_ff = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (color)
|
||||
printf("%s", ATTRESET);
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
if (color)
|
||||
printf("%s", ATTRESET);
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
close(s);
|
||||
|
||||
+162
-162
@@ -243,177 +243,177 @@ int main(int argc, char **argv)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check extended address if provided */
|
||||
if (ext && extaddr != frame.data[0])
|
||||
continue;
|
||||
|
||||
/* only get flow control information from dst CAN ID */
|
||||
if (frame.can_id == dst) {
|
||||
/* check extended address if provided */
|
||||
if (ext && extaddr != frame.data[0])
|
||||
if (rx_ext && frame.data[0] != rx_extaddr)
|
||||
continue;
|
||||
|
||||
/* only get flow control information from dst CAN ID */
|
||||
if (frame.can_id == dst) {
|
||||
/* check extended address if provided */
|
||||
if (rx_ext && frame.data[0] != rx_extaddr)
|
||||
continue;
|
||||
n_pci = frame.data[rx_ext];
|
||||
/* check flow control PCI only */
|
||||
if ((n_pci & 0xF0) != 0x30)
|
||||
continue;
|
||||
|
||||
n_pci = frame.data[rx_ext];
|
||||
/* check flow control PCI only */
|
||||
if ((n_pci & 0xF0) != 0x30)
|
||||
continue;
|
||||
bs = frame.data[rx_ext + 1];
|
||||
stmin = frame.data[rx_ext + 2];
|
||||
}
|
||||
|
||||
bs = frame.data[rx_ext + 1];
|
||||
stmin = frame.data[rx_ext + 2];
|
||||
/* data content starts and index datidx */
|
||||
datidx = 0;
|
||||
|
||||
n_pci = frame.data[ext];
|
||||
switch (n_pci & 0xF0) {
|
||||
|
||||
case 0x00:
|
||||
/* SF */
|
||||
if (n_pci & 0xF) {
|
||||
fflen = rcvlen = n_pci & 0xF;
|
||||
datidx = ext+1;
|
||||
} else {
|
||||
fflen = rcvlen = frame.data[ext + 1];
|
||||
datidx = ext+2;
|
||||
}
|
||||
|
||||
/* data content starts and index datidx */
|
||||
datidx = 0;
|
||||
|
||||
n_pci = frame.data[ext];
|
||||
switch (n_pci & 0xF0) {
|
||||
|
||||
case 0x00:
|
||||
/* SF */
|
||||
if (n_pci & 0xF) {
|
||||
fflen = rcvlen = n_pci & 0xF;
|
||||
datidx = ext+1;
|
||||
} else {
|
||||
fflen = rcvlen = frame.data[ext + 1];
|
||||
datidx = ext+2;
|
||||
}
|
||||
|
||||
/* ignore incorrect SF PDUs */
|
||||
if (frame.len < rcvlen + datidx)
|
||||
fflen = rcvlen = 0;
|
||||
|
||||
/* get number of digits for printing */
|
||||
fflen_digits = getdigits(fflen);
|
||||
|
||||
/* get CAN FD bitrate & LL_DL setting information */
|
||||
brs = frame.flags & CANFD_BRS;
|
||||
ll_dl = frame.len;
|
||||
if (ll_dl < 8)
|
||||
ll_dl = 8;
|
||||
|
||||
ioctl(s, SIOCGSTAMP, &start_tv);
|
||||
|
||||
/* determine CAN frame mode for this PDU */
|
||||
if (nbytes == CAN_MTU)
|
||||
canfd_on = 0;
|
||||
else
|
||||
canfd_on = 1;
|
||||
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
/* FF */
|
||||
fflen = ((n_pci & 0x0F)<<8) + frame.data[ext+1];
|
||||
if (fflen)
|
||||
datidx = ext+2;
|
||||
else {
|
||||
fflen = (frame.data[ext+2]<<24) +
|
||||
(frame.data[ext+3]<<16) +
|
||||
(frame.data[ext+4]<<8) +
|
||||
frame.data[ext+5];
|
||||
datidx = ext+6;
|
||||
}
|
||||
|
||||
/* to increase the time resolution we multiply fflen with 1000 later */
|
||||
if (fflen >= (UINT32_MAX / 1000)) {
|
||||
printf("fflen %lu is more than ~4.2 MB - ignoring PDU\n", fflen);
|
||||
fflush(stdout);
|
||||
fflen = rcvlen = 0;
|
||||
continue;
|
||||
}
|
||||
rcvlen = frame.len - datidx;
|
||||
last_sn = 0;
|
||||
|
||||
/* get number of digits for printing */
|
||||
fflen_digits = getdigits(fflen);
|
||||
|
||||
/* get CAN FD bitrate & LL_DL setting information */
|
||||
brs = frame.flags & CANFD_BRS;
|
||||
ll_dl = frame.len;
|
||||
|
||||
ioctl(s, SIOCGSTAMP, &start_tv);
|
||||
|
||||
/* determine CAN frame mode for this PDU */
|
||||
if (nbytes == CAN_MTU)
|
||||
canfd_on = 0;
|
||||
else
|
||||
canfd_on = 1;
|
||||
|
||||
break;
|
||||
|
||||
case 0x20:
|
||||
/* CF */
|
||||
if (rcvlen) {
|
||||
sn = n_pci & 0x0F;
|
||||
if (sn == ((last_sn + 1) & 0xF)) {
|
||||
last_sn = sn;
|
||||
datidx = ext+1;
|
||||
rcvlen += frame.len - datidx;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* PDU reception in process */
|
||||
if (rcvlen) {
|
||||
if (rcvlen > fflen)
|
||||
rcvlen = fflen;
|
||||
|
||||
percent = (rcvlen * 100 / fflen);
|
||||
printf("\r %3lu%% ", percent);
|
||||
|
||||
printf("|");
|
||||
|
||||
if (percent > 100)
|
||||
percent = 100;
|
||||
|
||||
for (i=0; i < NUMBAR; i++){
|
||||
if (i < (int)(percent/PERCENTRES))
|
||||
printf("X");
|
||||
else
|
||||
printf(".");
|
||||
}
|
||||
printf("| %*lu/%lu ", fflen_digits, rcvlen, fflen);
|
||||
}
|
||||
|
||||
/* PDU complete */
|
||||
if (rcvlen && rcvlen >= fflen) {
|
||||
|
||||
printf("\r%s %02d%c (BS:%2hhu # ", canfd_on?"CAN-FD":"CAN2.0", ll_dl, brs?'*':' ', bs);
|
||||
if (stmin < 0x80)
|
||||
printf("STmin:%3hhu msec)", stmin);
|
||||
else if (stmin > 0xF0 && stmin < 0xFA)
|
||||
printf("STmin:%3u usec)", (stmin & 0xF) * 100);
|
||||
else
|
||||
printf("STmin: invalid )");
|
||||
|
||||
printf(" : %lu byte in ", fflen);
|
||||
|
||||
/* calculate time */
|
||||
ioctl(s, SIOCGSTAMP, &end_tv);
|
||||
diff_tv.tv_sec = end_tv.tv_sec - start_tv.tv_sec;
|
||||
diff_tv.tv_usec = end_tv.tv_usec - start_tv.tv_usec;
|
||||
if (diff_tv.tv_usec < 0)
|
||||
diff_tv.tv_sec--, diff_tv.tv_usec += 1000000;
|
||||
if (diff_tv.tv_sec < 0)
|
||||
diff_tv.tv_sec = diff_tv.tv_usec = 0;
|
||||
|
||||
/* check devisor to be not zero */
|
||||
if (diff_tv.tv_sec * 1000 + diff_tv.tv_usec / 1000){
|
||||
printf("%llu.%06llus ", (unsigned long long)diff_tv.tv_sec, (unsigned long long)diff_tv.tv_usec);
|
||||
printf("=> %lu byte/s", (fflen * 1000) /
|
||||
(unsigned long)(diff_tv.tv_sec * 1000 + diff_tv.tv_usec / 1000));
|
||||
} else
|
||||
printf("(no time available) ");
|
||||
|
||||
printf("\n");
|
||||
/* wait for next PDU */
|
||||
/* ignore incorrect SF PDUs */
|
||||
if (frame.len < rcvlen + datidx)
|
||||
fflen = rcvlen = 0;
|
||||
|
||||
/* get number of digits for printing */
|
||||
fflen_digits = getdigits(fflen);
|
||||
|
||||
/* get CAN FD bitrate & LL_DL setting information */
|
||||
brs = frame.flags & CANFD_BRS;
|
||||
ll_dl = frame.len;
|
||||
if (ll_dl < 8)
|
||||
ll_dl = 8;
|
||||
|
||||
ioctl(s, SIOCGSTAMP, &start_tv);
|
||||
|
||||
/* determine CAN frame mode for this PDU */
|
||||
if (nbytes == CAN_MTU)
|
||||
canfd_on = 0;
|
||||
else
|
||||
canfd_on = 1;
|
||||
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
/* FF */
|
||||
fflen = ((n_pci & 0x0F)<<8) + frame.data[ext+1];
|
||||
if (fflen)
|
||||
datidx = ext+2;
|
||||
else {
|
||||
fflen = (frame.data[ext+2]<<24) +
|
||||
(frame.data[ext+3]<<16) +
|
||||
(frame.data[ext+4]<<8) +
|
||||
frame.data[ext+5];
|
||||
datidx = ext+6;
|
||||
}
|
||||
fflush(stdout);
|
||||
|
||||
/* to increase the time resolution we multiply fflen with 1000 later */
|
||||
if (fflen >= (UINT32_MAX / 1000)) {
|
||||
printf("fflen %lu is more than ~4.2 MB - ignoring PDU\n", fflen);
|
||||
fflush(stdout);
|
||||
fflen = rcvlen = 0;
|
||||
continue;
|
||||
}
|
||||
rcvlen = frame.len - datidx;
|
||||
last_sn = 0;
|
||||
|
||||
/* get number of digits for printing */
|
||||
fflen_digits = getdigits(fflen);
|
||||
|
||||
/* get CAN FD bitrate & LL_DL setting information */
|
||||
brs = frame.flags & CANFD_BRS;
|
||||
ll_dl = frame.len;
|
||||
|
||||
ioctl(s, SIOCGSTAMP, &start_tv);
|
||||
|
||||
/* determine CAN frame mode for this PDU */
|
||||
if (nbytes == CAN_MTU)
|
||||
canfd_on = 0;
|
||||
else
|
||||
canfd_on = 1;
|
||||
|
||||
break;
|
||||
|
||||
case 0x20:
|
||||
/* CF */
|
||||
if (rcvlen) {
|
||||
sn = n_pci & 0x0F;
|
||||
if (sn == ((last_sn + 1) & 0xF)) {
|
||||
last_sn = sn;
|
||||
datidx = ext+1;
|
||||
rcvlen += frame.len - datidx;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* PDU reception in process */
|
||||
if (rcvlen) {
|
||||
if (rcvlen > fflen)
|
||||
rcvlen = fflen;
|
||||
|
||||
percent = (rcvlen * 100 / fflen);
|
||||
printf("\r %3lu%% ", percent);
|
||||
|
||||
printf("|");
|
||||
|
||||
if (percent > 100)
|
||||
percent = 100;
|
||||
|
||||
for (i=0; i < NUMBAR; i++){
|
||||
if (i < (int)(percent/PERCENTRES))
|
||||
printf("X");
|
||||
else
|
||||
printf(".");
|
||||
}
|
||||
printf("| %*lu/%lu ", fflen_digits, rcvlen, fflen);
|
||||
}
|
||||
|
||||
/* PDU complete */
|
||||
if (rcvlen && rcvlen >= fflen) {
|
||||
|
||||
printf("\r%s %02d%c (BS:%2hhu # ", canfd_on?"CAN-FD":"CAN2.0", ll_dl, brs?'*':' ', bs);
|
||||
if (stmin < 0x80)
|
||||
printf("STmin:%3hhu msec)", stmin);
|
||||
else if (stmin > 0xF0 && stmin < 0xFA)
|
||||
printf("STmin:%3u usec)", (stmin & 0xF) * 100);
|
||||
else
|
||||
printf("STmin: invalid )");
|
||||
|
||||
printf(" : %lu byte in ", fflen);
|
||||
|
||||
/* calculate time */
|
||||
ioctl(s, SIOCGSTAMP, &end_tv);
|
||||
diff_tv.tv_sec = end_tv.tv_sec - start_tv.tv_sec;
|
||||
diff_tv.tv_usec = end_tv.tv_usec - start_tv.tv_usec;
|
||||
if (diff_tv.tv_usec < 0)
|
||||
diff_tv.tv_sec--, diff_tv.tv_usec += 1000000;
|
||||
if (diff_tv.tv_sec < 0)
|
||||
diff_tv.tv_sec = diff_tv.tv_usec = 0;
|
||||
|
||||
/* check devisor to be not zero */
|
||||
if (diff_tv.tv_sec * 1000 + diff_tv.tv_usec / 1000){
|
||||
printf("%llu.%06llus ", (unsigned long long)diff_tv.tv_sec, (unsigned long long)diff_tv.tv_usec);
|
||||
printf("=> %lu byte/s", (fflen * 1000) /
|
||||
(unsigned long)(diff_tv.tv_sec * 1000 + diff_tv.tv_usec / 1000));
|
||||
} else
|
||||
printf("(no time available) ");
|
||||
|
||||
printf("\n");
|
||||
/* wait for next PDU */
|
||||
fflen = rcvlen = 0;
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
close(s);
|
||||
|
||||
+155
-155
@@ -82,183 +82,183 @@ void print_usage(char *prg)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int s;
|
||||
struct sockaddr_can addr;
|
||||
static struct can_isotp_options opts;
|
||||
static struct can_isotp_fc_options fcopts;
|
||||
static struct can_isotp_ll_options llopts;
|
||||
int opt, i;
|
||||
extern int optind, opterr, optopt;
|
||||
__u32 force_rx_stmin = 0;
|
||||
int loop = 0;
|
||||
int s;
|
||||
struct sockaddr_can addr;
|
||||
static struct can_isotp_options opts;
|
||||
static struct can_isotp_fc_options fcopts;
|
||||
static struct can_isotp_ll_options llopts;
|
||||
int opt, i;
|
||||
extern int optind, opterr, optopt;
|
||||
__u32 force_rx_stmin = 0;
|
||||
int loop = 0;
|
||||
|
||||
unsigned char msg[BUFSIZE];
|
||||
int nbytes;
|
||||
unsigned char msg[BUFSIZE];
|
||||
int nbytes;
|
||||
|
||||
addr.can_addr.tp.tx_id = addr.can_addr.tp.rx_id = NO_CAN_ID;
|
||||
addr.can_addr.tp.tx_id = addr.can_addr.tp.rx_id = NO_CAN_ID;
|
||||
|
||||
while ((opt = getopt(argc, argv, "s:d:x:p:P:b:m:w:f:lFL:?")) != -1) {
|
||||
switch (opt) {
|
||||
case 's':
|
||||
addr.can_addr.tp.tx_id = strtoul(optarg, NULL, 16);
|
||||
if (strlen(optarg) > 7)
|
||||
addr.can_addr.tp.tx_id |= CAN_EFF_FLAG;
|
||||
break;
|
||||
while ((opt = getopt(argc, argv, "s:d:x:p:P:b:m:w:f:lFL:?")) != -1) {
|
||||
switch (opt) {
|
||||
case 's':
|
||||
addr.can_addr.tp.tx_id = strtoul(optarg, NULL, 16);
|
||||
if (strlen(optarg) > 7)
|
||||
addr.can_addr.tp.tx_id |= CAN_EFF_FLAG;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
addr.can_addr.tp.rx_id = strtoul(optarg, NULL, 16);
|
||||
if (strlen(optarg) > 7)
|
||||
addr.can_addr.tp.rx_id |= CAN_EFF_FLAG;
|
||||
break;
|
||||
case 'd':
|
||||
addr.can_addr.tp.rx_id = strtoul(optarg, NULL, 16);
|
||||
if (strlen(optarg) > 7)
|
||||
addr.can_addr.tp.rx_id |= CAN_EFF_FLAG;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
{
|
||||
int elements = sscanf(optarg, "%hhx:%hhx",
|
||||
&opts.ext_address,
|
||||
&opts.rx_ext_address);
|
||||
case 'x':
|
||||
{
|
||||
int elements = sscanf(optarg, "%hhx:%hhx",
|
||||
&opts.ext_address,
|
||||
&opts.rx_ext_address);
|
||||
|
||||
if (elements == 1)
|
||||
opts.flags |= CAN_ISOTP_EXTEND_ADDR;
|
||||
else if (elements == 2)
|
||||
opts.flags |= (CAN_ISOTP_EXTEND_ADDR | CAN_ISOTP_RX_EXT_ADDR);
|
||||
else {
|
||||
printf("incorrect extended addr values '%s'.\n", optarg);
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (elements == 1)
|
||||
opts.flags |= CAN_ISOTP_EXTEND_ADDR;
|
||||
else if (elements == 2)
|
||||
opts.flags |= (CAN_ISOTP_EXTEND_ADDR | CAN_ISOTP_RX_EXT_ADDR);
|
||||
else {
|
||||
printf("incorrect extended addr values '%s'.\n", optarg);
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p':
|
||||
{
|
||||
int elements = sscanf(optarg, "%hhx:%hhx",
|
||||
&opts.txpad_content,
|
||||
&opts.rxpad_content);
|
||||
case 'p':
|
||||
{
|
||||
int elements = sscanf(optarg, "%hhx:%hhx",
|
||||
&opts.txpad_content,
|
||||
&opts.rxpad_content);
|
||||
|
||||
if (elements == 1)
|
||||
opts.flags |= CAN_ISOTP_TX_PADDING;
|
||||
else if (elements == 2)
|
||||
opts.flags |= (CAN_ISOTP_TX_PADDING | CAN_ISOTP_RX_PADDING);
|
||||
else if (sscanf(optarg, ":%hhx", &opts.rxpad_content) == 1)
|
||||
opts.flags |= CAN_ISOTP_RX_PADDING;
|
||||
else {
|
||||
printf("incorrect padding values '%s'.\n", optarg);
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (elements == 1)
|
||||
opts.flags |= CAN_ISOTP_TX_PADDING;
|
||||
else if (elements == 2)
|
||||
opts.flags |= (CAN_ISOTP_TX_PADDING | CAN_ISOTP_RX_PADDING);
|
||||
else if (sscanf(optarg, ":%hhx", &opts.rxpad_content) == 1)
|
||||
opts.flags |= CAN_ISOTP_RX_PADDING;
|
||||
else {
|
||||
printf("incorrect padding values '%s'.\n", optarg);
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'P':
|
||||
if (optarg[0] == 'l')
|
||||
opts.flags |= CAN_ISOTP_CHK_PAD_LEN;
|
||||
else if (optarg[0] == 'c')
|
||||
opts.flags |= CAN_ISOTP_CHK_PAD_DATA;
|
||||
else if (optarg[0] == 'a')
|
||||
opts.flags |= (CAN_ISOTP_CHK_PAD_LEN | CAN_ISOTP_CHK_PAD_DATA);
|
||||
else {
|
||||
printf("unknown padding check option '%c'.\n", optarg[0]);
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
case 'P':
|
||||
if (optarg[0] == 'l')
|
||||
opts.flags |= CAN_ISOTP_CHK_PAD_LEN;
|
||||
else if (optarg[0] == 'c')
|
||||
opts.flags |= CAN_ISOTP_CHK_PAD_DATA;
|
||||
else if (optarg[0] == 'a')
|
||||
opts.flags |= (CAN_ISOTP_CHK_PAD_LEN | CAN_ISOTP_CHK_PAD_DATA);
|
||||
else {
|
||||
printf("unknown padding check option '%c'.\n", optarg[0]);
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
fcopts.bs = strtoul(optarg, NULL, 16) & 0xFF;
|
||||
break;
|
||||
case 'b':
|
||||
fcopts.bs = strtoul(optarg, NULL, 16) & 0xFF;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
fcopts.stmin = strtoul(optarg, NULL, 16) & 0xFF;
|
||||
break;
|
||||
case 'm':
|
||||
fcopts.stmin = strtoul(optarg, NULL, 16) & 0xFF;
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
fcopts.wftmax = strtoul(optarg, NULL, 16) & 0xFF;
|
||||
break;
|
||||
case 'w':
|
||||
fcopts.wftmax = strtoul(optarg, NULL, 16) & 0xFF;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
opts.flags |= CAN_ISOTP_FORCE_RXSTMIN;
|
||||
force_rx_stmin = strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
case 'f':
|
||||
opts.flags |= CAN_ISOTP_FORCE_RXSTMIN;
|
||||
force_rx_stmin = strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
loop = 1;
|
||||
break;
|
||||
case 'l':
|
||||
loop = 1;
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
opts.flags |= CAN_ISOTP_DYN_FC_PARMS;
|
||||
break;
|
||||
case 'F':
|
||||
opts.flags |= CAN_ISOTP_DYN_FC_PARMS;
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
if (sscanf(optarg, "%hhu:%hhu:%hhu",
|
||||
&llopts.mtu,
|
||||
&llopts.tx_dl,
|
||||
&llopts.tx_flags) != 3) {
|
||||
printf("unknown link layer options '%s'.\n", optarg);
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
case 'L':
|
||||
if (sscanf(optarg, "%hhu:%hhu:%hhu",
|
||||
&llopts.mtu,
|
||||
&llopts.tx_dl,
|
||||
&llopts.tx_flags) != 3) {
|
||||
printf("unknown link layer options '%s'.\n", optarg);
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
|
||||
case '?':
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
break;
|
||||
case '?':
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unknown option %c\n", opt);
|
||||
print_usage(basename(argv[0]));
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((argc - optind != 1) ||
|
||||
(addr.can_addr.tp.tx_id == NO_CAN_ID) ||
|
||||
(addr.can_addr.tp.rx_id == NO_CAN_ID)) {
|
||||
print_usage(basename(argv[0]));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((s = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP)) < 0) {
|
||||
perror("socket");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts));
|
||||
setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_RECV_FC, &fcopts, sizeof(fcopts));
|
||||
|
||||
if (llopts.tx_dl) {
|
||||
if (setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_LL_OPTS, &llopts, sizeof(llopts)) < 0) {
|
||||
perror("link layer sockopt");
|
||||
exit(1);
|
||||
default:
|
||||
fprintf(stderr, "Unknown option %c\n", opt);
|
||||
print_usage(basename(argv[0]));
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.flags & CAN_ISOTP_FORCE_RXSTMIN)
|
||||
setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_RX_STMIN, &force_rx_stmin, sizeof(force_rx_stmin));
|
||||
if ((argc - optind != 1) ||
|
||||
(addr.can_addr.tp.tx_id == NO_CAN_ID) ||
|
||||
(addr.can_addr.tp.rx_id == NO_CAN_ID)) {
|
||||
print_usage(basename(argv[0]));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
addr.can_family = AF_CAN;
|
||||
addr.can_ifindex = if_nametoindex(argv[optind]);
|
||||
if (!addr.can_ifindex) {
|
||||
perror("if_nametoindex");
|
||||
exit(1);
|
||||
}
|
||||
if ((s = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP)) < 0) {
|
||||
perror("socket");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts));
|
||||
setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_RECV_FC, &fcopts, sizeof(fcopts));
|
||||
|
||||
if (llopts.tx_dl) {
|
||||
if (setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_LL_OPTS, &llopts, sizeof(llopts)) < 0) {
|
||||
perror("link layer sockopt");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.flags & CAN_ISOTP_FORCE_RXSTMIN)
|
||||
setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_RX_STMIN, &force_rx_stmin, sizeof(force_rx_stmin));
|
||||
|
||||
addr.can_family = AF_CAN;
|
||||
addr.can_ifindex = if_nametoindex(argv[optind]);
|
||||
if (!addr.can_ifindex) {
|
||||
perror("if_nametoindex");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
perror("bind");
|
||||
close(s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
do {
|
||||
nbytes = read(s, msg, BUFSIZE);
|
||||
if (nbytes > 0 && nbytes < BUFSIZE)
|
||||
for (i=0; i < nbytes; i++)
|
||||
printf("%02X ", msg[i]);
|
||||
printf("\n");
|
||||
} while (loop);
|
||||
|
||||
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
perror("bind");
|
||||
close(s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
do {
|
||||
nbytes = read(s, msg, BUFSIZE);
|
||||
if (nbytes > 0 && nbytes < BUFSIZE)
|
||||
for (i=0; i < nbytes; i++)
|
||||
printf("%02X ", msg[i]);
|
||||
printf("\n");
|
||||
} while (loop);
|
||||
|
||||
close(s);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
+200
-200
@@ -86,238 +86,238 @@ void print_usage(char *prg)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int s;
|
||||
struct sockaddr_can addr;
|
||||
static struct can_isotp_options opts;
|
||||
static struct can_isotp_ll_options llopts;
|
||||
int opt;
|
||||
extern int optind, opterr, optopt;
|
||||
unsigned int loops = 1; /* one (== no) loop by default */
|
||||
useconds_t usecs = 0; /* wait before sending the PDU */
|
||||
__u32 force_tx_stmin = 0;
|
||||
unsigned char buf[BUFSIZE];
|
||||
int buflen = 0;
|
||||
int datalen = 0;
|
||||
int retval = 0;
|
||||
int s;
|
||||
struct sockaddr_can addr;
|
||||
static struct can_isotp_options opts;
|
||||
static struct can_isotp_ll_options llopts;
|
||||
int opt;
|
||||
extern int optind, opterr, optopt;
|
||||
unsigned int loops = 1; /* one (== no) loop by default */
|
||||
useconds_t usecs = 0; /* wait before sending the PDU */
|
||||
__u32 force_tx_stmin = 0;
|
||||
unsigned char buf[BUFSIZE];
|
||||
int buflen = 0;
|
||||
int datalen = 0;
|
||||
int retval = 0;
|
||||
|
||||
addr.can_addr.tp.tx_id = addr.can_addr.tp.rx_id = NO_CAN_ID;
|
||||
addr.can_addr.tp.tx_id = addr.can_addr.tp.rx_id = NO_CAN_ID;
|
||||
|
||||
while ((opt = getopt(argc, argv, "s:d:x:p:P:t:f:D:l:g:bSCL:?")) != -1) {
|
||||
switch (opt) {
|
||||
case 's':
|
||||
addr.can_addr.tp.tx_id = strtoul(optarg, NULL, 16);
|
||||
if (strlen(optarg) > 7)
|
||||
addr.can_addr.tp.tx_id |= CAN_EFF_FLAG;
|
||||
break;
|
||||
while ((opt = getopt(argc, argv, "s:d:x:p:P:t:f:D:l:g:bSCL:?")) != -1) {
|
||||
switch (opt) {
|
||||
case 's':
|
||||
addr.can_addr.tp.tx_id = strtoul(optarg, NULL, 16);
|
||||
if (strlen(optarg) > 7)
|
||||
addr.can_addr.tp.tx_id |= CAN_EFF_FLAG;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
addr.can_addr.tp.rx_id = strtoul(optarg, NULL, 16);
|
||||
if (strlen(optarg) > 7)
|
||||
addr.can_addr.tp.rx_id |= CAN_EFF_FLAG;
|
||||
break;
|
||||
case 'd':
|
||||
addr.can_addr.tp.rx_id = strtoul(optarg, NULL, 16);
|
||||
if (strlen(optarg) > 7)
|
||||
addr.can_addr.tp.rx_id |= CAN_EFF_FLAG;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
{
|
||||
int elements = sscanf(optarg, "%hhx:%hhx",
|
||||
&opts.ext_address,
|
||||
&opts.rx_ext_address);
|
||||
case 'x':
|
||||
{
|
||||
int elements = sscanf(optarg, "%hhx:%hhx",
|
||||
&opts.ext_address,
|
||||
&opts.rx_ext_address);
|
||||
|
||||
if (elements == 1)
|
||||
opts.flags |= CAN_ISOTP_EXTEND_ADDR;
|
||||
else if (elements == 2)
|
||||
opts.flags |= (CAN_ISOTP_EXTEND_ADDR | CAN_ISOTP_RX_EXT_ADDR);
|
||||
else {
|
||||
printf("incorrect extended addr values '%s'.\n", optarg);
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (elements == 1)
|
||||
opts.flags |= CAN_ISOTP_EXTEND_ADDR;
|
||||
else if (elements == 2)
|
||||
opts.flags |= (CAN_ISOTP_EXTEND_ADDR | CAN_ISOTP_RX_EXT_ADDR);
|
||||
else {
|
||||
printf("incorrect extended addr values '%s'.\n", optarg);
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p':
|
||||
{
|
||||
int elements = sscanf(optarg, "%hhx:%hhx",
|
||||
&opts.txpad_content,
|
||||
&opts.rxpad_content);
|
||||
case 'p':
|
||||
{
|
||||
int elements = sscanf(optarg, "%hhx:%hhx",
|
||||
&opts.txpad_content,
|
||||
&opts.rxpad_content);
|
||||
|
||||
if (elements == 1)
|
||||
opts.flags |= CAN_ISOTP_TX_PADDING;
|
||||
else if (elements == 2)
|
||||
opts.flags |= (CAN_ISOTP_TX_PADDING | CAN_ISOTP_RX_PADDING);
|
||||
else if (sscanf(optarg, ":%hhx", &opts.rxpad_content) == 1)
|
||||
opts.flags |= CAN_ISOTP_RX_PADDING;
|
||||
else {
|
||||
printf("incorrect padding values '%s'.\n", optarg);
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (elements == 1)
|
||||
opts.flags |= CAN_ISOTP_TX_PADDING;
|
||||
else if (elements == 2)
|
||||
opts.flags |= (CAN_ISOTP_TX_PADDING | CAN_ISOTP_RX_PADDING);
|
||||
else if (sscanf(optarg, ":%hhx", &opts.rxpad_content) == 1)
|
||||
opts.flags |= CAN_ISOTP_RX_PADDING;
|
||||
else {
|
||||
printf("incorrect padding values '%s'.\n", optarg);
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'P':
|
||||
if (optarg[0] == 'l')
|
||||
opts.flags |= CAN_ISOTP_CHK_PAD_LEN;
|
||||
else if (optarg[0] == 'c')
|
||||
opts.flags |= CAN_ISOTP_CHK_PAD_DATA;
|
||||
else if (optarg[0] == 'a')
|
||||
opts.flags |= (CAN_ISOTP_CHK_PAD_LEN | CAN_ISOTP_CHK_PAD_DATA);
|
||||
else {
|
||||
printf("unknown padding check option '%c'.\n", optarg[0]);
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
case 'P':
|
||||
if (optarg[0] == 'l')
|
||||
opts.flags |= CAN_ISOTP_CHK_PAD_LEN;
|
||||
else if (optarg[0] == 'c')
|
||||
opts.flags |= CAN_ISOTP_CHK_PAD_DATA;
|
||||
else if (optarg[0] == 'a')
|
||||
opts.flags |= (CAN_ISOTP_CHK_PAD_LEN | CAN_ISOTP_CHK_PAD_DATA);
|
||||
else {
|
||||
printf("unknown padding check option '%c'.\n", optarg[0]);
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (!strncmp(optarg, ZERO_STRING, strlen(ZERO_STRING)))
|
||||
opts.frame_txtime = CAN_ISOTP_FRAME_TXTIME_ZERO;
|
||||
else
|
||||
opts.frame_txtime = strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
case 't':
|
||||
if (!strncmp(optarg, ZERO_STRING, strlen(ZERO_STRING)))
|
||||
opts.frame_txtime = CAN_ISOTP_FRAME_TXTIME_ZERO;
|
||||
else
|
||||
opts.frame_txtime = strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
opts.flags |= CAN_ISOTP_FORCE_TXSTMIN;
|
||||
force_tx_stmin = strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
case 'f':
|
||||
opts.flags |= CAN_ISOTP_FORCE_TXSTMIN;
|
||||
force_tx_stmin = strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
datalen = strtoul(optarg, NULL, 10);
|
||||
if (!datalen || datalen >= BUFSIZE) {
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
datalen = strtoul(optarg, NULL, 10);
|
||||
if (!datalen || datalen >= BUFSIZE) {
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
if (optarg[0] == 'i') {
|
||||
loops = 0; /* infinite loop */
|
||||
} else {
|
||||
loops = strtoul(optarg, NULL, 10);
|
||||
if (!loops) {
|
||||
fprintf(stderr, "Invalid argument for option -l!\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
if (optarg[0] == 'i') {
|
||||
loops = 0; /* infinite loop */
|
||||
} else {
|
||||
loops = strtoul(optarg, NULL, 10);
|
||||
if (!loops) {
|
||||
fprintf(stderr, "Invalid argument for option -l!\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
usecs = strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
case 'g':
|
||||
usecs = strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
opts.flags |= CAN_ISOTP_WAIT_TX_DONE;
|
||||
break;
|
||||
case 'b':
|
||||
opts.flags |= CAN_ISOTP_WAIT_TX_DONE;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
opts.flags |= CAN_ISOTP_SF_BROADCAST;
|
||||
break;
|
||||
case 'S':
|
||||
opts.flags |= CAN_ISOTP_SF_BROADCAST;
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
opts.flags |= CAN_ISOTP_CF_BROADCAST;
|
||||
break;
|
||||
case 'C':
|
||||
opts.flags |= CAN_ISOTP_CF_BROADCAST;
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
if (sscanf(optarg, "%hhu:%hhu:%hhu",
|
||||
&llopts.mtu,
|
||||
&llopts.tx_dl,
|
||||
&llopts.tx_flags) != 3) {
|
||||
printf("unknown link layer options '%s'.\n", optarg);
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
case 'L':
|
||||
if (sscanf(optarg, "%hhu:%hhu:%hhu",
|
||||
&llopts.mtu,
|
||||
&llopts.tx_dl,
|
||||
&llopts.tx_flags) != 3) {
|
||||
printf("unknown link layer options '%s'.\n", optarg);
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
|
||||
case '?':
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
break;
|
||||
case '?':
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unknown option %c\n", opt);
|
||||
print_usage(basename(argv[0]));
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
fprintf(stderr, "Unknown option %c\n", opt);
|
||||
print_usage(basename(argv[0]));
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define BC_FLAGS (CAN_ISOTP_SF_BROADCAST | CAN_ISOTP_CF_BROADCAST)
|
||||
|
||||
if ((argc - optind != 1) ||
|
||||
(addr.can_addr.tp.tx_id == NO_CAN_ID) ||
|
||||
((opts.flags & BC_FLAGS) == BC_FLAGS) ||
|
||||
((addr.can_addr.tp.rx_id == NO_CAN_ID) &&
|
||||
(!(opts.flags & BC_FLAGS)))) {
|
||||
print_usage(basename(argv[0]));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((s = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP)) < 0) {
|
||||
perror("socket");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts)) < 0) {
|
||||
perror("sockopt");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if (llopts.tx_dl) {
|
||||
if (setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_LL_OPTS, &llopts, sizeof(llopts)) < 0) {
|
||||
perror("link layer sockopt");
|
||||
exit(1);
|
||||
if ((argc - optind != 1) ||
|
||||
(addr.can_addr.tp.tx_id == NO_CAN_ID) ||
|
||||
((opts.flags & BC_FLAGS) == BC_FLAGS) ||
|
||||
((addr.can_addr.tp.rx_id == NO_CAN_ID) &&
|
||||
(!(opts.flags & BC_FLAGS)))) {
|
||||
print_usage(basename(argv[0]));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.flags & CAN_ISOTP_FORCE_TXSTMIN)
|
||||
setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_TX_STMIN, &force_tx_stmin, sizeof(force_tx_stmin));
|
||||
if ((s = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP)) < 0) {
|
||||
perror("socket");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
addr.can_family = AF_CAN;
|
||||
addr.can_ifindex = if_nametoindex(argv[optind]);
|
||||
if (!addr.can_ifindex) {
|
||||
perror("if_nametoindex");
|
||||
exit(1);
|
||||
}
|
||||
if (setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts)) < 0) {
|
||||
perror("sockopt");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
perror("bind");
|
||||
close(s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!datalen) {
|
||||
while (buflen < BUFSIZE && scanf("%hhx", &buf[buflen]) == 1)
|
||||
buflen++;
|
||||
} else {
|
||||
for (buflen = 0; buflen < datalen; buflen++)
|
||||
buf[buflen] = ((buflen % 0xFF) + 1) & 0xFF;
|
||||
}
|
||||
if (llopts.tx_dl) {
|
||||
if (setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_LL_OPTS, &llopts, sizeof(llopts)) < 0) {
|
||||
perror("link layer sockopt");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.flags & CAN_ISOTP_FORCE_TXSTMIN)
|
||||
setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_TX_STMIN, &force_tx_stmin, sizeof(force_tx_stmin));
|
||||
|
||||
addr.can_family = AF_CAN;
|
||||
addr.can_ifindex = if_nametoindex(argv[optind]);
|
||||
if (!addr.can_ifindex) {
|
||||
perror("if_nametoindex");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
perror("bind");
|
||||
close(s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!datalen) {
|
||||
while (buflen < BUFSIZE && scanf("%hhx", &buf[buflen]) == 1)
|
||||
buflen++;
|
||||
} else {
|
||||
for (buflen = 0; buflen < datalen; buflen++)
|
||||
buf[buflen] = ((buflen % 0xFF) + 1) & 0xFF;
|
||||
}
|
||||
|
||||
loop:
|
||||
if (usecs)
|
||||
usleep(usecs);
|
||||
if (usecs)
|
||||
usleep(usecs);
|
||||
|
||||
retval = write(s, buf, buflen);
|
||||
if (retval < 0) {
|
||||
perror("write");
|
||||
return retval;
|
||||
}
|
||||
retval = write(s, buf, buflen);
|
||||
if (retval < 0) {
|
||||
perror("write");
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (retval != buflen)
|
||||
fprintf(stderr, "wrote only %d from %d byte\n", retval, buflen);
|
||||
if (retval != buflen)
|
||||
fprintf(stderr, "wrote only %d from %d byte\n", retval, buflen);
|
||||
|
||||
if (loops) {
|
||||
if (--loops)
|
||||
goto loop;
|
||||
} else {
|
||||
goto loop;
|
||||
}
|
||||
if (loops) {
|
||||
if (--loops)
|
||||
goto loop;
|
||||
} else {
|
||||
goto loop;
|
||||
}
|
||||
|
||||
/*
|
||||
* due to a Kernel internal wait queue the PDU is sent completely
|
||||
* before close() returns.
|
||||
*/
|
||||
close(s);
|
||||
/*
|
||||
* due to a Kernel internal wait queue the PDU is sent completely
|
||||
* before close() returns.
|
||||
*/
|
||||
close(s);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -41,16 +41,22 @@ static void gmtime_to_j1939_pgn_65254_td(struct j1939_time_date_packet *tdp)
|
||||
utc_tm = gmtime_r(&now, &utc_tm_buf);
|
||||
local_tm = localtime_r(&now, &local_tm_buf);
|
||||
|
||||
/* Calculate the offsets */
|
||||
hour_offset = local_tm->tm_hour - utc_tm->tm_hour;
|
||||
minute_offset = local_tm->tm_min - utc_tm->tm_min;
|
||||
if (local_tm) {
|
||||
/* Calculate the offsets */
|
||||
hour_offset = local_tm->tm_hour - utc_tm->tm_hour;
|
||||
minute_offset = local_tm->tm_min - utc_tm->tm_min;
|
||||
|
||||
/* Handle date rollover */
|
||||
if (local_tm->tm_mday != utc_tm->tm_mday) {
|
||||
if (local_tm->tm_hour < 12)
|
||||
hour_offset += 24; /* past midnight */
|
||||
else
|
||||
hour_offset -= 24; /* before midnight */
|
||||
/* Handle date rollover */
|
||||
if (local_tm->tm_mday != utc_tm->tm_mday) {
|
||||
if (local_tm->tm_hour < 12)
|
||||
hour_offset += 24; /* past midnight */
|
||||
else
|
||||
hour_offset -= 24; /* before midnight */
|
||||
}
|
||||
} else {
|
||||
/* The local time offsets cannot be determined at the moment */
|
||||
hour_offset = 0xF9;
|
||||
minute_offset = 0xFF;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -51,7 +51,7 @@ struct j1939_vp_err_msg {
|
||||
#define J1939_VP1_PRIO_DEFAULT 6
|
||||
#define J1939_VP1_MAX_TRANSFER_LENGH \
|
||||
sizeof(struct j1939_vp1_packet)
|
||||
#define J1939_VP1_REPETITION_RATE_MS 5000
|
||||
#define J1939_VP1_REPETITION_RATE_MS 1000
|
||||
#define J1939_VP1_JITTER_MS 500
|
||||
|
||||
/**
|
||||
@@ -63,8 +63,8 @@ struct j1939_vp_err_msg {
|
||||
* - Data Length: 4 bytes
|
||||
* - Resolution: 10^-7 deg/bit
|
||||
* - Offset: -210 degrees
|
||||
* - Range: -210 to +211.1008122 degrees
|
||||
* - Operating Range: -210 degrees (SOUTH) to +211.108122 degrees
|
||||
* - Range: -210 to +211.10081215 degrees
|
||||
* - Operating Range: -210 degrees (SOUTH) to +211.1081215 degrees
|
||||
* (NORTH)
|
||||
*
|
||||
* @longitude: Raw longitude position of the vehicle
|
||||
@@ -72,8 +72,8 @@ struct j1939_vp_err_msg {
|
||||
* - Data Length: 4 bytes
|
||||
* - Resolution: 10^-7 deg/bit
|
||||
* - Offset: -210 degrees
|
||||
* - Range: -210 to +211.1008122 degrees
|
||||
* - Operating Range: -210 degrees (WEST) to +211.108122 degrees
|
||||
* - Range: -210 to +211.10081215 degrees
|
||||
* - Operating Range: -210 degrees (WEST) to +211.1081215 degrees
|
||||
* (EAST)
|
||||
*
|
||||
* This structure defines each component of the Vehicle Position as described in
|
||||
@@ -142,42 +142,48 @@ j1939_vp1_set_longitude(struct j1939_vp1_packet *packet, int32_t longitude)
|
||||
/**
|
||||
* struct j1939_vp2_packet - Represents the PGN 64502 Vehicle
|
||||
* Position 2 packet
|
||||
* FIXME: current packet layout is guessed based on limited information:
|
||||
* https://www.isobus.net/isobus/pGNAndSPN/10801?type=PGN
|
||||
*
|
||||
* @total_satellites: Total number of satellites in view
|
||||
* - SPN: 8128
|
||||
* - Data Length: 1 byte
|
||||
* - Range: 0 to 250
|
||||
*
|
||||
* @hdop: Horizontal dilution of precision
|
||||
* - SPN: 8129
|
||||
* - Data Length: 1 byte
|
||||
* - Resolution: 0.1
|
||||
* - Range: 0.0 to 25.0
|
||||
*
|
||||
* @vdop: Vertical dilution of precision
|
||||
* - SPN: 8130
|
||||
* - Data Length: 1 byte
|
||||
* - Resolution: 0.1
|
||||
* - Range: 0.0 to 25.0
|
||||
*
|
||||
* @pdop: Position dilution of precision
|
||||
* - SPN: 8131
|
||||
* - Data Length: 1 byte
|
||||
* - Resolution: 0.1
|
||||
* - Range: 0.0 to 25.0
|
||||
*
|
||||
* @tdop: Time dilution of precision
|
||||
* - SPN: 8132
|
||||
* - Data Length: 1 byte
|
||||
* - Resolution: 0.1
|
||||
* - Range: 0.0 to 25.0
|
||||
*
|
||||
* This structure defines each component of the Vehicle Position 2 as described
|
||||
* in PGN 64502.
|
||||
*/
|
||||
struct j1939_vp2_packet {
|
||||
uint8_t total_satellites; /* SPN 8128 */
|
||||
uint8_t hdop; /* SPN 8129 */
|
||||
uint8_t vdop; /* SPN 8130 */
|
||||
uint8_t pdop; /* SPN 8131 */
|
||||
uint8_t tdop; /* SPN 8132 */
|
||||
uint8_t hdop; /* SPN 8129 */
|
||||
uint8_t vdop; /* SPN 8130 */
|
||||
uint8_t pdop; /* SPN 8131 */
|
||||
uint8_t tdop; /* SPN 8132 */
|
||||
uint8_t unused5; /* Always 0xFF */
|
||||
uint8_t unused6; /* Always 0xFF */
|
||||
uint8_t unused7; /* Always 0xFF */
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/**
|
||||
|
||||
@@ -270,6 +270,12 @@ static int j1939_vp2_get_data(struct j1939_vp_srv_priv *priv,
|
||||
j1939_vp2_set_pdop(vp2p, pdop);
|
||||
j1939_vp2_set_tdop(vp2p, tdop);
|
||||
|
||||
/* This PG's last 3 bytes are not assigned and hence must be set
|
||||
* to 0xFF as per J1939-71, section 5.2 */
|
||||
vp2p->unused5 = 0xFF;
|
||||
vp2p->unused6 = 0xFF;
|
||||
vp2p->unused7 = 0xFF;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+8
-8
@@ -112,10 +112,10 @@ static struct {
|
||||
int sig_alrm;
|
||||
int sig_usr1;
|
||||
int state;
|
||||
#define STATE_INITIAL 0
|
||||
#define STATE_REQ_SENT 1
|
||||
#define STATE_REQ_PENDING 2 /* wait 1250 msec for first claim */
|
||||
#define STATE_OPERATIONAL 3
|
||||
#define STATE_INITIAL 0
|
||||
#define STATE_REQ_SENT 1
|
||||
#define STATE_REQ_PENDING 2 /* wait 1250 msec for first claim */
|
||||
#define STATE_OPERATIONAL 3
|
||||
} s = {
|
||||
.intf = default_intf,
|
||||
.ranges = default_range,
|
||||
@@ -126,8 +126,8 @@ static struct {
|
||||
struct {
|
||||
uint64_t name;
|
||||
int flags;
|
||||
#define F_USE 0x01
|
||||
#define F_SEEN 0x02
|
||||
#define F_USE 0x01
|
||||
#define F_SEEN 0x02
|
||||
} addr[J1939_IDLE_ADDR /* =254 */];
|
||||
|
||||
/* lookup by name */
|
||||
@@ -209,7 +209,7 @@ static int open_socket(const char *device, uint64_t name)
|
||||
if (s.verbose)
|
||||
fprintf(stderr, "- setsockopt(, SOL_CAN_J1939, SO_J1939_FILTER, <filter>, %zd);\n", sizeof(filt));
|
||||
ret = setsockopt(sock, SOL_CAN_J1939, SO_J1939_FILTER,
|
||||
&filt, sizeof(filt));
|
||||
&filt, sizeof(filt));
|
||||
if (ret < 0)
|
||||
err(1, "setsockopt filter");
|
||||
|
||||
@@ -217,7 +217,7 @@ static int open_socket(const char *device, uint64_t name)
|
||||
if (s.verbose)
|
||||
fprintf(stderr, "- setsockopt(, SOL_SOCKET, SO_BROADCAST, %d, %zd);\n", value, sizeof(value));
|
||||
ret = setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
|
||||
&value, sizeof(value));
|
||||
&value, sizeof(value));
|
||||
if (ret < 0)
|
||||
err(1, "setsockopt set broadcast");
|
||||
|
||||
|
||||
+18
-18
@@ -31,11 +31,11 @@
|
||||
* strict type-checking.. See the
|
||||
* "unnecessary" pointer comparison.
|
||||
*/
|
||||
#define min(x, y) ({ \
|
||||
typeof(x) _min1 = (x); \
|
||||
typeof(y) _min2 = (y); \
|
||||
(void) (&_min1 == &_min2); \
|
||||
_min1 < _min2 ? _min1 : _min2; })
|
||||
#define min(x, y) ({ \
|
||||
typeof(x) _min1 = (x); \
|
||||
typeof(y) _min2 = (y); \
|
||||
(void) (&_min1 == &_min2); \
|
||||
_min1 < _min2 ? _min1 : _min2; })
|
||||
|
||||
|
||||
struct j1939cat_stats {
|
||||
@@ -98,7 +98,7 @@ static const char help_msg[] =
|
||||
static const char optstring[] = "?hi:vs:rp:P:R:B";
|
||||
|
||||
static ssize_t j1939cat_send_one(struct j1939cat_priv *priv, int out_fd,
|
||||
const void *buf, size_t buf_size)
|
||||
const void *buf, size_t buf_size)
|
||||
{
|
||||
ssize_t num_sent;
|
||||
int flags = 0;
|
||||
@@ -132,7 +132,7 @@ static ssize_t j1939cat_send_one(struct j1939cat_priv *priv, int out_fd,
|
||||
}
|
||||
|
||||
static void j1939cat_print_timestamp(struct j1939cat_priv *priv, const char *name,
|
||||
struct timespec *cur)
|
||||
struct timespec *cur)
|
||||
{
|
||||
struct j1939cat_stats *stats = &priv->stats;
|
||||
|
||||
@@ -140,8 +140,8 @@ static void j1939cat_print_timestamp(struct j1939cat_priv *priv, const char *nam
|
||||
return;
|
||||
|
||||
fprintf(stderr, " %s: %llu s %llu us (seq=%03u, send=%07u)",
|
||||
name, (unsigned long long)cur->tv_sec, (unsigned long long)cur->tv_nsec / 1000,
|
||||
stats->tskey, stats->send);
|
||||
name, (unsigned long long)cur->tv_sec, (unsigned long long)cur->tv_nsec / 1000,
|
||||
stats->tskey, stats->send);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
@@ -226,7 +226,7 @@ static int j1939cat_extract_serr(struct j1939cat_priv *priv)
|
||||
stats->tskey = serr->ee_data;
|
||||
|
||||
j1939cat_print_timestamp(priv, j1939cat_tstype_to_str(serr->ee_info),
|
||||
&tss->ts[0]);
|
||||
&tss->ts[0]);
|
||||
|
||||
if (serr->ee_info == SCM_TSTAMP_SCHED)
|
||||
return -EINTR;
|
||||
@@ -338,7 +338,7 @@ static int j1939cat_recv_err(struct j1939cat_priv *priv)
|
||||
}
|
||||
|
||||
static int j1939cat_send_loop(struct j1939cat_priv *priv, int out_fd, char *buf,
|
||||
size_t buf_size)
|
||||
size_t buf_size)
|
||||
{
|
||||
struct j1939cat_stats *stats = &priv->stats;
|
||||
ssize_t count;
|
||||
@@ -411,7 +411,7 @@ static int j1939cat_send_loop(struct j1939cat_priv *priv, int out_fd, char *buf,
|
||||
}
|
||||
|
||||
static int j1939cat_sendfile(struct j1939cat_priv *priv, int out_fd, int in_fd,
|
||||
off_t *offset, size_t count)
|
||||
off_t *offset, size_t count)
|
||||
{
|
||||
int ret = EXIT_SUCCESS;
|
||||
off_t orig = 0;
|
||||
@@ -617,7 +617,7 @@ static int j1939cat_sock_prepare(struct j1939cat_priv *priv)
|
||||
|
||||
if (priv->todo_prio >= 0) {
|
||||
ret = setsockopt(priv->sock, SOL_CAN_J1939, SO_J1939_SEND_PRIO,
|
||||
&priv->todo_prio, sizeof(priv->todo_prio));
|
||||
&priv->todo_prio, sizeof(priv->todo_prio));
|
||||
if (ret < 0) {
|
||||
warn("set priority %i", priv->todo_prio);
|
||||
return EXIT_FAILURE;
|
||||
@@ -633,11 +633,11 @@ static int j1939cat_sock_prepare(struct j1939cat_priv *priv)
|
||||
}
|
||||
|
||||
sock_opt = SOF_TIMESTAMPING_SOFTWARE |
|
||||
SOF_TIMESTAMPING_OPT_CMSG |
|
||||
SOF_TIMESTAMPING_TX_ACK |
|
||||
SOF_TIMESTAMPING_TX_SCHED |
|
||||
SOF_TIMESTAMPING_OPT_STATS | SOF_TIMESTAMPING_OPT_TSONLY |
|
||||
SOF_TIMESTAMPING_OPT_ID | SOF_TIMESTAMPING_RX_SOFTWARE;
|
||||
SOF_TIMESTAMPING_OPT_CMSG |
|
||||
SOF_TIMESTAMPING_TX_ACK |
|
||||
SOF_TIMESTAMPING_TX_SCHED |
|
||||
SOF_TIMESTAMPING_OPT_STATS | SOF_TIMESTAMPING_OPT_TSONLY |
|
||||
SOF_TIMESTAMPING_OPT_ID | SOF_TIMESTAMPING_RX_SOFTWARE;
|
||||
|
||||
if (setsockopt(priv->sock, SOL_SOCKET, SO_TIMESTAMPING,
|
||||
(char *) &sock_opt, sizeof(sock_opt)))
|
||||
|
||||
+4
-4
@@ -76,7 +76,7 @@ static struct {
|
||||
static const int ival_1 = 1;
|
||||
|
||||
static char ctrlmsg[
|
||||
CMSG_SPACE(sizeof(struct timeval))
|
||||
CMSG_SPACE(sizeof(struct timeval))
|
||||
+ CMSG_SPACE(sizeof(uint8_t)) /* dest addr */
|
||||
+ CMSG_SPACE(sizeof(uint64_t)) /* dest name */
|
||||
+ CMSG_SPACE(sizeof(uint8_t)) /* priority */
|
||||
@@ -264,9 +264,9 @@ abs_time:
|
||||
struct tm tm;
|
||||
tm = *localtime(&tdut.tv_sec);
|
||||
printf("(%04u%02u%02uT%02u%02u%02u.%04llu)",
|
||||
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec,
|
||||
(unsigned long long)tdut.tv_usec/100);
|
||||
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||
tm.tm_hour, tm.tm_min, tm.tm_sec,
|
||||
(unsigned long long)tdut.tv_usec/100);
|
||||
}
|
||||
}
|
||||
printf(" %s ", libj1939_addr2str(&src));
|
||||
|
||||
@@ -68,9 +68,9 @@ static struct {
|
||||
int pkt_len;
|
||||
int priority;
|
||||
int defined;
|
||||
#define DEF_SRC 1
|
||||
#define DEF_DST 2
|
||||
#define DEF_PRIO 4
|
||||
#define DEF_SRC 1
|
||||
#define DEF_DST 2
|
||||
#define DEF_PRIO 4
|
||||
struct sockaddr_can src, dst;
|
||||
} s = {
|
||||
.priority = 6,
|
||||
|
||||
@@ -83,8 +83,8 @@ static inline void _put_id(char *buf, int end_offset, canid_t id)
|
||||
|
||||
/* CAN DLC to real data length conversion helpers */
|
||||
|
||||
static const unsigned char dlc2len[] = {0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 12, 16, 20, 24, 32, 48, 64};
|
||||
static const unsigned char dlc2len[] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64};
|
||||
|
||||
/* get data length from raw data length code (DLC) */
|
||||
unsigned char can_fd_dlc2len(unsigned char dlc)
|
||||
@@ -92,16 +92,17 @@ unsigned char can_fd_dlc2len(unsigned char dlc)
|
||||
return dlc2len[dlc & 0x0F];
|
||||
}
|
||||
|
||||
static const unsigned char len2dlc[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, /* 0 - 8 */
|
||||
9, 9, 9, 9, /* 9 - 12 */
|
||||
10, 10, 10, 10, /* 13 - 16 */
|
||||
11, 11, 11, 11, /* 17 - 20 */
|
||||
12, 12, 12, 12, /* 21 - 24 */
|
||||
13, 13, 13, 13, 13, 13, 13, 13, /* 25 - 32 */
|
||||
14, 14, 14, 14, 14, 14, 14, 14, /* 33 - 40 */
|
||||
14, 14, 14, 14, 14, 14, 14, 14, /* 41 - 48 */
|
||||
15, 15, 15, 15, 15, 15, 15, 15, /* 49 - 56 */
|
||||
15, 15, 15, 15, 15, 15, 15, 15}; /* 57 - 64 */
|
||||
static const unsigned char len2dlc[] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, /* 0 - 8 */
|
||||
9, 9, 9, 9, /* 9 - 12 */
|
||||
10, 10, 10, 10, /* 13 - 16 */
|
||||
11, 11, 11, 11, /* 17 - 20 */
|
||||
12, 12, 12, 12, /* 21 - 24 */
|
||||
13, 13, 13, 13, 13, 13, 13, 13, /* 25 - 32 */
|
||||
14, 14, 14, 14, 14, 14, 14, 14, /* 33 - 40 */
|
||||
14, 14, 14, 14, 14, 14, 14, 14, /* 41 - 48 */
|
||||
15, 15, 15, 15, 15, 15, 15, 15, /* 49 - 56 */
|
||||
15, 15, 15, 15, 15, 15, 15, 15}; /* 57 - 64 */
|
||||
|
||||
/* map the sanitized data length to an appropriate data length code */
|
||||
unsigned char can_fd_len2dlc(unsigned char len)
|
||||
@@ -154,7 +155,7 @@ int hexstring2data(char *arg, unsigned char *data, int maxdlen)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_canframe(char *cs, cu_t *cu)
|
||||
int parse_canframe(char *cs, union cfu *cu)
|
||||
{
|
||||
/* documentation see lib.h */
|
||||
|
||||
@@ -169,21 +170,23 @@ int parse_canframe(char *cs, cu_t *cu)
|
||||
|
||||
memset(cu, 0, sizeof(*cu)); /* init CAN CC/FD/XL frame, e.g. LEN = 0 */
|
||||
|
||||
if (len < 4)
|
||||
return 0;
|
||||
if (len >= 4 && cs[3] == CANID_DELIM) { /* 3 digits SFF CAN ID */
|
||||
|
||||
if (cs[3] == CANID_DELIM) { /* 3 digits SFF */
|
||||
idx = 4; /* start of frame data */
|
||||
|
||||
idx = 4;
|
||||
/* get 3 digits SFF CAN ID value */
|
||||
for (i = 0; i < 3; i++) {
|
||||
if ((tmp = asc2nibble(cs[i])) > 0x0F)
|
||||
return 0;
|
||||
cu->cc.can_id |= tmp << (2 - i) * 4;
|
||||
}
|
||||
|
||||
} else if (cs[5] == CANID_DELIM) { /* 5 digits CAN XL VCID/PRIO*/
|
||||
} else if (len >= 21 && cs[5] == CANID_DELIM && cs[20] == CANID_DELIM) {
|
||||
/* 5 digits CAN XL VCID/PRIO - but also check for 2nd '#' here */
|
||||
|
||||
idx = 6;
|
||||
idx = 6; /* start of CAN XL frame extra content (AF, SDT, etc) */
|
||||
|
||||
/* get 5 digits CAN XL VCID/PRIO */
|
||||
for (i = 0; i < 5; i++) {
|
||||
if ((tmp = asc2nibble(cs[i])) > 0x0F)
|
||||
return 0;
|
||||
@@ -195,9 +198,11 @@ int parse_canframe(char *cs, cu_t *cu)
|
||||
cu->xl.prio &= CANXL_PRIO_MASK;
|
||||
cu->xl.prio |= tmp;
|
||||
|
||||
} else if (cs[8] == CANID_DELIM) { /* 8 digits EFF */
|
||||
} else if (len >= 9 && cs[8] == CANID_DELIM) { /* 8 digits EFF CAN ID */
|
||||
|
||||
idx = 9;
|
||||
idx = 9; /* start of frame data */
|
||||
|
||||
/* get 8 digits EFF CAN ID value */
|
||||
for (i = 0; i < 8; i++) {
|
||||
if ((tmp = asc2nibble(cs[i])) > 0x0F)
|
||||
return 0;
|
||||
@@ -238,11 +243,12 @@ int parse_canframe(char *cs, cu_t *cu)
|
||||
cu->fd.flags |= CANFD_FDF; /* dual-use */
|
||||
idx += 2;
|
||||
|
||||
} else if (cs[idx + 14] == CANID_DELIM) { /* CAN XL frame '#80:00:11223344#' */
|
||||
} else if (idx == 6) { /* CAN XL frame extra content '#80:00:11223344#' */
|
||||
maxdlen = CANXL_MAX_DLEN;
|
||||
mtu = CANXL_MTU;
|
||||
data = cu->xl.data; /* fill CAN XL data */
|
||||
data = cu->xl.data; /* overwrite pointer to CAN XL data */
|
||||
|
||||
/* get CAN XL frame extra content */
|
||||
if ((cs[idx + 2] != XL_HDR_DELIM) || (cs[idx + 5] != XL_HDR_DELIM))
|
||||
return 0;
|
||||
|
||||
@@ -276,6 +282,7 @@ int parse_canframe(char *cs, cu_t *cu)
|
||||
idx++; /* skip CANID_DELIM */
|
||||
}
|
||||
|
||||
/* copy CAN frame data content */
|
||||
for (i = 0, dlen = 0; i < maxdlen; i++) {
|
||||
if (cs[idx] == DATA_SEPERATOR) /* skip (optional) separator */
|
||||
idx++;
|
||||
@@ -308,7 +315,7 @@ int parse_canframe(char *cs, cu_t *cu)
|
||||
return mtu;
|
||||
}
|
||||
|
||||
int snprintf_canframe(char *buf, size_t size, cu_t *cu, int sep)
|
||||
int snprintf_canframe(char *buf, size_t size, union cfu *cu, int sep)
|
||||
{
|
||||
/* documentation see lib.h */
|
||||
|
||||
@@ -432,7 +439,7 @@ int snprintf_canframe(char *buf, size_t size, cu_t *cu, int sep)
|
||||
return offset;
|
||||
}
|
||||
|
||||
int snprintf_long_canframe(char *buf, size_t size, cu_t *cu, int view)
|
||||
int snprintf_long_canframe(char *buf, size_t size, union cfu *cu, int view)
|
||||
{
|
||||
/* documentation see lib.h */
|
||||
|
||||
@@ -777,8 +784,8 @@ static int snprintf_error_ctrl(char *buf, size_t len, const struct canfd_frame *
|
||||
|
||||
n += snprintf(buf + n, len - n, "{");
|
||||
n += snprintf_error_data(buf + n, len - n, cf->data[1],
|
||||
controller_problems,
|
||||
ARRAY_SIZE(controller_problems));
|
||||
controller_problems,
|
||||
ARRAY_SIZE(controller_problems));
|
||||
n += snprintf(buf + n, len - n, "}");
|
||||
|
||||
return n;
|
||||
@@ -793,8 +800,8 @@ static int snprintf_error_prot(char *buf, size_t len, const struct canfd_frame *
|
||||
|
||||
n += snprintf(buf + n, len - n, "{{");
|
||||
n += snprintf_error_data(buf + n, len - n, cf->data[2],
|
||||
protocol_violation_types,
|
||||
ARRAY_SIZE(protocol_violation_types));
|
||||
protocol_violation_types,
|
||||
ARRAY_SIZE(protocol_violation_types));
|
||||
n += snprintf(buf + n, len - n, "}{");
|
||||
if (cf->data[3] > 0 &&
|
||||
cf->data[3] < ARRAY_SIZE(protocol_violation_locations))
|
||||
@@ -819,7 +826,7 @@ static int snprintf_error_cnt(char *buf, size_t len, const struct canfd_frame *c
|
||||
}
|
||||
|
||||
int snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *cf,
|
||||
const char* sep)
|
||||
const char* sep)
|
||||
{
|
||||
canid_t class, mask;
|
||||
int i, n = 0, classes = 0;
|
||||
@@ -858,7 +865,7 @@ int snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *cf
|
||||
n += tmp_n;
|
||||
if (mask == CAN_ERR_LOSTARB)
|
||||
n += snprintf_error_lostarb(buf + n, len - n,
|
||||
cf);
|
||||
cf);
|
||||
if (mask == CAN_ERR_CRTL)
|
||||
n += snprintf_error_ctrl(buf + n, len - n, cf);
|
||||
if (mask == CAN_ERR_PROT)
|
||||
@@ -878,7 +885,7 @@ int snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *cf
|
||||
}
|
||||
|
||||
int64_t timespec_diff_ms(struct timespec *ts1,
|
||||
struct timespec *ts2)
|
||||
struct timespec *ts2)
|
||||
{
|
||||
int64_t diff = (ts1->tv_sec - ts2->tv_sec) * 1000;
|
||||
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <linux/can.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#define pr_debug(fmt, args...) printf(fmt, ##args)
|
||||
#else
|
||||
@@ -57,11 +59,11 @@ static inline int pr_debug(const char* fmt, ...) {return 0;}
|
||||
#endif
|
||||
|
||||
/* CAN CC/FD/XL frame union */
|
||||
typedef union {
|
||||
union cfu {
|
||||
struct can_frame cc;
|
||||
struct canfd_frame fd;
|
||||
struct canxl_frame xl;
|
||||
} cu_t;
|
||||
};
|
||||
|
||||
/*
|
||||
* The buffer size for ASCII CAN frame string representations
|
||||
@@ -108,7 +110,7 @@ int hexstring2data(char *arg, unsigned char *data, int maxdlen);
|
||||
*
|
||||
*/
|
||||
|
||||
int parse_canframe(char *cs, cu_t *cu);
|
||||
int parse_canframe(char *cs, union cfu *cu);
|
||||
/*
|
||||
* Transfers a valid ASCII string describing a CAN frame into the CAN union
|
||||
* containing CAN CC/FD/XL structs.
|
||||
@@ -178,7 +180,7 @@ int parse_canframe(char *cs, cu_t *cu);
|
||||
* - CAN FD frames do not have a RTR bit
|
||||
*/
|
||||
|
||||
int snprintf_canframe(char *buf, size_t size, cu_t *cu, int sep);
|
||||
int snprintf_canframe(char *buf, size_t size, union cfu *cu, int sep);
|
||||
/*
|
||||
* Creates a CAN frame hexadecimal output in compact format.
|
||||
* The CAN data[] is separated by '.' when sep != 0.
|
||||
@@ -211,7 +213,7 @@ int snprintf_canframe(char *buf, size_t size, cu_t *cu, int sep);
|
||||
|
||||
#define SWAP_DELIMITER '`'
|
||||
|
||||
int snprintf_long_canframe(char *buf, size_t size, cu_t *cu, int view);
|
||||
int snprintf_long_canframe(char *buf, size_t size, union cfu *cu, int view);
|
||||
/*
|
||||
* Creates a CAN frame hexadecimal output in user readable format.
|
||||
*
|
||||
|
||||
@@ -183,7 +183,7 @@ static void canfd_asc(struct canfd_frame *cf, int devno, int mtu,
|
||||
fprintf(outfile, " %8d %4d %8X 0 0 0 0 0", 130000, 130, flags);
|
||||
}
|
||||
|
||||
static void canxl_asc(cu_t *cu, int devno, int mtu,
|
||||
static void canxl_asc(union cfu *cu, int devno, int mtu,
|
||||
char *extra_info, FILE *outfile)
|
||||
{
|
||||
char id[10];
|
||||
@@ -296,7 +296,7 @@ static void canxl_asc(cu_t *cu, int devno, int mtu,
|
||||
|
||||
#define DEVSZ 22
|
||||
#define EXTRASZ 20
|
||||
#define TIMESZ sizeof("(1345212884.318850) ")
|
||||
#define TIMESZ sizeof("(1345212884.318850123) ")
|
||||
#define BUFSZ (DEVSZ + AFRSZ + EXTRASZ + TIMESZ)
|
||||
|
||||
/* adapt sscanf() functions below on error */
|
||||
@@ -314,7 +314,7 @@ int main(int argc, char **argv)
|
||||
{
|
||||
static char buf[BUFSZ], device[DEVSZ], afrbuf[AFRSZ], extra_info[EXTRASZ];
|
||||
|
||||
static cu_t cu;
|
||||
static union cfu cu;
|
||||
static struct timeval tv, start_tv;
|
||||
FILE *infile = stdin;
|
||||
FILE *outfile = stdout;
|
||||
@@ -407,7 +407,22 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
tv.tv_sec = sec;
|
||||
tv.tv_usec = usec;
|
||||
|
||||
/*
|
||||
* ensure the fractions of seconds are 6 or 9 decimal places long to catch
|
||||
* 3rd party or handcrafted logfiles that treat the timestamp as float
|
||||
*/
|
||||
switch (strchr(buf, ')') - strchr(buf, '.')) {
|
||||
case 7: //6
|
||||
tv.tv_usec = usec;
|
||||
break;
|
||||
case 10: //9
|
||||
tv.tv_usec = usec / 1000;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "timestamp format in logfile requires 6 or 9 decimal places\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (print_banner) { /* print banner */
|
||||
print_banner = 0;
|
||||
|
||||
+4
-4
@@ -51,7 +51,7 @@
|
||||
#include "lib.h"
|
||||
|
||||
#define DEVSZ 22
|
||||
#define TIMESZ 22 /* sizeof("(1345212884.318850) ") */
|
||||
#define TIMESZ 25 /* sizeof("(1345212884.318850123) ") */
|
||||
#define BUFSZ (DEVSZ + AFRSZ + TIMESZ)
|
||||
|
||||
/* adapt sscanf() functions below on error */
|
||||
@@ -61,14 +61,14 @@
|
||||
#if (DEVSZ != 22)
|
||||
#error "DEVSZ value does not fit sscanf restrictions!"
|
||||
#endif
|
||||
#if (TIMESZ != 22)
|
||||
#if (TIMESZ != 25)
|
||||
#error "TIMESZ value does not fit sscanf restrictions!"
|
||||
#endif
|
||||
|
||||
int main(void)
|
||||
{
|
||||
static char buf[BUFSZ], timestamp[TIMESZ], device[DEVSZ], afrbuf[AFRSZ];
|
||||
static cu_t cu;
|
||||
static union cfu cu;
|
||||
int mtu;
|
||||
|
||||
while (fgets(buf, BUFSZ-1, stdin)) {
|
||||
@@ -78,7 +78,7 @@ int main(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (sscanf(buf, "%21s %21s %6299s", timestamp, device, afrbuf) != 3)
|
||||
if (sscanf(buf, "%24s %21s %6299s", timestamp, device, afrbuf) != 3)
|
||||
return 1;
|
||||
|
||||
mtu = parse_canframe(afrbuf, &cu);
|
||||
|
||||
@@ -72,8 +72,7 @@ int mcp251xfd_regmap_read(struct mcp251xfd_priv *priv,
|
||||
return 0;
|
||||
|
||||
/* maybe it's something like "spi0.0" */
|
||||
tmp = strchr(file_path, '/');
|
||||
if (tmp)
|
||||
if (strchr(file_path, '/'))
|
||||
return -ENOENT;
|
||||
|
||||
/* first try literally */
|
||||
|
||||
+5
-5
@@ -197,7 +197,7 @@ int main(int argc, char *argv[])
|
||||
if (verbose)
|
||||
fprintf(stderr, "- setsockopt(, SOL_CAN_J1939, SO_J1939_SEND_PRIO, &%i);\n", todo_prio);
|
||||
ret = setsockopt(sock, SOL_CAN_J1939, SO_J1939_SEND_PRIO,
|
||||
&todo_prio, sizeof(todo_prio));
|
||||
&todo_prio, sizeof(todo_prio));
|
||||
if (ret < 0)
|
||||
err(1, "set priority %i", todo_prio);
|
||||
}
|
||||
@@ -246,7 +246,7 @@ int main(int argc, char *argv[])
|
||||
if (verbose)
|
||||
fprintf(stderr, "- sendto(, <dat>, %i, 0, %s, %zi);\n", todo_send, libj1939_addr2str(&peername), sizeof(peername));
|
||||
ret = sendto(sock, dat, todo_send, 0,
|
||||
(void *)&peername, sizeof(peername));
|
||||
(void *)&peername, sizeof(peername));
|
||||
} else {
|
||||
/*
|
||||
* we may do sendto(sock, dat, todo_send, 0, NULL, 0)
|
||||
@@ -273,7 +273,7 @@ int main(int argc, char *argv[])
|
||||
fprintf(stderr, "- recvfrom(, <dat>, %zi, 0, &<peername>, %zi);\n", sizeof(peername), sizeof(peername));
|
||||
peernamelen = sizeof(peername);
|
||||
ret = recvfrom(sock, dat, sizeof(dat), 0,
|
||||
(void *)&peername, &peernamelen);
|
||||
(void *)&peername, &peernamelen);
|
||||
if (ret < 0) {
|
||||
if (EINTR == errno) {
|
||||
if (verbose)
|
||||
@@ -287,7 +287,7 @@ int main(int argc, char *argv[])
|
||||
if (verbose)
|
||||
fprintf(stderr, "- sendto(, <dat>, %i, 0, %s, %i);\n", ret, libj1939_addr2str(&peername), peernamelen);
|
||||
ret = sendto(sock, dat, ret, 0,
|
||||
(void *)&peername, peernamelen);
|
||||
(void *)&peername, peernamelen);
|
||||
if (ret < 0)
|
||||
err(1, "sendto");
|
||||
}
|
||||
@@ -297,7 +297,7 @@ int main(int argc, char *argv[])
|
||||
if (todo_names && peername.can_addr.j1939.name)
|
||||
printf("%016llx ", peername.can_addr.j1939.name);
|
||||
printf("%02x %05x:", peername.can_addr.j1939.addr,
|
||||
peername.can_addr.j1939.pgn);
|
||||
peername.can_addr.j1939.pgn);
|
||||
for (i = 0, j = 0; i < ret; ++i, j++) {
|
||||
if (j == 8) {
|
||||
printf("\n%05x ", i);
|
||||
|
||||
Reference in New Issue
Block a user