asc2log: support CANFD tagged asc file content
Handles CANFD asc files with classic CAN and CAN FD frames. Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>pull/203/head
parent
3c8197e4d1
commit
df0b25c17e
129
asc2log.c
129
asc2log.c
|
|
@ -70,7 +70,7 @@ void print_usage(char *prg)
|
|||
fprintf(stderr, "\t-O <outfile>\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;
|
||||
else
|
||||
for (i = 0; i < dlc; i++)
|
||||
cf.data[i] = data[i] & 0xFFU;
|
||||
|
||||
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
||||
prframe(outfile, &tv, interface, &cf);
|
||||
prframe(outfile, &tv, interface, &cf, CAN_MAX_DLEN);
|
||||
fflush(outfile);
|
||||
return;
|
||||
}
|
||||
|
|
@ -193,16 +196,118 @@ void eval_can(char* buf, struct timeval *date_tvp, char timestamps, char base, i
|
|||
memset(&cf, 0, sizeof(cf));
|
||||
/* do not know more than 'Error' */
|
||||
cf.can_id = (CAN_ERR_FLAG | CAN_ERR_BUSERROR);
|
||||
cf.can_dlc = CAN_ERR_DLC;
|
||||
cf.len = CAN_ERR_DLC;
|
||||
|
||||
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
||||
prframe(outfile, &tv, interface, &cf);
|
||||
prframe(outfile, &tv, interface, &cf, CAN_MAX_DLEN);
|
||||
fflush(outfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps, char base, int dplace, FILE *outfile) {
|
||||
void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps, int dplace, FILE *outfile) {
|
||||
|
||||
int interface;
|
||||
static struct timeval tv; /* current frame timestamp */
|
||||
static struct timeval read_tv; /* frame timestamp from ASC file */
|
||||
struct canfd_frame cf;
|
||||
unsigned char brs, esi, ctmp;
|
||||
unsigned int flags;
|
||||
int dlc, dlen = 0;
|
||||
char tmp1[BUFLEN];
|
||||
char *ptr;
|
||||
int i;
|
||||
|
||||
/* The CANFD format is mainly in hex representation but <DataLength>
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue