diff --git a/include/linux/can/isotp.h b/include/linux/can/isotp.h index 590f8ae..439c982 100644 --- a/include/linux/can/isotp.h +++ b/include/linux/can/isotp.h @@ -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 */ diff --git a/isotpsend.c b/isotpsend.c index ef3d19d..deac601 100644 --- a/isotpsend.c +++ b/isotpsend.c @@ -75,7 +75,8 @@ void print_usage(char *prg) fprintf(stderr, " -l (send num PDUs - use 'i' for infinite loop)\n"); fprintf(stderr, " -g (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 :: (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"); @@ -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); @@ -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, @@ -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) {