isotpsend: add support for transmission without flow control
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 <socketcan@hartkopp.net>pull/365/head
parent
d320a4a871
commit
6e7f845a68
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
20
isotpsend.c
20
isotpsend.c
|
|
@ -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");
|
||||
|
|
@ -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,10 +240,13 @@ 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);
|
||||
}
|
||||
|
|
@ -248,7 +256,11 @@ int main(int argc, char **argv)
|
|||
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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue