diff --git a/asc2log.c b/asc2log.c index 4ed8134..303803a 100644 --- a/asc2log.c +++ b/asc2log.c @@ -70,7 +70,7 @@ void print_usage(char *prg) fprintf(stderr, "\t-O \t(default stdout)\n"); } -void prframe(FILE *file, struct timeval *tv, int dev, struct can_frame *cf) { +void prframe(FILE *file, struct timeval *tv, int dev, struct canfd_frame *cf, unsigned int max_dlen) { fprintf(file, "(%ld.%06ld) ", tv->tv_sec, tv->tv_usec); @@ -79,11 +79,10 @@ void prframe(FILE *file, struct timeval *tv, int dev, struct can_frame *cf) { else fprintf(file, "canX "); - /* no CAN FD support so far */ - fprint_canframe(file, (struct canfd_frame *)cf, "\n", 0, CAN_MAX_DLEN); + fprint_canframe(file, cf, "\n", 0, max_dlen); } -void get_can_id(struct can_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; @@ -131,7 +130,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 can_frame cf; + struct canfd_frame cf; char rtr; int dlc = 0; int data[8]; @@ -170,15 +169,19 @@ void eval_can(char* buf, struct timeval *date_tvp, char timestamps, char base, i } if (found) { + + if (dlc > CAN_MAX_DLC) + return; + + cf.len = dlc; if (rtr == 'r') cf.can_id |= CAN_RTR_FLAG; - - cf.can_dlc = dlc & 0x0FU; - for (i=0; i + and probably some content we skip anyway. Don't trust the docs! */ + + /* 21.671796 CANFD 1 Tx 11 msgCanFdFr1 1 0 a 16 \ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 59 c0 \ + 100000 214 223040 80000000 46500250 460a0250 20011736 20010205 */ + + memset(&cf, 0, sizeof(cf)); + + if (sscanf(buf, "%ld.%ld %*s %d %*s %s %hhx %hhx %x %d ", + &read_tv.tv_sec, &read_tv.tv_usec, &interface, + tmp1, &brs, &esi, &dlc, &dlen) == 8) { + /* no symbolic name */ + } else if (sscanf(buf, "%ld.%ld %*s %d %*s %s %*s %hhx %hhx %x %d ", + &read_tv.tv_sec, &read_tv.tv_usec, &interface, + tmp1, &brs, &esi, &dlc, &dlen) == 8) { + /* with symbolic name */ + } else + return; /* no valid CANFD format pattern */ + + get_can_id(&cf, tmp1, 16); + + /* now search for the beginning of the data[] content */ + sprintf(tmp1, " %x %x %x %2d ", brs, esi, dlc, dlen); + + /* search for the pattern generated by real data */ + ptr = strcasestr(buf, tmp1); + if (ptr == NULL) + return; + + ptr += strlen(tmp1); /* hop to the start of hex data */ + + if (dlen > CANFD_MAX_DLEN) + return; + + /* don't trust ASCII content - sanitize data length */ + if (dlen != can_dlc2len(can_len2dlc(dlen))) + return; + + cf.len = dlen; + + for (i = 0; i < dlen; i++) { + ctmp = asc2nibble(ptr[0]); + if (ctmp > 0x0F) + return; + + cf.data[i] = (ctmp << 4); + + ctmp = asc2nibble(ptr[1]); + if (ctmp > 0x0F) + return; + + cf.data[i] |= ctmp; + + ptr += 3; /* start of next ASCII hex byte */ + } + + /* skip MessageDuration and MessageLength to get Flags value */ + if (sscanf(ptr, " %*x %*x %x ", &flags) != 1) + return; + + /* relevant flags in Flags field */ +#define ASC_F_RTR 0x00000010 +#define ASC_F_FDF 0x00001000 +#define ASC_F_BRS 0x00002000 +#define ASC_F_ESI 0x00004000 + + if (flags & ASC_F_FDF) { + dlen = CANFD_MAX_DLEN; + 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 + but the DLC value is valid in RTR cases */ + cf.len = dlc; + } + } + + calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace); + prframe(outfile, &tv, interface, &cf, dlen); + fflush(outfile); + return; + + /* No support for really strange CANFD ErrorFrames format m( */ } int get_date(struct timeval *tv, char *date) { @@ -368,7 +473,7 @@ int main(int argc, char **argv) /* check classic CAN format or the CANFD tag which can take both types */ if (sscanf(buf, "%ld.%ld %s ", &tmp_tv.tv_sec, &tmp_tv.tv_usec, tmp1) == 3){ if (!strncmp(tmp1, "CANFD", 5)) - eval_canfd(buf, &date_tv, timestamps, base, dplace, outfile); + eval_canfd(buf, &date_tv, timestamps, dplace, outfile); else eval_can(buf, &date_tv, timestamps, base, dplace, outfile); }