Commit ef0841e4 authored by Carlos Sanchez's avatar Carlos Sanchez Committed by Marc Kleine-Budde
Browse files

can: slcan: allow reception of short error messages



Allows slcan to receive short messages (typically errors) from the serial
interface.

When error support was added to slcan protocol in
b32ff466 ("can: slcan: extend the protocol
with error info") the minimum valid message size changed from 5 (minimum
standard can frame tIII0) to 3 ("e1a" is a valid protocol message, it is
one of the examples given in the comments for slcan_bump_err() ), but the
check for minimum message length prodicating all decoding was not adjusted.
This makes short error messages discarded and error frames not being
generated.

This patch changes the minimum length to the new minimum (3 characters,
excluding terminator, is now a valid message).

Signed-off-by: default avatarCarlos Sanchez <carlossanchez@geotab.com>
Fixes: b32ff466 ("can: slcan: extend the protocol with error info")
Reviewed-by: default avatarVincent Mailhol <mailhol.vincent@wanadoo.fr>
Link: https://patch.msgid.link/20250520102305.1097494-1-carlossanchez@geotab.com


Cc: stable@vger.kernel.org
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent be19a922
Loading
Loading
Loading
Loading
+20 −6
Original line number Diff line number Diff line
@@ -71,12 +71,21 @@ MODULE_AUTHOR("Dario Binacchi <dario.binacchi@amarulasolutions.com>");
#define SLCAN_CMD_LEN 1
#define SLCAN_SFF_ID_LEN 3
#define SLCAN_EFF_ID_LEN 8
#define SLCAN_DATA_LENGTH_LEN 1
#define SLCAN_ERROR_LEN 1
#define SLCAN_STATE_LEN 1
#define SLCAN_STATE_BE_RXCNT_LEN 3
#define SLCAN_STATE_BE_TXCNT_LEN 3
#define SLCAN_STATE_FRAME_LEN       (1 + SLCAN_CMD_LEN + \
#define SLCAN_STATE_MSG_LEN     (SLCAN_CMD_LEN +		\
                                 SLCAN_STATE_LEN +		\
                                 SLCAN_STATE_BE_RXCNT_LEN +	\
                                 SLCAN_STATE_BE_TXCNT_LEN)
#define SLCAN_ERROR_MSG_LEN_MIN (SLCAN_CMD_LEN +	\
                                 SLCAN_ERROR_LEN +	\
                                 SLCAN_DATA_LENGTH_LEN)
#define SLCAN_FRAME_MSG_LEN_MIN (SLCAN_CMD_LEN +	\
                                 SLCAN_SFF_ID_LEN +	\
                                 SLCAN_DATA_LENGTH_LEN)
struct slcan {
	struct can_priv         can;

@@ -176,6 +185,9 @@ static void slcan_bump_frame(struct slcan *sl)
	u32 tmpid;
	char *cmd = sl->rbuff;

	if (sl->rcount < SLCAN_FRAME_MSG_LEN_MIN)
		return;

	skb = alloc_can_skb(sl->dev, &cf);
	if (unlikely(!skb)) {
		sl->dev->stats.rx_dropped++;
@@ -281,7 +293,7 @@ static void slcan_bump_state(struct slcan *sl)
		return;
	}

	if (state == sl->can.state || sl->rcount < SLCAN_STATE_FRAME_LEN)
	if (state == sl->can.state || sl->rcount != SLCAN_STATE_MSG_LEN)
		return;

	cmd += SLCAN_STATE_BE_RXCNT_LEN + SLCAN_CMD_LEN + 1;
@@ -328,6 +340,9 @@ static void slcan_bump_err(struct slcan *sl)
	bool rx_errors = false, tx_errors = false, rx_over_errors = false;
	int i, len;

	if (sl->rcount < SLCAN_ERROR_MSG_LEN_MIN)
		return;

	/* get len from sanitized ASCII value */
	len = cmd[1];
	if (len >= '0' && len < '9')
@@ -456,8 +471,7 @@ static void slcan_bump(struct slcan *sl)
static void slcan_unesc(struct slcan *sl, unsigned char s)
{
	if ((s == '\r') || (s == '\a')) { /* CR or BEL ends the pdu */
		if (!test_and_clear_bit(SLF_ERROR, &sl->flags) &&
		    sl->rcount > 4)
		if (!test_and_clear_bit(SLF_ERROR, &sl->flags))
			slcan_bump(sl);

		sl->rcount = 0;