isotp: added support for separate extended address in rx path
As requested by Laurent Vaudoit the extended address can be different in the tx and he rx path: (..) how can i have a segmented transfer like this: 0x6a7 0x55 0x10 0x08 ........ 0x687 0xAA 0x30 0x00 0x00 0x6a7 0x55 0x21 ..... The connection i need is between two ECU, using IDs 0x6a7/687 and one has adress extension 0x55, the other 0xAA (this adressing method is used on some FIAT ECUs for example). http://marc.info/?l=linux-can&m=140354647413513&w=2 Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>pull/1/head
parent
c517af5a0b
commit
4ffb7fe5c7
|
|
@ -82,6 +82,9 @@ struct can_isotp_options {
|
||||||
|
|
||||||
__u8 rxpad_content; /* set content of padding byte (rx) */
|
__u8 rxpad_content; /* set content of padding byte (rx) */
|
||||||
/* __u8 value : content on rx path */
|
/* __u8 value : content on rx path */
|
||||||
|
|
||||||
|
__u8 rx_ext_address; /* set address for extended addressing */
|
||||||
|
/* __u8 value : extended address (rx) */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct can_isotp_fc_options {
|
struct can_isotp_fc_options {
|
||||||
|
|
@ -112,6 +115,7 @@ struct can_isotp_fc_options {
|
||||||
#define CAN_ISOTP_HALF_DUPLEX 0x040 /* half duplex error state handling */
|
#define CAN_ISOTP_HALF_DUPLEX 0x040 /* half duplex error state handling */
|
||||||
#define CAN_ISOTP_FORCE_TXSTMIN 0x080 /* ignore stmin from received FC */
|
#define CAN_ISOTP_FORCE_TXSTMIN 0x080 /* ignore stmin from received FC */
|
||||||
#define CAN_ISOTP_FORCE_RXSTMIN 0x100 /* ignore CFs depending on rx stmin */
|
#define CAN_ISOTP_FORCE_RXSTMIN 0x100 /* ignore CFs depending on rx stmin */
|
||||||
|
#define CAN_ISOTP_RX_EXT_ADDR 0x200 /* different rx extended addressing */
|
||||||
|
|
||||||
|
|
||||||
/* default values */
|
/* default values */
|
||||||
|
|
|
||||||
23
isotpdump.c
23
isotpdump.c
|
|
@ -67,6 +67,7 @@ void print_usage(char *prg)
|
||||||
fprintf(stderr, "Options: -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
|
fprintf(stderr, "Options: -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
|
||||||
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
|
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
|
||||||
fprintf(stderr, " -x <addr> (extended addressing mode. Use 'any' for all addresses)\n");
|
fprintf(stderr, " -x <addr> (extended addressing mode. Use 'any' for all addresses)\n");
|
||||||
|
fprintf(stderr, " -X <addr> (extended addressing mode (rx addr). Use 'any' for all)\n");
|
||||||
fprintf(stderr, " -c (color mode)\n");
|
fprintf(stderr, " -c (color mode)\n");
|
||||||
fprintf(stderr, " -a (print data also in ASCII-chars)\n");
|
fprintf(stderr, " -a (print data also in ASCII-chars)\n");
|
||||||
fprintf(stderr, " -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n");
|
fprintf(stderr, " -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n");
|
||||||
|
|
@ -86,6 +87,9 @@ int main(int argc, char **argv)
|
||||||
int ext = 0;
|
int ext = 0;
|
||||||
int extaddr = 0;
|
int extaddr = 0;
|
||||||
int extany = 0;
|
int extany = 0;
|
||||||
|
int rx_ext = 0;
|
||||||
|
int rx_extaddr = 0;
|
||||||
|
int rx_extany = 0;
|
||||||
int asc = 0;
|
int asc = 0;
|
||||||
int color = 0;
|
int color = 0;
|
||||||
int timestamp = 0;
|
int timestamp = 0;
|
||||||
|
|
@ -99,7 +103,7 @@ int main(int argc, char **argv)
|
||||||
last_tv.tv_sec = 0;
|
last_tv.tv_sec = 0;
|
||||||
last_tv.tv_usec = 0;
|
last_tv.tv_usec = 0;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "s:d:ax:ct:?")) != -1) {
|
while ((opt = getopt(argc, argv, "s:d:ax:X:ct:?")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 's':
|
case 's':
|
||||||
src = strtoul(optarg, (char **)NULL, 16);
|
src = strtoul(optarg, (char **)NULL, 16);
|
||||||
|
|
@ -127,7 +131,14 @@ int main(int argc, char **argv)
|
||||||
extany = 1;
|
extany = 1;
|
||||||
else
|
else
|
||||||
extaddr = strtoul(optarg, (char **)NULL, 16) & 0xFF;
|
extaddr = strtoul(optarg, (char **)NULL, 16) & 0xFF;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'X':
|
||||||
|
rx_ext = 1;
|
||||||
|
if (!strncmp(optarg, "any", 3))
|
||||||
|
rx_extany = 1;
|
||||||
|
else
|
||||||
|
rx_extaddr = strtoul(optarg, (char **)NULL, 16) & 0xFF;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
|
|
@ -153,6 +164,11 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rx_ext && !ext) {
|
||||||
|
print_usage(basename(argv[0]));
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
if ((argc - optind) != 1 || src == NO_CAN_ID || dst == NO_CAN_ID) {
|
if ((argc - optind) != 1 || src == NO_CAN_ID || dst == NO_CAN_ID) {
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|
@ -204,7 +220,10 @@ int main(int argc, char **argv)
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (ext && !extany && extaddr != frame.data[0])
|
if (frame.can_id == src && ext && !extany && extaddr != frame.data[0])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (frame.can_id == dst && rx_ext && !rx_extany && rx_extaddr != frame.data[0])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (color)
|
if (color)
|
||||||
|
|
|
||||||
13
isotprecv.c
13
isotprecv.c
|
|
@ -64,6 +64,7 @@ void print_usage(char *prg)
|
||||||
fprintf(stderr, "Options: -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
|
fprintf(stderr, "Options: -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
|
||||||
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
|
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
|
||||||
fprintf(stderr, " -x <addr> (extended addressing mode.)\n");
|
fprintf(stderr, " -x <addr> (extended addressing mode.)\n");
|
||||||
|
fprintf(stderr, " -X <addr> (extended addressing mode (rx addr).)\n");
|
||||||
fprintf(stderr, " -p <byte> (set and enable padding byte)\n");
|
fprintf(stderr, " -p <byte> (set and enable padding byte)\n");
|
||||||
fprintf(stderr, " -P <mode> (check padding in SF/CF. (l)ength (c)ontent (a)ll)\n");
|
fprintf(stderr, " -P <mode> (check padding in SF/CF. (l)ength (c)ontent (a)ll)\n");
|
||||||
fprintf(stderr, " -b <bs> (blocksize. 0 = off)\n");
|
fprintf(stderr, " -b <bs> (blocksize. 0 = off)\n");
|
||||||
|
|
@ -93,7 +94,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
addr.can_addr.tp.tx_id = addr.can_addr.tp.rx_id = NO_CAN_ID;
|
addr.can_addr.tp.tx_id = addr.can_addr.tp.rx_id = NO_CAN_ID;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "s:d:x:p:P:b:m:w:f:l?")) != -1) {
|
while ((opt = getopt(argc, argv, "s:d:x:X:p:P:b:m:w:f:l?")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 's':
|
case 's':
|
||||||
addr.can_addr.tp.tx_id = strtoul(optarg, (char **)NULL, 16);
|
addr.can_addr.tp.tx_id = strtoul(optarg, (char **)NULL, 16);
|
||||||
|
|
@ -112,6 +113,11 @@ int main(int argc, char **argv)
|
||||||
opts.ext_address = strtoul(optarg, (char **)NULL, 16) & 0xFF;
|
opts.ext_address = strtoul(optarg, (char **)NULL, 16) & 0xFF;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'X':
|
||||||
|
opts.flags |= CAN_ISOTP_RX_EXT_ADDR;
|
||||||
|
opts.rx_ext_address = strtoul(optarg, (char **)NULL, 16) & 0xFF;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
opts.flags |= CAN_ISOTP_RX_PADDING;
|
opts.flags |= CAN_ISOTP_RX_PADDING;
|
||||||
opts.rxpad_content = strtoul(optarg, (char **)NULL, 16) & 0xFF;
|
opts.rxpad_content = strtoul(optarg, (char **)NULL, 16) & 0xFF;
|
||||||
|
|
@ -172,6 +178,11 @@ int main(int argc, char **argv)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((opts.flags & CAN_ISOTP_RX_EXT_ADDR) && (!(opts.flags & CAN_ISOTP_EXTEND_ADDR))) {
|
||||||
|
print_usage(basename(argv[0]));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if ((s = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP)) < 0) {
|
if ((s = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP)) < 0) {
|
||||||
perror("socket");
|
perror("socket");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
|
||||||
15
isotpsend.c
15
isotpsend.c
|
|
@ -63,7 +63,8 @@ void print_usage(char *prg)
|
||||||
fprintf(stderr, "\nUsage: %s [options] <CAN interface>\n", prg);
|
fprintf(stderr, "\nUsage: %s [options] <CAN interface>\n", prg);
|
||||||
fprintf(stderr, "Options: -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
|
fprintf(stderr, "Options: -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
|
||||||
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
|
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
|
||||||
fprintf(stderr, " -x <addr> (extended addressing mode. Use 'any' for all addresses)\n");
|
fprintf(stderr, " -x <addr> (extended addressing mode)\n");
|
||||||
|
fprintf(stderr, " -X <addr> (extended addressing mode - rx addr)\n");
|
||||||
fprintf(stderr, " -p <byte> (set and enable padding byte)\n");
|
fprintf(stderr, " -p <byte> (set and enable padding byte)\n");
|
||||||
fprintf(stderr, " -P <mode> (check padding in FC. (l)ength (c)ontent (a)ll)\n");
|
fprintf(stderr, " -P <mode> (check padding in FC. (l)ength (c)ontent (a)ll)\n");
|
||||||
fprintf(stderr, " -t <time ns> (frame transmit time (N_As) in nanosecs)\n");
|
fprintf(stderr, " -t <time ns> (frame transmit time (N_As) in nanosecs)\n");
|
||||||
|
|
@ -90,7 +91,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
addr.can_addr.tp.tx_id = addr.can_addr.tp.rx_id = NO_CAN_ID;
|
addr.can_addr.tp.tx_id = addr.can_addr.tp.rx_id = NO_CAN_ID;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "s:d:x:p:P:t:f:D:?")) != -1) {
|
while ((opt = getopt(argc, argv, "s:d:x:X:p:P:t:f:D:?")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 's':
|
case 's':
|
||||||
addr.can_addr.tp.tx_id = strtoul(optarg, (char **)NULL, 16);
|
addr.can_addr.tp.tx_id = strtoul(optarg, (char **)NULL, 16);
|
||||||
|
|
@ -109,6 +110,11 @@ int main(int argc, char **argv)
|
||||||
opts.ext_address = strtoul(optarg, (char **)NULL, 16) & 0xFF;
|
opts.ext_address = strtoul(optarg, (char **)NULL, 16) & 0xFF;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'X':
|
||||||
|
opts.flags |= CAN_ISOTP_RX_EXT_ADDR;
|
||||||
|
opts.rx_ext_address = strtoul(optarg, (char **)NULL, 16) & 0xFF;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
opts.flags |= CAN_ISOTP_TX_PADDING;
|
opts.flags |= CAN_ISOTP_TX_PADDING;
|
||||||
opts.txpad_content = strtoul(optarg, (char **)NULL, 16) & 0xFF;
|
opts.txpad_content = strtoul(optarg, (char **)NULL, 16) & 0xFF;
|
||||||
|
|
@ -165,6 +171,11 @@ int main(int argc, char **argv)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((opts.flags & CAN_ISOTP_RX_EXT_ADDR) && (!(opts.flags & CAN_ISOTP_EXTEND_ADDR))) {
|
||||||
|
print_usage(basename(argv[0]));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if ((s = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP)) < 0) {
|
if ((s = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP)) < 0) {
|
||||||
perror("socket");
|
perror("socket");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,8 @@ void print_usage(char *prg)
|
||||||
fprintf(stderr, "\nUsage: %s [options] <CAN interface>\n", prg);
|
fprintf(stderr, "\nUsage: %s [options] <CAN interface>\n", prg);
|
||||||
fprintf(stderr, "Options: -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
|
fprintf(stderr, "Options: -s <can_id> (source can_id. Use 8 digits for extended IDs)\n");
|
||||||
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
|
fprintf(stderr, " -d <can_id> (destination can_id. Use 8 digits for extended IDs)\n");
|
||||||
fprintf(stderr, " -x <addr> (extended addressing mode.)\n");
|
fprintf(stderr, " -x <addr> (extended addressing mode)\n");
|
||||||
|
fprintf(stderr, " -X <addr> (extended addressing mode - rx addr)\n");
|
||||||
fprintf(stderr, " -c (color mode)\n");
|
fprintf(stderr, " -c (color mode)\n");
|
||||||
fprintf(stderr, " -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n");
|
fprintf(stderr, " -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n");
|
||||||
fprintf(stderr, " -f <format> (1 = HEX, 2 = ASCII, 3 = HEX & ASCII - default: %d)\n", FORMAT_DEFAULT);
|
fprintf(stderr, " -f <format> (1 = HEX, 2 = ASCII, 3 = HEX & ASCII - default: %d)\n", FORMAT_DEFAULT);
|
||||||
|
|
@ -189,7 +190,7 @@ int main(int argc, char **argv)
|
||||||
unsigned char buffer[4096];
|
unsigned char buffer[4096];
|
||||||
int nbytes;
|
int nbytes;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "s:d:x:h:ct:f:?")) != -1) {
|
while ((opt = getopt(argc, argv, "s:d:x:X:h:ct:f:?")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 's':
|
case 's':
|
||||||
src = strtoul(optarg, (char **)NULL, 16);
|
src = strtoul(optarg, (char **)NULL, 16);
|
||||||
|
|
@ -208,6 +209,11 @@ int main(int argc, char **argv)
|
||||||
opts.ext_address = strtoul(optarg, (char **)NULL, 16) & 0xFF;
|
opts.ext_address = strtoul(optarg, (char **)NULL, 16) & 0xFF;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'X':
|
||||||
|
opts.flags |= CAN_ISOTP_RX_EXT_ADDR;
|
||||||
|
opts.rx_ext_address = strtoul(optarg, (char **)NULL, 16) & 0xFF;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
format = (atoi(optarg) & (FORMAT_ASCII | FORMAT_HEX));
|
format = (atoi(optarg) & (FORMAT_ASCII | FORMAT_HEX));
|
||||||
break;
|
break;
|
||||||
|
|
@ -248,6 +254,11 @@ int main(int argc, char **argv)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((opts.flags & CAN_ISOTP_RX_EXT_ADDR) && (!(opts.flags & CAN_ISOTP_EXTEND_ADDR))) {
|
||||||
|
print_usage(basename(argv[0]));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if ((s = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP)) < 0) {
|
if ((s = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP)) < 0) {
|
||||||
perror("socket");
|
perror("socket");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
@ -260,16 +271,15 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
opts.flags |= CAN_ISOTP_LISTEN_MODE;
|
opts.flags |= CAN_ISOTP_LISTEN_MODE;
|
||||||
|
|
||||||
setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts));
|
|
||||||
setsockopt(t, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts));
|
|
||||||
|
|
||||||
addr.can_family = AF_CAN;
|
addr.can_family = AF_CAN;
|
||||||
strcpy(ifr.ifr_name, argv[optind]);
|
strcpy(ifr.ifr_name, argv[optind]);
|
||||||
ioctl(s, SIOCGIFINDEX, &ifr);
|
ioctl(s, SIOCGIFINDEX, &ifr);
|
||||||
addr.can_ifindex = ifr.ifr_ifindex;
|
addr.can_ifindex = ifr.ifr_ifindex;
|
||||||
|
|
||||||
addr.can_addr.tp.tx_id = dst;
|
setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts));
|
||||||
addr.can_addr.tp.rx_id = src;
|
|
||||||
|
addr.can_addr.tp.tx_id = src;
|
||||||
|
addr.can_addr.tp.rx_id = dst;
|
||||||
|
|
||||||
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||||
perror("bind");
|
perror("bind");
|
||||||
|
|
@ -277,8 +287,19 @@ int main(int argc, char **argv)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
addr.can_addr.tp.tx_id = src;
|
if (opts.flags & CAN_ISOTP_RX_EXT_ADDR) {
|
||||||
addr.can_addr.tp.rx_id = dst;
|
/* flip extended address info due to separate rx ext addr */
|
||||||
|
__u8 tmpext;
|
||||||
|
|
||||||
|
tmpext = opts.ext_address;
|
||||||
|
opts.ext_address = opts.rx_ext_address;
|
||||||
|
opts.rx_ext_address = tmpext;
|
||||||
|
}
|
||||||
|
|
||||||
|
setsockopt(t, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts));
|
||||||
|
|
||||||
|
addr.can_addr.tp.tx_id = dst;
|
||||||
|
addr.can_addr.tp.rx_id = src;
|
||||||
|
|
||||||
if (bind(t, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
if (bind(t, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||||
perror("bind");
|
perror("bind");
|
||||||
|
|
@ -312,8 +333,8 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
if (nbytes > 4095)
|
if (nbytes > 4095)
|
||||||
return -1;
|
return -1;
|
||||||
printbuf(buffer, nbytes, color?1:0, timestamp, format,
|
printbuf(buffer, nbytes, color?2:0, timestamp, format,
|
||||||
&tv, &last_tv, src, s, ifr.ifr_name, head);
|
&tv, &last_tv, dst, s, ifr.ifr_name, head);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FD_ISSET(t, &rdfs)) {
|
if (FD_ISSET(t, &rdfs)) {
|
||||||
|
|
@ -324,8 +345,8 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
if (nbytes > 4095)
|
if (nbytes > 4095)
|
||||||
return -1;
|
return -1;
|
||||||
printbuf(buffer, nbytes, color?2:0, timestamp, format,
|
printbuf(buffer, nbytes, color?1:0, timestamp, format,
|
||||||
&tv, &last_tv, dst, t, ifr.ifr_name, head);
|
&tv, &last_tv, src, t, ifr.ifr_name, head);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue