Skip to content

Commit

Permalink
isotpsend: add support for transmission without flow control
Browse files Browse the repository at this point in the history
Usually the ISO 15765-2 protocol is a point-to-point protocol to transfer
segmented PDUs to a dedicated receiver. This receiver sends a flow control
message to specify protocol options and timings (e.g. block size / STmin).

The so called functional addressing communication allows a 1:N
communication but is limited to a single frame length.

The new CAN_ISOTP_CF_BROADCAST flag introduced in Linux 5.19 allows an
unconfirmed 1:N communication with PDU lengths that would not fit into a
single frame. This feature is not covered by the ISO 15765-2 standard.

The isotpsend tool gets a new option '-C' to enable this unconfirmed 1:N
communication by setting the CAN_ISOTP_CF_BROADCAST flag.

Signed-off-by: Oliver Hartkopp <[email protected]>
  • Loading branch information
hartkopp committed May 13, 2022
1 parent d320a4a commit 6e7f845
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 17 deletions.
25 changes: 13 additions & 12 deletions include/linux/can/isotp.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,18 +124,19 @@ struct can_isotp_ll_options {

/* flags for isotp behaviour */

#define CAN_ISOTP_LISTEN_MODE 0x001 /* listen only (do not send FC) */
#define CAN_ISOTP_EXTEND_ADDR 0x002 /* enable extended addressing */
#define CAN_ISOTP_TX_PADDING 0x004 /* enable CAN frame padding tx path */
#define CAN_ISOTP_RX_PADDING 0x008 /* enable CAN frame padding rx path */
#define CAN_ISOTP_CHK_PAD_LEN 0x010 /* check received CAN frame padding */
#define CAN_ISOTP_CHK_PAD_DATA 0x020 /* check received CAN frame padding */
#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_RXSTMIN 0x100 /* ignore CFs depending on rx stmin */
#define CAN_ISOTP_RX_EXT_ADDR 0x200 /* different rx extended addressing */
#define CAN_ISOTP_WAIT_TX_DONE 0x400 /* wait for tx completion */
#define CAN_ISOTP_SF_BROADCAST 0x800 /* 1-to-N functional addressing */
#define CAN_ISOTP_LISTEN_MODE 0x0001 /* listen only (do not send FC) */
#define CAN_ISOTP_EXTEND_ADDR 0x0002 /* enable extended addressing */
#define CAN_ISOTP_TX_PADDING 0x0004 /* enable CAN frame padding tx path */
#define CAN_ISOTP_RX_PADDING 0x0008 /* enable CAN frame padding rx path */
#define CAN_ISOTP_CHK_PAD_LEN 0x0010 /* check received CAN frame padding */
#define CAN_ISOTP_CHK_PAD_DATA 0x0020 /* check received CAN frame padding */
#define CAN_ISOTP_HALF_DUPLEX 0x0040 /* half duplex error state handling */
#define CAN_ISOTP_FORCE_TXSTMIN 0x0080 /* ignore stmin from received FC */
#define CAN_ISOTP_FORCE_RXSTMIN 0x0100 /* ignore CFs depending on rx stmin */
#define CAN_ISOTP_RX_EXT_ADDR 0x0200 /* different rx extended addressing */
#define CAN_ISOTP_WAIT_TX_DONE 0x0400 /* wait for tx completion */
#define CAN_ISOTP_SF_BROADCAST 0x0800 /* 1-to-N functional addressing */
#define CAN_ISOTP_CF_BROADCAST 0x1000 /* 1-to-N transmission w/o FC */

/* protocol machine default values */

Expand Down
22 changes: 17 additions & 5 deletions isotpsend.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ void print_usage(char *prg)
fprintf(stderr, " -l <num> (send num PDUs - use 'i' for infinite loop)\n");
fprintf(stderr, " -g <usecs> (wait given usecs before sending a PDU)\n");
fprintf(stderr, " -b (block until the PDU transmission is completed)\n");
fprintf(stderr, " -S (SF broadcast mode for functional addressing)\n");
fprintf(stderr, " -S (SF broadcast mode - for functional addressing)\n");
fprintf(stderr, " -C (CF broadcast mode - no wait for flow controls)\n");
fprintf(stderr, " -L <mtu>:<tx_dl>:<tx_flags> (link layer options for CAN FD)\n");
fprintf(stderr, "\nCAN IDs and addresses are given and expected in hexadecimal values.\n");
fprintf(stderr, "The pdu data is expected on STDIN in space separated ASCII hex values.\n");
Expand All @@ -101,7 +102,7 @@ int main(int argc, char **argv)

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:l:g:bSL:?")) != -1) {
while ((opt = getopt(argc, argv, "s:d:x:p:P:t:f:D:l:g:bSCL:?")) != -1) {
switch (opt) {
case 's':
addr.can_addr.tp.tx_id = strtoul(optarg, NULL, 16);
Expand Down Expand Up @@ -211,6 +212,10 @@ int main(int argc, char **argv)
opts.flags |= CAN_ISOTP_SF_BROADCAST;
break;

case 'C':
opts.flags |= CAN_ISOTP_CF_BROADCAST;
break;

case 'L':
if (sscanf(optarg, "%hhu:%hhu:%hhu",
&llopts.mtu,
Expand All @@ -235,20 +240,27 @@ int main(int argc, char **argv)
}
}

#define BC_FLAGS (CAN_ISOTP_SF_BROADCAST | CAN_ISOTP_CF_BROADCAST)

if ((argc - optind != 1) ||
(addr.can_addr.tp.tx_id == NO_CAN_ID) ||
((opts.flags & BC_FLAGS) == BC_FLAGS) ||
((addr.can_addr.tp.rx_id == NO_CAN_ID) &&
(!(opts.flags & CAN_ISOTP_SF_BROADCAST)))) {
(!(opts.flags & BC_FLAGS)))) {
print_usage(basename(argv[0]));
exit(1);
}

if ((s = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP)) < 0) {
perror("socket");
exit(1);
}

setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts));
if (setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts)) < 0) {
perror("sockopt");
exit(1);
}


if (llopts.tx_dl) {
if (setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_LL_OPTS, &llopts, sizeof(llopts)) < 0) {
Expand Down

0 comments on commit 6e7f845

Please sign in to comment.