From 2522ec127b480ce46016c81631c5e77e468db7ed Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Thu, 22 Feb 2024 22:26:07 +0100 Subject: [PATCH 01/27] lib: integrate CAN FD indicator into dual-use struct canfd_frame Replace maxdlen parameter and use CANFD_FDF flags instead. Since the CANFD_FDF flag has been introduced in can.h the struct canfd_frame can be used for CAN CC and CAN FD frames as a dual-use data structure. Remove the extra maxdlen parameter in library calls and only use the CANFD_FDF flag to differentiate the two CAN CC/FD frames. Signed-off-by: Oliver Hartkopp --- asc2log.c | 16 +++++++--------- candump.c | 13 +++++++------ cangen.c | 5 +++-- canlogserver.c | 9 +++++---- canplayer.c | 8 ++------ lib.c | 49 +++++++++++++++++++++++++++++++++---------------- lib.h | 26 ++++++++++++++------------ log2long.c | 12 +++++++----- 8 files changed, 78 insertions(+), 60 deletions(-) diff --git a/asc2log.c b/asc2log.c index 4eb3609..951835b 100644 --- a/asc2log.c +++ b/asc2log.c @@ -71,7 +71,7 @@ void print_usage(char *prg) fprintf(stderr, "\t-O \t(default stdout)\n"); } -void prframe(FILE *file, struct timeval *tv, int dev, struct canfd_frame *cf, unsigned int max_dlen, char *extra_info) { +void prframe(FILE *file, struct timeval *tv, int dev, struct canfd_frame *cf, char *extra_info) { fprintf(file, "(%llu.%06llu) ", (unsigned long long)tv->tv_sec, (unsigned long long)tv->tv_usec); @@ -80,7 +80,7 @@ void prframe(FILE *file, struct timeval *tv, int dev, struct canfd_frame *cf, un else fprintf(file, "canX "); - fprint_canframe(file, cf, extra_info, 0, max_dlen); + fprint_canframe(file, cf, extra_info, 0); } void get_can_id(struct canfd_frame *cf, char *idstring, int base) { @@ -131,7 +131,7 @@ void eval_can(char* buf, struct timeval *date_tvp, char timestamps, char base, i int interface; static struct timeval tv; /* current frame timestamp */ static struct timeval read_tv; /* frame timestamp from ASC file */ - struct canfd_frame cf; + struct canfd_frame cf = { 0 }; struct can_frame *ccf = (struct can_frame *)&cf; /* for len8_dlc */ char rtr; int dlc = 0; @@ -152,13 +152,12 @@ void eval_can(char* buf, struct timeval *date_tvp, char timestamps, char base, i if (!strncmp(tmp1, "ErrorFrame", strlen("ErrorFrame"))) { - memset(&cf, 0, sizeof(cf)); /* do not know more than 'Error' */ cf.can_id = (CAN_ERR_FLAG | CAN_ERR_BUSERROR); cf.len = CAN_ERR_DLC; calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace); - prframe(outfile, &tv, interface, &cf, CAN_MAX_DLEN, "\n"); + prframe(outfile, &tv, interface, &cf, "\n"); fflush(outfile); return; } @@ -232,7 +231,7 @@ void eval_can(char* buf, struct timeval *date_tvp, char timestamps, char base, i cf.data[i] = data[i] & 0xFFU; calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace); - prframe(outfile, &tv, interface, &cf, CAN_MAX_DLEN, extra_info); + prframe(outfile, &tv, interface, &cf, extra_info); fflush(outfile); } } @@ -343,14 +342,13 @@ void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps, int dplace #define ASC_F_ESI 0x00004000 if (flags & ASC_F_FDF) { - dlen = CANFD_MAX_DLEN; + cf.flags = CANFD_FDF; if (flags & ASC_F_BRS) cf.flags |= CANFD_BRS; if (flags & ASC_F_ESI) cf.flags |= CANFD_ESI; } else { /* yes. The 'CANFD' format supports classic CAN content! */ - dlen = CAN_MAX_DLEN; if (flags & ASC_F_RTR) { cf.can_id |= CAN_RTR_FLAG; /* dlen is always 0 for classic CAN RTR frames @@ -369,7 +367,7 @@ void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps, int dplace } calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace); - prframe(outfile, &tv, interface, &cf, dlen, extra_info); + prframe(outfile, &tv, interface, &cf, extra_info); fflush(outfile); /* No support for really strange CANFD ErrorFrames format m( */ diff --git a/candump.c b/candump.c index 334e202..51e35e6 100644 --- a/candump.c +++ b/candump.c @@ -310,7 +310,7 @@ int main(int argc, char **argv) struct can_filter *rfilter; can_err_mask_t err_mask; struct canfd_frame frame; - int nbytes, i, maxdlen; + int nbytes, i; struct ifreq ifr; struct timeval tv, last_tv; int timeout_ms = -1; /* default to no timeout */ @@ -736,10 +736,11 @@ int main(int argc, char **argv) return 1; } + /* mark dual-use struct canfd_frame */ if ((size_t)nbytes == CAN_MTU) - maxdlen = CAN_MAX_DLEN; + frame.flags = 0; else if ((size_t)nbytes == CANFD_MTU) - maxdlen = CANFD_MAX_DLEN; + frame.flags |= CANFD_FDF; else { fprintf(stderr, "read: incomplete CAN frame\n"); return 1; @@ -803,7 +804,7 @@ int main(int argc, char **argv) sprint_timestamp(logtimestamp, &tv, &last_tv, ts_buf); /* log CAN frame with absolute timestamp & device */ - sprint_canframe(buf, &frame, 0, maxdlen); + sprint_canframe(buf, &frame, 0); fprintf(logfile, "%s%*s %s%s\n", ts_buf, max_devname_len, devname[idx], buf, extra_info); @@ -813,7 +814,7 @@ int main(int argc, char **argv) char buf[CL_CFSZ]; /* max length */ /* print CAN frame in log file style to stdout */ - sprint_canframe(buf, &frame, 0, maxdlen); + sprint_canframe(buf, &frame, 0); print_timestamp(logtimestamp, &tv, &last_tv); printf("%*s %s%s\n", @@ -844,7 +845,7 @@ int main(int argc, char **argv) printf("%s ", (color == 1) ? col_off : ""); - fprint_long_canframe(stdout, &frame, NULL, view, maxdlen); + fprint_long_canframe(stdout, &frame, NULL, view); printf("%s", (color > 1) ? col_off : ""); printf("\n"); diff --git a/cangen.c b/cangen.c index 0614f42..64ea934 100644 --- a/cangen.c +++ b/cangen.c @@ -730,6 +730,7 @@ int main(int argc, char **argv) if (canfd) { mtu = CANFD_MTU; maxdlen = CANFD_MAX_DLEN; + frame.flags |= CANFD_FDF; if (brs) frame.flags |= CANFD_BRS; if (esi) @@ -830,9 +831,9 @@ int main(int argc, char **argv) printf(" %s ", argv[optind]); if (verbose > 1) - fprint_long_canframe(stdout, &frame, "\n", (verbose > 2) ? 1 : 0, maxdlen); + fprint_long_canframe(stdout, &frame, "\n", (verbose > 2) ? 1 : 0); else - fprint_canframe(stdout, &frame, "\n", 1, maxdlen); + fprint_canframe(stdout, &frame, "\n", 1); } ret = do_send_one(s, &frame, mtu, polltimeout); diff --git a/canlogserver.c b/canlogserver.c index 23478b7..eb9167a 100644 --- a/canlogserver.c +++ b/canlogserver.c @@ -192,7 +192,7 @@ int main(int argc, char **argv) struct can_filter rfilter; struct canfd_frame frame; const int canfd_on = 1; - int nbytes, i, j, maxdlen; + int nbytes, i, j; struct ifreq ifr; struct timeval tv; int port = DEFPORT; @@ -400,10 +400,11 @@ int main(int argc, char **argv) return 1; } + /* mark dual-use struct canfd_frame */ if ((size_t)nbytes == CAN_MTU) - maxdlen = CAN_MAX_DLEN; + frame.flags = 0; else if ((size_t)nbytes == CANFD_MTU) - maxdlen = CANFD_MAX_DLEN; + frame.flags |= CANFD_FDF; else { fprintf(stderr, "read: incomplete CAN frame\n"); return 1; @@ -417,7 +418,7 @@ int main(int argc, char **argv) sprintf(temp, "(%llu.%06llu) %*s ", (unsigned long long)tv.tv_sec, (unsigned long long)tv.tv_usec, max_devname_len, devname[idx]); - sprint_canframe(temp+strlen(temp), &frame, 0, maxdlen); + sprint_canframe(temp+strlen(temp), &frame, 0); strcat(temp, "\n"); if (write(accsocket, temp, strlen(temp)) < 0) { diff --git a/canplayer.c b/canplayer.c index e1b7ce3..1f2d6cc 100644 --- a/canplayer.c +++ b/canplayer.c @@ -470,7 +470,7 @@ int main(int argc, char **argv) } else if (txidx > 0) { /* only send to valid CAN devices */ - txmtu = parse_canframe(ascframe, &frame); + txmtu = parse_canframe(ascframe, &frame); /* dual-use frame */ if (!txmtu) { fprintf(stderr, "wrong CAN frame format: '%s'!", ascframe); return 1; @@ -486,11 +486,7 @@ int main(int argc, char **argv) if (verbose) { printf("%s (%s) ", get_txname(device), device); - - if (txmtu == CAN_MTU) - fprint_long_canframe(stdout, &frame, "\n", CANLIB_VIEW_INDENT_SFF, CAN_MAX_DLEN); - else - fprint_long_canframe(stdout, &frame, "\n", CANLIB_VIEW_INDENT_SFF, CANFD_MAX_DLEN); + fprint_long_canframe(stdout, &frame, "\n", CANLIB_VIEW_INDENT_SFF); } if (count && (--count == 0)) diff --git a/lib.c b/lib.c index 260d908..47fb95b 100644 --- a/lib.c +++ b/lib.c @@ -223,6 +223,7 @@ int parse_canframe(char *cs, struct canfd_frame *cf) return 0; cf->flags = tmp; + cf->flags |= CANFD_FDF; /* dual-use */ idx += 2; } @@ -257,24 +258,31 @@ int parse_canframe(char *cs, struct canfd_frame *cf) return ret; } -void fprint_canframe(FILE *stream, struct canfd_frame *cf, char *eol, int sep, int maxdlen) +void fprint_canframe(FILE *stream, struct canfd_frame *cf, char *eol, int sep) { /* documentation see lib.h */ char buf[CL_CFSZ]; /* max length */ - sprint_canframe(buf, cf, sep, maxdlen); + sprint_canframe(buf, cf, sep); fprintf(stream, "%s", buf); if (eol) fprintf(stream, "%s", eol); } -void sprint_canframe(char *buf, struct canfd_frame *cf, int sep, int maxdlen) +void sprint_canframe(char *buf, struct canfd_frame *cf, int sep) { /* documentation see lib.h */ + unsigned char is_canfd = cf->flags; int i, offset; - int len = (cf->len > maxdlen) ? maxdlen : cf->len; + int len; + + /* ensure max length values */ + if (is_canfd) + len = (cf->len > CANFD_MAX_DLEN) ? CANFD_MAX_DLEN : cf->len; + else + len = (cf->len > CAN_MAX_DLEN) ? CAN_MAX_DLEN : cf->len; if (cf->can_id & CAN_ERR_FLAG) { put_eff_id(buf, cf->can_id & (CAN_ERR_MASK | CAN_ERR_FLAG)); @@ -290,15 +298,15 @@ void sprint_canframe(char *buf, struct canfd_frame *cf, int sep, int maxdlen) offset = 4; } - /* standard CAN frames may have RTR enabled. There are no ERR frames with RTR */ - if (maxdlen == CAN_MAX_DLEN && cf->can_id & CAN_RTR_FLAG) { + /* CAN CC frames may have RTR enabled. There are no ERR frames with RTR */ + if (!(is_canfd) && cf->can_id & CAN_RTR_FLAG) { buf[offset++] = 'R'; /* print a given CAN 2.0B DLC if it's not zero */ - if (cf->len && cf->len <= CAN_MAX_DLEN) { + if (len && len <= CAN_MAX_DLEN) { buf[offset++] = hex_asc_upper_lo(cf->len); /* check for optional raw DLC value for CAN 2.0B frames */ - if (cf->len == CAN_MAX_DLEN) { + if (len == CAN_MAX_DLEN) { struct can_frame *ccf = (struct can_frame *)cf; if ((ccf->len8_dlc > CAN_MAX_DLEN) && (ccf->len8_dlc <= CAN_MAX_RAW_DLC)) { @@ -312,7 +320,8 @@ void sprint_canframe(char *buf, struct canfd_frame *cf, int sep, int maxdlen) return; } - if (maxdlen == CANFD_MAX_DLEN) { + /* any CAN FD flags */ + if (is_canfd) { /* add CAN FD specific escape char and flags */ buf[offset++] = '#'; buf[offset++] = hex_asc_upper_lo(cf->flags); @@ -320,6 +329,7 @@ void sprint_canframe(char *buf, struct canfd_frame *cf, int sep, int maxdlen) buf[offset++] = '.'; } + /* data */ for (i = 0; i < len; i++) { put_hex_byte(buf + offset, cf->data[i]); offset += 2; @@ -328,7 +338,7 @@ void sprint_canframe(char *buf, struct canfd_frame *cf, int sep, int maxdlen) } /* check for extra DLC when having a Classic CAN with 8 bytes payload */ - if ((maxdlen == CAN_MAX_DLEN) && (len == CAN_MAX_DLEN)) { + if (!(is_canfd) && (len == CAN_MAX_DLEN)) { struct can_frame *ccf = (struct can_frame *)cf; unsigned char dlc = ccf->len8_dlc; @@ -341,13 +351,13 @@ void sprint_canframe(char *buf, struct canfd_frame *cf, int sep, int maxdlen) buf[offset] = 0; } -void fprint_long_canframe(FILE *stream, struct canfd_frame *cf, char *eol, int view, int maxdlen) +void fprint_long_canframe(FILE *stream, struct canfd_frame *cf, char *eol, int view) { /* documentation see lib.h */ char buf[CL_LONGCFSZ]; - sprint_long_canframe(buf, cf, view, maxdlen); + sprint_long_canframe(buf, cf, view); fprintf(stream, "%s", buf); if ((view & CANLIB_VIEW_ERROR) && (cf->can_id & CAN_ERR_FLAG)) { snprintf_can_error_frame(buf, sizeof(buf), cf, "\n\t"); @@ -357,12 +367,19 @@ void fprint_long_canframe(FILE *stream, struct canfd_frame *cf, char *eol, int v fprintf(stream, "%s", eol); } -void sprint_long_canframe(char *buf, struct canfd_frame *cf, int view, int maxdlen) +void sprint_long_canframe(char *buf, struct canfd_frame *cf, int view) { /* documentation see lib.h */ + unsigned char is_canfd = cf->flags; int i, j, dlen, offset; - int len = (cf->len > maxdlen) ? maxdlen : cf->len; + int len; + + /* ensure max length values */ + if (is_canfd) + len = (cf->len > CANFD_MAX_DLEN) ? CANFD_MAX_DLEN : cf->len; + else + len = (cf->len > CAN_MAX_DLEN) ? CAN_MAX_DLEN : cf->len; /* initialize space for CAN-ID and length information */ memset(buf, ' ', 15); @@ -383,8 +400,8 @@ void sprint_long_canframe(char *buf, struct canfd_frame *cf, int view, int maxdl } } - /* The len value is sanitized by maxdlen (see above) */ - if (maxdlen == CAN_MAX_DLEN) { + /* The len value is sanitized (see above) */ + if (!(is_canfd)) { if (view & CANLIB_VIEW_LEN8_DLC) { struct can_frame *ccf = (struct can_frame *)cf; unsigned char dlc = ccf->len8_dlc; diff --git a/lib.h b/lib.h index 0efd1cb..817eb0d 100644 --- a/lib.h +++ b/lib.h @@ -160,15 +160,16 @@ int parse_canframe(char *cs, struct canfd_frame *cf); * - CAN FD frames do not have a RTR bit */ -void fprint_canframe(FILE *stream , struct canfd_frame *cf, char *eol, int sep, int maxdlen); -void sprint_canframe(char *buf , struct canfd_frame *cf, int sep, int maxdlen); +void fprint_canframe(FILE *stream , struct canfd_frame *cf, char *eol, int sep); +void sprint_canframe(char *buf , struct canfd_frame *cf, int sep); /* * Creates a CAN frame hexadecimal output in compact format. * The CAN data[] is separated by '.' when sep != 0. * - * The type of the CAN frame (CAN 2.0 / CAN FD) is specified by maxdlen: - * maxdlen = 8 -> CAN2.0 frame (aka Classical CAN) - * maxdlen = 64 -> CAN FD frame + * The type of the CAN frame (CAN CC / CAN FD) is specified by + * by the dual-use struct canfd_frame.flags element: + * w/o CAN FD flags (== 0) -> CAN CC frame (aka Classical CAN, CAN2.0B) + * with CAN FD flags (!= 0) -> CAN FD frame (with CANFD_[FDF/BRS/ESI]) * * 12345678#112233 -> extended CAN-Id = 0x12345678, len = 3, data, sep = 0 * 123#1122334455667788_E -> standard CAN-Id = 0x123, len = 8, dlc = 14, data, sep = 0 @@ -195,14 +196,15 @@ void sprint_canframe(char *buf , struct canfd_frame *cf, int sep, int maxdlen); #define SWAP_DELIMITER '`' -void fprint_long_canframe(FILE *stream , struct canfd_frame *cf, char *eol, int view, int maxdlen); -void sprint_long_canframe(char *buf , struct canfd_frame *cf, int view, int maxdlen); +void fprint_long_canframe(FILE *stream , struct canfd_frame *cf, char *eol, int view); +void sprint_long_canframe(char *buf , struct canfd_frame *cf, int view); /* * Creates a CAN frame hexadecimal output in user readable format. * - * The type of the CAN frame (CAN 2.0 / CAN FD) is specified by maxdlen: - * maxdlen = 8 -> CAN2.0 frame (aka Classical CAN) - * maxdlen = 64 -> CAN FD frame + * The type of the CAN frame (CAN CC / CAN FD) is specified by + * by the dual-use struct canfd_frame.flags element: + * w/o CAN FD flags (== 0) -> CAN CC frame (aka Classical CAN, CAN2.0B) + * with CAN FD flags (!= 0) -> CAN FD frame (with CANFD_[FDF/BRS/ESI]) * * 12345678 [3] 11 22 33 -> extended CAN-Id = 0x12345678, len = 3, data * 12345678 [0] remote request -> extended CAN-Id = 0x12345678, RTR @@ -217,10 +219,10 @@ void sprint_long_canframe(char *buf , struct canfd_frame *cf, int view, int maxd * Examples: * * // CAN FD frame with eol to STDOUT - * fprint_long_canframe(stdout, &frame, "\n", 0, CANFD_MAX_DLEN); + * fprint_long_canframe(stdout, &frame, "\n", 0); * * // Classical CAN 2.0 frame without eol to STDERR - * fprint_long_canframe(stderr, &frame, NULL, 0, CAN_MAX_DLEN); + * fprint_long_canframe(stderr, &frame, NULL, 0); * */ diff --git a/log2long.c b/log2long.c index 25814e2..61208a3 100644 --- a/log2long.c +++ b/log2long.c @@ -56,25 +56,27 @@ int main(void) { char buf[BUFSZ], timestamp[BUFSZ], device[BUFSZ], ascframe[BUFSZ]; struct canfd_frame cf; - int mtu, maxdlen; + int mtu; while (fgets(buf, BUFSZ-1, stdin)) { if (sscanf(buf, "%s %s %s", timestamp, device, ascframe) != 3) return 1; mtu = parse_canframe(ascframe, &cf); + + /* mark dual-use struct canfd_frame */ if (mtu == CAN_MTU) - maxdlen = CAN_MAX_DLEN; + cf.flags = 0; else if (mtu == CANFD_MTU) - maxdlen = CANFD_MAX_DLEN; + cf.flags |= CANFD_FDF; else { fprintf(stderr, "read: incomplete CAN frame\n"); return 1; } + /* with ASCII output */ sprint_long_canframe(ascframe, &cf, - (CANLIB_VIEW_INDENT_SFF | CANLIB_VIEW_ASCII), - maxdlen); /* with ASCII output */ + (CANLIB_VIEW_INDENT_SFF | CANLIB_VIEW_ASCII)); printf("%s %s %s\n", timestamp, device, ascframe); } From c6cc7151b780fc59dab9021f66c45135cb1eccc0 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Mon, 26 Feb 2024 21:32:58 +0100 Subject: [PATCH 02/27] candump/lib: convert to single output buffer Build the CAN frame ASCII output inside a single (big) buffer as preparation for CAN XL support. This unifies different output modes (fprintf/sprintf/printf) at the time of the CAN frame text generation. Signed-off-by: Oliver Hartkopp --- candump.c | 91 ++++++++++++++++++++++++++++++------------------------- lib.c | 36 +++++++++++++--------- lib.h | 8 ++--- 3 files changed, 75 insertions(+), 60 deletions(-) diff --git a/candump.c b/candump.c index 51e35e6..ecbcfa0 100644 --- a/candump.c +++ b/candump.c @@ -220,12 +220,16 @@ static int idx2dindex(int ifidx, int socket) return i; } -static inline void sprint_timestamp(const char timestamp, const struct timeval *tv, - struct timeval *const last_tv, char *ts_buffer) +static int sprint_timestamp(char *ts_buffer, const char timestamp, + const struct timeval *tv, struct timeval *const last_tv) { + int numchars = 0; + switch (timestamp) { case 'a': /* absolute with timestamp */ - sprintf(ts_buffer, "(%010llu.%06llu) ", (unsigned long long)tv->tv_sec, (unsigned long long)tv->tv_usec); + numchars = sprintf(ts_buffer, "(%010llu.%06llu) ", + (unsigned long long)tv->tv_sec, + (unsigned long long)tv->tv_usec); break; case 'A': /* absolute with date */ @@ -235,7 +239,8 @@ static inline void sprint_timestamp(const char timestamp, const struct timeval * tm = *localtime(&tv->tv_sec); strftime(timestring, 24, "%Y-%m-%d %H:%M:%S", &tm); - sprintf(ts_buffer, "(%s.%06llu) ", timestring, (unsigned long long)tv->tv_usec); + numchars = sprintf(ts_buffer, "(%s.%06llu) ", timestring, + (unsigned long long)tv->tv_usec); } break; @@ -252,7 +257,9 @@ static inline void sprint_timestamp(const char timestamp, const struct timeval * diff.tv_sec--, diff.tv_usec += 1000000; if (diff.tv_sec < 0) diff.tv_sec = diff.tv_usec = 0; - sprintf(ts_buffer, "(%03llu.%06llu) ", (unsigned long long)diff.tv_sec, (unsigned long long)diff.tv_usec); + numchars = sprintf(ts_buffer, "(%03llu.%06llu) ", + (unsigned long long)diff.tv_sec, + (unsigned long long)diff.tv_usec); if (timestamp == 'd') *last_tv = *tv; /* update for delta calculation */ @@ -262,15 +269,8 @@ static inline void sprint_timestamp(const char timestamp, const struct timeval * default: /* no timestamp output */ break; } -} -static inline void print_timestamp(const char timestamp, const struct timeval *tv, - struct timeval *const last_tv) -{ - static char buffer[TIMESTAMPSZ]; - - sprint_timestamp(timestamp, tv, last_tv, buffer); - printf("%s", buffer); + return numchars; } int main(int argc, char **argv) @@ -317,6 +317,8 @@ int main(int argc, char **argv) FILE *logfile = NULL; char fname[83]; /* suggested by -Wformat-overflow= */ const char *logname = NULL; + static char abuf[10000]; /* ASCII buf FIXME - use calculated value */ + static int alen; signal(SIGTERM, sigterm); signal(SIGHUP, sigterm); @@ -797,32 +799,29 @@ int main(int argc, char **argv) extra_info = " R"; } - if (log) { - char buf[CL_CFSZ]; /* max length */ - char ts_buf[TIMESTAMPSZ]; + /* build common log format output */ + if ((log) || ((logfrmt) && (silent == SILENT_OFF))) { - sprint_timestamp(logtimestamp, &tv, &last_tv, ts_buf); + alen = sprint_timestamp(abuf, logtimestamp, + &tv, &last_tv); - /* log CAN frame with absolute timestamp & device */ - sprint_canframe(buf, &frame, 0); - fprintf(logfile, "%s%*s %s%s\n", ts_buf, - max_devname_len, devname[idx], buf, - extra_info); + alen += sprintf(abuf + alen, "%*s ", + max_devname_len, devname[idx]); + + alen += sprint_canframe(abuf + alen, &frame, 0); } + /* write CAN frame in log file style to logfile */ + if (log) + fprintf(logfile, "%s%s\n", abuf, extra_info); + + /* print CAN frame in log file style to stdout */ if ((logfrmt) && (silent == SILENT_OFF)) { - char buf[CL_CFSZ]; /* max length */ - - /* print CAN frame in log file style to stdout */ - sprint_canframe(buf, &frame, 0); - print_timestamp(logtimestamp, &tv, &last_tv); - - printf("%*s %s%s\n", - max_devname_len, devname[idx], buf, - extra_info); + printf("%s%s\n", abuf, extra_info); goto out_fflush; /* no other output to stdout */ } + /* print only animation */ if (silent != SILENT_OFF) { if (silent == SILENT_ANI) { printf("%c\b", anichar[silentani %= MAXANI]); @@ -831,25 +830,33 @@ int main(int argc, char **argv) goto out_fflush; /* no other output to stdout */ } - printf(" %s", (color > 2) ? col_on[idx % MAXCOL] : ""); - print_timestamp(timestamp, &tv, &last_tv); - printf(" %s", (color && (color < 3)) ? col_on[idx % MAXCOL] : ""); - printf("%*s", max_devname_len, devname[idx]); + /* print (colored) long CAN frame style to stdout */ + alen = sprintf(abuf, " %s", (color > 2) ? col_on[idx % MAXCOL] : ""); + alen += sprint_timestamp(abuf + alen, timestamp, &tv, &last_tv); + alen += sprintf(abuf + alen, " %s%*s", + (color && (color < 3)) ? col_on[idx % MAXCOL] : "", + max_devname_len, devname[idx]); if (extra_msg_info) { if (msg.msg_flags & MSG_DONTROUTE) - printf(" TX %s", extra_m_info[frame.flags & 3]); + alen += sprintf(abuf + alen, " TX %s", + extra_m_info[frame.flags & 3]); else - printf(" RX %s", extra_m_info[frame.flags & 3]); + alen += sprintf(abuf + alen, " RX %s", + extra_m_info[frame.flags & 3]); } - printf("%s ", (color == 1) ? col_off : ""); + alen += sprintf(abuf + alen, "%s ", (color == 1) ? col_off : ""); + alen += sprint_long_canframe(abuf + alen, &frame, view); - fprint_long_canframe(stdout, &frame, NULL, view); - - printf("%s", (color > 1) ? col_off : ""); - printf("\n"); + if ((view & CANLIB_VIEW_ERROR) && (frame.can_id & CAN_ERR_FLAG)) { + alen += sprintf(abuf + alen, "\n\t"); + alen += snprintf_can_error_frame(abuf + alen, + sizeof(abuf) - alen, + &frame, "\n\t"); + } + printf("%s%s\n", abuf, (color > 1) ? col_off : ""); out_fflush: fflush(stdout); } diff --git a/lib.c b/lib.c index 47fb95b..69320ae 100644 --- a/lib.c +++ b/lib.c @@ -270,7 +270,7 @@ void fprint_canframe(FILE *stream, struct canfd_frame *cf, char *eol, int sep) fprintf(stream, "%s", eol); } -void sprint_canframe(char *buf, struct canfd_frame *cf, int sep) +int sprint_canframe(char *buf, struct canfd_frame *cf, int sep) { /* documentation see lib.h */ @@ -317,7 +317,7 @@ void sprint_canframe(char *buf, struct canfd_frame *cf, int sep) } buf[offset] = 0; - return; + return offset; } /* any CAN FD flags */ @@ -349,6 +349,8 @@ void sprint_canframe(char *buf, struct canfd_frame *cf, int sep) } buf[offset] = 0; + + return offset; } void fprint_long_canframe(FILE *stream, struct canfd_frame *cf, char *eol, int view) @@ -367,7 +369,7 @@ void fprint_long_canframe(FILE *stream, struct canfd_frame *cf, char *eol, int v fprintf(stream, "%s", eol); } -void sprint_long_canframe(char *buf, struct canfd_frame *cf, int view) +int sprint_long_canframe(char *buf, struct canfd_frame *cf, int view) { /* documentation see lib.h */ @@ -422,8 +424,8 @@ void sprint_long_canframe(char *buf, struct canfd_frame *cf, int view) /* standard CAN frames may have RTR enabled */ if (cf->can_id & CAN_RTR_FLAG) { - sprintf(buf + offset + 5, " remote request"); - return; + offset += sprintf(buf + offset + 5, " remote request"); + return offset + 5; } } else { buf[offset] = '['; @@ -477,10 +479,10 @@ void sprint_long_canframe(char *buf, struct canfd_frame *cf, int view) * Does it make sense to write 64 ASCII byte behind 64 ASCII HEX data on the console? */ if (len > CAN_MAX_DLEN) - return; + return offset; if (cf->can_id & CAN_ERR_FLAG) - sprintf(buf + offset, "%*s", dlen * (8 - len) + 13, "ERRORFRAME"); + offset += sprintf(buf + offset, "%*s", dlen * (8 - len) + 13, "ERRORFRAME"); else if (view & CANLIB_VIEW_ASCII) { j = dlen * (8 - len) + 4; if (view & CANLIB_VIEW_SWAP) { @@ -492,7 +494,7 @@ void sprint_long_canframe(char *buf, struct canfd_frame *cf, int view) else buf[offset++] = '.'; - sprintf(buf + offset, "`"); + offset += sprintf(buf + offset, "`"); } else { sprintf(buf + offset, "%*s", j, "'"); offset += j; @@ -502,9 +504,11 @@ void sprint_long_canframe(char *buf, struct canfd_frame *cf, int view) else buf[offset++] = '.'; - sprintf(buf + offset, "'"); + offset += sprintf(buf + offset, "'"); } } + + return offset; } static const char *error_classes[] = { @@ -668,7 +672,7 @@ static int snprintf_error_cnt(char *buf, size_t len, const struct canfd_frame *c return n; } -void snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *cf, +int snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *cf, const char* sep) { canid_t class, mask; @@ -676,12 +680,12 @@ void snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *c char *defsep = ","; if (!(cf->can_id & CAN_ERR_FLAG)) - return; + return 0; class = cf->can_id & CAN_EFF_MASK; if (class > (1 << ARRAY_SIZE(error_classes))) { fprintf(stderr, "Error class %#x is invalid\n", class); - return; + return 0; } if (!sep) @@ -695,13 +699,15 @@ void snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *c /* Fix for potential buffer overflow https://lgtm.com/rules/1505913226124/ */ tmp_n = snprintf(buf + n, len - n, "%s", sep); if (tmp_n < 0 || (size_t)tmp_n >= len - n) { - return; + buf[0] = 0; /* empty terminated string */ + return 0; } n += tmp_n; } tmp_n = snprintf(buf + n, len - n, "%s", error_classes[i]); if (tmp_n < 0 || (size_t)tmp_n >= len - n) { - return; + buf[0] = 0; /* empty terminated string */ + return 0; } n += tmp_n; if (mask == CAN_ERR_LOSTARB) @@ -721,6 +727,8 @@ void snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *c n += snprintf(buf + n, len - n, "%serror-counter-tx-rx", sep); n += snprintf_error_cnt(buf + n, len - n, cf); } + + return n; } int64_t timespec_diff_ms(struct timespec *ts1, diff --git a/lib.h b/lib.h index 817eb0d..6b49759 100644 --- a/lib.h +++ b/lib.h @@ -161,7 +161,7 @@ int parse_canframe(char *cs, struct canfd_frame *cf); */ void fprint_canframe(FILE *stream , struct canfd_frame *cf, char *eol, int sep); -void sprint_canframe(char *buf , struct canfd_frame *cf, int sep); +int sprint_canframe(char *buf , struct canfd_frame *cf, int sep); /* * Creates a CAN frame hexadecimal output in compact format. * The CAN data[] is separated by '.' when sep != 0. @@ -197,7 +197,7 @@ void sprint_canframe(char *buf , struct canfd_frame *cf, int sep); #define SWAP_DELIMITER '`' void fprint_long_canframe(FILE *stream , struct canfd_frame *cf, char *eol, int view); -void sprint_long_canframe(char *buf , struct canfd_frame *cf, int view); +int sprint_long_canframe(char *buf , struct canfd_frame *cf, int view); /* * Creates a CAN frame hexadecimal output in user readable format. * @@ -226,8 +226,8 @@ void sprint_long_canframe(char *buf , struct canfd_frame *cf, int view); * */ -void snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *cf, - const char *sep); +int snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *cf, + const char *sep); /* * Creates a CAN error frame output in user readable format. */ From 8d8d17e25d6c6a7d8c867e51c821b78d47dcfbea Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 27 Feb 2024 10:11:17 +0100 Subject: [PATCH 03/27] asc2log: remove fprint_canframe usage Signed-off-by: Oliver Hartkopp --- asc2log.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/asc2log.c b/asc2log.c index 951835b..fb16db3 100644 --- a/asc2log.c +++ b/asc2log.c @@ -73,6 +73,8 @@ void print_usage(char *prg) void prframe(FILE *file, struct timeval *tv, int dev, struct canfd_frame *cf, char *extra_info) { + static char abuf[BUFLEN]; + fprintf(file, "(%llu.%06llu) ", (unsigned long long)tv->tv_sec, (unsigned long long)tv->tv_usec); if (dev > 0) @@ -80,7 +82,8 @@ void prframe(FILE *file, struct timeval *tv, int dev, struct canfd_frame *cf, ch else fprintf(file, "canX "); - fprint_canframe(file, cf, extra_info, 0); + sprint_canframe(abuf, cf, 0); + fprintf(file, "%s%s", abuf, extra_info); } void get_can_id(struct canfd_frame *cf, char *idstring, int base) { From 9d900f913cc404010de4c167f1944053f21a9267 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 27 Feb 2024 10:57:55 +0100 Subject: [PATCH 04/27] cangen: remove fprint_(long_)canframe usage Signed-off-by: Oliver Hartkopp --- cangen.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cangen.c b/cangen.c index 64ea934..8825175 100644 --- a/cangen.c +++ b/cangen.c @@ -828,12 +828,16 @@ int main(int argc, char **argv) } if (verbose) { + static char abuf[10000]; /* ASCII buf FIXME - use calculated value */ + printf(" %s ", argv[optind]); if (verbose > 1) - fprint_long_canframe(stdout, &frame, "\n", (verbose > 2) ? 1 : 0); + sprint_long_canframe(abuf, &frame, (verbose > 2) ? CANLIB_VIEW_ASCII : 0); else - fprint_canframe(stdout, &frame, "\n", 1); + sprint_canframe(abuf, &frame, 1); + + printf("%s\n", abuf); } ret = do_send_one(s, &frame, mtu, polltimeout); From 48e10c9c57026d5bb1ef3b8c22ed67c3471f4ccb Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 27 Feb 2024 11:04:42 +0100 Subject: [PATCH 05/27] canplayer: remove fprint_long_canframe usage Signed-off-by: Oliver Hartkopp --- canplayer.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/canplayer.c b/canplayer.c index 1f2d6cc..bd93740 100644 --- a/canplayer.c +++ b/canplayer.c @@ -485,8 +485,11 @@ int main(int argc, char **argv) } if (verbose) { + static char abuf[10000]; /* ASCII buf FIXME - use calculated value */ + printf("%s (%s) ", get_txname(device), device); - fprint_long_canframe(stdout, &frame, "\n", CANLIB_VIEW_INDENT_SFF); + sprint_long_canframe(abuf, &frame, CANLIB_VIEW_INDENT_SFF); + printf("%s\n", abuf); } if (count && (--count == 0)) From 3b36edf1280b12096e3df4f96e8818f43239158c Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 27 Feb 2024 11:14:18 +0100 Subject: [PATCH 06/27] canlogserver: remove fprint_canframe usage Signed-off-by: Oliver Hartkopp --- canlogserver.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/canlogserver.c b/canlogserver.c index eb9167a..fcb25d3 100644 --- a/canlogserver.c +++ b/canlogserver.c @@ -428,9 +428,7 @@ int main(int argc, char **argv) #if 0 /* print CAN frame in log file style to stdout */ - printf("(%lu.%06lu) ", tv.tv_sec, tv.tv_usec); - printf("%*s ", max_devname_len, devname[idx]); - fprint_canframe(stdout, &frame, "\n", 0, maxdlen); + printf("%s", temp); #endif } From f491175d7238ca960b1a8ec9211abe10809d568c Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 27 Feb 2024 11:17:49 +0100 Subject: [PATCH 07/27] lib: remove obsolete fprint_(long_)canframe functions Signed-off-by: Oliver Hartkopp --- lib.c | 28 ---------------------------- lib.h | 15 --------------- 2 files changed, 43 deletions(-) diff --git a/lib.c b/lib.c index 69320ae..cb84e68 100644 --- a/lib.c +++ b/lib.c @@ -258,18 +258,6 @@ int parse_canframe(char *cs, struct canfd_frame *cf) return ret; } -void fprint_canframe(FILE *stream, struct canfd_frame *cf, char *eol, int sep) -{ - /* documentation see lib.h */ - - char buf[CL_CFSZ]; /* max length */ - - sprint_canframe(buf, cf, sep); - fprintf(stream, "%s", buf); - if (eol) - fprintf(stream, "%s", eol); -} - int sprint_canframe(char *buf, struct canfd_frame *cf, int sep) { /* documentation see lib.h */ @@ -353,22 +341,6 @@ int sprint_canframe(char *buf, struct canfd_frame *cf, int sep) return offset; } -void fprint_long_canframe(FILE *stream, struct canfd_frame *cf, char *eol, int view) -{ - /* documentation see lib.h */ - - char buf[CL_LONGCFSZ]; - - sprint_long_canframe(buf, cf, view); - fprintf(stream, "%s", buf); - if ((view & CANLIB_VIEW_ERROR) && (cf->can_id & CAN_ERR_FLAG)) { - snprintf_can_error_frame(buf, sizeof(buf), cf, "\n\t"); - fprintf(stream, "\n\t%s", buf); - } - if (eol) - fprintf(stream, "%s", eol); -} - int sprint_long_canframe(char *buf, struct canfd_frame *cf, int view) { /* documentation see lib.h */ diff --git a/lib.h b/lib.h index 6b49759..fc58814 100644 --- a/lib.h +++ b/lib.h @@ -160,7 +160,6 @@ int parse_canframe(char *cs, struct canfd_frame *cf); * - CAN FD frames do not have a RTR bit */ -void fprint_canframe(FILE *stream , struct canfd_frame *cf, char *eol, int sep); int sprint_canframe(char *buf , struct canfd_frame *cf, int sep); /* * Creates a CAN frame hexadecimal output in compact format. @@ -180,11 +179,6 @@ int sprint_canframe(char *buf , struct canfd_frame *cf, int sep); * 123##0112233 -> CAN FD frame standard CAN-Id = 0x123, flags = 0, len = 3 * 123##2112233 -> CAN FD frame, flags = CANFD_ESI, len = 3 * - * Examples: - * - * fprint_canframe(stdout, &frame, "\n", 0); // with eol to STDOUT - * fprint_canframe(stderr, &frame, NULL, 0); // no eol to STDERR - * */ #define CANLIB_VIEW_ASCII 0x1 @@ -196,7 +190,6 @@ int sprint_canframe(char *buf , struct canfd_frame *cf, int sep); #define SWAP_DELIMITER '`' -void fprint_long_canframe(FILE *stream , struct canfd_frame *cf, char *eol, int view); int sprint_long_canframe(char *buf , struct canfd_frame *cf, int view); /* * Creates a CAN frame hexadecimal output in user readable format. @@ -216,14 +209,6 @@ int sprint_long_canframe(char *buf , struct canfd_frame *cf, int view); * 123 [3] 11 22 33 -> CANLIB_VIEW_INDENT_SFF == 0 * 123 [3] 11 22 33 -> CANLIB_VIEW_INDENT_SFF == set * - * Examples: - * - * // CAN FD frame with eol to STDOUT - * fprint_long_canframe(stdout, &frame, "\n", 0); - * - * // Classical CAN 2.0 frame without eol to STDERR - * fprint_long_canframe(stderr, &frame, NULL, 0); - * */ int snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *cf, From 57238d5f810a13e099f28d6d0ce4caf929d0b329 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 27 Feb 2024 11:33:01 +0100 Subject: [PATCH 08/27] candump: add sprintf error handling in sprint_timestamp Signed-off-by: Oliver Hartkopp --- candump.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/candump.c b/candump.c index ecbcfa0..e62acf2 100644 --- a/candump.c +++ b/candump.c @@ -270,6 +270,11 @@ static int sprint_timestamp(char *ts_buffer, const char timestamp, break; } + if (numchars <= 0) { + ts_buffer[0] = 0; /* empty terminated string */ + numchars = 0; + } + return numchars; } From 04312e5a10df828b69752f9538e22fad7c04b722 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 27 Feb 2024 18:23:29 +0100 Subject: [PATCH 09/27] candump/lib: make sprint_canframe CAN XL aware Signed-off-by: Oliver Hartkopp --- asc2log.c | 2 +- candump.c | 52 ++++++++++++++++++++++++++-------------- cangen.c | 2 +- canlogserver.c | 2 +- lib.c | 64 +++++++++++++++++++++++++++++++++----------------- lib.h | 10 +++++++- 6 files changed, 88 insertions(+), 44 deletions(-) diff --git a/asc2log.c b/asc2log.c index fb16db3..d861c67 100644 --- a/asc2log.c +++ b/asc2log.c @@ -82,7 +82,7 @@ void prframe(FILE *file, struct timeval *tv, int dev, struct canfd_frame *cf, ch else fprintf(file, "canX "); - sprint_canframe(abuf, cf, 0); + sprint_canframe(abuf, (cu_t *)cf, 0); fprintf(file, "%s%s", abuf, extra_info); } diff --git a/candump.c b/candump.c index e62acf2..c5500ad 100644 --- a/candump.c +++ b/candump.c @@ -109,7 +109,7 @@ static char *progname; static char devname[MAXIFNAMES][IFNAMSIZ + 1]; static int dindex[MAXIFNAMES]; static int max_devname_len; /* to prevent frazzled device name output */ -static const int canfd_on = 1; +static const int canfx_on = 1; #define MAXANI 4 static const char anichar[MAXANI] = { '|', '/', '-', '\\' }; @@ -314,7 +314,7 @@ int main(int argc, char **argv) struct cmsghdr *cmsg; struct can_filter *rfilter; can_err_mask_t err_mask; - struct canfd_frame frame; + static cu_t cu; /* union for CAN CC/FD/XL frames */ int nbytes, i; struct ifreq ifr; struct timeval tv, last_tv; @@ -596,7 +596,10 @@ int main(int argc, char **argv) } /* if (nptr) */ /* try to switch the socket into CAN FD mode */ - setsockopt(obj->s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &canfd_on, sizeof(canfd_on)); + setsockopt(obj->s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &canfx_on, sizeof(canfx_on)); + + /* try to switch the socket into CAN XL mode */ + setsockopt(obj->s, SOL_CAN_RAW, CAN_RAW_XL_FRAMES, &canfx_on, sizeof(canfx_on)); if (rcvbuf_size) { int curr_rcvbuf_size; @@ -700,7 +703,7 @@ int main(int argc, char **argv) } /* these settings are static and can be held out of the hot path */ - iov.iov_base = &frame; + iov.iov_base = &cu; msg.msg_name = &addr; msg.msg_iov = &iov; msg.msg_iovlen = 1; @@ -726,7 +729,7 @@ int main(int argc, char **argv) char *extra_info = ""; /* these settings may be modified by recvmsg() */ - iov.iov_len = sizeof(frame); + iov.iov_len = sizeof(cu); msg.msg_namelen = sizeof(addr); msg.msg_controllen = sizeof(ctrlmsg); msg.msg_flags = 0; @@ -744,15 +747,28 @@ int main(int argc, char **argv) } /* mark dual-use struct canfd_frame */ - if ((size_t)nbytes == CAN_MTU) - frame.flags = 0; - else if ((size_t)nbytes == CANFD_MTU) - frame.flags |= CANFD_FDF; - else { - fprintf(stderr, "read: incomplete CAN frame\n"); + if (nbytes < CANXL_HDR_SIZE + CANXL_MIN_DLEN) { + fprintf(stderr, "read: no CAN frame\n"); return 1; } + if (cu.xl.flags & CANXL_XLF) { + if (nbytes != CANXL_HDR_SIZE + cu.xl.len) { + printf("nbytes = %d\n", nbytes); + fprintf(stderr, "read: no CAN XL frame\n"); + return 1; + } + } else { + if (nbytes == CAN_MTU) + cu.fd.flags = 0; + else if (nbytes == CANFD_MTU) + cu.fd.flags |= CANFD_FDF; + else { + fprintf(stderr, "read: incomplete CAN CC/FD frame\n"); + return 1; + } + } + if (count && (--count == 0)) running = 0; @@ -794,7 +810,7 @@ int main(int argc, char **argv) } /* once we detected a EFF frame indent SFF frames accordingly */ - if (frame.can_id & CAN_EFF_FLAG) + if (cu.fd.can_id & CAN_EFF_FLAG) view |= CANLIB_VIEW_INDENT_SFF; if (extra_msg_info) { @@ -813,7 +829,7 @@ int main(int argc, char **argv) alen += sprintf(abuf + alen, "%*s ", max_devname_len, devname[idx]); - alen += sprint_canframe(abuf + alen, &frame, 0); + alen += sprint_canframe(abuf + alen, &cu, 0); } /* write CAN frame in log file style to logfile */ @@ -845,20 +861,20 @@ int main(int argc, char **argv) if (extra_msg_info) { if (msg.msg_flags & MSG_DONTROUTE) alen += sprintf(abuf + alen, " TX %s", - extra_m_info[frame.flags & 3]); + extra_m_info[cu.fd.flags & 3]); else alen += sprintf(abuf + alen, " RX %s", - extra_m_info[frame.flags & 3]); + extra_m_info[cu.fd.flags & 3]); } alen += sprintf(abuf + alen, "%s ", (color == 1) ? col_off : ""); - alen += sprint_long_canframe(abuf + alen, &frame, view); + alen += sprint_long_canframe(abuf + alen, &cu.fd, view); - if ((view & CANLIB_VIEW_ERROR) && (frame.can_id & CAN_ERR_FLAG)) { + if ((view & CANLIB_VIEW_ERROR) && (cu.fd.can_id & CAN_ERR_FLAG)) { alen += sprintf(abuf + alen, "\n\t"); alen += snprintf_can_error_frame(abuf + alen, sizeof(abuf) - alen, - &frame, "\n\t"); + &cu.fd, "\n\t"); } printf("%s%s\n", abuf, (color > 1) ? col_off : ""); diff --git a/cangen.c b/cangen.c index 8825175..ad93ea8 100644 --- a/cangen.c +++ b/cangen.c @@ -835,7 +835,7 @@ int main(int argc, char **argv) if (verbose > 1) sprint_long_canframe(abuf, &frame, (verbose > 2) ? CANLIB_VIEW_ASCII : 0); else - sprint_canframe(abuf, &frame, 1); + sprint_canframe(abuf, (cu_t *)&frame, 1); printf("%s\n", abuf); } diff --git a/canlogserver.c b/canlogserver.c index fcb25d3..e64cc86 100644 --- a/canlogserver.c +++ b/canlogserver.c @@ -418,7 +418,7 @@ int main(int argc, char **argv) sprintf(temp, "(%llu.%06llu) %*s ", (unsigned long long)tv.tv_sec, (unsigned long long)tv.tv_usec, max_devname_len, devname[idx]); - sprint_canframe(temp+strlen(temp), &frame, 0); + sprint_canframe(temp+strlen(temp), (cu_t *)&frame, 0); strcat(temp, "\n"); if (write(accsocket, temp, strlen(temp)) < 0) { diff --git a/lib.c b/lib.c index cb84e68..53defb6 100644 --- a/lib.c +++ b/lib.c @@ -258,48 +258,69 @@ int parse_canframe(char *cs, struct canfd_frame *cf) return ret; } -int sprint_canframe(char *buf, struct canfd_frame *cf, int sep) +int sprint_canframe(char *buf, cu_t *cu, int sep) { /* documentation see lib.h */ - unsigned char is_canfd = cf->flags; + unsigned char is_canfd = cu->fd.flags; int i, offset; int len; - /* ensure max length values */ - if (is_canfd) - len = (cf->len > CANFD_MAX_DLEN) ? CANFD_MAX_DLEN : cf->len; - else - len = (cf->len > CAN_MAX_DLEN) ? CAN_MAX_DLEN : cf->len; + /* handle CAN XL frames */ + if (cu->xl.flags & CANXL_XLF) { + len = cu->xl.len; - if (cf->can_id & CAN_ERR_FLAG) { - put_eff_id(buf, cf->can_id & (CAN_ERR_MASK | CAN_ERR_FLAG)); + /* print prio and CAN XL header content */ + offset = sprintf(buf, "%02X%03X#%02X:%02X:%08X#", + (canid_t)(cu->xl.prio & CANXL_VCID_MASK) >> CANXL_VCID_OFFSET, + (canid_t)(cu->xl.prio & CANXL_PRIO_MASK), + cu->xl.flags, cu->xl.sdt, cu->xl.af); + + /* data */ + for (i = 0; i < len; i++) { + put_hex_byte(buf + offset, cu->xl.data[i]); + offset += 2; + if (sep && (i + 1 < len)) + buf[offset++] = '.'; + } + + buf[offset] = 0; + + return offset; + } + + /* handle CAN CC/FD frames - ensure max length values */ + if (is_canfd) + len = (cu->fd.len > CANFD_MAX_DLEN) ? CANFD_MAX_DLEN : cu->fd.len; + else + len = (cu->fd.len > CAN_MAX_DLEN) ? CAN_MAX_DLEN : cu->fd.len; + + if (cu->fd.can_id & CAN_ERR_FLAG) { + put_eff_id(buf, cu->fd.can_id & (CAN_ERR_MASK | CAN_ERR_FLAG)); buf[8] = '#'; offset = 9; - } else if (cf->can_id & CAN_EFF_FLAG) { - put_eff_id(buf, cf->can_id & CAN_EFF_MASK); + } else if (cu->fd.can_id & CAN_EFF_FLAG) { + put_eff_id(buf, cu->fd.can_id & CAN_EFF_MASK); buf[8] = '#'; offset = 9; } else { - put_sff_id(buf, cf->can_id & CAN_SFF_MASK); + put_sff_id(buf, cu->fd.can_id & CAN_SFF_MASK); buf[3] = '#'; offset = 4; } /* CAN CC frames may have RTR enabled. There are no ERR frames with RTR */ - if (!(is_canfd) && cf->can_id & CAN_RTR_FLAG) { + if (!(is_canfd) && cu->fd.can_id & CAN_RTR_FLAG) { buf[offset++] = 'R'; /* print a given CAN 2.0B DLC if it's not zero */ if (len && len <= CAN_MAX_DLEN) { - buf[offset++] = hex_asc_upper_lo(cf->len); + buf[offset++] = hex_asc_upper_lo(cu->fd.len); /* check for optional raw DLC value for CAN 2.0B frames */ if (len == CAN_MAX_DLEN) { - struct can_frame *ccf = (struct can_frame *)cf; - - if ((ccf->len8_dlc > CAN_MAX_DLEN) && (ccf->len8_dlc <= CAN_MAX_RAW_DLC)) { + if ((cu->cc.len8_dlc > CAN_MAX_DLEN) && (cu->cc.len8_dlc <= CAN_MAX_RAW_DLC)) { buf[offset++] = CC_DLC_DELIM; - buf[offset++] = hex_asc_upper_lo(ccf->len8_dlc); + buf[offset++] = hex_asc_upper_lo(cu->cc.len8_dlc); } } } @@ -312,14 +333,14 @@ int sprint_canframe(char *buf, struct canfd_frame *cf, int sep) if (is_canfd) { /* add CAN FD specific escape char and flags */ buf[offset++] = '#'; - buf[offset++] = hex_asc_upper_lo(cf->flags); + buf[offset++] = hex_asc_upper_lo(cu->fd.flags); if (sep && len) buf[offset++] = '.'; } /* data */ for (i = 0; i < len; i++) { - put_hex_byte(buf + offset, cf->data[i]); + put_hex_byte(buf + offset, cu->fd.data[i]); offset += 2; if (sep && (i + 1 < len)) buf[offset++] = '.'; @@ -327,8 +348,7 @@ int sprint_canframe(char *buf, struct canfd_frame *cf, int sep) /* check for extra DLC when having a Classic CAN with 8 bytes payload */ if (!(is_canfd) && (len == CAN_MAX_DLEN)) { - struct can_frame *ccf = (struct can_frame *)cf; - unsigned char dlc = ccf->len8_dlc; + unsigned char dlc = cu->cc.len8_dlc; if ((dlc > CAN_MAX_DLEN) && (dlc <= CAN_MAX_RAW_DLC)) { buf[offset++] = CC_DLC_DELIM; diff --git a/lib.h b/lib.h index fc58814..fc8e17b 100644 --- a/lib.h +++ b/lib.h @@ -46,6 +46,7 @@ #define CAN_UTILS_LIB_H #include +#include #include #ifdef DEBUG @@ -55,6 +56,13 @@ __attribute__((format (printf, 1, 2))) static inline int pr_debug(const char* fmt, ...) {return 0;} #endif +/* CAN CC/FD/XL frame union */ +typedef union { + struct can_frame cc; + struct canfd_frame fd; + struct canxl_frame xl; +} cu_t; + /* buffer sizes for CAN frame string representations */ #define CL_ID (sizeof("12345678##1")) @@ -160,7 +168,7 @@ int parse_canframe(char *cs, struct canfd_frame *cf); * - CAN FD frames do not have a RTR bit */ -int sprint_canframe(char *buf , struct canfd_frame *cf, int sep); +int sprint_canframe(char *buf , cu_t *cu, int sep); /* * Creates a CAN frame hexadecimal output in compact format. * The CAN data[] is separated by '.' when sep != 0. From 3644a54d5b78854719b045dac9a5955d73630495 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 27 Feb 2024 20:03:07 +0100 Subject: [PATCH 10/27] candump/lib: make sprint_long_canframe CAN XL aware The 'long' CAN frame representation does not really fit for CAN XL content. Therefore just a cropped output is provided to be able to see the CAN XL header information and up to 64 byte of data (without binary or swap formating options). To get the full qualified CAN XL content use the log file format. Signed-off-by: Oliver Hartkopp --- candump.c | 2 +- cangen.c | 2 +- canplayer.c | 2 +- lib.c | 89 +++++++++++++++++++++++++++++++++++++---------------- lib.h | 2 +- log2long.c | 2 +- 6 files changed, 68 insertions(+), 31 deletions(-) diff --git a/candump.c b/candump.c index c5500ad..d1bc975 100644 --- a/candump.c +++ b/candump.c @@ -868,7 +868,7 @@ int main(int argc, char **argv) } alen += sprintf(abuf + alen, "%s ", (color == 1) ? col_off : ""); - alen += sprint_long_canframe(abuf + alen, &cu.fd, view); + alen += sprint_long_canframe(abuf + alen, &cu, view); if ((view & CANLIB_VIEW_ERROR) && (cu.fd.can_id & CAN_ERR_FLAG)) { alen += sprintf(abuf + alen, "\n\t"); diff --git a/cangen.c b/cangen.c index ad93ea8..11b156f 100644 --- a/cangen.c +++ b/cangen.c @@ -833,7 +833,7 @@ int main(int argc, char **argv) printf(" %s ", argv[optind]); if (verbose > 1) - sprint_long_canframe(abuf, &frame, (verbose > 2) ? CANLIB_VIEW_ASCII : 0); + sprint_long_canframe(abuf, (cu_t *)&frame, (verbose > 2) ? CANLIB_VIEW_ASCII : 0); else sprint_canframe(abuf, (cu_t *)&frame, 1); diff --git a/canplayer.c b/canplayer.c index bd93740..cefc78d 100644 --- a/canplayer.c +++ b/canplayer.c @@ -488,7 +488,7 @@ int main(int argc, char **argv) static char abuf[10000]; /* ASCII buf FIXME - use calculated value */ printf("%s (%s) ", get_txname(device), device); - sprint_long_canframe(abuf, &frame, CANLIB_VIEW_INDENT_SFF); + sprint_long_canframe(abuf, (cu_t *)&frame, CANLIB_VIEW_INDENT_SFF); printf("%s\n", abuf); } diff --git a/lib.c b/lib.c index 53defb6..fec71ac 100644 --- a/lib.c +++ b/lib.c @@ -361,35 +361,73 @@ int sprint_canframe(char *buf, cu_t *cu, int sep) return offset; } -int sprint_long_canframe(char *buf, struct canfd_frame *cf, int view) +int sprint_long_canframe(char *buf, cu_t *cu, int view) { /* documentation see lib.h */ - unsigned char is_canfd = cf->flags; + unsigned char is_canfd = cu->fd.flags; int i, j, dlen, offset; int len; - /* ensure max length values */ - if (is_canfd) - len = (cf->len > CANFD_MAX_DLEN) ? CANFD_MAX_DLEN : cf->len; - else - len = (cf->len > CAN_MAX_DLEN) ? CAN_MAX_DLEN : cf->len; - /* initialize space for CAN-ID and length information */ memset(buf, ' ', 15); - if (cf->can_id & CAN_ERR_FLAG) { - put_eff_id(buf, cf->can_id & (CAN_ERR_MASK | CAN_ERR_FLAG)); + /* handle CAN XL frames */ + if (cu->xl.flags & CANXL_XLF) { + len = cu->xl.len; + + if (view & CANLIB_VIEW_INDENT_SFF) { + put_sff_id(buf + 5, cu->xl.prio & CANXL_PRIO_MASK); + offset = 9; + } else { + put_sff_id(buf, cu->xl.prio & CANXL_PRIO_MASK); + offset = 4; + } + + /* print prio and CAN XL header content */ + offset += sprintf(buf + offset, "[%04d] (%02X|%02X:%02X:%08X) ", + len, + (canid_t)(cu->xl.prio & CANXL_VCID_MASK) >> CANXL_VCID_OFFSET, + cu->xl.flags, cu->xl.sdt, cu->xl.af); + + /* data - crop to CANFD_MAX_DLEN */ + if (len > CANFD_MAX_DLEN) + len = CANFD_MAX_DLEN; + + for (i = 0; i < len; i++) { + put_hex_byte(buf + offset, cu->xl.data[i]); + offset += 2; + if (i + 1 < len) + buf[offset++] = ' '; + } + + /* indicate cropped output */ + if (cu->xl.len > len) + offset += sprintf(buf + offset, " ..."); + + buf[offset] = 0; + + return offset; + } + + /* ensure max length values */ + if (is_canfd) + len = (cu->fd.len > CANFD_MAX_DLEN) ? CANFD_MAX_DLEN : cu->fd.len; + else + len = (cu->fd.len > CAN_MAX_DLEN) ? CAN_MAX_DLEN : cu->fd.len; + + if (cu->cc.can_id & CAN_ERR_FLAG) { + put_eff_id(buf, cu->cc.can_id & (CAN_ERR_MASK | CAN_ERR_FLAG)); offset = 10; - } else if (cf->can_id & CAN_EFF_FLAG) { - put_eff_id(buf, cf->can_id & CAN_EFF_MASK); + } else if (cu->fd.can_id & CAN_EFF_FLAG) { + put_eff_id(buf, cu->fd.can_id & CAN_EFF_MASK); offset = 10; } else { if (view & CANLIB_VIEW_INDENT_SFF) { - put_sff_id(buf + 5, cf->can_id & CAN_SFF_MASK); + put_sff_id(buf + 5, cu->fd.can_id & CAN_SFF_MASK); offset = 10; } else { - put_sff_id(buf, cf->can_id & CAN_SFF_MASK); + put_sff_id(buf, cu->fd.can_id & CAN_SFF_MASK); offset = 5; } } @@ -397,8 +435,7 @@ int sprint_long_canframe(char *buf, struct canfd_frame *cf, int view) /* The len value is sanitized (see above) */ if (!(is_canfd)) { if (view & CANLIB_VIEW_LEN8_DLC) { - struct can_frame *ccf = (struct can_frame *)cf; - unsigned char dlc = ccf->len8_dlc; + unsigned char dlc = cu->cc.len8_dlc; /* fall back to len if we don't have a valid DLC > 8 */ if (!((len == CAN_MAX_DLEN) && (dlc > CAN_MAX_DLEN) && @@ -415,7 +452,7 @@ int sprint_long_canframe(char *buf, struct canfd_frame *cf, int view) } /* standard CAN frames may have RTR enabled */ - if (cf->can_id & CAN_RTR_FLAG) { + if (cu->fd.can_id & CAN_RTR_FLAG) { offset += sprintf(buf + offset + 5, " remote request"); return offset + 5; } @@ -433,13 +470,13 @@ int sprint_long_canframe(char *buf, struct canfd_frame *cf, int view) for (i = len - 1; i >= 0; i--) { buf[offset++] = (i == len - 1) ? ' ' : SWAP_DELIMITER; for (j = 7; j >= 0; j--) - buf[offset++] = (1 << j & cf->data[i]) ? '1' : '0'; + buf[offset++] = (1 << j & cu->fd.data[i]) ? '1' : '0'; } } else { for (i = 0; i < len; i++) { buf[offset++] = ' '; for (j = 7; j >= 0; j--) - buf[offset++] = (1 << j & cf->data[i]) ? '1' : '0'; + buf[offset++] = (1 << j & cu->fd.data[i]) ? '1' : '0'; } } } else { @@ -451,13 +488,13 @@ int sprint_long_canframe(char *buf, struct canfd_frame *cf, int view) else buf[offset++] = SWAP_DELIMITER; - put_hex_byte(buf + offset, cf->data[i]); + put_hex_byte(buf + offset, cu->fd.data[i]); offset += 2; } } else { for (i = 0; i < len; i++) { buf[offset++] = ' '; - put_hex_byte(buf + offset, cf->data[i]); + put_hex_byte(buf + offset, cu->fd.data[i]); offset += 2; } } @@ -473,7 +510,7 @@ int sprint_long_canframe(char *buf, struct canfd_frame *cf, int view) if (len > CAN_MAX_DLEN) return offset; - if (cf->can_id & CAN_ERR_FLAG) + if (cu->fd.can_id & CAN_ERR_FLAG) offset += sprintf(buf + offset, "%*s", dlen * (8 - len) + 13, "ERRORFRAME"); else if (view & CANLIB_VIEW_ASCII) { j = dlen * (8 - len) + 4; @@ -481,8 +518,8 @@ int sprint_long_canframe(char *buf, struct canfd_frame *cf, int view) sprintf(buf + offset, "%*s", j, "`"); offset += j; for (i = len - 1; i >= 0; i--) - if ((cf->data[i] > 0x1F) && (cf->data[i] < 0x7F)) - buf[offset++] = cf->data[i]; + if ((cu->fd.data[i] > 0x1F) && (cu->fd.data[i] < 0x7F)) + buf[offset++] = cu->fd.data[i]; else buf[offset++] = '.'; @@ -491,8 +528,8 @@ int sprint_long_canframe(char *buf, struct canfd_frame *cf, int view) sprintf(buf + offset, "%*s", j, "'"); offset += j; for (i = 0; i < len; i++) - if ((cf->data[i] > 0x1F) && (cf->data[i] < 0x7F)) - buf[offset++] = cf->data[i]; + if ((cu->fd.data[i] > 0x1F) && (cu->fd.data[i] < 0x7F)) + buf[offset++] = cu->fd.data[i]; else buf[offset++] = '.'; diff --git a/lib.h b/lib.h index fc8e17b..67902fc 100644 --- a/lib.h +++ b/lib.h @@ -198,7 +198,7 @@ int sprint_canframe(char *buf , cu_t *cu, int sep); #define SWAP_DELIMITER '`' -int sprint_long_canframe(char *buf , struct canfd_frame *cf, int view); +int sprint_long_canframe(char *buf , cu_t *cu, int view); /* * Creates a CAN frame hexadecimal output in user readable format. * diff --git a/log2long.c b/log2long.c index 61208a3..97e25ab 100644 --- a/log2long.c +++ b/log2long.c @@ -75,7 +75,7 @@ int main(void) } /* with ASCII output */ - sprint_long_canframe(ascframe, &cf, + sprint_long_canframe(ascframe, (cu_t *)&cf, (CANLIB_VIEW_INDENT_SFF | CANLIB_VIEW_ASCII)); printf("%s %s %s\n", timestamp, device, ascframe); From 34a1cfad29beec92d201963e1abf8daff443f044 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 27 Feb 2024 22:22:24 +0100 Subject: [PATCH 11/27] lib: make parse_canframe CAN XL aware Signed-off-by: Oliver Hartkopp --- candump.c | 8 ++++ canplayer.c | 31 ++++++++++----- cansend.c | 50 +++++++++++++++++------- lib.c | 110 ++++++++++++++++++++++++++++++++++++++-------------- lib.h | 3 +- log2asc.c | 19 +++++---- log2long.c | 14 +++---- 7 files changed, 164 insertions(+), 71 deletions(-) diff --git a/candump.c b/candump.c index d1bc975..d70a8b1 100644 --- a/candump.c +++ b/candump.c @@ -306,6 +306,11 @@ int main(int argc, char **argv) struct sockaddr_can addr = { .can_family = AF_CAN, }; + struct can_raw_vcid_options vcid_opts = { + .flags = CAN_RAW_XL_VCID_RX_FILTER, + .rx_vcid = 0, + .rx_vcid_mask = 0, + }; char ctrlmsg[CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(3 * sizeof(struct timespec)) + CMSG_SPACE(sizeof(__u32))]; @@ -601,6 +606,9 @@ int main(int argc, char **argv) /* try to switch the socket into CAN XL mode */ setsockopt(obj->s, SOL_CAN_RAW, CAN_RAW_XL_FRAMES, &canfx_on, sizeof(canfx_on)); + /* try to enable the CAN XL VCID pass through mode */ + setsockopt(obj->s, SOL_CAN_RAW, CAN_RAW_XL_VCID_OPTS, &vcid_opts, sizeof(vcid_opts)); + if (rcvbuf_size) { int curr_rcvbuf_size; socklen_t curr_rcvbuf_size_len = sizeof(curr_rcvbuf_size); diff --git a/canplayer.c b/canplayer.c index cefc78d..4987428 100644 --- a/canplayer.c +++ b/canplayer.c @@ -71,7 +71,7 @@ struct assignment { char rxif[IFNAMSIZ]; }; static struct assignment asgn[CHANNELS]; -const int canfd_on = 1; +const int canfx_on = 1; extern int optind, opterr, optopt; @@ -239,9 +239,12 @@ int add_assignment(char *mode, int socket, char *txname, char *rxname, int verbo int main(int argc, char **argv) { - static char buf[BUFSZ], device[BUFSZ], ascframe[BUFSZ]; + static char buf[BUFSZ], device[BUFSZ], ascframe[10000]; struct sockaddr_can addr; - static struct canfd_frame frame; + struct can_raw_vcid_options vcid_opts = { + .flags = CAN_RAW_XL_VCID_TX_PASS, + }; + static cu_t cu; static struct timeval today_tv, log_tv, last_log_tv, diff_tv; struct timespec sleep_ts; int s; /* CAN_RAW socket */ @@ -360,7 +363,13 @@ int main(int argc, char **argv) setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0); /* try to switch the socket into CAN FD mode */ - setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &canfd_on, sizeof(canfd_on)); + setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &canfx_on, sizeof(canfx_on)); + + /* try to switch the socket into CAN XL mode */ + setsockopt(s, SOL_CAN_RAW, CAN_RAW_XL_FRAMES, &canfx_on, sizeof(canfx_on)); + + /* try to enable the CAN XL VCID pass through mode */ + setsockopt(s, SOL_CAN_RAW, CAN_RAW_XL_VCID_OPTS, &vcid_opts, sizeof(vcid_opts)); if (loopback_disable) { int loopback = 0; @@ -470,26 +479,28 @@ int main(int argc, char **argv) } else if (txidx > 0) { /* only send to valid CAN devices */ - txmtu = parse_canframe(ascframe, &frame); /* dual-use frame */ + txmtu = parse_canframe(ascframe, &cu); /* dual-use frame */ if (!txmtu) { fprintf(stderr, "wrong CAN frame format: '%s'!", ascframe); return 1; } + /* CAN XL frames need real frame length for sending */ + if (txmtu == CANXL_MTU) + txmtu = CANXL_HDR_SIZE + cu.xl.len; + addr.can_family = AF_CAN; addr.can_ifindex = txidx; /* send via this interface */ - if (sendto(s, &frame, txmtu, 0, (struct sockaddr *)&addr, sizeof(addr)) != txmtu) { + if (sendto(s, &cu, txmtu, 0, (struct sockaddr *)&addr, sizeof(addr)) != txmtu) { perror("sendto"); return 1; } if (verbose) { - static char abuf[10000]; /* ASCII buf FIXME - use calculated value */ - printf("%s (%s) ", get_txname(device), device); - sprint_long_canframe(abuf, (cu_t *)&frame, CANLIB_VIEW_INDENT_SFF); - printf("%s\n", abuf); + sprint_long_canframe(ascframe, &cu, CANLIB_VIEW_INDENT_SFF); + printf("%s\n", ascframe); } if (count && (--count == 0)) diff --git a/cansend.c b/cansend.c index c2eb30c..033692f 100644 --- a/cansend.c +++ b/cansend.c @@ -92,9 +92,12 @@ int main(int argc, char **argv) int s; /* can raw socket */ int required_mtu; int mtu; - int enable_canfd = 1; + int enable_canfx = 1; struct sockaddr_can addr; - struct canfd_frame frame; + struct can_raw_vcid_options vcid_opts = { + .flags = CAN_RAW_XL_VCID_TX_PASS, + }; + static cu_t cu; struct ifreq ifr; /* check command line options */ @@ -104,7 +107,7 @@ int main(int argc, char **argv) } /* parse CAN frame */ - required_mtu = parse_canframe(argv[2], &frame); + required_mtu = parse_canframe(argv[2], &cu); if (!required_mtu) { fprintf(stderr, "\nWrong CAN-frame format!\n\n"); print_usage(argv[0]); @@ -137,22 +140,39 @@ int main(int argc, char **argv) } mtu = ifr.ifr_mtu; - if (mtu != CANFD_MTU && mtu != CANXL_MTU) { - printf("CAN interface is only Classical CAN capable - sorry.\n"); - return 1; + if (mtu == 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; + } } - /* interface is ok - try to switch the socket into CAN FD mode */ - if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, - &enable_canfd, sizeof(enable_canfd))){ - printf("error when enabling CAN FD support\n"); - return 1; + if (mtu >= 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; + } } - - /* ensure discrete CAN FD length values 0..8, 12, 16, 20, 24, 32, 64 */ - frame.len = can_fd_dlc2len(can_fd_len2dlc(frame.len)); } + /* ensure discrete CAN FD length values 0..8, 12, 16, 20, 24, 32, 64 */ + if (required_mtu == CANFD_MTU) + cu.fd.len = can_fd_dlc2len(can_fd_len2dlc(cu.fd.len)); + + /* CAN XL frames need real frame length for sending */ + if (required_mtu == CANXL_MTU) + required_mtu = CANXL_HDR_SIZE + cu.xl.len; + /* * disable default receive filter on this RAW socket This is * obsolete as we do not read from the socket at all, but for @@ -167,7 +187,7 @@ int main(int argc, char **argv) } /* send frame */ - if (write(s, &frame, required_mtu) != required_mtu) { + if (write(s, &cu, required_mtu) != required_mtu) { perror("write"); return 1; } diff --git a/lib.c b/lib.c index fec71ac..f80a70b 100644 --- a/lib.c +++ b/lib.c @@ -55,6 +55,7 @@ #define CANID_DELIM '#' #define CC_DLC_DELIM '_' +#define XL_HDR_DELIM ':' #define DATA_SEPERATOR '.' const char hex_asc_upper[] = "0123456789ABCDEF"; @@ -153,78 +154,128 @@ int hexstring2data(char *arg, unsigned char *data, int maxdlen) return 0; } -int parse_canframe(char *cs, struct canfd_frame *cf) +int parse_canframe(char *cs, cu_t *cu) { /* documentation see lib.h */ int i, idx, dlen, len; int maxdlen = CAN_MAX_DLEN; - int ret = CAN_MTU; + int mtu = CAN_MTU; + __u8 *data = cu->fd.data; /* fill CAN CC/FD data by default */ canid_t tmp; len = strlen(cs); //printf("'%s' len %d\n", cs, len); - memset(cf, 0, sizeof(*cf)); /* init CAN FD frame, e.g. LEN = 0 */ + memset(cu, 0, sizeof(*cu)); /* init CAN CC/FD/XL frame, e.g. LEN = 0 */ if (len < 4) return 0; - if (cs[3] == CANID_DELIM) { /* 3 digits */ + if (cs[3] == CANID_DELIM) { /* 3 digits SFF */ idx = 4; for (i = 0; i < 3; i++) { if ((tmp = asc2nibble(cs[i])) > 0x0F) return 0; - cf->can_id |= (tmp << (2 - i) * 4); + cu->cc.can_id |= (tmp << (2 - i) * 4); } - } else if (cs[8] == CANID_DELIM) { /* 8 digits */ + } else if (cs[5] == CANID_DELIM) { /* 5 digits CAN XL VCID/PRIO*/ + + idx = 6; + for (i = 0; i < 5; i++) { + if ((tmp = asc2nibble(cs[i])) > 0x0F) + return 0; + cu->xl.prio |= (tmp << (4 - i) * 4); + } + + /* the VCID starts at bit position 16 */ + tmp = (cu->xl.prio << 4) & CANXL_VCID_MASK; + cu->xl.prio &= CANXL_PRIO_MASK; + cu->xl.prio |= tmp; + + } else if (cs[8] == CANID_DELIM) { /* 8 digits EFF */ idx = 9; for (i = 0; i < 8; i++) { if ((tmp = asc2nibble(cs[i])) > 0x0F) return 0; - cf->can_id |= (tmp << (7 - i) * 4); + cu->cc.can_id |= (tmp << (7 - i) * 4); } - if (!(cf->can_id & CAN_ERR_FLAG)) /* 8 digits but no errorframe? */ - cf->can_id |= CAN_EFF_FLAG; /* then it is an extended frame */ + if (!(cu->cc.can_id & CAN_ERR_FLAG)) /* 8 digits but no errorframe? */ + cu->cc.can_id |= CAN_EFF_FLAG; /* then it is an extended frame */ } else return 0; if ((cs[idx] == 'R') || (cs[idx] == 'r')) { /* RTR frame */ - cf->can_id |= CAN_RTR_FLAG; + cu->cc.can_id |= CAN_RTR_FLAG; /* check for optional DLC value for CAN 2.0B frames */ if (cs[++idx] && (tmp = asc2nibble(cs[idx++])) <= CAN_MAX_DLEN) { - cf->len = tmp; + cu->cc.len = tmp; /* check for optional raw DLC value for CAN 2.0B frames */ if ((tmp == CAN_MAX_DLEN) && (cs[idx++] == CC_DLC_DELIM)) { tmp = asc2nibble(cs[idx]); - if ((tmp > CAN_MAX_DLEN) && (tmp <= CAN_MAX_RAW_DLC)) { - struct can_frame *ccf = (struct can_frame *)cf; - - ccf->len8_dlc = tmp; - } + if ((tmp > CAN_MAX_DLEN) && (tmp <= CAN_MAX_RAW_DLC)) + cu->cc.len8_dlc = tmp; } } - return ret; + return mtu; } if (cs[idx] == CANID_DELIM) { /* CAN FD frame escape char '##' */ maxdlen = CANFD_MAX_DLEN; - ret = CANFD_MTU; + mtu = CANFD_MTU; /* CAN FD frame ##* */ if ((tmp = asc2nibble(cs[idx + 1])) > 0x0F) return 0; - cf->flags = tmp; - cf->flags |= CANFD_FDF; /* dual-use */ + cu->fd.flags = tmp; + cu->fd.flags |= CANFD_FDF; /* dual-use */ idx += 2; + + } else if (cs[idx + 14] == CANID_DELIM) { /* CAN XL frame '#80:00:11223344#' */ + + maxdlen = CANXL_MAX_DLEN; + mtu = CANXL_MTU; + data = cu->xl.data; /* fill CAN XL data */ + + if ((cs[idx + 2] != XL_HDR_DELIM) || (cs[idx + 5] != XL_HDR_DELIM)) + return 0; + + if ((tmp = asc2nibble(cs[idx++])) > 0x0F) + return 0; + cu->xl.flags = (tmp << 4); + if ((tmp = asc2nibble(cs[idx++])) > 0x0F) + return 0; + cu->xl.flags |= tmp; + + /* force CAN XL flag if it was missing in the ASCII string */ + cu->xl.flags |= CANXL_XLF; + + idx++; /* skip XL_HDR_DELIM */ + + if ((tmp = asc2nibble(cs[idx++])) > 0x0F) + return 0; + cu->xl.sdt = (tmp << 4); + if ((tmp = asc2nibble(cs[idx++])) > 0x0F) + return 0; + cu->xl.sdt |= tmp; + + idx++; /* skip XL_HDR_DELIM */ + + for (i = 0; i < 8; i++) { + if ((tmp = asc2nibble(cs[idx++])) > 0x0F) + return 0; + cu->xl.af |= (tmp << (7 - i) * 4); + } + + idx++; /* skip CANID_DELIM */ } for (i = 0, dlen = 0; i < maxdlen; i++) { @@ -236,26 +287,27 @@ int parse_canframe(char *cs, struct canfd_frame *cf) if ((tmp = asc2nibble(cs[idx++])) > 0x0F) return 0; - cf->data[i] = (tmp << 4); + data[i] = (tmp << 4); if ((tmp = asc2nibble(cs[idx++])) > 0x0F) return 0; - cf->data[i] |= tmp; + data[i] |= tmp; dlen++; } - cf->len = dlen; + + if (mtu == CANXL_MTU) + cu->xl.len = dlen; + else + cu->fd.len = dlen; /* check for extra DLC when having a Classic CAN with 8 bytes payload */ if ((maxdlen == CAN_MAX_DLEN) && (dlen == CAN_MAX_DLEN) && (cs[idx++] == CC_DLC_DELIM)) { unsigned char dlc = asc2nibble(cs[idx]); - if ((dlc > CAN_MAX_DLEN) && (dlc <= CAN_MAX_RAW_DLC)) { - struct can_frame *ccf = (struct can_frame *)cf; - - ccf->len8_dlc = dlc; - } + if ((dlc > CAN_MAX_DLEN) && (dlc <= CAN_MAX_RAW_DLC)) + cu->cc.len8_dlc = dlc; } - return ret; + return mtu; } int sprint_canframe(char *buf, cu_t *cu, int sep) diff --git a/lib.h b/lib.h index 67902fc..3ddf1e8 100644 --- a/lib.h +++ b/lib.h @@ -111,8 +111,7 @@ int hexstring2data(char *arg, unsigned char *data, int maxdlen); * */ -struct canfd_frame; -int parse_canframe(char *cs, struct canfd_frame *cf); +int parse_canframe(char *cs, cu_t *cu); /* * Transfers a valid ASCII string describing a CAN frame into struct canfd_frame. * diff --git a/log2asc.c b/log2asc.c index 0640f3c..87279cd 100644 --- a/log2asc.c +++ b/log2asc.c @@ -183,9 +183,9 @@ void canfd_asc(struct canfd_frame *cf, int devno, int mtu, char *extra_info, FIL int main(int argc, char **argv) { - static char buf[BUFSZ], device[BUFSZ], ascframe[BUFSZ], extra_info[BUFSZ]; + static char buf[BUFSZ], device[BUFSZ], ascframe[10000], extra_info[BUFSZ]; - struct canfd_frame cf; + static cu_t cu; static struct timeval tv, start_tv; FILE *infile = stdin; FILE *outfile = stdout; @@ -286,20 +286,23 @@ int main(int argc, char **argv) (crlf)?"\r\n":"\n"); } - for (i=0, devno=0; i Date: Thu, 29 Feb 2024 07:07:20 +0100 Subject: [PATCH 12/27] unify buffer size for ASCII CAN frame string representations Signed-off-by: Oliver Hartkopp --- candump.c | 34 +++++++++++++++++----------------- cangen.c | 9 +++++---- canplayer.c | 16 ++++++++-------- lib.h | 19 +++++++++---------- log2asc.c | 8 ++++---- 5 files changed, 43 insertions(+), 43 deletions(-) diff --git a/candump.c b/candump.c index d70a8b1..87958cd 100644 --- a/candump.c +++ b/candump.c @@ -327,7 +327,7 @@ int main(int argc, char **argv) FILE *logfile = NULL; char fname[83]; /* suggested by -Wformat-overflow= */ const char *logname = NULL; - static char abuf[10000]; /* ASCII buf FIXME - use calculated value */ + static char afrbuf[AFRSZ]; /* ASCII CAN frame buffer size */ static int alen; signal(SIGTERM, sigterm); @@ -831,22 +831,22 @@ int main(int argc, char **argv) /* build common log format output */ if ((log) || ((logfrmt) && (silent == SILENT_OFF))) { - alen = sprint_timestamp(abuf, logtimestamp, + alen = sprint_timestamp(afrbuf, logtimestamp, &tv, &last_tv); - alen += sprintf(abuf + alen, "%*s ", + alen += sprintf(afrbuf + alen, "%*s ", max_devname_len, devname[idx]); - alen += sprint_canframe(abuf + alen, &cu, 0); + alen += sprint_canframe(afrbuf + alen, &cu, 0); } /* write CAN frame in log file style to logfile */ if (log) - fprintf(logfile, "%s%s\n", abuf, extra_info); + fprintf(logfile, "%s%s\n", afrbuf, extra_info); /* print CAN frame in log file style to stdout */ if ((logfrmt) && (silent == SILENT_OFF)) { - printf("%s%s\n", abuf, extra_info); + printf("%s%s\n", afrbuf, extra_info); goto out_fflush; /* no other output to stdout */ } @@ -860,32 +860,32 @@ int main(int argc, char **argv) } /* print (colored) long CAN frame style to stdout */ - alen = sprintf(abuf, " %s", (color > 2) ? col_on[idx % MAXCOL] : ""); - alen += sprint_timestamp(abuf + alen, timestamp, &tv, &last_tv); - alen += sprintf(abuf + alen, " %s%*s", + alen = sprintf(afrbuf, " %s", (color > 2) ? col_on[idx % MAXCOL] : ""); + alen += sprint_timestamp(afrbuf + alen, timestamp, &tv, &last_tv); + alen += sprintf(afrbuf + alen, " %s%*s", (color && (color < 3)) ? col_on[idx % MAXCOL] : "", max_devname_len, devname[idx]); if (extra_msg_info) { if (msg.msg_flags & MSG_DONTROUTE) - alen += sprintf(abuf + alen, " TX %s", + alen += sprintf(afrbuf + alen, " TX %s", extra_m_info[cu.fd.flags & 3]); else - alen += sprintf(abuf + alen, " RX %s", + alen += sprintf(afrbuf + alen, " RX %s", extra_m_info[cu.fd.flags & 3]); } - alen += sprintf(abuf + alen, "%s ", (color == 1) ? col_off : ""); - alen += sprint_long_canframe(abuf + alen, &cu, view); + alen += sprintf(afrbuf + alen, "%s ", (color == 1) ? col_off : ""); + alen += sprint_long_canframe(afrbuf + alen, &cu, view); if ((view & CANLIB_VIEW_ERROR) && (cu.fd.can_id & CAN_ERR_FLAG)) { - alen += sprintf(abuf + alen, "\n\t"); - alen += snprintf_can_error_frame(abuf + alen, - sizeof(abuf) - alen, + alen += sprintf(afrbuf + alen, "\n\t"); + alen += snprintf_can_error_frame(afrbuf + alen, + sizeof(afrbuf) - alen, &cu.fd, "\n\t"); } - printf("%s%s\n", abuf, (color > 1) ? col_off : ""); + printf("%s%s\n", afrbuf, (color > 1) ? col_off : ""); out_fflush: fflush(stdout); } diff --git a/cangen.c b/cangen.c index 11b156f..a2c5c50 100644 --- a/cangen.c +++ b/cangen.c @@ -828,16 +828,17 @@ int main(int argc, char **argv) } if (verbose) { - static char abuf[10000]; /* ASCII buf FIXME - use calculated value */ + static char afrbuf[AFRSZ]; /* ASCII CAN frame buffer size */ + printf(" %s ", argv[optind]); if (verbose > 1) - sprint_long_canframe(abuf, (cu_t *)&frame, (verbose > 2) ? CANLIB_VIEW_ASCII : 0); + sprint_long_canframe(afrbuf, (cu_t *)&frame, (verbose > 2) ? CANLIB_VIEW_ASCII : 0); else - sprint_canframe(abuf, (cu_t *)&frame, 1); + sprint_canframe(afrbuf, (cu_t *)&frame, 1); - printf("%s\n", abuf); + printf("%s\n", afrbuf); } ret = do_send_one(s, &frame, mtu, polltimeout); diff --git a/canplayer.c b/canplayer.c index 4987428..9499077 100644 --- a/canplayer.c +++ b/canplayer.c @@ -239,7 +239,7 @@ int add_assignment(char *mode, int socket, char *txname, char *rxname, int verbo int main(int argc, char **argv) { - static char buf[BUFSZ], device[BUFSZ], ascframe[10000]; + static char buf[BUFSZ], device[BUFSZ], afrbuf[AFRSZ]; struct sockaddr_can addr; struct can_raw_vcid_options vcid_opts = { .flags = CAN_RAW_XL_VCID_TX_PASS, @@ -426,7 +426,7 @@ int main(int argc, char **argv) eof = 0; - if (sscanf(buf, "(%llu.%llu) %s %s", &sec, &usec, device, ascframe) != 4) { + if (sscanf(buf, "(%llu.%llu) %s %s", &sec, &usec, device, afrbuf) != 4) { fprintf(stderr, "incorrect line format in logfile\n"); return 1; } @@ -455,7 +455,7 @@ int main(int argc, char **argv) if (interactive) getchar(); - /* log_tv/device/ascframe are valid here */ + /* log_tv/device/afrbuf are valid here */ if (strlen(device) >= IFNAMSIZ) { fprintf(stderr, "log interface name '%s' too long!", device); @@ -479,9 +479,9 @@ int main(int argc, char **argv) } else if (txidx > 0) { /* only send to valid CAN devices */ - txmtu = parse_canframe(ascframe, &cu); /* dual-use frame */ + txmtu = parse_canframe(afrbuf, &cu); /* dual-use frame */ if (!txmtu) { - fprintf(stderr, "wrong CAN frame format: '%s'!", ascframe); + fprintf(stderr, "wrong CAN frame format: '%s'!", afrbuf); return 1; } @@ -499,8 +499,8 @@ int main(int argc, char **argv) if (verbose) { printf("%s (%s) ", get_txname(device), device); - sprint_long_canframe(ascframe, &cu, CANLIB_VIEW_INDENT_SFF); - printf("%s\n", ascframe); + sprint_long_canframe(afrbuf, &cu, CANLIB_VIEW_INDENT_SFF); + printf("%s\n", afrbuf); } if (count && (--count == 0)) @@ -520,7 +520,7 @@ int main(int argc, char **argv) break; } - if (sscanf(buf, "(%llu.%llu) %s %s", &sec, &usec, device, ascframe) != 4) { + if (sscanf(buf, "(%llu.%llu) %s %s", &sec, &usec, device, afrbuf) != 4) { fprintf(stderr, "incorrect line format in logfile\n"); return 1; } diff --git a/lib.h b/lib.h index 3ddf1e8..a0f2b99 100644 --- a/lib.h +++ b/lib.h @@ -63,17 +63,16 @@ typedef union { struct canxl_frame xl; } cu_t; -/* buffer sizes for CAN frame string representations */ +#define CL_CFSZ 400 /* to be removed */ -#define CL_ID (sizeof("12345678##1")) -#define CL_DATA sizeof(".AA") -#define CL_BINDATA sizeof(".10101010") - - /* CAN FD ASCII hex short representation with DATA_SEPERATORs */ -#define CL_CFSZ (2*CL_ID + 64*CL_DATA) - -/* CAN FD ASCII hex long representation with binary output */ -#define CL_LONGCFSZ (2*CL_ID + sizeof(" [255] ") + (64*CL_BINDATA)) +/* + * The buffer size for ASCII CAN frame string representations + * covers also the 'long' CAN frame output from sprint_long_canframe() + * including (swapped) binary represetations, timestamps, netdevice names, + * lengths and error message details as the CAN XL data is cropped to 64 + * byte (the 'long' CAN frame output is only for display on terminals). + */ +#define AFRSZ 6300 /* 3*2048 (data) + 22 (timestamp) + 18 (netdev) + ID/HDR */ /* CAN DLC to real data length conversion helpers especially for CAN FD */ diff --git a/log2asc.c b/log2asc.c index 87279cd..f87a7bb 100644 --- a/log2asc.c +++ b/log2asc.c @@ -183,7 +183,7 @@ void canfd_asc(struct canfd_frame *cf, int devno, int mtu, char *extra_info, FIL int main(int argc, char **argv) { - static char buf[BUFSZ], device[BUFSZ], ascframe[10000], extra_info[BUFSZ]; + static char buf[BUFSZ], device[BUFSZ], afrbuf[AFRSZ], extra_info[BUFSZ]; static cu_t cu; static struct timeval tv, start_tv; @@ -262,13 +262,13 @@ int main(int argc, char **argv) continue; if (sscanf(buf, "(%llu.%llu) %s %s %s", &sec, &usec, - device, ascframe, extra_info) != 5) { + device, afrbuf, extra_info) != 5) { /* do not evaluate the extra info */ extra_info[0] = 0; if (sscanf(buf, "(%llu.%llu) %s %s", &sec, &usec, - device, ascframe) != 4) { + device, afrbuf) != 4) { fprintf(stderr, "incorrect line format in logfile\n"); return 1; } @@ -295,7 +295,7 @@ int main(int argc, char **argv) if (devno) { /* only convert for selected CAN devices */ - mtu = parse_canframe(ascframe, &cu); + mtu = parse_canframe(afrbuf, &cu); /* convert only CAN CC and CAN FD frames */ if ((mtu != CAN_MTU) && (mtu != CANFD_MTU)) From 29290505f76f2d70c28216c50b7e44dbf5ccd665 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Thu, 29 Feb 2024 08:15:53 +0100 Subject: [PATCH 13/27] log: finalize unified buffer handling Signed-off-by: Oliver Hartkopp --- canlogserver.c | 15 ++++++--------- canplayer.c | 22 ++++++++++++++++++---- lib.h | 2 -- log2asc.c | 24 +++++++++++++++++++----- log2long.c | 33 ++++++++++++++++++++++++++------- 5 files changed, 69 insertions(+), 27 deletions(-) diff --git a/canlogserver.c b/canlogserver.c index e64cc86..e9c2b80 100644 --- a/canlogserver.c +++ b/canlogserver.c @@ -72,9 +72,6 @@ #define ANYDEV "any" #define ANL "\r\n" /* newline in ASC mode */ -#define COMMENTSZ 200 -#define BUFSZ (sizeof("(1345212884.318850)") + IFNAMSIZ + 4 + CL_CFSZ + COMMENTSZ) /* for one line in the logfile */ - #define DEFPORT 28700 static char devname[MAXDEV][IFNAMSIZ+1]; @@ -199,7 +196,7 @@ int main(int argc, char **argv) struct sockaddr_in inaddr; struct sockaddr_in clientaddr; socklen_t sin_size = sizeof(clientaddr); - char temp[BUFSZ]; + char afrbuf[AFRSZ]; sigemptyset(&sigset); signalaction.sa_handler = &childdied; @@ -416,19 +413,19 @@ int main(int argc, char **argv) idx = idx2dindex(addr.can_ifindex, s[i]); - sprintf(temp, "(%llu.%06llu) %*s ", + sprintf(afrbuf, "(%llu.%06llu) %*s ", (unsigned long long)tv.tv_sec, (unsigned long long)tv.tv_usec, max_devname_len, devname[idx]); - sprint_canframe(temp+strlen(temp), (cu_t *)&frame, 0); - strcat(temp, "\n"); + sprint_canframe(afrbuf+strlen(afrbuf), (cu_t *)&frame, 0); + strcat(afrbuf, "\n"); - if (write(accsocket, temp, strlen(temp)) < 0) { + if (write(accsocket, afrbuf, strlen(afrbuf)) < 0) { perror("writeaccsock"); return 1; } #if 0 /* print CAN frame in log file style to stdout */ - printf("%s", temp); + printf("%s", afrbuf); #endif } diff --git a/canplayer.c b/canplayer.c index 9499077..a38a82a 100644 --- a/canplayer.c +++ b/canplayer.c @@ -61,10 +61,24 @@ #define DEFAULT_GAP 1 /* ms */ #define DEFAULT_LOOPS 1 /* only one replay */ #define CHANNELS 20 /* anyone using more than 20 CAN interfaces at a time? */ -#define COMMENTSZ 200 -#define BUFSZ (sizeof("(1345212884.318850)") + IFNAMSIZ + 4 + CL_CFSZ + COMMENTSZ) /* for one line in the logfile */ #define STDOUTIDX 65536 /* interface index for printing on stdout - bigger than max uint16 */ +#if (IFNAMSIZ != 16) +#error "IFNAMSIZ value does not to DEVSZ calculation!" +#endif + +#define DEVSZ 22 /* IFNAMSZ + 6 */ +#define TIMESZ sizeof("(1345212884.318850) ") +#define BUFSZ (TIMESZ + DEVSZ + AFRSZ) + +/* adapt sscanf() functions below on error */ +#if (AFRSZ != 6300) +#error "AFRSZ value does not fit sscanf restrictions!" +#endif +#if (DEVSZ != 22) +#error "DEVSZ value does not fit sscanf restrictions!" +#endif + struct assignment { char txif[IFNAMSIZ]; int txifidx; @@ -239,7 +253,7 @@ int add_assignment(char *mode, int socket, char *txname, char *rxname, int verbo int main(int argc, char **argv) { - static char buf[BUFSZ], device[BUFSZ], afrbuf[AFRSZ]; + static char buf[BUFSZ], device[DEVSZ], afrbuf[AFRSZ]; struct sockaddr_can addr; struct can_raw_vcid_options vcid_opts = { .flags = CAN_RAW_XL_VCID_TX_PASS, @@ -426,7 +440,7 @@ int main(int argc, char **argv) eof = 0; - 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; } diff --git a/lib.h b/lib.h index a0f2b99..d31f50b 100644 --- a/lib.h +++ b/lib.h @@ -63,8 +63,6 @@ typedef union { struct canxl_frame xl; } cu_t; -#define CL_CFSZ 400 /* to be removed */ - /* * The buffer size for ASCII CAN frame string representations * covers also the 'long' CAN frame output from sprint_long_canframe() diff --git a/log2asc.c b/log2asc.c index f87a7bb..81d69bc 100644 --- a/log2asc.c +++ b/log2asc.c @@ -54,8 +54,6 @@ #include "lib.h" -#define BUFSZ 400 /* for one line in the logfile */ - extern int optind, opterr, optopt; void print_usage(char *prg) @@ -181,9 +179,25 @@ void canfd_asc(struct canfd_frame *cf, int devno, int mtu, char *extra_info, FIL fprintf(outfile, " %8d %4d %8X 0 0 0 0 0", 130000, 130, flags); } +#define DEVSZ 22 +#define EXTRASZ 20 +#define TIMESZ sizeof("(1345212884.318850) ") +#define BUFSZ (DEVSZ + AFRSZ + EXTRASZ + TIMESZ) + +/* adapt sscanf() functions below on error */ +#if (AFRSZ != 6300) +#error "AFRSZ value does not fit sscanf restrictions!" +#endif +#if (DEVSZ != 22) +#error "DEVSZ value does not fit sscanf restrictions!" +#endif +#if (EXTRASZ != 20) +#error "EXTRASZ value does not fit sscanf restrictions!" +#endif + int main(int argc, char **argv) { - static char buf[BUFSZ], device[BUFSZ], afrbuf[AFRSZ], extra_info[BUFSZ]; + static char buf[BUFSZ], device[DEVSZ], afrbuf[AFRSZ], extra_info[EXTRASZ]; static cu_t cu; static struct timeval tv, start_tv; @@ -261,13 +275,13 @@ int main(int argc, char **argv) if (buf[0] != '(') continue; - if (sscanf(buf, "(%llu.%llu) %s %s %s", &sec, &usec, + if (sscanf(buf, "(%llu.%llu) %21s %6299s %19s", &sec, &usec, device, afrbuf, extra_info) != 5) { /* do not evaluate the extra info */ extra_info[0] = 0; - if (sscanf(buf, "(%llu.%llu) %s %s", &sec, &usec, + if (sscanf(buf, "(%llu.%llu) %21s %6299s", &sec, &usec, device, afrbuf) != 4) { fprintf(stderr, "incorrect line format in logfile\n"); return 1; diff --git a/log2long.c b/log2long.c index 332aa6c..0fcb0cc 100644 --- a/log2long.c +++ b/log2long.c @@ -43,26 +43,45 @@ */ #include +#include #include #include #include "lib.h" -#define COMMENTSZ 200 -#define BUFSZ (sizeof("(1345212884.318850)") + IFNAMSIZ + 4 + CL_CFSZ + COMMENTSZ) /* for one line in the logfile */ +#define DEVSZ 22 +#define TIMESZ 22 /* sizeof("(1345212884.318850) ") */ +#define BUFSZ (DEVSZ + AFRSZ + TIMESZ) + +/* adapt sscanf() functions below on error */ +#if (AFRSZ != 6300) +#error "AFRSZ value does not fit sscanf restrictions!" +#endif +#if (DEVSZ != 22) +#error "DEVSZ value does not fit sscanf restrictions!" +#endif +#if (TIMESZ != 22) +#error "TIMESZ value does not fit sscanf restrictions!" +#endif int main(void) { - char buf[BUFSZ], timestamp[BUFSZ], device[BUFSZ], ascframe[BUFSZ]; + char buf[BUFSZ], timestamp[TIMESZ], device[DEVSZ], afrbuf[AFRSZ]; static cu_t cu; int mtu; while (fgets(buf, BUFSZ-1, stdin)) { - if (sscanf(buf, "%s %s %s", timestamp, device, ascframe) != 3) + + if (strlen(buf) >= BUFSZ-2) { + fprintf(stderr, "line too long for input buffer\n"); + return 1; + } + + if (sscanf(buf, "%21s %21s %6299s", timestamp, device, afrbuf) != 3) return 1; - mtu = parse_canframe(ascframe, &cu); + mtu = parse_canframe(afrbuf, &cu); /* mark dual-use struct canfd_frame - no CAN_XL support */ if (mtu == CAN_MTU) @@ -75,10 +94,10 @@ int main(void) } /* with ASCII output */ - sprint_long_canframe(ascframe, &cu, + sprint_long_canframe(afrbuf, &cu, (CANLIB_VIEW_INDENT_SFF | CANLIB_VIEW_ASCII)); - printf("%s %s %s\n", timestamp, device, ascframe); + printf("%s %s %s\n", timestamp, device, afrbuf); } return 0; From 7761d8bcf83c7cabcfc4207587c57fd53be90886 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Thu, 29 Feb 2024 08:44:27 +0100 Subject: [PATCH 14/27] canlogserver: add CAN XL support Signed-off-by: Oliver Hartkopp --- canlogserver.c | 48 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/canlogserver.c b/canlogserver.c index e9c2b80..ef6f943 100644 --- a/canlogserver.c +++ b/canlogserver.c @@ -186,9 +186,14 @@ int main(int argc, char **argv) int opt, ret; int currmax = 1; /* we assume at least one can bus ;-) */ struct sockaddr_can addr; + struct can_raw_vcid_options vcid_opts = { + .flags = CAN_RAW_XL_VCID_RX_FILTER, + .rx_vcid = 0, + .rx_vcid_mask = 0, + }; struct can_filter rfilter; - struct canfd_frame frame; - const int canfd_on = 1; + static cu_t cu; /* union for CAN CC/FD/XL frames */ + const int canfx_on = 1; int nbytes, i, j; struct ifreq ifr; struct timeval tv; @@ -342,7 +347,13 @@ int main(int argc, char **argv) &err_mask[i], sizeof(err_mask[i])); /* try to switch the socket into CAN FD mode */ - setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &canfd_on, sizeof(canfd_on)); + setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &canfx_on, sizeof(canfx_on)); + + /* try to switch the socket into CAN XL mode */ + setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_XL_FRAMES, &canfx_on, sizeof(canfx_on)); + + /* try to enable the CAN XL VCID pass through mode */ + setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_XL_VCID_OPTS, &vcid_opts, sizeof(vcid_opts)); j = strlen(argv[optind+i]); @@ -391,22 +402,35 @@ int main(int argc, char **argv) socklen_t len = sizeof(addr); int idx; - if ((nbytes = recvfrom(s[i], &frame, CANFD_MTU, 0, + if ((nbytes = recvfrom(s[i], &cu, sizeof(cu), 0, (struct sockaddr*)&addr, &len)) < 0) { perror("read"); return 1; } - /* mark dual-use struct canfd_frame */ - if ((size_t)nbytes == CAN_MTU) - frame.flags = 0; - else if ((size_t)nbytes == CANFD_MTU) - frame.flags |= CANFD_FDF; - else { - fprintf(stderr, "read: incomplete CAN frame\n"); + if (nbytes < CANXL_HDR_SIZE + CANXL_MIN_DLEN) { + fprintf(stderr, "read: no CAN frame\n"); return 1; } + if (cu.xl.flags & CANXL_XLF) { + if (nbytes != CANXL_HDR_SIZE + cu.xl.len) { + printf("nbytes = %d\n", nbytes); + fprintf(stderr, "read: no CAN XL frame\n"); + return 1; + } + } else { + /* mark dual-use struct canfd_frame */ + if (nbytes == CAN_MTU) + cu.fd.flags = 0; + else if (nbytes == CANFD_MTU) + cu.fd.flags |= CANFD_FDF; + else { + fprintf(stderr, "read: incomplete CAN CC/FD frame\n"); + return 1; + } + } + if (ioctl(s[i], SIOCGSTAMP, &tv) < 0) perror("SIOCGSTAMP"); @@ -415,7 +439,7 @@ int main(int argc, char **argv) sprintf(afrbuf, "(%llu.%06llu) %*s ", (unsigned long long)tv.tv_sec, (unsigned long long)tv.tv_usec, max_devname_len, devname[idx]); - sprint_canframe(afrbuf+strlen(afrbuf), (cu_t *)&frame, 0); + sprint_canframe(afrbuf+strlen(afrbuf), &cu, 0); strcat(afrbuf, "\n"); if (write(accsocket, afrbuf, strlen(afrbuf)) < 0) { From 740c0ba1561d81dc501a439cdb26e85a817f4417 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Thu, 29 Feb 2024 09:54:47 +0100 Subject: [PATCH 15/27] lib/cansend: update documentation for CAN XL frame format Signed-off-by: Oliver Hartkopp --- cansend.c | 28 ++++++++++++++++++++++------ lib.h | 33 +++++++++++++++++++++++++++------ 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/cansend.c b/cansend.c index 033692f..2749482 100644 --- a/cansend.c +++ b/cansend.c @@ -64,11 +64,13 @@ static void print_usage(char *prg) "Usage: %s .\n" "\n" ":\n" - " #{data} for Classical CAN 2.0 data frames\n" - " #R{len} for Classical CAN 2.0 data frames\n" - " #{data}_{dlc} for Classical CAN 2.0 data frames\n" - " #R{len}_{dlc} for Classical CAN 2.0 data frames\n" - " ##{data} for CAN FD frames\n\n" + " #{data} for CAN CC (Classical CAN 2.0B) data frames\n" + " #R{len} for CAN CC (Classical CAN 2.0B) data frames\n" + " #{data}_{dlc} for CAN CC (Classical CAN 2.0B) data frames\n" + " #R{len}_{dlc} for CAN CC (Classical CAN 2.0B) data frames\n" + " ##{data} for CAN FD frames\n" + " #::# for CAN XL frames\n" + "\n" ":\n" " 3 (SFF) or 8 (EFF) hex chars\n" "{data}:\n" @@ -80,9 +82,23 @@ static void print_usage(char *prg) ":\n" " a single ASCII Hex value (0 .. F) which defines canfd_frame.flags\n" "\n" + ":\n" + " 2 hex chars - virtual CAN network identifier (00 .. FF)\n" + ":\n" + " 3 hex chars - 11 bit priority value (000 .. 7FF)\n" + ":\n" + " 2 hex chars values (00 .. FF) which defines canxl_frame.flags\n" + ":\n" + " 2 hex chars values (00 .. FF) which defines canxl_frame.sdt\n" + ":\n" + " 8 hex chars - 32 bit acceptance field (canxl_frame.af)\n" + ":\n" + " 1..2048 ASCII hex-values (optionally separated by '.')\n" + "\n" "Examples:\n" " 5A1#11.2233.44556677.88 / 123#DEADBEEF / 5AA# / 123##1 / 213##311223344 /\n" - " 1F334455#1122334455667788_B / 123#R / 00000123#R3 / 333#R8_E\n" + " 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); } diff --git a/lib.h b/lib.h index d31f50b..23514c7 100644 --- a/lib.h +++ b/lib.h @@ -110,9 +110,10 @@ int hexstring2data(char *arg, unsigned char *data, int maxdlen); int parse_canframe(char *cs, cu_t *cu); /* - * Transfers a valid ASCII string describing a CAN frame into struct canfd_frame. + * Transfers a valid ASCII string describing a CAN frame into the CAN union + * containing CAN CC/FD/XL structs. * - * CAN 2.0 frames (aka Classical CAN) + * CAN CC frames (aka Classical CAN, CAN 2.0B) * - string layout #{R{len}|data}{_len8_dlc} * - {data} has 0 to 8 hex-values that can (optionally) be separated by '.' * - {len} can take values from 0 to 8 and can be omitted if zero @@ -125,6 +126,16 @@ int parse_canframe(char *cs, cu_t *cu); * - {data} has 0 to 64 hex-values that can (optionally) be separated by '.' * - return value on successful parsing: CANFD_MTU * + * CAN XL frames + * - string layout #::#{data} + * - a two ASCII Hex value (00 .. FF) which defines the VCID + * - a three ASCII Hex value (000 .. 7FF) which defines the 11 bit PRIO + * - a two ASCII Hex value (00 .. FF) which defines canxl_frame.flags + * - a two ASCII Hex value (00 .. FF) which defines canxl_frame.sdt + * - a 8 digit ASCII Hex value which defines the 32 bit canxl_frame.af + * - {data} has 1 to 2048 hex-values that can (optionally) be separated by '.' + * - return value on successful parsing: CANXL_MTU + * * Return value on detected problems: 0 * * can have 3 (standard frame format) or 8 (extended frame format) @@ -155,6 +166,9 @@ int parse_canframe(char *cs, cu_t *cu); * ^^ * CAN FD extension to handle the canfd_frame.flags content * + * 45123#81:00:12345678#11223344.556677 -> CAN XL frame with len = 7, + * VCID = 0x45, PRIO = 0x123, flags = 0x81, sdt = 0x00, af = 0x12345678 + * * Simple facts on this compact ASCII CAN frame representation: * * - 3 digits: standard frame format @@ -169,8 +183,9 @@ int sprint_canframe(char *buf , cu_t *cu, int sep); * Creates a CAN frame hexadecimal output in compact format. * The CAN data[] is separated by '.' when sep != 0. * - * The type of the CAN frame (CAN CC / CAN FD) is specified by - * by the dual-use struct canfd_frame.flags element: + * A CAN XL frame is detected when CANXL_XLF is set in the struct + * cu.canxl_frame.flags. Otherwise the type of the CAN frame (CAN CC/FD) + * is specified by the dual-use struct cu.canfd_frame.flags element: * w/o CAN FD flags (== 0) -> CAN CC frame (aka Classical CAN, CAN2.0B) * with CAN FD flags (!= 0) -> CAN FD frame (with CANFD_[FDF/BRS/ESI]) * @@ -182,6 +197,8 @@ int sprint_canframe(char *buf , cu_t *cu, int sep); * 32345678#112233 -> error frame with CAN_ERR_FLAG (0x2000000) set * 123##0112233 -> CAN FD frame standard CAN-Id = 0x123, flags = 0, len = 3 * 123##2112233 -> CAN FD frame, flags = CANFD_ESI, len = 3 + * 45123#81:00:12345678#11223344.556677 -> CAN XL frame with len = 7, + * VCID = 0x45, PRIO = 0x123, flags = 0x81, sdt = 0x00, af = 0x12345678 * */ @@ -198,8 +215,9 @@ int sprint_long_canframe(char *buf , cu_t *cu, int view); /* * Creates a CAN frame hexadecimal output in user readable format. * - * The type of the CAN frame (CAN CC / CAN FD) is specified by - * by the dual-use struct canfd_frame.flags element: + * A CAN XL frame is detected when CANXL_XLF is set in the struct + * cu.canxl_frame.flags. Otherwise the type of the CAN frame (CAN CC/FD) + * is specified by the dual-use struct cu.canfd_frame.flags element: * w/o CAN FD flags (== 0) -> CAN CC frame (aka Classical CAN, CAN2.0B) * with CAN FD flags (!= 0) -> CAN FD frame (with CANFD_[FDF/BRS/ESI]) * @@ -209,10 +227,13 @@ int sprint_long_canframe(char *buf , cu_t *cu, int view); * 321 {B} 11 22 33 44 55 66 77 88 -> Classical CAN with raw '{DLC}' value B * 20001111 [7] C6 23 7B 32 69 98 3C ERRORFRAME -> (CAN_ERR_FLAG set) * 12345678 [03] 11 22 33 -> CAN FD with extended CAN-Id = 0x12345678, len = 3 + * 123 [0003] (45|81:00:12345678) 11 22 33 -> CAN XL frame with VCID 0x45 * * 123 [3] 11 22 33 -> CANLIB_VIEW_INDENT_SFF == 0 * 123 [3] 11 22 33 -> CANLIB_VIEW_INDENT_SFF == set * + * There are no binary or ASCII view modes for CAN XL and the number of displayed + * data bytes is limited to 64 to fit terminal output use-cases. */ int snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *cf, From 2af5e6aaaa6de7b934ecc2241d85743155a209eb Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Fri, 1 Mar 2024 15:56:21 +0100 Subject: [PATCH 16/27] canlogserver/log2long: make CAN XL ASCII buffer static Signed-off-by: Oliver Hartkopp --- canlogserver.c | 2 +- log2long.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/canlogserver.c b/canlogserver.c index ef6f943..cdd25d5 100644 --- a/canlogserver.c +++ b/canlogserver.c @@ -201,7 +201,7 @@ int main(int argc, char **argv) struct sockaddr_in inaddr; struct sockaddr_in clientaddr; socklen_t sin_size = sizeof(clientaddr); - char afrbuf[AFRSZ]; + static char afrbuf[AFRSZ]; sigemptyset(&sigset); signalaction.sa_handler = &childdied; diff --git a/log2long.c b/log2long.c index 0fcb0cc..731d29a 100644 --- a/log2long.c +++ b/log2long.c @@ -67,7 +67,7 @@ int main(void) { - char buf[BUFSZ], timestamp[TIMESZ], device[DEVSZ], afrbuf[AFRSZ]; + static char buf[BUFSZ], timestamp[TIMESZ], device[DEVSZ], afrbuf[AFRSZ]; static cu_t cu; int mtu; From 9a21de13f8be01a6654aa7380545950ca13654a3 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Sat, 2 Mar 2024 21:55:32 +0100 Subject: [PATCH 17/27] cangen: convert to CAN frame unit type As preparation for CAN XL support. Signed-off-by: Oliver Hartkopp --- cangen.c | 115 +++++++++++++++++++++++++++---------------------------- 1 file changed, 57 insertions(+), 58 deletions(-) diff --git a/cangen.c b/cangen.c index a2c5c50..21203f5 100644 --- a/cangen.c +++ b/cangen.c @@ -293,11 +293,11 @@ static int setsockopt_txtime(int fd) return 0; } -static int do_send_one(int fd, void *buf, size_t len, int timeout) +static int do_send_one(int fd, cu_t *cu, size_t len, int timeout) { uint8_t control[CMSG_SPACE(sizeof(uint64_t))] = { 0 }; struct iovec iov = { - .iov_base = buf, + .iov_base = cu, .iov_len = len, }; struct msghdr msg = { @@ -466,8 +466,7 @@ int main(int argc, char **argv) int s; /* socket */ struct sockaddr_can addr = { 0 }; - static struct canfd_frame frame; - struct can_frame *ccf = (struct can_frame *)&frame; + static cu_t cu; int i; struct ifreq ifr; @@ -556,7 +555,7 @@ int main(int argc, char **argv) id_mode = MODE_RANDOM_ODD; } else { id_mode = MODE_FIX; - frame.can_id = strtoul(optarg, NULL, 16); + cu.fd.can_id = strtoul(optarg, NULL, 16); } break; @@ -567,7 +566,7 @@ int main(int argc, char **argv) dlc_mode = MODE_INCREMENT; } else { dlc_mode = MODE_FIX; - frame.len = atoi(optarg) & 0xFF; /* is cut to 8 / 64 later */ + cu.fd.len = atoi(optarg) & 0xFF; /* is cut to 8 / 64 later */ } break; @@ -630,7 +629,7 @@ int main(int argc, char **argv) ts_gap = double_to_timespec(gap / 1000); /* recognize obviously missing commandline option */ - if (id_mode == MODE_FIX && frame.can_id > 0x7FF && !extended) { + if (id_mode == MODE_FIX && cu.fd.can_id > 0x7FF && !extended) { printf("The given CAN-ID is greater than 0x7FF and the '-e' option is not set.\n"); return 1; } @@ -691,19 +690,19 @@ int main(int argc, char **argv) } /* ensure discrete CAN FD length values 0..8, 12, 16, 20, 24, 32, 64 */ - frame.len = can_fd_dlc2len(can_fd_len2dlc(frame.len)); + cu.fd.len = can_fd_dlc2len(can_fd_len2dlc(cu.fd.len)); } else { /* sanitize Classical CAN 2.0 frame length */ if (len8_dlc) { - if (frame.len > CAN_MAX_RAW_DLC) - frame.len = CAN_MAX_RAW_DLC; + if (cu.cc.len > CAN_MAX_RAW_DLC) + cu.cc.len = CAN_MAX_RAW_DLC; - if (frame.len > CAN_MAX_DLEN) - ccf->len8_dlc = frame.len; + if (cu.cc.len > CAN_MAX_DLEN) + cu.cc.len8_dlc = cu.cc.len; } - if (frame.len > CAN_MAX_DLEN) - frame.len = CAN_MAX_DLEN; + if (cu.cc.len > CAN_MAX_DLEN) + cu.cc.len = CAN_MAX_DLEN; } if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { @@ -722,7 +721,7 @@ int main(int argc, char **argv) return 1; while (running) { - frame.flags = 0; + cu.fd.flags = 0; if (count && (--count == 0)) running = 0; @@ -730,89 +729,89 @@ int main(int argc, char **argv) if (canfd) { mtu = CANFD_MTU; maxdlen = CANFD_MAX_DLEN; - frame.flags |= CANFD_FDF; + cu.fd.flags |= CANFD_FDF; if (brs) - frame.flags |= CANFD_BRS; + cu.fd.flags |= CANFD_BRS; if (esi) - frame.flags |= CANFD_ESI; + cu.fd.flags |= CANFD_ESI; } else { mtu = CAN_MTU; maxdlen = CAN_MAX_DLEN; } if (id_mode == MODE_RANDOM) - frame.can_id = random(); + cu.fd.can_id = random(); else if (id_mode == MODE_RANDOM_EVEN) - frame.can_id = random() & ~0x1; + cu.fd.can_id = random() & ~0x1; else if (id_mode == MODE_RANDOM_ODD) - frame.can_id = random() | 0x1; + cu.fd.can_id = random() | 0x1; if (extended) { - frame.can_id &= CAN_EFF_MASK; - frame.can_id |= CAN_EFF_FLAG; + cu.fd.can_id &= CAN_EFF_MASK; + cu.fd.can_id |= CAN_EFF_FLAG; } else - frame.can_id &= CAN_SFF_MASK; + cu.fd.can_id &= CAN_SFF_MASK; if (rtr_frame && !canfd) - frame.can_id |= CAN_RTR_FLAG; + cu.fd.can_id |= CAN_RTR_FLAG; if (dlc_mode == MODE_RANDOM) { if (canfd) - frame.len = can_fd_dlc2len(random() & 0xF); + cu.fd.len = can_fd_dlc2len(random() & 0xF); else { - frame.len = random() & 0xF; + cu.cc.len = random() & 0xF; - if (frame.len > CAN_MAX_DLEN) { + if (cu.cc.len > CAN_MAX_DLEN) { /* generate Classic CAN len8 DLCs? */ if (len8_dlc) - ccf->len8_dlc = frame.len; + cu.cc.len8_dlc = cu.cc.len; - frame.len = 8; /* for about 50% of the frames */ + cu.cc.len = 8; /* for about 50% of the frames */ } else { - ccf->len8_dlc = 0; + cu.cc.len8_dlc = 0; } } } - if (data_mode == MODE_INCREMENT && !frame.len) - frame.len = 1; /* min dlc value for incr. data */ + if (data_mode == MODE_INCREMENT && !cu.cc.len) + cu.cc.len = 1; /* min dlc value for incr. data */ if (data_mode == MODE_RANDOM) { rnd = random(); - memcpy(&frame.data[0], &rnd, 4); + memcpy(&cu.cc.data[0], &rnd, 4); rnd = random(); - memcpy(&frame.data[4], &rnd, 4); + memcpy(&cu.cc.data[4], &rnd, 4); /* omit extra random number generation for CAN FD */ - if (canfd && frame.len > 8) { - memcpy(&frame.data[8], &frame.data[0], 8); - memcpy(&frame.data[16], &frame.data[0], 16); - memcpy(&frame.data[32], &frame.data[0], 32); + if (canfd && cu.fd.len > 8) { + memcpy(&cu.fd.data[8], &cu.fd.data[0], 8); + memcpy(&cu.fd.data[16], &cu.fd.data[0], 16); + memcpy(&cu.fd.data[32], &cu.fd.data[0], 32); } } if (data_mode == MODE_RANDOM_FIX) { int i; - memcpy(frame.data, fixdata, CANFD_MAX_DLEN); + memcpy(cu.fd.data, fixdata, CANFD_MAX_DLEN); - for (i = 0; i < frame.len; i++) { + for (i = 0; i < cu.fd.len; i++) { if (rand_position[i] == (NIBBLE_H | NIBBLE_L)) { - frame.data[i] = random(); + cu.fd.data[i] = random(); } else if (rand_position[i] == NIBBLE_H) { - frame.data[i] = (frame.data[i] & 0x0f) | (random() & 0xf0); + cu.fd.data[i] = (cu.fd.data[i] & 0x0f) | (random() & 0xf0); } else if (rand_position[i] == NIBBLE_L) { - frame.data[i] = (frame.data[i] & 0xf0) | (random() & 0x0f); + cu.fd.data[i] = (cu.fd.data[i] & 0xf0) | (random() & 0x0f); } } } if (data_mode == MODE_FIX) - memcpy(frame.data, fixdata, CANFD_MAX_DLEN); + memcpy(cu.fd.data, fixdata, CANFD_MAX_DLEN); /* set unused payload data to zero like the CAN driver does it on rx */ - if (frame.len < maxdlen) - memset(&frame.data[frame.len], 0, maxdlen - frame.len); + if (cu.fd.len < maxdlen) + memset(&cu.fd.data[cu.fd.len], 0, maxdlen - cu.fd.len); if (!use_so_txtime && (ts.tv_sec || ts.tv_nsec) && @@ -834,14 +833,14 @@ int main(int argc, char **argv) printf(" %s ", argv[optind]); if (verbose > 1) - sprint_long_canframe(afrbuf, (cu_t *)&frame, (verbose > 2) ? CANLIB_VIEW_ASCII : 0); + sprint_long_canframe(afrbuf, &cu, (verbose > 2) ? CANLIB_VIEW_ASCII : 0); else - sprint_canframe(afrbuf, (cu_t *)&frame, 1); + sprint_canframe(afrbuf, &cu, 1); printf("%s\n", afrbuf); } - ret = do_send_one(s, &frame, mtu, polltimeout); + ret = do_send_one(s, &cu, mtu, polltimeout); if (ret) return 1; @@ -850,25 +849,25 @@ int main(int argc, char **argv) burst_sent_count++; if (id_mode == MODE_INCREMENT) - frame.can_id++; + cu.cc.can_id++; if (dlc_mode == MODE_INCREMENT) { incdlc++; incdlc %= CAN_MAX_RAW_DLC + 1; if (canfd && !mix) - frame.len = can_fd_dlc2len(incdlc); + cu.fd.len = can_fd_dlc2len(incdlc); else if (len8_dlc) { if (incdlc > CAN_MAX_DLEN) { - frame.len = CAN_MAX_DLEN; - ccf->len8_dlc = incdlc; + cu.cc.len = CAN_MAX_DLEN; + cu.cc.len8_dlc = incdlc; } else { - frame.len = incdlc; - ccf->len8_dlc = 0; + cu.cc.len = incdlc; + cu.cc.len8_dlc = 0; } } else { incdlc %= CAN_MAX_DLEN + 1; - frame.len = incdlc; + cu.fd.len = incdlc; } } @@ -876,7 +875,7 @@ int main(int argc, char **argv) incdata++; for (i = 0; i < 8; i++) - frame.data[i] = incdata >> i * 8; + cu.cc.data[i] = incdata >> i * 8; } if (mix) { From 09b8a6431f13c1367870caae20c4e45fddb0ffa5 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Sat, 2 Mar 2024 22:14:50 +0100 Subject: [PATCH 18/27] cangen: add missing long CAN frame view for len8_dlc and eff Signed-off-by: Oliver Hartkopp --- cangen.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cangen.c b/cangen.c index 21203f5..473e016 100644 --- a/cangen.c +++ b/cangen.c @@ -453,6 +453,7 @@ int main(int argc, char **argv) unsigned char verbose = 0; unsigned char rtr_frame = 0; unsigned char len8_dlc = 0; + unsigned char view = 0; int count = 0; unsigned long burst_sent_count = 0; int mtu, maxdlen; @@ -515,6 +516,7 @@ int main(int argc, char **argv) break; case 'e': extended = 1; + view |= CANLIB_VIEW_INDENT_SFF; break; case 'f': @@ -537,11 +539,13 @@ int main(int argc, char **argv) case '8': len8_dlc = 1; + view |= CANLIB_VIEW_LEN8_DLC; break; case 'm': mix = 1; canfd = 1; /* to switch the socket into CAN FD mode */ + view |= CANLIB_VIEW_INDENT_SFF; break; case 'I': @@ -626,6 +630,9 @@ int main(int argc, char **argv) return 1; } + if (verbose > 2) + view |= CANLIB_VIEW_ASCII; + ts_gap = double_to_timespec(gap / 1000); /* recognize obviously missing commandline option */ @@ -829,11 +836,10 @@ int main(int argc, char **argv) if (verbose) { static char afrbuf[AFRSZ]; /* ASCII CAN frame buffer size */ - printf(" %s ", argv[optind]); if (verbose > 1) - sprint_long_canframe(afrbuf, &cu, (verbose > 2) ? CANLIB_VIEW_ASCII : 0); + sprint_long_canframe(afrbuf, &cu, view); else sprint_canframe(afrbuf, &cu, 1); From 443312d6ce4b159ba061a6f921b4b6e8df2d9982 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Sun, 3 Mar 2024 13:07:08 +0100 Subject: [PATCH 19/27] cangen: add initial CAN XL support TODO: - Test all features - make CAN XL content variable Signed-off-by: Oliver Hartkopp --- cangen.c | 140 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 109 insertions(+), 31 deletions(-) diff --git a/cangen.c b/cangen.c index 473e016..71bbdc4 100644 --- a/cangen.c +++ b/cangen.c @@ -177,9 +177,10 @@ static void print_usage(char *prg) fprintf(stderr, " -f (generate CAN FD CAN frames)\n"); fprintf(stderr, " -b (generate CAN FD CAN frames with bitrate switch (BRS))\n"); fprintf(stderr, " -E (generate CAN FD CAN frames with error state (ESI))\n"); + 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 frames)\n"); + fprintf(stderr, " -m (mix -e -f -b -E -R -X frames)\n"); fprintf(stderr, " -I (CAN ID generation mode - see below)\n"); fprintf(stderr, " -L (CAN data length code (dlc) generation mode - see below)\n"); fprintf(stderr, " -D (CAN data (payload) generation mode - see below)\n"); @@ -298,7 +299,6 @@ static int do_send_one(int fd, cu_t *cu, size_t len, int timeout) uint8_t control[CMSG_SPACE(sizeof(uint64_t))] = { 0 }; struct iovec iov = { .iov_base = cu, - .iov_len = len, }; struct msghdr msg = { .msg_iov = &iov, @@ -307,6 +307,12 @@ static int do_send_one(int fd, cu_t *cu, size_t len, int timeout) ssize_t nbytes; int ret; + /* CAN XL frames need real frame length for sending */ + if (len == CANXL_MTU) + len = CANXL_HDR_SIZE + cu->xl.len; + + iov.iov_len = len; + if (use_so_txtime) { struct cmsghdr *cm; uint64_t tdeliver; @@ -443,6 +449,7 @@ int main(int argc, char **argv) unsigned long polltimeout = 0; unsigned char extended = 0; unsigned char canfd = 0; + unsigned char canxl = 0; unsigned char brs = 0; unsigned char esi = 0; unsigned char mix = 0; @@ -458,6 +465,7 @@ int main(int argc, char **argv) unsigned long burst_sent_count = 0; int mtu, maxdlen; uint64_t incdata = 0; + __u8 *data; /* base pointer for CC/FD or XL data */ int incdlc = 0; unsigned long rnd; unsigned char fixdata[CANFD_MAX_DLEN]; @@ -467,9 +475,13 @@ int main(int argc, char **argv) int s; /* socket */ struct sockaddr_can addr = { 0 }; + struct can_raw_vcid_options vcid_opts = { + .flags = CAN_RAW_XL_VCID_TX_PASS, + }; static cu_t cu; int i; - struct ifreq ifr; + static struct ifreq ifr; + const int enable_canfx = 1; struct timeval now; int ret; @@ -488,7 +500,7 @@ int main(int argc, char **argv) { 0, 0, 0, 0 }, }; - while ((opt = getopt_long(argc, argv, "g:atefbER8mI:L:D:p:n:ixc:vh?", long_options, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "g:atefbEXR8mI:L:D:p:n:ixc:vh?", long_options, NULL)) != -1) { switch (opt) { case 'g': gap = strtod(optarg, NULL); @@ -533,6 +545,10 @@ int main(int argc, char **argv) canfd = 1; break; + case 'X': + canxl = 1; + break; + case 'R': rtr_frame = 1; break; @@ -676,8 +692,7 @@ int main(int argc, char **argv) &loopback, sizeof(loopback)); } - if (canfd) { - const int enable_canfd = 1; + if (canfd || canxl) { /* check if the frame fits into the CAN netdevice */ if (ioctl(s, SIOCGIFMTU, &ifr) < 0) { @@ -685,19 +700,49 @@ int main(int argc, char **argv) return 1; } - if (ifr.ifr_mtu != CANFD_MTU && ifr.ifr_mtu != CANXL_MTU) { - printf("CAN interface is only Classical CAN capable - sorry.\n"); + 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)); + } else { + /* limit fixed CAN XL data length to 64 */ + if (cu.fd.len > CANFD_MAX_DLEN) + cu.fd.len = CANFD_MAX_DLEN; + } + + if (canxl && (ifr.ifr_mtu < CANXL_MIN_MTU)) { + printf("CAN interface not CAN XL capable - sorry.\n"); return 1; } - /* interface is ok - try to switch the socket into CAN FD mode */ - if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &enable_canfd, sizeof(enable_canfd))) { - printf("error when enabling CAN FD support\n"); + if (canfd && (ifr.ifr_mtu < CANFD_MTU)) { + printf("CAN interface not CAN FD capable - sorry.\n"); return 1; } - /* 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)); + if (ifr.ifr_mtu == 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 >= 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) { @@ -733,10 +778,16 @@ int main(int argc, char **argv) if (count && (--count == 0)) running = 0; - if (canfd) { + if (canxl) { + mtu = CANXL_MTU; + maxdlen = CANFD_MAX_DLEN; /* generate up to 64 byte */ + extended = 0; /* prio has only 11 bit ID content */ + data = cu.xl.data; /* fill CAN XL data */ + } else if (canfd) { mtu = CANFD_MTU; maxdlen = CANFD_MAX_DLEN; - cu.fd.flags |= CANFD_FDF; + data = cu.fd.data; /* fill CAN CC/FD data */ + cu.fd.flags = CANFD_FDF; if (brs) cu.fd.flags |= CANFD_BRS; if (esi) @@ -744,6 +795,7 @@ int main(int argc, char **argv) } else { mtu = CAN_MTU; maxdlen = CAN_MAX_DLEN; + data = cu.cc.data; /* fill CAN CC/FD data */ } if (id_mode == MODE_RANDOM) @@ -759,11 +811,13 @@ int main(int argc, char **argv) } else cu.fd.can_id &= CAN_SFF_MASK; - if (rtr_frame && !canfd) + if (rtr_frame && !canfd && !canxl) cu.fd.can_id |= CAN_RTR_FLAG; if (dlc_mode == MODE_RANDOM) { - if (canfd) + if (canxl) + cu.fd.len = CANXL_MIN_DLEN + (random() & 0x3F); + else if (canfd) cu.fd.len = can_fd_dlc2len(random() & 0xF); else { cu.cc.len = random() & 0xF; @@ -785,40 +839,40 @@ int main(int argc, char **argv) if (data_mode == MODE_RANDOM) { rnd = random(); - memcpy(&cu.cc.data[0], &rnd, 4); + memcpy(&data[0], &rnd, 4); rnd = random(); - memcpy(&cu.cc.data[4], &rnd, 4); + memcpy(&data[4], &rnd, 4); /* omit extra random number generation for CAN FD */ - if (canfd && cu.fd.len > 8) { - memcpy(&cu.fd.data[8], &cu.fd.data[0], 8); - memcpy(&cu.fd.data[16], &cu.fd.data[0], 16); - memcpy(&cu.fd.data[32], &cu.fd.data[0], 32); + if ((canfd || canxl) && cu.fd.len > 8) { + memcpy(&data[8], &data[0], 8); + memcpy(&data[16], &data[0], 16); + memcpy(&data[32], &data[0], 32); } } if (data_mode == MODE_RANDOM_FIX) { int i; - memcpy(cu.fd.data, fixdata, CANFD_MAX_DLEN); + memcpy(data, fixdata, CANFD_MAX_DLEN); for (i = 0; i < cu.fd.len; i++) { if (rand_position[i] == (NIBBLE_H | NIBBLE_L)) { - cu.fd.data[i] = random(); + data[i] = random(); } else if (rand_position[i] == NIBBLE_H) { - cu.fd.data[i] = (cu.fd.data[i] & 0x0f) | (random() & 0xf0); + data[i] = (data[i] & 0x0f) | (random() & 0xf0); } else if (rand_position[i] == NIBBLE_L) { - cu.fd.data[i] = (cu.fd.data[i] & 0xf0) | (random() & 0x0f); + data[i] = (data[i] & 0xf0) | (random() & 0x0f); } } } if (data_mode == MODE_FIX) - memcpy(cu.fd.data, fixdata, CANFD_MAX_DLEN); + memcpy(data, fixdata, CANFD_MAX_DLEN); /* set unused payload data to zero like the CAN driver does it on rx */ if (cu.fd.len < maxdlen) - memset(&cu.fd.data[cu.fd.len], 0, maxdlen - cu.fd.len); + memset(&data[cu.fd.len], 0, maxdlen - cu.fd.len); if (!use_so_txtime && (ts.tv_sec || ts.tv_nsec) && @@ -833,6 +887,21 @@ int main(int argc, char **argv) } } + if (canxl) { + /* convert some CAN FD frame content into a CAN XL frame */ + if (cu.fd.len < CANXL_MIN_DLEN) { + cu.fd.len = CANXL_MIN_DLEN; + data[0] = 0xCC; /* default filler */ + } + cu.xl.len = cu.fd.len; + cu.xl.flags = CANXL_XLF; + + /* static values for now */ + cu.xl.sdt = 0x22; + cu.xl.af = 0x12345678; + cu.xl.prio |= (0x33 << CANXL_VCID_OFFSET); + } + if (verbose) { static char afrbuf[AFRSZ]; /* ASCII CAN frame buffer size */ @@ -854,6 +923,11 @@ int main(int argc, char **argv) burst_sent_count = 0; burst_sent_count++; + if (canxl) { + /* restore some CAN FD frame content from CAN XL frame */ + cu.fd.len = cu.xl.len; + } + if (id_mode == MODE_INCREMENT) cu.cc.can_id++; @@ -861,7 +935,7 @@ int main(int argc, char **argv) incdlc++; incdlc %= CAN_MAX_RAW_DLC + 1; - if (canfd && !mix) + if ((canfd || canxl) && !mix) cu.fd.len = can_fd_dlc2len(incdlc); else if (len8_dlc) { if (incdlc > CAN_MAX_DLEN) { @@ -881,7 +955,7 @@ int main(int argc, char **argv) incdata++; for (i = 0; i < 8; i++) - cu.cc.data[i] = incdata >> i * 8; + data[i] = incdata >> i * 8; } if (mix) { @@ -892,6 +966,10 @@ int main(int argc, char **argv) brs = i & 4; esi = i & 8; } + /* generate CAN XL traffic if the interface is capable */ + if (ifr.ifr_mtu >= CANXL_MIN_MTU) + canxl = ((i & 96) == 96); + rtr_frame = ((i & 24) == 24); /* reduce RTR frames to 1/4 */ } } From 87a3058019a32310b93317c1b381fbba512bbad6 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Mon, 4 Mar 2024 22:50:52 +0100 Subject: [PATCH 20/27] cangen: support generation features for CAN XL specific content Signed-off-by: Oliver Hartkopp --- cangen.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 106 insertions(+), 6 deletions(-) diff --git a/cangen.c b/cangen.c index 71bbdc4..70ea97d 100644 --- a/cangen.c +++ b/cangen.c @@ -184,6 +184,10 @@ static void print_usage(char *prg) fprintf(stderr, " -I (CAN ID generation mode - see below)\n"); fprintf(stderr, " -L (CAN data length code (dlc) generation mode - see below)\n"); fprintf(stderr, " -D (CAN data (payload) generation mode - see below)\n"); + fprintf(stderr, " -F (CAN XL Flags generation mode - see below, no e/o mode)\n"); + fprintf(stderr, " -S (CAN XL SDT generation mode - see below, no e/o mode)\n"); + fprintf(stderr, " -A (CAN XL AF generation mode - see below, no e/o mode)\n"); + fprintf(stderr, " -V (CAN XL VCID generation mode - see below, no e/o mode)\n"); fprintf(stderr, " -p (poll on -ENOBUFS to write frames with ms)\n"); fprintf(stderr, " -n (terminate after CAN frames - default infinite)\n"); fprintf(stderr, " -i (ignore -ENOBUFS return values on write() syscalls)\n"); @@ -456,6 +460,14 @@ int main(int argc, char **argv) unsigned char id_mode = MODE_RANDOM; unsigned char data_mode = MODE_RANDOM; unsigned char dlc_mode = MODE_RANDOM; + __u8 xl_flags = 0; + __u8 xl_sdt = 0; + __u32 xl_af = 0; + __u8 xl_vcid = 0; + unsigned char xl_flags_mode = MODE_RANDOM; + unsigned char xl_sdt_mode = MODE_RANDOM; + unsigned char xl_af_mode = MODE_RANDOM; + unsigned char xl_vcid_mode = MODE_RANDOM; unsigned char loopback_disable = 0; unsigned char verbose = 0; unsigned char rtr_frame = 0; @@ -500,7 +512,7 @@ int main(int argc, char **argv) { 0, 0, 0, 0 }, }; - while ((opt = getopt_long(argc, argv, "g:atefbEXR8mI:L:D:p:n:ixc:vh?", long_options, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "g:atefbEXR8mI:L:D:F:S:A:V:p:n:ixc:vh?", long_options, NULL)) != -1) { switch (opt) { case 'g': gap = strtod(optarg, NULL); @@ -605,6 +617,59 @@ int main(int argc, char **argv) } break; + case 'F': + if (optarg[0] == 'r') { + xl_flags_mode = MODE_RANDOM; + } else if (optarg[0] == 'i') { + xl_flags_mode = MODE_INCREMENT; + } else { + xl_flags_mode = MODE_FIX; + if (sscanf(optarg, "%hhx", &xl_flags) != 1) { + printf("Bad xl_flags definition '%s'.\n", optarg); + exit(1); + } + } + break; + + case 'S': + if (optarg[0] == 'r') { + xl_sdt_mode = MODE_RANDOM; + } else if (optarg[0] == 'i') { + xl_sdt_mode = MODE_INCREMENT; + } else { + xl_sdt_mode = MODE_FIX; + if (sscanf(optarg, "%hhx", &xl_sdt) != 1) { + printf("Bad xl_sdt definition '%s'.\n", optarg); + exit(1); + } + } + break; + + case 'A': + if (optarg[0] == 'r') { + xl_af_mode = MODE_RANDOM; + } else if (optarg[0] == 'i') { + xl_af_mode = MODE_INCREMENT; + } else { + xl_af_mode = MODE_FIX; + xl_af = strtoul(optarg, NULL, 16); + } + break; + + case 'V': + if (optarg[0] == 'r') { + xl_vcid_mode = MODE_RANDOM; + } else if (optarg[0] == 'i') { + xl_vcid_mode = MODE_INCREMENT; + } else { + xl_vcid_mode = MODE_FIX; + if (sscanf(optarg, "%hhx", &xl_vcid) != 1) { + printf("Bad xl_vcid definition '%s'.\n", optarg); + exit(1); + } + } + break; + case 'p': polltimeout = strtoul(optarg, NULL, 10); break; @@ -894,12 +959,47 @@ int main(int argc, char **argv) data[0] = 0xCC; /* default filler */ } cu.xl.len = cu.fd.len; - cu.xl.flags = CANXL_XLF; - /* static values for now */ - cu.xl.sdt = 0x22; - cu.xl.af = 0x12345678; - cu.xl.prio |= (0x33 << CANXL_VCID_OFFSET); + rnd = random(); + + if (xl_flags_mode == MODE_RANDOM) + cu.xl.flags = (__u8)(rnd & CANXL_SEC); + else if (xl_flags_mode == MODE_FIX) + cu.xl.flags = xl_flags; + else if (xl_flags_mode == MODE_INCREMENT) { + xl_flags ^= CANXL_SEC; + cu.xl.flags = (xl_flags & CANXL_SEC); + } + + /* mark CAN XL frame */ + cu.xl.flags |= CANXL_XLF; + + if (xl_sdt_mode == MODE_RANDOM) + cu.xl.sdt = (__u8)(rnd & 0xFF); + else if (xl_sdt_mode == MODE_FIX) + cu.xl.sdt = xl_sdt; + else if (xl_sdt_mode == MODE_INCREMENT) { + xl_sdt++; + cu.xl.sdt = xl_sdt; + } + + if (xl_af_mode == MODE_RANDOM) + cu.xl.af = (__u32)(rnd & 0xFFFFFFFF); + else if (xl_af_mode == MODE_FIX) + cu.xl.af = xl_af; + else if (xl_af_mode == MODE_INCREMENT) { + xl_af++; + cu.xl.af = xl_af; + } + + if (xl_vcid_mode == MODE_RANDOM) + cu.xl.prio |= (__u32)(rnd & CANXL_VCID_MASK); + else if (xl_vcid_mode == MODE_FIX) + cu.xl.prio |= (xl_vcid << CANXL_VCID_OFFSET); + else if (xl_vcid_mode == MODE_INCREMENT) { + xl_vcid++; + cu.xl.prio |= (xl_vcid << CANXL_VCID_OFFSET); + } } if (verbose) { From 09aa4d55bff15e44acce17029d82b1586f67e2d1 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Wed, 6 Mar 2024 11:42:13 +0100 Subject: [PATCH 21/27] asc2log: unify curly brackets at function definition Move the curly brackets to the start of the next line to follow the common coding style in can-utils. Signed-off-by: Oliver Hartkopp --- asc2log.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/asc2log.c b/asc2log.c index d861c67..fbbb01b 100644 --- a/asc2log.c +++ b/asc2log.c @@ -71,8 +71,8 @@ void print_usage(char *prg) fprintf(stderr, "\t-O \t(default stdout)\n"); } -void prframe(FILE *file, struct timeval *tv, int dev, struct canfd_frame *cf, char *extra_info) { - +void prframe(FILE *file, struct timeval *tv, int dev, struct canfd_frame *cf, char *extra_info) +{ static char abuf[BUFLEN]; fprintf(file, "(%llu.%06llu) ", (unsigned long long)tv->tv_sec, (unsigned long long)tv->tv_usec); @@ -86,8 +86,8 @@ void prframe(FILE *file, struct timeval *tv, int dev, struct canfd_frame *cf, ch fprintf(file, "%s%s", abuf, extra_info); } -void get_can_id(struct canfd_frame *cf, char *idstring, int base) { - +void get_can_id(struct canfd_frame *cf, char *idstring, int base) +{ if (idstring[strlen(idstring)-1] == 'x') { cf->can_id = CAN_EFF_FLAG; idstring[strlen(idstring)-1] = 0; @@ -98,8 +98,8 @@ void get_can_id(struct canfd_frame *cf, char *idstring, int base) { } void calc_tv(struct timeval *tv, struct timeval *read_tv, - struct timeval *date_tv, char timestamps, int dplace) { - + struct timeval *date_tv, char timestamps, int dplace) +{ if (dplace == 4) /* shift values having only 4 decimal places */ read_tv->tv_usec *= 100; /* and need for 6 */ @@ -129,8 +129,8 @@ void calc_tv(struct timeval *tv, struct timeval *read_tv, } } -void eval_can(char* buf, struct timeval *date_tvp, char timestamps, char base, int dplace, FILE *outfile) { - +void eval_can(char* buf, struct timeval *date_tvp, char timestamps, char base, int dplace, FILE *outfile) +{ int interface; static struct timeval tv; /* current frame timestamp */ static struct timeval read_tv; /* frame timestamp from ASC file */ @@ -239,8 +239,8 @@ void eval_can(char* buf, struct timeval *date_tvp, char timestamps, char base, i } } -void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps, int dplace, FILE *outfile) { - +void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps, int dplace, FILE *outfile) +{ int interface; static struct timeval tv; /* current frame timestamp */ static struct timeval read_tv; /* frame timestamp from ASC file */ @@ -376,8 +376,8 @@ void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps, int dplace /* No support for really strange CANFD ErrorFrames format m( */ } -int get_date(struct timeval *tv, char *date) { - +int get_date(struct timeval *tv, char *date) +{ struct tm tms; unsigned int msecs = 0; From 6f7b146166fc96f36f429a6cdd18e6d971d0dad5 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Wed, 6 Mar 2024 11:57:54 +0100 Subject: [PATCH 22/27] cangen: unify curly brackets and apply review feedback Signed-off-by: Oliver Hartkopp --- cangen.c | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/cangen.c b/cangen.c index 70ea97d..0e5ec8d 100644 --- a/cangen.c +++ b/cangen.c @@ -492,7 +492,7 @@ int main(int argc, char **argv) }; static cu_t cu; int i; - static struct ifreq ifr; + struct ifreq ifr = { 0 }; const int enable_canfx = 1; struct timeval now; @@ -873,8 +873,9 @@ int main(int argc, char **argv) if (extended) { cu.fd.can_id &= CAN_EFF_MASK; cu.fd.can_id |= CAN_EFF_FLAG; - } else + } else { cu.fd.can_id &= CAN_SFF_MASK; + } if (rtr_frame && !canfd && !canxl) cu.fd.can_id |= CAN_RTR_FLAG; @@ -962,11 +963,11 @@ int main(int argc, char **argv) rnd = random(); - if (xl_flags_mode == MODE_RANDOM) - cu.xl.flags = (__u8)(rnd & CANXL_SEC); - else if (xl_flags_mode == MODE_FIX) + if (xl_flags_mode == MODE_RANDOM) { + cu.xl.flags = rnd & CANXL_SEC; + } else if (xl_flags_mode == MODE_FIX) { cu.xl.flags = xl_flags; - else if (xl_flags_mode == MODE_INCREMENT) { + } else if (xl_flags_mode == MODE_INCREMENT) { xl_flags ^= CANXL_SEC; cu.xl.flags = (xl_flags & CANXL_SEC); } @@ -974,31 +975,31 @@ int main(int argc, char **argv) /* mark CAN XL frame */ cu.xl.flags |= CANXL_XLF; - if (xl_sdt_mode == MODE_RANDOM) - cu.xl.sdt = (__u8)(rnd & 0xFF); - else if (xl_sdt_mode == MODE_FIX) + if (xl_sdt_mode == MODE_RANDOM) { + cu.xl.sdt = rnd & 0xFF; + } else if (xl_sdt_mode == MODE_FIX) { cu.xl.sdt = xl_sdt; - else if (xl_sdt_mode == MODE_INCREMENT) { + } else if (xl_sdt_mode == MODE_INCREMENT) { xl_sdt++; cu.xl.sdt = xl_sdt; } - if (xl_af_mode == MODE_RANDOM) - cu.xl.af = (__u32)(rnd & 0xFFFFFFFF); - else if (xl_af_mode == MODE_FIX) + if (xl_af_mode == MODE_RANDOM) { + cu.xl.af = rnd; + } else if (xl_af_mode == MODE_FIX) { cu.xl.af = xl_af; - else if (xl_af_mode == MODE_INCREMENT) { + } else if (xl_af_mode == MODE_INCREMENT) { xl_af++; cu.xl.af = xl_af; } - if (xl_vcid_mode == MODE_RANDOM) - cu.xl.prio |= (__u32)(rnd & CANXL_VCID_MASK); - else if (xl_vcid_mode == MODE_FIX) - cu.xl.prio |= (xl_vcid << CANXL_VCID_OFFSET); - else if (xl_vcid_mode == MODE_INCREMENT) { + if (xl_vcid_mode == MODE_RANDOM) { + cu.xl.prio |= rnd & CANXL_VCID_MASK; + } else if (xl_vcid_mode == MODE_FIX) { + cu.xl.prio |= xl_vcid << CANXL_VCID_OFFSET; + } else if (xl_vcid_mode == MODE_INCREMENT) { xl_vcid++; - cu.xl.prio |= (xl_vcid << CANXL_VCID_OFFSET); + cu.xl.prio |= xl_vcid << CANXL_VCID_OFFSET; } } @@ -1023,10 +1024,9 @@ int main(int argc, char **argv) burst_sent_count = 0; burst_sent_count++; - if (canxl) { - /* restore some CAN FD frame content from CAN XL frame */ + /* restore some CAN FD frame content from CAN XL frame */ + if (canxl) cu.fd.len = cu.xl.len; - } if (id_mode == MODE_INCREMENT) cu.cc.can_id++; From 7905b632ffb740e27e59dd2e0c870348aa564a96 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Wed, 6 Mar 2024 12:01:39 +0100 Subject: [PATCH 23/27] canlogserver: unify curly brackets in if statements Signed-off-by: Oliver Hartkopp --- canlogserver.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/canlogserver.c b/canlogserver.c index cdd25d5..ca900ef 100644 --- a/canlogserver.c +++ b/canlogserver.c @@ -421,11 +421,11 @@ int main(int argc, char **argv) } } else { /* mark dual-use struct canfd_frame */ - if (nbytes == CAN_MTU) + if (nbytes == CAN_MTU) { cu.fd.flags = 0; - else if (nbytes == CANFD_MTU) + } else if (nbytes == CANFD_MTU) { cu.fd.flags |= CANFD_FDF; - else { + } else { fprintf(stderr, "read: incomplete CAN CC/FD frame\n"); return 1; } From 8e131401c14031497a13953d7d5b78fc69950fbc Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Wed, 6 Mar 2024 12:10:32 +0100 Subject: [PATCH 24/27] lib: remove obsolete brackets From review feedback. Signed-off-by: Oliver Hartkopp --- lib.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/lib.c b/lib.c index f80a70b..bd8d3cf 100644 --- a/lib.c +++ b/lib.c @@ -178,7 +178,7 @@ int parse_canframe(char *cs, cu_t *cu) for (i = 0; i < 3; i++) { if ((tmp = asc2nibble(cs[i])) > 0x0F) return 0; - cu->cc.can_id |= (tmp << (2 - i) * 4); + cu->cc.can_id |= tmp << (2 - i) * 4; } } else if (cs[5] == CANID_DELIM) { /* 5 digits CAN XL VCID/PRIO*/ @@ -187,7 +187,7 @@ int parse_canframe(char *cs, cu_t *cu) for (i = 0; i < 5; i++) { if ((tmp = asc2nibble(cs[i])) > 0x0F) return 0; - cu->xl.prio |= (tmp << (4 - i) * 4); + cu->xl.prio |= tmp << (4 - i) * 4; } /* the VCID starts at bit position 16 */ @@ -201,7 +201,7 @@ int parse_canframe(char *cs, cu_t *cu) for (i = 0; i < 8; i++) { if ((tmp = asc2nibble(cs[i])) > 0x0F) return 0; - cu->cc.can_id |= (tmp << (7 - i) * 4); + cu->cc.can_id |= tmp << (7 - i) * 4; } if (!(cu->cc.can_id & CAN_ERR_FLAG)) /* 8 digits but no errorframe? */ cu->cc.can_id |= CAN_EFF_FLAG; /* then it is an extended frame */ @@ -227,7 +227,6 @@ int parse_canframe(char *cs, cu_t *cu) } if (cs[idx] == CANID_DELIM) { /* CAN FD frame escape char '##' */ - maxdlen = CANFD_MAX_DLEN; mtu = CANFD_MTU; @@ -240,7 +239,6 @@ int parse_canframe(char *cs, cu_t *cu) idx += 2; } else if (cs[idx + 14] == CANID_DELIM) { /* CAN XL frame '#80:00:11223344#' */ - maxdlen = CANXL_MAX_DLEN; mtu = CANXL_MTU; data = cu->xl.data; /* fill CAN XL data */ @@ -250,7 +248,7 @@ int parse_canframe(char *cs, cu_t *cu) if ((tmp = asc2nibble(cs[idx++])) > 0x0F) return 0; - cu->xl.flags = (tmp << 4); + cu->xl.flags = tmp << 4; if ((tmp = asc2nibble(cs[idx++])) > 0x0F) return 0; cu->xl.flags |= tmp; @@ -262,7 +260,7 @@ int parse_canframe(char *cs, cu_t *cu) if ((tmp = asc2nibble(cs[idx++])) > 0x0F) return 0; - cu->xl.sdt = (tmp << 4); + cu->xl.sdt = tmp << 4; if ((tmp = asc2nibble(cs[idx++])) > 0x0F) return 0; cu->xl.sdt |= tmp; @@ -272,7 +270,7 @@ int parse_canframe(char *cs, cu_t *cu) for (i = 0; i < 8; i++) { if ((tmp = asc2nibble(cs[idx++])) > 0x0F) return 0; - cu->xl.af |= (tmp << (7 - i) * 4); + cu->xl.af |= tmp << (7 - i) * 4; } idx++; /* skip CANID_DELIM */ @@ -287,7 +285,7 @@ int parse_canframe(char *cs, cu_t *cu) if ((tmp = asc2nibble(cs[idx++])) > 0x0F) return 0; - data[i] = (tmp << 4); + data[i] = tmp << 4; if ((tmp = asc2nibble(cs[idx++])) > 0x0F) return 0; data[i] |= tmp; @@ -362,7 +360,7 @@ int sprint_canframe(char *buf, cu_t *cu, int sep) } /* CAN CC frames may have RTR enabled. There are no ERR frames with RTR */ - if (!(is_canfd) && cu->fd.can_id & CAN_RTR_FLAG) { + if (!is_canfd && cu->fd.can_id & CAN_RTR_FLAG) { buf[offset++] = 'R'; /* print a given CAN 2.0B DLC if it's not zero */ if (len && len <= CAN_MAX_DLEN) { @@ -399,7 +397,7 @@ int sprint_canframe(char *buf, cu_t *cu, int sep) } /* check for extra DLC when having a Classic CAN with 8 bytes payload */ - if (!(is_canfd) && (len == CAN_MAX_DLEN)) { + if (!is_canfd && (len == CAN_MAX_DLEN)) { unsigned char dlc = cu->cc.len8_dlc; if ((dlc > CAN_MAX_DLEN) && (dlc <= CAN_MAX_RAW_DLC)) { @@ -485,7 +483,7 @@ int sprint_long_canframe(char *buf, cu_t *cu, int view) } /* The len value is sanitized (see above) */ - if (!(is_canfd)) { + if (!is_canfd) { if (view & CANLIB_VIEW_LEN8_DLC) { unsigned char dlc = cu->cc.len8_dlc; From 27030b3e54911727142d71c60c93ea57699fa592 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Mon, 11 Mar 2024 22:47:15 +0100 Subject: [PATCH 25/27] lib: make sprint_canframe the buffer size aware snprintf_canframe Make sure the library functions to convert CAN frames into ASCII represenation do not exceed the given buffer size. This also applies to the long CAN frame output library function. Signed-off-by: Oliver Hartkopp --- asc2log.c | 2 +- candump.c | 4 +- cangen.c | 4 +- canlogserver.c | 2 +- canplayer.c | 2 +- lib.c | 100 ++++++++++++++++++++++++++++++++++++++++--------- lib.h | 4 +- log2long.c | 4 +- 8 files changed, 94 insertions(+), 28 deletions(-) diff --git a/asc2log.c b/asc2log.c index fbbb01b..5ffc1be 100644 --- a/asc2log.c +++ b/asc2log.c @@ -82,7 +82,7 @@ void prframe(FILE *file, struct timeval *tv, int dev, struct canfd_frame *cf, ch else fprintf(file, "canX "); - sprint_canframe(abuf, (cu_t *)cf, 0); + snprintf_canframe(abuf, sizeof(abuf), (cu_t *)cf, 0); fprintf(file, "%s%s", abuf, extra_info); } diff --git a/candump.c b/candump.c index 87958cd..2c57b8d 100644 --- a/candump.c +++ b/candump.c @@ -837,7 +837,7 @@ int main(int argc, char **argv) alen += sprintf(afrbuf + alen, "%*s ", max_devname_len, devname[idx]); - alen += sprint_canframe(afrbuf + alen, &cu, 0); + alen += snprintf_canframe(afrbuf + alen, sizeof(afrbuf) - alen, &cu, 0); } /* write CAN frame in log file style to logfile */ @@ -876,7 +876,7 @@ int main(int argc, char **argv) } alen += sprintf(afrbuf + alen, "%s ", (color == 1) ? col_off : ""); - alen += sprint_long_canframe(afrbuf + alen, &cu, view); + alen += snprintf_long_canframe(afrbuf + alen, sizeof(afrbuf) - alen, &cu, view); if ((view & CANLIB_VIEW_ERROR) && (cu.fd.can_id & CAN_ERR_FLAG)) { alen += sprintf(afrbuf + alen, "\n\t"); diff --git a/cangen.c b/cangen.c index 0e5ec8d..4e27261 100644 --- a/cangen.c +++ b/cangen.c @@ -1009,9 +1009,9 @@ int main(int argc, char **argv) printf(" %s ", argv[optind]); if (verbose > 1) - sprint_long_canframe(afrbuf, &cu, view); + snprintf_long_canframe(afrbuf, sizeof(afrbuf), &cu, view); else - sprint_canframe(afrbuf, &cu, 1); + snprintf_canframe(afrbuf, sizeof(afrbuf), &cu, 1); printf("%s\n", afrbuf); } diff --git a/canlogserver.c b/canlogserver.c index ca900ef..1921e23 100644 --- a/canlogserver.c +++ b/canlogserver.c @@ -439,7 +439,7 @@ int main(int argc, char **argv) sprintf(afrbuf, "(%llu.%06llu) %*s ", (unsigned long long)tv.tv_sec, (unsigned long long)tv.tv_usec, max_devname_len, devname[idx]); - sprint_canframe(afrbuf+strlen(afrbuf), &cu, 0); + snprintf_canframe(afrbuf + strlen(afrbuf), sizeof(afrbuf) - strlen(afrbuf), &cu, 0); strcat(afrbuf, "\n"); if (write(accsocket, afrbuf, strlen(afrbuf)) < 0) { diff --git a/canplayer.c b/canplayer.c index a38a82a..dfd1919 100644 --- a/canplayer.c +++ b/canplayer.c @@ -513,7 +513,7 @@ int main(int argc, char **argv) if (verbose) { printf("%s (%s) ", get_txname(device), device); - sprint_long_canframe(afrbuf, &cu, CANLIB_VIEW_INDENT_SFF); + snprintf_long_canframe(afrbuf, sizeof(afrbuf), &cu, CANLIB_VIEW_INDENT_SFF); printf("%s\n", afrbuf); } diff --git a/lib.c b/lib.c index bd8d3cf..1c2ec0c 100644 --- a/lib.c +++ b/lib.c @@ -308,7 +308,7 @@ int parse_canframe(char *cs, cu_t *cu) return mtu; } -int sprint_canframe(char *buf, cu_t *cu, int sep) +int snprintf_canframe(char *buf, size_t size, cu_t *cu, int sep) { /* documentation see lib.h */ @@ -316,10 +316,22 @@ int sprint_canframe(char *buf, cu_t *cu, int sep) int i, offset; int len; + /* ensure space for string termination */ + if (size < 1) + return size; + /* handle CAN XL frames */ if (cu->xl.flags & CANXL_XLF) { len = cu->xl.len; + /* check if the CAN frame fits into the provided buffer */ + if (sizeof("00123#11:22:12345678#") + 2 * len + (sep ? len : 0) > size - 1) { + /* mark buffer overflow in output */ + memset(buf, '-', size - 1); + buf[size - 1] = 0; + return size; + } + /* print prio and CAN XL header content */ offset = sprintf(buf, "%02X%03X#%02X:%02X:%08X#", (canid_t)(cu->xl.prio & CANXL_VCID_MASK) >> CANXL_VCID_OFFSET, @@ -345,6 +357,15 @@ int sprint_canframe(char *buf, cu_t *cu, int sep) else len = (cu->fd.len > CAN_MAX_DLEN) ? CAN_MAX_DLEN : cu->fd.len; + /* check if the CAN frame fits into the provided buffer */ + if (sizeof("12345678#_F") + 2 * len + (sep ? len : 0) + \ + (cu->fd.can_id & CAN_RTR_FLAG ? 2 : 0) > size - 1) { + /* mark buffer overflow in output */ + memset(buf, '-', size - 1); + buf[size - 1] = 0; + return size; + } + if (cu->fd.can_id & CAN_ERR_FLAG) { put_eff_id(buf, cu->fd.can_id & (CAN_ERR_MASK | CAN_ERR_FLAG)); buf[8] = '#'; @@ -411,48 +432,60 @@ int sprint_canframe(char *buf, cu_t *cu, int sep) return offset; } -int sprint_long_canframe(char *buf, cu_t *cu, int view) +int snprintf_long_canframe(char *buf, size_t size, cu_t *cu, int view) { /* documentation see lib.h */ unsigned char is_canfd = cu->fd.flags; - int i, j, dlen, offset; + int i, j, dlen, offset, maxsize; int len; - /* initialize space for CAN-ID and length information */ - memset(buf, ' ', 15); + /* ensure space for string termination */ + if (size < 1) + return size; /* handle CAN XL frames */ if (cu->xl.flags & CANXL_XLF) { len = cu->xl.len; + /* crop to CANFD_MAX_DLEN */ + if (len > CANFD_MAX_DLEN) + dlen = CANFD_MAX_DLEN; + else + dlen = len; + + /* check if the CAN frame fits into the provided buffer */ + if (sizeof(".....123 [2048] (00|11:22:12345678) ...") + 3 * dlen > size - 1) { + /* mark buffer overflow in output */ + memset(buf, '-', size - 1); + buf[size - 1] = 0; + return size; + } + if (view & CANLIB_VIEW_INDENT_SFF) { + memset(buf, ' ', 5); put_sff_id(buf + 5, cu->xl.prio & CANXL_PRIO_MASK); - offset = 9; + offset = 8; } else { put_sff_id(buf, cu->xl.prio & CANXL_PRIO_MASK); - offset = 4; + offset = 3; } /* print prio and CAN XL header content */ - offset += sprintf(buf + offset, "[%04d] (%02X|%02X:%02X:%08X) ", + offset += sprintf(buf + offset, " [%04d] (%02X|%02X:%02X:%08X) ", len, (canid_t)(cu->xl.prio & CANXL_VCID_MASK) >> CANXL_VCID_OFFSET, cu->xl.flags, cu->xl.sdt, cu->xl.af); - /* data - crop to CANFD_MAX_DLEN */ - if (len > CANFD_MAX_DLEN) - len = CANFD_MAX_DLEN; - - for (i = 0; i < len; i++) { + for (i = 0; i < dlen; i++) { put_hex_byte(buf + offset, cu->xl.data[i]); offset += 2; - if (i + 1 < len) + if (i + 1 < dlen) buf[offset++] = ' '; } /* indicate cropped output */ - if (cu->xl.len > len) + if (cu->xl.len > dlen) offset += sprintf(buf + offset, " ..."); buf[offset] = 0; @@ -466,6 +499,39 @@ int sprint_long_canframe(char *buf, cu_t *cu, int view) else len = (cu->fd.len > CAN_MAX_DLEN) ? CAN_MAX_DLEN : cu->fd.len; + /* check if the CAN frame fits into the provided buffer */ + maxsize = sizeof("12345678 [12] "); + if (view & CANLIB_VIEW_BINARY) + dlen = 9; /* _10101010 */ + else + dlen = 3; /* _AA */ + + if (cu->fd.can_id & CAN_RTR_FLAG) { + maxsize += sizeof(" remote request"); + } else { + maxsize += len * dlen; + + if (len <= CAN_MAX_DLEN) { + if (cu->fd.can_id & CAN_ERR_FLAG) { + maxsize += sizeof(" ERRORFRAME"); + maxsize += (8 - len) * dlen; + } else if (view & CANLIB_VIEW_ASCII) { + maxsize += sizeof(" 'a.b.CDEF'"); + maxsize += (8 - len) * dlen; + } + } + } + + if (maxsize > size - 1) { + /* mark buffer overflow in output */ + memset(buf, '-', size - 1); + buf[size - 1] = 0; + return size; + } + + /* initialize space for CAN-ID and length information */ + memset(buf, ' ', 15); + if (cu->cc.can_id & CAN_ERR_FLAG) { put_eff_id(buf, cu->cc.can_id & (CAN_ERR_MASK | CAN_ERR_FLAG)); offset = 10; @@ -515,7 +581,7 @@ int sprint_long_canframe(char *buf, cu_t *cu, int view) offset += 5; if (view & CANLIB_VIEW_BINARY) { - dlen = 9; /* _10101010 */ + /* _10101010 - dlen = 9, see above */ if (view & CANLIB_VIEW_SWAP) { for (i = len - 1; i >= 0; i--) { buf[offset++] = (i == len - 1) ? ' ' : SWAP_DELIMITER; @@ -530,7 +596,7 @@ int sprint_long_canframe(char *buf, cu_t *cu, int view) } } } else { - dlen = 3; /* _AA */ + /* _AA - dlen = 3, see above */ if (view & CANLIB_VIEW_SWAP) { for (i = len - 1; i >= 0; i--) { if (i == len - 1) diff --git a/lib.h b/lib.h index 23514c7..1ab0324 100644 --- a/lib.h +++ b/lib.h @@ -178,7 +178,7 @@ int parse_canframe(char *cs, cu_t *cu); * - CAN FD frames do not have a RTR bit */ -int sprint_canframe(char *buf , cu_t *cu, int sep); +int snprintf_canframe(char *buf, size_t size, cu_t *cu, int sep); /* * Creates a CAN frame hexadecimal output in compact format. * The CAN data[] is separated by '.' when sep != 0. @@ -211,7 +211,7 @@ int sprint_canframe(char *buf , cu_t *cu, int sep); #define SWAP_DELIMITER '`' -int sprint_long_canframe(char *buf , cu_t *cu, int view); +int snprintf_long_canframe(char *buf, size_t size, cu_t *cu, int view); /* * Creates a CAN frame hexadecimal output in user readable format. * diff --git a/log2long.c b/log2long.c index 731d29a..301f201 100644 --- a/log2long.c +++ b/log2long.c @@ -94,8 +94,8 @@ int main(void) } /* with ASCII output */ - sprint_long_canframe(afrbuf, &cu, - (CANLIB_VIEW_INDENT_SFF | CANLIB_VIEW_ASCII)); + snprintf_long_canframe(afrbuf, sizeof(afrbuf), &cu, + (CANLIB_VIEW_INDENT_SFF | CANLIB_VIEW_ASCII)); printf("%s %s %s\n", timestamp, device, afrbuf); } From 8535b1d2176862add056d28b3f24d27d1be8bbc9 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 12 Mar 2024 19:38:04 +0100 Subject: [PATCH 26/27] log2asc: print error message if no valid CAN CC/FD frame is received Signed-off-by: Oliver Hartkopp --- log2asc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/log2asc.c b/log2asc.c index 81d69bc..02b27f2 100644 --- a/log2asc.c +++ b/log2asc.c @@ -312,8 +312,10 @@ int main(int argc, char **argv) mtu = parse_canframe(afrbuf, &cu); /* convert only CAN CC and CAN FD frames */ - if ((mtu != CAN_MTU) && (mtu != CANFD_MTU)) + if ((mtu != CAN_MTU) && (mtu != CANFD_MTU)) { + printf("no valid CAN CC/FD frame\n"); return 1; + } /* we don't support error message frames in CAN FD */ if ((mtu == CANFD_MTU) && (cu.cc.can_id & CAN_ERR_FLAG)) From dd16f2603b542f1f3ec5f8ce6b60dc78987c8ac5 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 12 Mar 2024 19:58:12 +0100 Subject: [PATCH 27/27] can-utils: make local functions static Signed-off-by: Oliver Hartkopp --- asc2log.c | 19 +++++++++++-------- canbusload.c | 6 +++--- cangw.c | 28 ++++++++++++++-------------- canlogserver.c | 9 ++++----- canplayer.c | 9 +++++---- log2asc.c | 8 +++++--- slcanpty.c | 7 ++++--- 7 files changed, 46 insertions(+), 40 deletions(-) diff --git a/asc2log.c b/asc2log.c index 5ffc1be..210e008 100644 --- a/asc2log.c +++ b/asc2log.c @@ -62,7 +62,7 @@ extern int optind, opterr, optopt; -void print_usage(char *prg) +static void print_usage(char *prg) { fprintf(stderr, "%s - convert ASC logfile to compact CAN frame logfile.\n", prg); fprintf(stderr, "Usage: %s\n", prg); @@ -71,7 +71,8 @@ void print_usage(char *prg) fprintf(stderr, "\t-O \t(default stdout)\n"); } -void prframe(FILE *file, struct timeval *tv, int dev, struct canfd_frame *cf, char *extra_info) +static void prframe(FILE *file, struct timeval *tv, int dev, + struct canfd_frame *cf, char *extra_info) { static char abuf[BUFLEN]; @@ -86,7 +87,7 @@ void prframe(FILE *file, struct timeval *tv, int dev, struct canfd_frame *cf, ch fprintf(file, "%s%s", abuf, extra_info); } -void get_can_id(struct canfd_frame *cf, char *idstring, int base) +static void get_can_id(struct canfd_frame *cf, char *idstring, int base) { if (idstring[strlen(idstring)-1] == 'x') { cf->can_id = CAN_EFF_FLAG; @@ -97,8 +98,8 @@ void get_can_id(struct canfd_frame *cf, char *idstring, int base) cf->can_id |= strtoul(idstring, NULL, base); } -void calc_tv(struct timeval *tv, struct timeval *read_tv, - struct timeval *date_tv, char timestamps, int dplace) +static void calc_tv(struct timeval *tv, struct timeval *read_tv, + struct timeval *date_tv, char timestamps, int dplace) { if (dplace == 4) /* shift values having only 4 decimal places */ read_tv->tv_usec *= 100; /* and need for 6 */ @@ -129,7 +130,8 @@ void calc_tv(struct timeval *tv, struct timeval *read_tv, } } -void eval_can(char* buf, struct timeval *date_tvp, char timestamps, char base, int dplace, FILE *outfile) +static void eval_can(char* buf, struct timeval *date_tvp, char timestamps, + char base, int dplace, FILE *outfile) { int interface; static struct timeval tv; /* current frame timestamp */ @@ -239,7 +241,8 @@ void eval_can(char* buf, struct timeval *date_tvp, char timestamps, char base, i } } -void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps, int dplace, FILE *outfile) +static void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps, + int dplace, FILE *outfile) { int interface; static struct timeval tv; /* current frame timestamp */ @@ -376,7 +379,7 @@ void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps, int dplace /* No support for really strange CANFD ErrorFrames format m( */ } -int get_date(struct timeval *tv, char *date) +static int get_date(struct timeval *tv, char *date) { struct tm tms; unsigned int msecs = 0; diff --git a/canbusload.c b/canbusload.c index 4409a4b..d2906ae 100644 --- a/canbusload.c +++ b/canbusload.c @@ -94,7 +94,7 @@ static unsigned char bargraph; static enum cfl_mode mode = CFL_WORSTCASE; static char *prg; -void print_usage(char *prg) +static void print_usage(char *prg) { fprintf(stderr, "%s - monitor CAN bus load.\n", prg); fprintf(stderr, "\nUsage: %s [options] +\n", prg); @@ -124,13 +124,13 @@ void print_usage(char *prg) fprintf(stderr, "\n"); } -void sigterm(int signo) +static void sigterm(int signo) { running = 0; signal_num = signo; } -void printstats(int signo) +static void printstats(int signo) { int i, j, percent; diff --git a/cangw.c b/cangw.c index f7a6678..f99a956 100644 --- a/cangw.c +++ b/cangw.c @@ -82,8 +82,8 @@ struct fdmodattr { #define NLMSG_TAIL(nmsg) \ ((struct rtattr *)(((char *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) -int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, - int alen) +static int addattr_l(struct nlmsghdr *n, int maxlen, int type, + const void *data, int alen) { int len = RTA_LENGTH(alen); struct rtattr *rta; @@ -101,7 +101,7 @@ int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, return 0; } -void printfilter(const void *data) +static void printfilter(const void *data) { struct can_filter *filter = (struct can_filter *)data; @@ -111,7 +111,7 @@ void printfilter(const void *data) printf("-f %03X:%X ", filter->can_id, filter->can_mask); } -void printmod(const char *type, const void *data) +static void printmod(const char *type, const void *data) { struct modattr mod; int i; @@ -137,7 +137,7 @@ void printmod(const char *type, const void *data) printf(" "); } -void printfdmod(const char *type, const void *data) +static void printfdmod(const char *type, const void *data) { struct fdmodattr mod; int i; @@ -166,14 +166,14 @@ void printfdmod(const char *type, const void *data) printf(" "); } -void print_cs_xor(struct cgw_csum_xor *cs_xor) +static void print_cs_xor(struct cgw_csum_xor *cs_xor) { printf("-x %d:%d:%d:%02X ", cs_xor->from_idx, cs_xor->to_idx, cs_xor->result_idx, cs_xor->init_xor_val); } -void print_cs_crc8_profile(struct cgw_csum_crc8 *cs_crc8) +static void print_cs_crc8_profile(struct cgw_csum_crc8 *cs_crc8) { int i; @@ -202,7 +202,7 @@ void print_cs_crc8_profile(struct cgw_csum_crc8 *cs_crc8) printf(" "); } -void print_cs_crc8(struct cgw_csum_crc8 *cs_crc8) +static void print_cs_crc8(struct cgw_csum_crc8 *cs_crc8) { int i; @@ -220,7 +220,7 @@ void print_cs_crc8(struct cgw_csum_crc8 *cs_crc8) print_cs_crc8_profile(cs_crc8); } -void print_usage(char *prg) +static void print_usage(char *prg) { fprintf(stderr, "%s - manage PF_CAN netlink gateway.\n", prg); fprintf(stderr, "\nUsage: %s [options]\n\n", prg); @@ -279,7 +279,7 @@ void print_usage(char *prg) fprintf(stderr, "\n"); } -int b64hex(char *asc, unsigned char *bin, int len) +static int b64hex(char *asc, unsigned char *bin, int len) { int i; @@ -290,7 +290,7 @@ int b64hex(char *asc, unsigned char *bin, int len) return 0; } -int parse_crc8_profile(char *optarg, struct cgw_csum_crc8 *crc8) +static int parse_crc8_profile(char *optarg, struct cgw_csum_crc8 *crc8) { int ret = 1; char *ptr; @@ -329,7 +329,7 @@ int parse_crc8_profile(char *optarg, struct cgw_csum_crc8 *crc8) return ret; } -int parse_mod(char *optarg, struct modattr *modmsg) +static int parse_mod(char *optarg, struct modattr *modmsg) { char *ptr, *nptr; char hexdata[(CAN_MAX_DLEN * 2) + 1] = {0}; @@ -397,7 +397,7 @@ int parse_mod(char *optarg, struct modattr *modmsg) return 0; /* ok */ } -int parse_fdmod(char *optarg, struct fdmodattr *modmsg) +static int parse_fdmod(char *optarg, struct fdmodattr *modmsg) { char *ptr, *nptr; char hexdata[(CANFD_MAX_DLEN * 2) + 1] = {0}; @@ -470,7 +470,7 @@ int parse_fdmod(char *optarg, struct fdmodattr *modmsg) return 0; /* ok */ } -int parse_rtlist(char *prgname, unsigned char *rxbuf, int len) +static int parse_rtlist(char *prgname, unsigned char *rxbuf, int len) { char ifname[IF_NAMESIZE]; /* interface name for if_indextoname() */ struct rtcanmsg *rtc; diff --git a/canlogserver.c b/canlogserver.c index 1921e23..4d9cba8 100644 --- a/canlogserver.c +++ b/canlogserver.c @@ -83,7 +83,7 @@ extern int optind, opterr, optopt; static volatile int running = 1; static volatile sig_atomic_t signal_num; -void print_usage(char *prg) +static void print_usage(char *prg) { fprintf(stderr, "%s - log CAN frames and serves them.\n", prg); fprintf(stderr, "\nUsage: %s [options] +\n", prg); @@ -107,7 +107,7 @@ void print_usage(char *prg) fprintf(stderr, "\n"); } -int idx2dindex(int ifidx, int socket) +static int idx2dindex(int ifidx, int socket) { int i; struct ifreq ifr; @@ -157,7 +157,7 @@ int idx2dindex(int ifidx, int socket) * This is a Signalhandler. When we get a signal, that a child * terminated, we wait for it, so the zombie will disappear. */ -void childdied(int i) +static void childdied(int i) { wait(NULL); } @@ -165,13 +165,12 @@ void childdied(int i) /* * This is a Signalhandler for a caught SIGTERM */ -void shutdown_gra(int i) +static void shutdown_gra(int i) { running = 0; signal_num = i; } - int main(int argc, char **argv) { struct sigaction signalaction; diff --git a/canplayer.c b/canplayer.c index dfd1919..eb9c569 100644 --- a/canplayer.c +++ b/canplayer.c @@ -89,7 +89,7 @@ const int canfx_on = 1; extern int optind, opterr, optopt; -void print_usage(char *prg) +static void print_usage(char *prg) { fprintf(stderr, "%s - replay a compact CAN frame logfile to CAN devices.\n", prg); fprintf(stderr, "\nUsage: %s [interface assignment]*\n\n", prg); @@ -172,7 +172,7 @@ static inline int frames_to_send(struct timeval *today, struct timeval *diff, st return timeval_compare(&cmp, today); } -int get_txidx(char *logif_name) +static int get_txidx(char *logif_name) { int i; @@ -189,7 +189,7 @@ int get_txidx(char *logif_name) return asgn[i].txifidx; /* return interface index */ } -char *get_txname(char *logif_name) +static char *get_txname(char *logif_name) { int i; @@ -206,7 +206,8 @@ char *get_txname(char *logif_name) return asgn[i].txif; /* return interface name */ } -int add_assignment(char *mode, int socket, char *txname, char *rxname, int verbose) +static int add_assignment(char *mode, int socket, char *txname, + char *rxname, int verbose) { struct ifreq ifr; int i; diff --git a/log2asc.c b/log2asc.c index 02b27f2..a0a325f 100644 --- a/log2asc.c +++ b/log2asc.c @@ -56,7 +56,7 @@ extern int optind, opterr, optopt; -void print_usage(char *prg) +static void print_usage(char *prg) { fprintf(stderr, "%s - convert compact CAN frame logfile to ASC logfile.\n", prg); fprintf(stderr, "Usage: %s [can-interfaces]\n", prg); @@ -69,7 +69,8 @@ void print_usage(char *prg) fprintf(stderr, " -r (suppress dlc for RTR frames - pre v8.5 tools)\n"); } -void can_asc(struct canfd_frame *cfd, int devno, int nortrdlc, char *extra_info, FILE *outfile) +static void can_asc(struct canfd_frame *cfd, int devno, int nortrdlc, + char *extra_info, FILE *outfile) { int i; char id[10]; @@ -116,7 +117,8 @@ void can_asc(struct canfd_frame *cfd, int devno, int nortrdlc, char *extra_info, } } -void canfd_asc(struct canfd_frame *cf, int devno, int mtu, char *extra_info, FILE *outfile) +static void canfd_asc(struct canfd_frame *cf, int devno, int mtu, + char *extra_info, FILE *outfile) { int i; char id[10]; diff --git a/slcanpty.c b/slcanpty.c index 393d67b..76699be 100644 --- a/slcanpty.c +++ b/slcanpty.c @@ -50,7 +50,8 @@ #define DEVICE_NAME_PTMX "/dev/ptmx" /* read data from pty, send CAN frames to CAN socket and answer commands */ -int pty2can(int pty, int socket, struct can_filter *fi, int *is_open, int *tstamp) +static int pty2can(int pty, int socket, struct can_filter *fi, + int *is_open, int *tstamp) { unsigned int nbytes; char cmd; @@ -313,7 +314,7 @@ rx_out: } /* read CAN frames from CAN interface and write it to the pty */ -int can2pty(int pty, int socket, int *tstamp) +static int can2pty(int pty, int socket, int *tstamp) { int nbytes; char cmd; @@ -365,7 +366,7 @@ int can2pty(int pty, int socket, int *tstamp) return 0; } -int check_select_stdin(void) +static int check_select_stdin(void) { fd_set rdfs; struct timeval timeout;