From 2522ec127b480ce46016c81631c5e77e468db7ed Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Thu, 22 Feb 2024 22:26:07 +0100 Subject: [PATCH] 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); }