From: Oliver Hartkopp <socketcan@hartkopp.net>
To: Alexander Stein <alexander.stein@systec-electronic.com>,
Wolfgang Grandegger <wg@grandegger.com>,
Marc Kleine-Budde <mkl@pengutronix.de>
Cc: linux-can@vger.kernel.org
Subject: Re: [PATCH 5/5] can: slcan: Add CAN status flag support
Date: Sat, 19 Apr 2014 22:38:43 +0200 [thread overview]
Message-ID: <5352DED3.8080900@hartkopp.net> (raw)
In-Reply-To: <1397573468-7619-6-git-send-email-alexander.stein@systec-electronic.com>
Hi Alexander,
On 15.04.2014 16:51, Alexander Stein wrote:
> CAN status flags have to be polled from the serial device. So send the
> request every 10ms by default.
here's my suggestion for the status retrieval from the user space by
sending a CAN frame with CAN_ERR_FLAG to the slcan device.
(I don't have this hardware with me - therefore compile tested only)
Regards,
Oliver
---
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index f5b16e0..750b002 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -54,6 +54,7 @@
#include <linux/kernel.h>
#include <linux/can.h>
#include <linux/can/skb.h>
+#include <linux/can/error.h>
static __initconst const char banner[] =
KERN_INFO "slcan: serial line CAN interface driver\n";
@@ -78,6 +79,16 @@ MODULE_PARM_DESC(maxdev, "Maximum number of slcan interfaces");
#define SLC_SFF_ID_LEN 3
#define SLC_EFF_ID_LEN 8
+/* slcan status bits returned in 'F' response */
+#define SLC_CAN_FLAG_ERR_WARN BIT(2)
+#define SLC_CAN_FLAG_OVERRUN BIT(3)
+#define SLC_CAN_FLAG_ERR_PASV BIT(5)
+#define SLC_CAN_FLAG_ARB_LOST BIT(6)
+#define SLC_CAN_FLAG_BUS_ERR BIT(7)
+#define SLC_CAN_FLAG_VALID (SLC_CAN_FLAG_ERR_WARN | SLC_CAN_FLAG_OVERRUN \
+ | SLC_CAN_FLAG_ERR_PASV | SLC_CAN_FLAG_ARB_LOST \
+ | SLC_CAN_FLAG_BUS_ERR)
+
struct slcan {
int magic;
@@ -135,6 +146,46 @@ static struct net_device **slcan_devs;
*
*/
+void slc_fill_err_msg(struct can_frame *cf, int tmp)
+{
+ tmp &= SLC_CAN_FLAG_VALID;
+
+ cf->can_id = CAN_ERR_FLAG;
+ cf->can_dlc = CAN_ERR_DLC;
+ *(u64 *) (&cf->data) = 0; /* clear payload */
+
+ if (tmp & SLC_CAN_FLAG_ARB_LOST)
+ cf->can_id |= CAN_ERR_LOSTARB;
+
+ if (tmp & SLC_CAN_FLAG_OVERRUN) {
+ cf->can_id |= CAN_ERR_CRTL;
+ cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+ }
+
+ /* CAN state: Check most severe problems first */
+
+ if (tmp & SLC_CAN_FLAG_BUS_ERR) {
+ cf->can_id |= CAN_ERR_BUSOFF;
+ return;
+ }
+
+ if (tmp & SLC_CAN_FLAG_ERR_PASV) {
+ cf->can_id |= CAN_ERR_CRTL;
+ cf->data[1] = CAN_ERR_CRTL_RX_PASSIVE | CAN_ERR_CRTL_TX_PASSIVE;
+ return;
+ }
+
+ if (tmp & SLC_CAN_FLAG_ERR_WARN) {
+ cf->can_id |= CAN_ERR_CRTL;
+ cf->data[1] = CAN_ERR_CRTL_RX_WARNING | CAN_ERR_CRTL_TX_WARNING;
+ return;
+ }
+
+ /* error active - no real problem detected */
+ cf->can_id |= CAN_ERR_PROT;
+ cf->data[2] = CAN_ERR_PROT_ACTIVE;
+}
+
/************************************************************************
* STANDARD SLCAN DECAPSULATION *
************************************************************************/
@@ -151,6 +202,14 @@ static void slc_bump(struct slcan *sl)
cf.can_id = 0;
switch (*cmd) {
+ case 'F':
+ /* retrieve adapter status information */
+ cmd += SLC_CMD_LEN;
+ tmp = hex_to_bin(*cmd);
+ if (tmp < 0)
+ return;
+ slc_fill_err_msg(&cf, tmp);
+ goto send_cf;
case 'r':
cf.can_id = CAN_RTR_FLAG;
/* fallthrough */
@@ -203,6 +262,7 @@ static void slc_bump(struct slcan *sl)
}
}
+send_cf:
skb = dev_alloc_skb(sizeof(struct can_frame) +
sizeof(struct can_skb_priv));
if (!skb)
@@ -229,7 +289,7 @@ 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)) {
+ (sl->rcount > 2)) {
slc_bump(sl);
}
sl->rcount = 0;
@@ -260,6 +320,11 @@ static void slc_encaps(struct slcan *sl, struct can_frame *cf)
pos = sl->xbuff;
+ if (cf->can_id & CAN_ERR_FLAG) {
+ *pos++ = 'F';
+ goto cmd_done;
+ }
+
if (cf->can_id & CAN_RTR_FLAG)
*pos = 'R'; /* becomes 'r' in standard frame format (SFF) */
else
@@ -292,6 +357,7 @@ static void slc_encaps(struct slcan *sl, struct can_frame *cf)
pos = hex_byte_pack_upper(pos, cf->data[i]);
}
+cmd_done:
*pos++ = '\r';
/* Order of next two lines is *very* important.
next prev parent reply other threads:[~2014-04-19 20:38 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-04-15 14:51 Bitrate and CAN status support for slcan Alexander Stein
2014-04-15 14:51 ` [PATCH 1/5] can: slcan: Fix spinlock variant Alexander Stein
2014-04-22 19:58 ` Oliver Hartkopp
2014-04-24 20:32 ` Marc Kleine-Budde
2014-04-15 14:51 ` [PATCH 2/5] can: slcan: Convert to can_dev interface Alexander Stein
2014-04-17 19:10 ` Marc Kleine-Budde
2014-04-15 14:51 ` [PATCH 3/5] can: slcan: Send open/close command upon interface up/down Alexander Stein
2014-04-15 14:51 ` [PATCH 4/5] can: slcan: Add bitrate change support Alexander Stein
2014-04-17 19:13 ` Marc Kleine-Budde
2014-04-15 14:51 ` [PATCH 5/5] can: slcan: Add CAN status flag support Alexander Stein
2014-04-17 19:22 ` Marc Kleine-Budde
2014-04-19 20:38 ` Oliver Hartkopp [this message]
2014-04-19 19:24 ` Bitrate and CAN status support for slcan Oliver Hartkopp
2014-04-22 7:08 ` Alexander Stein
2014-04-22 19:50 ` Oliver Hartkopp
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5352DED3.8080900@hartkopp.net \
--to=socketcan@hartkopp.net \
--cc=alexander.stein@systec-electronic.com \
--cc=linux-can@vger.kernel.org \
--cc=mkl@pengutronix.de \
--cc=wg@grandegger.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.