diff --git a/lib.c b/lib.c index 38a79ca..aed3734 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; } @@ -337,9 +381,23 @@ void sprint_long_canframe(char *buf , struct canfd_frame *cf, int view, int maxd /* The len value is sanitized by maxdlen (see above) */ if (maxdlen == CAN_MAX_DLEN) { - buf[offset + 1] = '['; - buf[offset + 2] = len + '0'; - buf[offset + 3] = ']'; + if (view & CANLIB_VIEW_LEN8_DLC) { + struct can_frame *ccf = (struct can_frame *)cf; + unsigned char dlc = ccf->len8_dlc; + + /* fall back to len if we don't have a valid DLC > 8 */ + if (!((len == CAN_MAX_DLEN) && (dlc > CAN_MAX_DLEN) && + (dlc <= CAN_MAX_RAW_DLC))) + dlc = len; + + buf[offset + 1] = '{'; + buf[offset + 2] = hex_asc_upper[dlc]; + buf[offset + 3] = '}'; + } else { + buf[offset + 1] = '['; + buf[offset + 2] = len + '0'; + buf[offset + 3] = ']'; + } /* standard CAN frames may have RTR enabled */ if (cf->can_id & CAN_RTR_FLAG) { diff --git a/lib.h b/lib.h index 7d82d80..e0a0e1c 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 @@ -178,6 +182,7 @@ void sprint_canframe(char *buf , struct canfd_frame *cf, int sep, int maxdlen); #define CANLIB_VIEW_SWAP 0x4 #define CANLIB_VIEW_ERROR 0x8 #define CANLIB_VIEW_INDENT_SFF 0x10 +#define CANLIB_VIEW_LEN8_DLC 0x20 #define SWAP_DELIMITER '`' @@ -187,14 +192,15 @@ 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 + * 12345678 [3] 11 22 33 -> extended CAN-Id = 0x12345678, len = 3, data * 12345678 [0] remote request -> extended CAN-Id = 0x12345678, RTR * 14B0DC51 [8] 4A 94 E8 2A EC 58 55 62 'J..*.XUb' -> (with ASCII output) + * 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, dlc = 3 + * 12345678 [03] 11 22 33 -> CAN FD with extended CAN-Id = 0x12345678, len = 3 * * 123 [3] 11 22 33 -> CANLIB_VIEW_INDENT_SFF == 0 * 123 [3] 11 22 33 -> CANLIB_VIEW_INDENT_SFF == set @@ -204,7 +210,7 @@ void sprint_long_canframe(char *buf , struct canfd_frame *cf, int view, int maxd * // CAN FD frame with eol to STDOUT * fprint_long_canframe(stdout, &frame, "\n", 0, CANFD_MAX_DLEN); * - * // CAN 2.0 frame without eol to STDERR + * // Classical CAN 2.0 frame without eol to STDERR * fprint_long_canframe(stderr, &frame, NULL, 0, CAN_MAX_DLEN); * */