diff --git a/candump.c b/candump.c index d1bc975..d70a8b1 100644 --- a/candump.c +++ b/candump.c @@ -306,6 +306,11 @@ int main(int argc, char **argv) struct sockaddr_can addr = { .can_family = AF_CAN, }; + struct can_raw_vcid_options vcid_opts = { + .flags = CAN_RAW_XL_VCID_RX_FILTER, + .rx_vcid = 0, + .rx_vcid_mask = 0, + }; char ctrlmsg[CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(3 * sizeof(struct timespec)) + CMSG_SPACE(sizeof(__u32))]; @@ -601,6 +606,9 @@ int main(int argc, char **argv) /* try to switch the socket into CAN XL mode */ setsockopt(obj->s, SOL_CAN_RAW, CAN_RAW_XL_FRAMES, &canfx_on, sizeof(canfx_on)); + /* try to enable the CAN XL VCID pass through mode */ + setsockopt(obj->s, SOL_CAN_RAW, CAN_RAW_XL_VCID_OPTS, &vcid_opts, sizeof(vcid_opts)); + if (rcvbuf_size) { int curr_rcvbuf_size; socklen_t curr_rcvbuf_size_len = sizeof(curr_rcvbuf_size); diff --git a/canplayer.c b/canplayer.c index cefc78d..4987428 100644 --- a/canplayer.c +++ b/canplayer.c @@ -71,7 +71,7 @@ struct assignment { char rxif[IFNAMSIZ]; }; static struct assignment asgn[CHANNELS]; -const int canfd_on = 1; +const int canfx_on = 1; extern int optind, opterr, optopt; @@ -239,9 +239,12 @@ int add_assignment(char *mode, int socket, char *txname, char *rxname, int verbo int main(int argc, char **argv) { - static char buf[BUFSZ], device[BUFSZ], ascframe[BUFSZ]; + static char buf[BUFSZ], device[BUFSZ], ascframe[10000]; struct sockaddr_can addr; - static struct canfd_frame frame; + struct can_raw_vcid_options vcid_opts = { + .flags = CAN_RAW_XL_VCID_TX_PASS, + }; + static cu_t cu; static struct timeval today_tv, log_tv, last_log_tv, diff_tv; struct timespec sleep_ts; int s; /* CAN_RAW socket */ @@ -360,7 +363,13 @@ int main(int argc, char **argv) setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0); /* try to switch the socket into CAN FD mode */ - setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &canfd_on, sizeof(canfd_on)); + setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &canfx_on, sizeof(canfx_on)); + + /* try to switch the socket into CAN XL mode */ + setsockopt(s, SOL_CAN_RAW, CAN_RAW_XL_FRAMES, &canfx_on, sizeof(canfx_on)); + + /* try to enable the CAN XL VCID pass through mode */ + setsockopt(s, SOL_CAN_RAW, CAN_RAW_XL_VCID_OPTS, &vcid_opts, sizeof(vcid_opts)); if (loopback_disable) { int loopback = 0; @@ -470,26 +479,28 @@ int main(int argc, char **argv) } else if (txidx > 0) { /* only send to valid CAN devices */ - txmtu = parse_canframe(ascframe, &frame); /* dual-use frame */ + txmtu = parse_canframe(ascframe, &cu); /* dual-use frame */ if (!txmtu) { fprintf(stderr, "wrong CAN frame format: '%s'!", ascframe); return 1; } + /* CAN XL frames need real frame length for sending */ + if (txmtu == CANXL_MTU) + txmtu = CANXL_HDR_SIZE + cu.xl.len; + addr.can_family = AF_CAN; addr.can_ifindex = txidx; /* send via this interface */ - if (sendto(s, &frame, txmtu, 0, (struct sockaddr *)&addr, sizeof(addr)) != txmtu) { + if (sendto(s, &cu, txmtu, 0, (struct sockaddr *)&addr, sizeof(addr)) != txmtu) { perror("sendto"); return 1; } if (verbose) { - static char abuf[10000]; /* ASCII buf FIXME - use calculated value */ - printf("%s (%s) ", get_txname(device), device); - sprint_long_canframe(abuf, (cu_t *)&frame, CANLIB_VIEW_INDENT_SFF); - printf("%s\n", abuf); + sprint_long_canframe(ascframe, &cu, CANLIB_VIEW_INDENT_SFF); + printf("%s\n", ascframe); } if (count && (--count == 0)) diff --git a/cansend.c b/cansend.c index c2eb30c..033692f 100644 --- a/cansend.c +++ b/cansend.c @@ -92,9 +92,12 @@ int main(int argc, char **argv) int s; /* can raw socket */ int required_mtu; int mtu; - int enable_canfd = 1; + int enable_canfx = 1; struct sockaddr_can addr; - struct canfd_frame frame; + struct can_raw_vcid_options vcid_opts = { + .flags = CAN_RAW_XL_VCID_TX_PASS, + }; + static cu_t cu; struct ifreq ifr; /* check command line options */ @@ -104,7 +107,7 @@ int main(int argc, char **argv) } /* parse CAN frame */ - required_mtu = parse_canframe(argv[2], &frame); + required_mtu = parse_canframe(argv[2], &cu); if (!required_mtu) { fprintf(stderr, "\nWrong CAN-frame format!\n\n"); print_usage(argv[0]); @@ -137,22 +140,39 @@ int main(int argc, char **argv) } mtu = ifr.ifr_mtu; - if (mtu != CANFD_MTU && mtu != CANXL_MTU) { - printf("CAN interface is only Classical CAN capable - sorry.\n"); - return 1; + if (mtu == CANFD_MTU) { + /* interface is ok - try to switch the socket into CAN FD mode */ + if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, + &enable_canfx, sizeof(enable_canfx))){ + printf("error when enabling CAN FD support\n"); + return 1; + } } - /* interface is ok - try to switch the socket into CAN FD mode */ - if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, - &enable_canfd, sizeof(enable_canfd))){ - printf("error when enabling CAN FD support\n"); - return 1; + if (mtu >= CANXL_MIN_MTU) { + /* interface is ok - try to switch the socket into CAN XL mode */ + if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_XL_FRAMES, + &enable_canfx, sizeof(enable_canfx))){ + printf("error when enabling CAN XL support\n"); + return 1; + } + /* try to enable the CAN XL VCID pass through mode */ + if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_XL_VCID_OPTS, + &vcid_opts, sizeof(vcid_opts))) { + printf("error when enabling CAN XL VCID pass through\n"); + return 1; + } } - - /* ensure discrete CAN FD length values 0..8, 12, 16, 20, 24, 32, 64 */ - frame.len = can_fd_dlc2len(can_fd_len2dlc(frame.len)); } + /* ensure discrete CAN FD length values 0..8, 12, 16, 20, 24, 32, 64 */ + if (required_mtu == CANFD_MTU) + cu.fd.len = can_fd_dlc2len(can_fd_len2dlc(cu.fd.len)); + + /* CAN XL frames need real frame length for sending */ + if (required_mtu == CANXL_MTU) + required_mtu = CANXL_HDR_SIZE + cu.xl.len; + /* * disable default receive filter on this RAW socket This is * obsolete as we do not read from the socket at all, but for @@ -167,7 +187,7 @@ int main(int argc, char **argv) } /* send frame */ - if (write(s, &frame, required_mtu) != required_mtu) { + if (write(s, &cu, required_mtu) != required_mtu) { perror("write"); return 1; } diff --git a/lib.c b/lib.c index fec71ac..f80a70b 100644 --- a/lib.c +++ b/lib.c @@ -55,6 +55,7 @@ #define CANID_DELIM '#' #define CC_DLC_DELIM '_' +#define XL_HDR_DELIM ':' #define DATA_SEPERATOR '.' const char hex_asc_upper[] = "0123456789ABCDEF"; @@ -153,78 +154,128 @@ int hexstring2data(char *arg, unsigned char *data, int maxdlen) return 0; } -int parse_canframe(char *cs, struct canfd_frame *cf) +int parse_canframe(char *cs, cu_t *cu) { /* documentation see lib.h */ int i, idx, dlen, len; int maxdlen = CAN_MAX_DLEN; - int ret = CAN_MTU; + int mtu = CAN_MTU; + __u8 *data = cu->fd.data; /* fill CAN CC/FD data by default */ canid_t tmp; len = strlen(cs); //printf("'%s' len %d\n", cs, len); - memset(cf, 0, sizeof(*cf)); /* init CAN FD frame, e.g. LEN = 0 */ + memset(cu, 0, sizeof(*cu)); /* init CAN CC/FD/XL frame, e.g. LEN = 0 */ if (len < 4) return 0; - if (cs[3] == CANID_DELIM) { /* 3 digits */ + if (cs[3] == CANID_DELIM) { /* 3 digits SFF */ idx = 4; for (i = 0; i < 3; i++) { if ((tmp = asc2nibble(cs[i])) > 0x0F) return 0; - cf->can_id |= (tmp << (2 - i) * 4); + cu->cc.can_id |= (tmp << (2 - i) * 4); } - } else if (cs[8] == CANID_DELIM) { /* 8 digits */ + } else if (cs[5] == CANID_DELIM) { /* 5 digits CAN XL VCID/PRIO*/ + + idx = 6; + for (i = 0; i < 5; i++) { + if ((tmp = asc2nibble(cs[i])) > 0x0F) + return 0; + cu->xl.prio |= (tmp << (4 - i) * 4); + } + + /* the VCID starts at bit position 16 */ + tmp = (cu->xl.prio << 4) & CANXL_VCID_MASK; + cu->xl.prio &= CANXL_PRIO_MASK; + cu->xl.prio |= tmp; + + } else if (cs[8] == CANID_DELIM) { /* 8 digits EFF */ idx = 9; for (i = 0; i < 8; i++) { if ((tmp = asc2nibble(cs[i])) > 0x0F) return 0; - cf->can_id |= (tmp << (7 - i) * 4); + cu->cc.can_id |= (tmp << (7 - i) * 4); } - if (!(cf->can_id & CAN_ERR_FLAG)) /* 8 digits but no errorframe? */ - cf->can_id |= CAN_EFF_FLAG; /* then it is an extended frame */ + if (!(cu->cc.can_id & CAN_ERR_FLAG)) /* 8 digits but no errorframe? */ + cu->cc.can_id |= CAN_EFF_FLAG; /* then it is an extended frame */ } else return 0; if ((cs[idx] == 'R') || (cs[idx] == 'r')) { /* RTR frame */ - cf->can_id |= CAN_RTR_FLAG; + cu->cc.can_id |= CAN_RTR_FLAG; /* check for optional DLC value for CAN 2.0B frames */ if (cs[++idx] && (tmp = asc2nibble(cs[idx++])) <= CAN_MAX_DLEN) { - cf->len = tmp; + cu->cc.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; - } + if ((tmp > CAN_MAX_DLEN) && (tmp <= CAN_MAX_RAW_DLC)) + cu->cc.len8_dlc = tmp; } } - return ret; + return mtu; } if (cs[idx] == CANID_DELIM) { /* CAN FD frame escape char '##' */ maxdlen = CANFD_MAX_DLEN; - ret = CANFD_MTU; + mtu = CANFD_MTU; /* CAN FD frame ##* */ if ((tmp = asc2nibble(cs[idx + 1])) > 0x0F) return 0; - cf->flags = tmp; - cf->flags |= CANFD_FDF; /* dual-use */ + cu->fd.flags = tmp; + cu->fd.flags |= CANFD_FDF; /* dual-use */ idx += 2; + + } else if (cs[idx + 14] == CANID_DELIM) { /* CAN XL frame '#80:00:11223344#' */ + + maxdlen = CANXL_MAX_DLEN; + mtu = CANXL_MTU; + data = cu->xl.data; /* fill CAN XL data */ + + if ((cs[idx + 2] != XL_HDR_DELIM) || (cs[idx + 5] != XL_HDR_DELIM)) + return 0; + + if ((tmp = asc2nibble(cs[idx++])) > 0x0F) + return 0; + cu->xl.flags = (tmp << 4); + if ((tmp = asc2nibble(cs[idx++])) > 0x0F) + return 0; + cu->xl.flags |= tmp; + + /* force CAN XL flag if it was missing in the ASCII string */ + cu->xl.flags |= CANXL_XLF; + + idx++; /* skip XL_HDR_DELIM */ + + if ((tmp = asc2nibble(cs[idx++])) > 0x0F) + return 0; + cu->xl.sdt = (tmp << 4); + if ((tmp = asc2nibble(cs[idx++])) > 0x0F) + return 0; + cu->xl.sdt |= tmp; + + idx++; /* skip XL_HDR_DELIM */ + + for (i = 0; i < 8; i++) { + if ((tmp = asc2nibble(cs[idx++])) > 0x0F) + return 0; + cu->xl.af |= (tmp << (7 - i) * 4); + } + + idx++; /* skip CANID_DELIM */ } for (i = 0, dlen = 0; i < maxdlen; i++) { @@ -236,26 +287,27 @@ int parse_canframe(char *cs, struct canfd_frame *cf) if ((tmp = asc2nibble(cs[idx++])) > 0x0F) return 0; - cf->data[i] = (tmp << 4); + data[i] = (tmp << 4); if ((tmp = asc2nibble(cs[idx++])) > 0x0F) return 0; - cf->data[i] |= tmp; + data[i] |= tmp; dlen++; } - cf->len = dlen; + + if (mtu == CANXL_MTU) + cu->xl.len = dlen; + else + cu->fd.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; - } + if ((dlc > CAN_MAX_DLEN) && (dlc <= CAN_MAX_RAW_DLC)) + cu->cc.len8_dlc = dlc; } - return ret; + return mtu; } int sprint_canframe(char *buf, cu_t *cu, int sep) diff --git a/lib.h b/lib.h index 67902fc..3ddf1e8 100644 --- a/lib.h +++ b/lib.h @@ -111,8 +111,7 @@ int hexstring2data(char *arg, unsigned char *data, int maxdlen); * */ -struct canfd_frame; -int parse_canframe(char *cs, struct canfd_frame *cf); +int parse_canframe(char *cs, cu_t *cu); /* * Transfers a valid ASCII string describing a CAN frame into struct canfd_frame. * diff --git a/log2asc.c b/log2asc.c index 0640f3c..87279cd 100644 --- a/log2asc.c +++ b/log2asc.c @@ -183,9 +183,9 @@ void canfd_asc(struct canfd_frame *cf, int devno, int mtu, char *extra_info, FIL int main(int argc, char **argv) { - static char buf[BUFSZ], device[BUFSZ], ascframe[BUFSZ], extra_info[BUFSZ]; + static char buf[BUFSZ], device[BUFSZ], ascframe[10000], extra_info[BUFSZ]; - struct canfd_frame cf; + static cu_t cu; static struct timeval tv, start_tv; FILE *infile = stdin; FILE *outfile = stdout; @@ -286,20 +286,23 @@ int main(int argc, char **argv) (crlf)?"\r\n":"\n"); } - for (i=0, devno=0; i