diff --git a/cangen.c b/cangen.c index d80cf56..f565be5 100644 --- a/cangen.c +++ b/cangen.c @@ -413,8 +413,14 @@ int main(int argc, char **argv) frame.len = can_dlc2len(random() & 0xF); else { frame.len = random() & 0xF; - if (frame.len & 8) + + /* generate Classic CAN len8 DLCs */ + if (frame.len > CAN_MAX_DLEN) { + struct can_frame *ccf = (struct can_frame *)&frame; + + ccf->len8_dlc = frame.len; frame.len = 8; /* for about 50% of the frames */ + } } } diff --git a/cansend.c b/cansend.c index 76aacfc..3708d3e 100644 --- a/cansend.c +++ b/cansend.c @@ -61,8 +61,10 @@ void print_usage(char *prg) fprintf(stderr, "%s - send CAN-frames via CAN_RAW sockets.\n", prg); fprintf(stderr, "\nUsage: %s .\n", prg); fprintf(stderr, "\n:\n"); - fprintf(stderr, " #{data} for 'classic' CAN 2.0 data frames\n"); - fprintf(stderr, " #R{len} for 'classic' CAN 2.0 data frames\n"); + fprintf(stderr, " #{data} for Classical CAN 2.0 data frames\n"); + fprintf(stderr, " #R{len} for Classical CAN 2.0 data frames\n"); + fprintf(stderr, " #{data}_{dlc} for Classical CAN 2.0 data frames\n"); + fprintf(stderr, " #R{len}_{dlc} for Classical CAN 2.0 data frames\n"); fprintf(stderr, " ##{data} for CAN FD frames\n\n"); fprintf(stderr, ":\n" " 3 (SFF) or 8 (EFF) hex chars\n"); @@ -70,11 +72,13 @@ void print_usage(char *prg) " 0..8 (0..64 CAN FD) ASCII hex-values (optionally separated by '.')\n"); fprintf(stderr, "{len}:\n" " an optional 0..8 value as RTR frames can contain a valid dlc field\n"); + fprintf(stderr, "_{dlc}:\n" + " an optional 9..F data length code value when payload length is 8\n"); fprintf(stderr, ":\n" " a single ASCII Hex value (0 .. F) which defines canfd_frame.flags\n\n"); fprintf(stderr, "Examples:\n"); fprintf(stderr, " 5A1#11.2233.44556677.88 / 123#DEADBEEF / 5AA# / 123##1 / 213##311223344 /\n" - " 1F334455#1122334455667788 / 123#R / 00000123#R3\n\n"); + " 1F334455#1122334455667788_B / 123#R / 00000123#R3 / 333#R8_E\n\n"); } diff --git a/lib.c b/lib.c index 38a79ca..0642071 100644 --- a/lib.c +++ b/lib.c @@ -53,6 +53,7 @@ #include "lib.h" #define CANID_DELIM '#' +#define CC_DLC_DELIM '_' #define DATA_SEPERATOR '.' const char hex_asc_upper[] = "0123456789ABCDEF"; @@ -195,9 +196,19 @@ int parse_canframe(char *cs, struct canfd_frame *cf) { cf->can_id |= CAN_RTR_FLAG; /* check for optional DLC value for CAN 2.0B frames */ - if(cs[++idx] && (tmp = asc2nibble(cs[idx])) <= CAN_MAX_DLC) + if(cs[++idx] && (tmp = asc2nibble(cs[idx++])) <= CAN_MAX_DLEN) { cf->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; + } + } + } return ret; } @@ -232,6 +243,17 @@ int parse_canframe(char *cs, struct canfd_frame *cf) { } cf->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; + } + } + return ret; } @@ -270,9 +292,20 @@ void sprint_canframe(char *buf , struct canfd_frame *cf, int sep, int maxdlen) { if (maxdlen == CAN_MAX_DLEN && 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_DLC) + if (cf->len && cf->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) { + struct can_frame *ccf = (struct can_frame *)cf; + + if ((ccf->len8_dlc > CAN_MAX_DLEN) && (ccf->len8_dlc <= CAN_MAX_RAW_DLC)) { + buf[offset++] = CC_DLC_DELIM; + buf[offset++] = hex_asc_upper_lo(ccf->len8_dlc); + } + } + } + buf[offset] = 0; return; } @@ -292,6 +325,17 @@ void sprint_canframe(char *buf , struct canfd_frame *cf, int sep, int maxdlen) { buf[offset++] = '.'; } + /* check for extra DLC when having a Classic CAN with 8 bytes payload */ + if ((maxdlen == CAN_MAX_DLEN) && (len == CAN_MAX_DLEN)) { + struct can_frame *ccf = (struct can_frame *)cf; + unsigned char dlc = ccf->len8_dlc; + + if ((dlc > CAN_MAX_DLEN) && (dlc <= CAN_MAX_RAW_DLC)) { + buf[offset++] = CC_DLC_DELIM; + buf[offset++] = hex_asc_upper_lo(dlc); + } + } + buf[offset] = 0; } diff --git a/lib.h b/lib.h index 7d82d80..94760d4 100644 --- a/lib.h +++ b/lib.h @@ -99,10 +99,11 @@ int parse_canframe(char *cs, struct canfd_frame *cf); /* * Transfers a valid ASCII string describing a CAN frame into struct canfd_frame. * - * CAN 2.0 frames - * - string layout #{R{len}|data} + * CAN 2.0 frames (aka Classical CAN) + * - 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 + * - {_len8_dlc} can take hex values from '_9' to '_F' when len is CAN_MAX_DLEN * - return value on successful parsing: CAN_MTU * * CAN FD frames @@ -124,10 +125,12 @@ int parse_canframe(char *cs, struct canfd_frame *cf); * 123#R -> standard CAN-Id = 0x123, len = 0, RTR-frame * 123#R0 -> standard CAN-Id = 0x123, len = 0, RTR-frame * 123#R7 -> standard CAN-Id = 0x123, len = 7, RTR-frame + * 123#R8_9 -> standard CAN-Id = 0x123, len = 8, dlc = 9, RTR-frame * 7A1#r -> standard CAN-Id = 0x7A1, len = 0, RTR-frame * * 123#00 -> standard CAN-Id = 0x123, len = 1, data[0] = 0x00 * 123#1122334455667788 -> standard CAN-Id = 0x123, len = 8 + * 123#1122334455667788_E -> standard CAN-Id = 0x123, len = 8, dlc = 14 * 123#11.22.33.44.55.66.77.88 -> standard CAN-Id = 0x123, len = 8 * 123#11.2233.44556677.88 -> standard CAN-Id = 0x123, len = 8 * 32345678#112233 -> error frame with CAN_ERR_FLAG (0x2000000) set @@ -155,10 +158,11 @@ void sprint_canframe(char *buf , struct canfd_frame *cf, int sep, int maxdlen); * 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 + * maxdlen = 8 -> CAN2.0 frame (aka Classical CAN) * maxdlen = 64 -> CAN FD frame * * 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 * 12345678#R -> extended CAN-Id = 0x12345678, RTR, len = 0 * 12345678#R5 -> extended CAN-Id = 0x12345678, RTR, len = 5 * 123#11.22.33.44.55.66.77.88 -> standard CAN-Id = 0x123, dlc = 8, sep = 1 @@ -187,7 +191,7 @@ void sprint_long_canframe(char *buf , struct canfd_frame *cf, int view, int maxd * 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 + * maxdlen = 8 -> CAN2.0 frame (aka Classical CAN) * maxdlen = 64 -> CAN FD frame * * 12345678 [3] 11 22 33 -> extended CAN-Id = 0x12345678, dlc = 3, data