From 04312e5a10df828b69752f9538e22fad7c04b722 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Tue, 27 Feb 2024 18:23:29 +0100 Subject: [PATCH] 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.