All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/5][RFC] can: slcan: Replace sizeof struct can_frame with CAN_MTU
@ 2016-06-09 19:21 Marek Vasut
  2016-06-09 19:21 ` [PATCH 2/5][RFC] can: Factor out alloc_socketdev() Marek Vasut
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: Marek Vasut @ 2016-06-09 19:21 UTC (permalink / raw)
  To: linux-can; +Cc: Marek Vasut, Oliver Hartkopp, Marc Kleine-Budde

Use CAN_MTU macro instead of sizeof(struct can_frame) just like the
other drivers do.

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Oliver Hartkopp <socketcan@hartkopp.net>
Cc: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/slcan.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index 9a3f15c..eb71737 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -354,7 +354,7 @@ static netdev_tx_t slc_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct slcan *sl = netdev_priv(dev);
 
-	if (skb->len != sizeof(struct can_frame))
+	if (skb->len != CAN_MTU)
 		goto out;
 
 	spin_lock(&sl->lock);
@@ -442,7 +442,7 @@ static void slc_setup(struct net_device *dev)
 	dev->addr_len		= 0;
 	dev->tx_queue_len	= 10;
 
-	dev->mtu		= sizeof(struct can_frame);
+	dev->mtu		= CAN_MTU;
 	dev->type		= ARPHRD_CAN;
 
 	/* New-style flags. */
-- 
2.7.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/5][RFC] can: Factor out alloc_socketdev()
  2016-06-09 19:21 [PATCH 1/5][RFC] can: slcan: Replace sizeof struct can_frame with CAN_MTU Marek Vasut
@ 2016-06-09 19:21 ` Marek Vasut
  2016-06-09 19:21 ` [PATCH 3/5][RFC] can: Add register_candevice() Marek Vasut
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: Marek Vasut @ 2016-06-09 19:21 UTC (permalink / raw)
  To: linux-can; +Cc: Marek Vasut, Oliver Hartkopp, Marc Kleine-Budde

Factor out alloc_socketdev() from alloc_candev() to make it possible
to register different socket devices -- like kline -- using the same
codepath.

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Oliver Hartkopp <socketcan@hartkopp.net>
Cc: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/dev.c   | 11 +++++++++--
 include/linux/can/dev.h |  1 +
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index 141c2a4..f8ef6b0 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -641,7 +641,8 @@ EXPORT_SYMBOL_GPL(alloc_can_err_skb);
 /*
  * Allocate and setup space for the CAN network device
  */
-struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max)
+struct net_device *alloc_socketdev(const char *name, int sizeof_priv,
+				   unsigned int echo_skb_max)
 {
 	struct net_device *dev;
 	struct can_priv *priv;
@@ -653,7 +654,7 @@ struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max)
 	else
 		size = sizeof_priv;
 
-	dev = alloc_netdev(size, "can%d", NET_NAME_UNKNOWN, can_setup);
+	dev = alloc_netdev(size, name, NET_NAME_UNKNOWN, can_setup);
 	if (!dev)
 		return NULL;
 
@@ -671,6 +672,12 @@ struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max)
 
 	return dev;
 }
+EXPORT_SYMBOL_GPL(alloc_socketdev);
+
+struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max)
+{
+	return alloc_socketdev("can%d", sizeof_priv, echo_skb_max);
+}
 EXPORT_SYMBOL_GPL(alloc_candev);
 
 /*
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index 735f9f8..9b0520d 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -114,6 +114,7 @@ u8 can_dlc2len(u8 can_dlc);
 /* map the sanitized data length to an appropriate data length code */
 u8 can_len2dlc(u8 len);
 
+struct net_device *alloc_socketdev(const char *name, int sizeof_priv, unsigned int echo_skb_max);
 struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max);
 void free_candev(struct net_device *dev);
 
-- 
2.7.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/5][RFC] can: Add register_candevice()
  2016-06-09 19:21 [PATCH 1/5][RFC] can: slcan: Replace sizeof struct can_frame with CAN_MTU Marek Vasut
  2016-06-09 19:21 ` [PATCH 2/5][RFC] can: Factor out alloc_socketdev() Marek Vasut
@ 2016-06-09 19:21 ` Marek Vasut
  2016-06-09 19:21 ` [PATCH 4/5][RFC] can: kline: Add KLine rtnl configuration options Marek Vasut
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: Marek Vasut @ 2016-06-09 19:21 UTC (permalink / raw)
  To: linux-can; +Cc: Marek Vasut, Oliver Hartkopp, Marc Kleine-Budde

Add register_candevice() call, which unlike register_candev(),
registers the candev without rtnl lock held. This is very similar
to register_netdev() and register_netdevice().

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Oliver Hartkopp <socketcan@hartkopp.net>
Cc: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/dev.c   | 7 +++++++
 include/linux/can/dev.h | 1 +
 2 files changed, 8 insertions(+)

diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index f8ef6b0..0db16f6 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -984,6 +984,13 @@ static struct rtnl_link_ops can_link_ops __read_mostly = {
 /*
  * Register the CAN network device
  */
+int register_candevice(struct net_device *dev)
+{
+	dev->rtnl_link_ops = &can_link_ops;
+	return register_netdevice(dev);
+}
+EXPORT_SYMBOL_GPL(register_candevice);
+
 int register_candev(struct net_device *dev)
 {
 	dev->rtnl_link_ops = &can_link_ops;
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index 9b0520d..c67082d 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -125,6 +125,7 @@ int open_candev(struct net_device *dev);
 void close_candev(struct net_device *dev);
 int can_change_mtu(struct net_device *dev, int new_mtu);
 
+int register_candevice(struct net_device *dev);
 int register_candev(struct net_device *dev);
 void unregister_candev(struct net_device *dev);
 
-- 
2.7.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 4/5][RFC] can: kline: Add KLine rtnl configuration options
  2016-06-09 19:21 [PATCH 1/5][RFC] can: slcan: Replace sizeof struct can_frame with CAN_MTU Marek Vasut
  2016-06-09 19:21 ` [PATCH 2/5][RFC] can: Factor out alloc_socketdev() Marek Vasut
  2016-06-09 19:21 ` [PATCH 3/5][RFC] can: Add register_candevice() Marek Vasut
@ 2016-06-09 19:21 ` Marek Vasut
  2016-06-09 20:21   ` Menschel.P
  2016-06-09 19:21 ` [PATCH 5/5][RFC] can: kline: Add KLine ldisc Marek Vasut
  2016-06-17  9:24 ` [PATCH 1/5][RFC] can: slcan: Replace sizeof struct can_frame with CAN_MTU Marc Kleine-Budde
  4 siblings, 1 reply; 11+ messages in thread
From: Marek Vasut @ 2016-06-09 19:21 UTC (permalink / raw)
  To: linux-can; +Cc: Marek Vasut, Oliver Hartkopp, Marc Kleine-Budde

Extend the can rtnl with kline timing parameters W0...W5, P1...P4 .

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Oliver Hartkopp <socketcan@hartkopp.net>
Cc: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/dev.c            | 16 +++++++++++++++-
 include/linux/can/dev.h          |  2 ++
 include/uapi/linux/can/netlink.h | 18 ++++++++++++++++++
 3 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index 0db16f6..e867b7a 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -787,6 +787,7 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
 				= { .len = sizeof(struct can_bittiming) },
 	[IFLA_CAN_DATA_BITTIMING_CONST]
 				= { .len = sizeof(struct can_bittiming_const) },
+	[IFLA_KLINE_TIMING]	= { .len = sizeof(struct kline_timing) },
 };
 
 static int can_changelink(struct net_device *dev,
@@ -878,6 +879,14 @@ static int can_changelink(struct net_device *dev,
 		}
 	}
 
+	if (data[IFLA_KLINE_TIMING]) {
+		/* Do not allow changing bittiming while running */
+		if (dev->flags & IFF_UP)
+			return -EBUSY;
+		memcpy(&priv->kline_timing, nla_data(data[IFLA_KLINE_TIMING]),
+		       sizeof(struct kline_timing));
+	}
+
 	return 0;
 }
 
@@ -900,6 +909,7 @@ static size_t can_get_size(const struct net_device *dev)
 		size += nla_total_size(sizeof(struct can_bittiming));
 	if (priv->data_bittiming_const)				/* IFLA_CAN_DATA_BITTIMING_CONST */
 		size += nla_total_size(sizeof(struct can_bittiming_const));
+	size += nla_total_size(sizeof(struct kline_timing));	/* IFLA_KLINE_TIMING */
 
 	return size;
 }
@@ -938,7 +948,11 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
 	    (priv->data_bittiming_const &&
 	     nla_put(skb, IFLA_CAN_DATA_BITTIMING_CONST,
 		     sizeof(*priv->data_bittiming_const),
-		     priv->data_bittiming_const)))
+		     priv->data_bittiming_const)) ||
+
+	    nla_put(skb, IFLA_KLINE_TIMING,
+		    sizeof(priv->kline_timing), &priv->kline_timing)
+	    )
 		return -EMSGSIZE;
 
 	return 0;
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index c67082d..f95f24d 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -65,6 +65,8 @@ struct can_priv {
 	struct led_trigger *rxtx_led_trig;
 	char rxtx_led_trig_name[CAN_LED_NAME_SZ];
 #endif
+
+	struct kline_timing kline_timing;
 };
 
 /*
diff --git a/include/uapi/linux/can/netlink.h b/include/uapi/linux/can/netlink.h
index 94ffe0c..da5f4b3 100644
--- a/include/uapi/linux/can/netlink.h
+++ b/include/uapi/linux/can/netlink.h
@@ -113,6 +113,23 @@ struct can_device_stats {
 };
 
 /*
+ * KLine timing parameters
+ */
+struct kline_timing {
+	__u32 w0;
+	__u32 w1;
+	__u32 w2;
+	__u32 w3;
+	__u32 w4;
+	__u32 w5;
+	__u32 p1;
+	__u32 p2_94;
+	__u32 p2_08;
+	__u32 p3;
+	__u32 p4;
+};
+
+/*
  * CAN netlink interface
  */
 enum {
@@ -127,6 +144,7 @@ enum {
 	IFLA_CAN_BERR_COUNTER,
 	IFLA_CAN_DATA_BITTIMING,
 	IFLA_CAN_DATA_BITTIMING_CONST,
+	IFLA_KLINE_TIMING,
 	__IFLA_CAN_MAX
 };
 
-- 
2.7.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 5/5][RFC] can: kline: Add KLine ldisc
  2016-06-09 19:21 [PATCH 1/5][RFC] can: slcan: Replace sizeof struct can_frame with CAN_MTU Marek Vasut
                   ` (2 preceding siblings ...)
  2016-06-09 19:21 ` [PATCH 4/5][RFC] can: kline: Add KLine rtnl configuration options Marek Vasut
@ 2016-06-09 19:21 ` Marek Vasut
  2016-06-17  9:24 ` [PATCH 1/5][RFC] can: slcan: Replace sizeof struct can_frame with CAN_MTU Marc Kleine-Budde
  4 siblings, 0 replies; 11+ messages in thread
From: Marek Vasut @ 2016-06-09 19:21 UTC (permalink / raw)
  To: linux-can; +Cc: Marek Vasut, Oliver Hartkopp, Marc Kleine-Budde

Add initial TTY line discipline connected into the socketcan stack
which facilitates the communication with KLine device.

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Oliver Hartkopp <socketcan@hartkopp.net>
Cc: Marc Kleine-Budde <mkl@pengutronix.de>
---

NOTE: There is a lot of stuff in this patch which is not fleshed out yet.

 drivers/net/can/Kconfig    |  19 ++
 drivers/net/can/Makefile   |   1 +
 drivers/net/can/sl_kline.c | 683 +++++++++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/can.h   |  33 +++
 include/uapi/linux/tty.h   |   1 +
 net/can/af_can.c           |   6 +-
 net/can/raw.c              |   2 +-
 7 files changed, 743 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/can/sl_kline.c

diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index 20be638..e1a8728 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -29,6 +29,25 @@ config CAN_SLCAN
 	  can be changed by the 'maxdev=xx' module option. This driver can
 	  also be built as a module. If so, the module will be called slcan.
 
+config CAN_SL_KLINE
+	tristate "Serial K-Line protocol using SocketCAN (sl_kline)"
+	depends on TTY
+	---help---
+	  SocketCAN driver for the ISO 9141-2 K-Line protocol using TTY
+	  line discipline. This driver allows userland to communicate
+	  using standard SocketCAN interface to a device using K-Line
+	  protocol. Such K-Line device is connected to a regular serial
+	  port via level-shifter or similar logic. The TTY line discipline
+	  type is N_SL_KLINE.
+
+	  Userspace tools to attach the SL_KLINE ldisc (sl_kline_attach,
+	  sl_kline_d) can be found in the can-utils at the SocketCAN git).
+
+	  The sl_kline driver supports up to 10 KLine netdevices by default
+	  which can be changed by the 'maxdev=xx' module option. This driver
+	  can also be built as a module. If so, the module will be called
+	  sl_kline.
+
 config CAN_DEV
 	tristate "Platform CAN drivers with Netlink support"
 	default y
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index e3db0c8..60648e9 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_CAN_VCAN)		+= vcan.o
 obj-$(CONFIG_CAN_SLCAN)		+= slcan.o
+obj-$(CONFIG_CAN_SL_KLINE)	+= sl_kline.o
 
 obj-$(CONFIG_CAN_DEV)		+= can-dev.o
 can-dev-y			:= dev.o
diff --git a/drivers/net/can/sl_kline.c b/drivers/net/can/sl_kline.c
new file mode 100644
index 0000000..fc9ca24
--- /dev/null
+++ b/drivers/net/can/sl_kline.c
@@ -0,0 +1,683 @@
+/*
+ * sl_kline.c - serial line K-Line interface driver (using tty line discipline)
+ *
+ * Heavilty based on slcan.c by Oliver Hartkopp <socketcan@hartkopp.net>
+ *   serial line CAN interface driver (using tty line discipline)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+#include <linux/uaccess.h>
+#include <linux/bitops.h>
+#include <linux/string.h>
+#include <linux/tty.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/workqueue.h>
+#include <linux/can.h>
+#include <linux/can/skb.h>
+
+#include <linux/can/dev.h>
+
+MODULE_ALIAS_LDISC(N_SL_KLINE);
+MODULE_DESCRIPTION("serial line K-Line interface");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
+
+#define SL_KLINE_MAGIC 0x53CB	/* FIXME */
+
+static int maxdev = 10;		/* MAX number of SL_KLINE channels;
+				   This can be overridden with
+				   insmod sl_kline.ko maxdev=nnn	*/
+module_param(maxdev, int, 0);
+MODULE_PARM_DESC(maxdev, "Maximum number of sl_kline interfaces");
+
+struct sl_kline {
+	struct can_priv		can;	/* must be the first member */
+
+	int			magic;
+
+	/* Various fields. */
+	struct tty_struct	*tty;
+	struct net_device	*dev;
+	spinlock_t		lock;
+	struct work_struct	tx_work;	/* Flushes transmit buffer   */
+
+	/* These are pointers to the malloc()ed frame buffers. */
+	unsigned char		rbuff[KLINE_MAX_DLEN];
+	int			rcount;
+
+	unsigned long		flags;
+
+#define KLF_IN_USE		(1 << 0)
+#define KLF_INIT		(1 << 1)
+#define KLF_WAIT_FOR_55		(1 << 2)
+#define KLF_WAIT_FOR_ADDR1	(1 << 3)
+#define KLF_WAIT_FOR_ADDR2	(1 << 4)
+#define KLF_WAIT_FOR_CC		(1 << 5)
+
+	struct kline_frame	tx_kf;
+	struct timer_list	timer;
+};
+
+static struct net_device **sl_kline_devs;
+
+/* Send one kline_frame to the network layer */
+static void sl_kline_bump(struct sl_kline *sl)
+{
+	struct sk_buff *skb;
+	struct kline_frame kf;
+
+	kf.can_id = 0;
+	kf.len = sl->rcount;
+	memcpy(kf.data, sl->rbuff, sl->rcount);
+
+	skb = dev_alloc_skb(sizeof(struct kline_frame) +
+			    sizeof(struct can_skb_priv));
+	if (!skb)
+		return;
+
+	skb->dev = sl->dev;
+	skb->protocol = htons(ETH_P_CAN);
+	skb->pkt_type = PACKET_BROADCAST;
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+	can_skb_reserve(skb);
+	can_skb_prv(skb)->ifindex = sl->dev->ifindex;
+	can_skb_prv(skb)->skbcnt = 0;
+
+	memcpy(skb_put(skb, sizeof(struct kline_frame)),
+	       &kf, sizeof(struct kline_frame));
+
+	sl->dev->stats.rx_packets++;
+	sl->dev->stats.rx_bytes += kf.len;
+	netif_rx_ni(skb);
+}
+
+/* Write transmit buffer. Scheduled when tty is writable */
+static void sl_kline_transmit(struct work_struct *work)
+{
+	struct sl_kline *sl = container_of(work, struct sl_kline, tx_work);
+	struct kline_frame *kf = &sl->tx_kf;
+	struct ktermios ktermios = sl->tty->termios;
+	int i;
+
+	spin_lock_bh(&sl->lock);
+	/* First make sure we're connected. */
+	if (!sl->tty || sl->magic != SL_KLINE_MAGIC || !netif_running(sl->dev)) {
+		spin_unlock_bh(&sl->lock);
+		return;
+	}
+
+	/* Push out start frame */
+	if (kf->flags & (KLINE_ISO9141_START | KLINE_KWP_SLOW_START)) {
+		/* Wait time W0=2mS */
+		mdelay(sl->can.kline_timing.w0);
+
+		/* Set speed to 5 Bd/s */
+		ktermios.c_cflag &= ~CBAUD;
+		tty_termios_encode_baud_rate(&ktermios, 5, 5);
+		tty_set_termios(sl->tty, &ktermios);
+
+		/* Transmit init */
+		tty_put_char(sl->tty, 0x33);
+		sl->dev->stats.tx_bytes++;
+
+		sl->flags |= KLF_INIT | KLF_WAIT_FOR_55;
+		spin_unlock_bh(&sl->lock);
+
+		/* Start timer to measure W1 */
+		mod_timer(&sl->timer,
+			  jiffies + msecs_to_jiffies(sl->can.kline_timing.w1));
+		return;
+	}
+
+	/* We should NEVER end up here with KLF_INIT set. */
+	WARN_ON(sl->flags & KLF_INIT);
+
+	/* Just write the data and be done with it. */
+	for (i = 0; i < kf->len; i++) {
+		tty_put_char(sl->tty, kf->data[i]);
+		sl->dev->stats.tx_bytes++;
+		/* FIXME: Delay for the inter-byte interval */
+	}
+	spin_unlock_bh(&sl->lock);
+}
+
+static void sl_kline_timeout(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct sl_kline *sl = netdev_priv(dev);
+
+	/* Check if the link-partner responded */
+	if (sl->flags & KLF_WAIT_FOR_55) {	/* No response */
+		sl->flags &= ~(KLF_INIT | KLF_WAIT_FOR_55);
+		sl->dev->stats.tx_errors++;
+		netif_wake_queue(sl->dev);
+	}
+}
+
+/*
+ * Called by the driver when there's room for more data.
+ * Schedule the transmit.
+ */
+static void sl_kline_write_wakeup(struct tty_struct *tty)
+{
+	struct sl_kline *sl = tty->disc_data;
+
+	schedule_work(&sl->tx_work);
+}
+
+/* Send a kline_frame to a TTY queue. */
+static netdev_tx_t sl_kline_ndev_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct sl_kline *sl = netdev_priv(dev);
+
+	if (skb->len != sizeof(struct kline_frame))
+		goto out;
+
+	spin_lock(&sl->lock);
+	if (!netif_running(dev))  {
+		spin_unlock(&sl->lock);
+		printk(KERN_WARNING "%s: xmit: iface is down\n", dev->name);
+		goto out;
+	}
+	if (sl->tty == NULL) {
+		spin_unlock(&sl->lock);
+		goto out;
+	}
+
+	netif_stop_queue(sl->dev);
+	memcpy(&sl->tx_kf, (struct kline_frame *)skb->data, sizeof(sl->tx_kf));
+	schedule_work(&sl->tx_work);
+	spin_unlock(&sl->lock);
+
+out:
+	kfree_skb(skb);
+	return NETDEV_TX_OK;
+}
+
+
+/******************************************
+ *   Routines looking at netdevice side.
+ ******************************************/
+
+/* Netdevice UP -> DOWN routine */
+static int sl_kline_ndev_close(struct net_device *dev)
+{
+	struct sl_kline *sl = netdev_priv(dev);
+
+	spin_lock_bh(&sl->lock);
+	if (sl->tty) {
+		/* TTY discipline is running. */
+		clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
+	}
+	netif_stop_queue(dev);
+	sl->rcount   = 0;
+	spin_unlock_bh(&sl->lock);
+
+	return 0;
+}
+
+/* Netdevice DOWN -> UP routine */
+static int sl_kline_ndev_open(struct net_device *dev)
+{
+	struct sl_kline *sl = netdev_priv(dev);
+
+	if (sl->tty == NULL)
+		return -ENODEV;
+
+	setup_timer(&sl->timer, sl_kline_timeout, (unsigned long)dev);
+
+	sl->flags &= KLF_IN_USE;
+	netif_start_queue(dev);
+	return 0;
+}
+
+/* Hook the destructor so we can free sl_kline devs at the right point in time */
+static void sl_kline_ndev_free(struct net_device *dev)
+{
+	struct sl_kline *sl = netdev_priv(dev);
+	int i = dev->base_addr;
+
+	del_timer_sync(&sl->timer);
+
+	free_netdev(dev);
+	sl_kline_devs[i] = NULL;
+}
+
+static int sl_kline_ndev_change_mtu(struct net_device *dev, int new_mtu)
+{
+	return -EINVAL;
+}
+
+static const struct net_device_ops sl_kline_ndev_ops = {
+	.ndo_open               = sl_kline_ndev_open,
+	.ndo_stop               = sl_kline_ndev_close,
+	.ndo_start_xmit         = sl_kline_ndev_xmit,
+	.ndo_change_mtu         = sl_kline_ndev_change_mtu,
+};
+
+/******************************************
+  Routines looking at TTY side.
+ ******************************************/
+static void sl_kline_receive_buf(struct tty_struct *tty,
+			      const unsigned char *cp, char *fp, int count)
+{
+	struct sl_kline *sl = (struct sl_kline *) tty->disc_data;
+	struct ktermios ktermios = tty->termios;
+
+	if (!sl || sl->magic != SL_KLINE_MAGIC || !netif_running(sl->dev))
+		return;
+
+	/* FIXME: Add mutex for the flags */
+
+	/* Handle incoming data */
+	if (!(sl->flags & KLF_INIT)) {	/* Normal data. */
+		sl->rcount = 0;
+		while (count--) {
+			if (fp && *fp++) {
+				/* FIXME: Log RX errors ? */
+				sl->dev->stats.rx_errors++;
+				cp++;
+				continue;
+			} else {
+				sl->rbuff[sl->rcount++] = *cp++;
+			}
+		}
+		sl_kline_bump(sl);
+		netif_wake_queue(sl->dev);
+		return;
+	}
+
+	if (sl->flags & KLF_WAIT_FOR_55) {
+		if (!count)
+			return;
+
+		sl->flags &= ~KLF_WAIT_FOR_55;
+		if (*cp == 0x55) {	/* Valid response */
+			/* Set speed to 10400 Bd/s */
+			ktermios.c_cflag &= ~CBAUD;
+			tty_termios_encode_baud_rate(&ktermios, 10400, 10400);
+			tty_set_termios(tty, &ktermios);
+		}
+
+		if (*cp != 0x55)	/* Invalid response */
+			goto fail;
+
+		sl->rcount = 0;
+		sl->rbuff[sl->rcount++] = *cp++;
+
+		sl->flags |= KLF_WAIT_FOR_ADDR1;
+	}
+
+	if (sl->flags & KLF_WAIT_FOR_ADDR1) {
+		if (!count)
+			return;
+
+		sl->flags &= ~KLF_WAIT_FOR_ADDR1;
+		if (*cp != 0x08 && *cp != 0x94)	/* Invalid address */
+			goto fail;
+
+		sl->rbuff[sl->rcount++] = *cp++;
+
+		sl->flags |= KLF_WAIT_FOR_ADDR2;
+	}
+
+	if (sl->flags & KLF_WAIT_FOR_ADDR2) {
+		if (!count)
+			return;
+
+		sl->flags &= ~KLF_WAIT_FOR_ADDR2;
+		if (*cp != 0x08 && *cp != 0x94)	/* Invalid address */
+			goto fail;
+
+		/* Send negated address */
+		tty_put_char(sl->tty, ~(*cp) & 0xff);
+		sl->dev->stats.tx_bytes++;
+
+		sl->rbuff[sl->rcount++] = *cp++;
+
+		sl->flags |= KLF_WAIT_FOR_CC;
+	}
+
+	if (sl->flags & KLF_WAIT_FOR_CC) {
+		if (!count)
+			return;
+
+		sl->flags &= ~(KLF_WAIT_FOR_CC | KLF_INIT);
+		if (*cp != 0xcc)	/* Invalid response */
+			goto fail;
+
+		sl->rbuff[sl->rcount] = *cp;
+
+		sl_kline_bump(sl);
+
+		sl->rcount = 0;
+
+		/* Wakeup TX queue */
+		netif_wake_queue(sl->dev);
+	}
+	return;
+fail:
+	sl->dev->stats.rx_errors++;
+	while (count--)
+		sl->rbuff[sl->rcount++] = *cp++;
+	sl_kline_bump(sl);
+	netif_wake_queue(sl->dev);
+}
+
+/************************************
+ *  sl_kline_open helper routines.
+ ************************************/
+
+/* Collect hanged up channels */
+static void sl_kline_sync(void)
+{
+	int i;
+	struct net_device *dev;
+	struct sl_kline	  *sl;
+
+	for (i = 0; i < maxdev; i++) {
+		dev = sl_kline_devs[i];
+		if (dev == NULL)
+			break;
+
+		sl = netdev_priv(dev);
+		if (sl->tty)
+			continue;
+		if (dev->flags & IFF_UP)
+			dev_close(dev);
+	}
+}
+
+/* Find a free SL_KLINE channel, and link in this `tty' line. */
+static struct sl_kline *sl_kline_alloc(dev_t line)
+{
+	int i;
+	struct net_device *dev = NULL;
+	struct sl_kline       *sl;
+
+	for (i = 0; i < maxdev; i++) {
+		dev = sl_kline_devs[i];
+		if (dev == NULL)
+			break;
+	}
+
+	/* Sorry, too many, all slots in use */
+	if (i >= maxdev)
+		return NULL;
+
+	dev = alloc_socketdev("sl_kline%d", sizeof(*sl), 0);
+	if (!dev)
+		return NULL;
+	dev->netdev_ops = &sl_kline_ndev_ops;
+	dev->base_addr = i;
+	dev->destructor = sl_kline_ndev_free;
+	dev->mtu = KLINE_MTU;
+
+	sl = netdev_priv(dev);
+
+	/* Initialize channel control data */
+	sl->magic = SL_KLINE_MAGIC;
+	sl->dev	= dev;
+	spin_lock_init(&sl->lock);
+	INIT_WORK(&sl->tx_work, sl_kline_transmit);
+	init_timer(&sl->timer);
+	sl_kline_devs[i] = dev;
+
+	return sl;
+}
+
+/*
+ * Open the high-level part of the SL_KLINE channel.
+ * This function is called by the TTY module when the
+ * SL_KLINE line discipline is called for.  Because we are
+ * sure the tty line exists, we only have to link it to
+ * a free SL_KLINE channel...
+ *
+ * Called in process context serialized from other ldisc calls.
+ */
+
+static int sl_kline_open(struct tty_struct *tty)
+{
+	struct sl_kline *sl;
+	int err;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (tty->ops->write == NULL)
+		return -EOPNOTSUPP;
+
+	/* RTnetlink lock is misused here to serialize concurrent
+	   opens of sl_kline channels. There are better ways, but it is
+	   the simplest one.
+	 */
+	rtnl_lock();
+
+	/* Collect hanged up channels. */
+	sl_kline_sync();
+
+	sl = tty->disc_data;
+
+	err = -EEXIST;
+	/* First make sure we're not already connected. */
+	if (sl && sl->magic == SL_KLINE_MAGIC)
+		goto err_exit;
+
+	/* OK.  Find a free SL_KLINE channel to use. */
+	err = -ENFILE;
+	sl = sl_kline_alloc(tty_devnum(tty));
+	if (sl == NULL)
+		goto err_exit;
+
+	sl->tty = tty;
+	tty->disc_data = sl;
+
+	if (!(sl->flags & KLF_IN_USE)) {
+		/* Perform the low-level SL_KLINE initialization. */
+		sl->rcount   = 0;
+
+		sl->flags |= KLF_IN_USE;
+
+		err = register_candevice(sl->dev);
+		if (err)
+			goto err_free_chan;
+	}
+
+	/* Done.  We have linked the TTY line to a channel. */
+	rtnl_unlock();
+	tty->receive_room = 65536;	/* We don't flow control */
+
+	/* TTY layer expects 0 on success */
+	return 0;
+
+err_free_chan:
+	sl->tty = NULL;
+	tty->disc_data = NULL;
+	sl->flags &= ~KLF_IN_USE;
+
+err_exit:
+	rtnl_unlock();
+
+	/* Count references from TTY module */
+	return err;
+}
+
+/*
+ * Close down a SL_KLINE channel.
+ * This means flushing out any pending queues, and then returning. This
+ * call is serialized against other ldisc functions.
+ *
+ * We also use this method for a hangup event.
+ */
+
+static void sl_kline_close(struct tty_struct *tty)
+{
+	struct sl_kline *sl = (struct sl_kline *) tty->disc_data;
+
+	/* First make sure we're connected. */
+	if (!sl || sl->magic != SL_KLINE_MAGIC || sl->tty != tty)
+		return;
+
+	spin_lock_bh(&sl->lock);
+	tty->disc_data = NULL;
+	sl->tty = NULL;
+	spin_unlock_bh(&sl->lock);
+
+	flush_work(&sl->tx_work);
+
+	/* Flush network side */
+	unregister_netdev(sl->dev);
+	/* This will complete via sl_free_netdev */
+}
+
+static int sl_kline_hangup(struct tty_struct *tty)
+{
+	sl_kline_close(tty);
+	return 0;
+}
+
+/* Perform I/O control on an active SL_KLINE channel. */
+static int sl_kline_ioctl(struct tty_struct *tty, struct file *file,
+		       unsigned int cmd, unsigned long arg)
+{
+	struct sl_kline *sl = (struct sl_kline *) tty->disc_data;
+	unsigned int tmp;
+
+	/* First make sure we're connected. */
+	if (!sl || sl->magic != SL_KLINE_MAGIC)
+		return -EINVAL;
+
+	switch (cmd) {
+	case SIOCGIFNAME:
+		tmp = strlen(sl->dev->name) + 1;
+		if (copy_to_user((void __user *)arg, sl->dev->name, tmp))
+			return -EFAULT;
+		return 0;
+
+	case SIOCSIFHWADDR:
+		return -EINVAL;
+
+	default:
+		return tty_mode_ioctl(tty, file, cmd, arg);
+	}
+}
+
+static struct tty_ldisc_ops sl_kline_ldisc = {
+	.owner		= THIS_MODULE,
+	.magic		= TTY_LDISC_MAGIC,
+	.name		= "sl_kline",
+	.open		= sl_kline_open,
+	.close		= sl_kline_close,
+	.hangup		= sl_kline_hangup,
+	.ioctl		= sl_kline_ioctl,
+	.receive_buf	= sl_kline_receive_buf,
+	.write_wakeup	= sl_kline_write_wakeup,
+};
+
+static int __init sl_kline_init(void)
+{
+	int status;
+
+	if (maxdev < 4)
+		maxdev = 4; /* Sanity */
+
+	pr_info("sl_kline: serial line K-Line interface driver\n");
+	pr_info("sl_kline: %d dynamic interface channels.\n", maxdev);
+
+	sl_kline_devs = kzalloc(sizeof(struct net_device *)*maxdev, GFP_KERNEL);
+	if (!sl_kline_devs)
+		return -ENOMEM;
+
+	/* Fill in our line protocol discipline, and register it */
+	status = tty_register_ldisc(N_SL_KLINE, &sl_kline_ldisc);
+	if (status)  {
+		pr_err("sl_kline: can't register line discipline\n");
+		kfree(sl_kline_devs);
+	}
+	return status;
+}
+
+static void __exit sl_kline_exit(void)
+{
+	int i;
+	struct net_device *dev;
+	struct sl_kline *sl;
+	unsigned long timeout = jiffies + HZ;
+	int busy = 0;
+
+	if (sl_kline_devs == NULL)
+		return;
+
+	/* First of all: check for active disciplines and hangup them.
+	 */
+	do {
+		if (busy)
+			msleep_interruptible(100);
+
+		busy = 0;
+		for (i = 0; i < maxdev; i++) {
+			dev = sl_kline_devs[i];
+			if (!dev)
+				continue;
+			sl = netdev_priv(dev);
+			spin_lock_bh(&sl->lock);
+			if (sl->tty) {
+				busy++;
+				tty_hangup(sl->tty);
+			}
+			spin_unlock_bh(&sl->lock);
+		}
+	} while (busy && time_before(jiffies, timeout));
+
+	/* FIXME: hangup is async so we should wait when doing this second
+	   phase */
+
+	for (i = 0; i < maxdev; i++) {
+		dev = sl_kline_devs[i];
+		if (!dev)
+			continue;
+		sl_kline_devs[i] = NULL;
+
+		sl = netdev_priv(dev);
+		if (sl->tty) {
+			pr_err("%s: tty discipline still running\n",
+			       dev->name);
+			/* Intentionally leak the control block. */
+			dev->destructor = NULL;
+		}
+
+		unregister_netdev(dev);
+	}
+
+	kfree(sl_kline_devs);
+	sl_kline_devs = NULL;
+
+	i = tty_unregister_ldisc(N_SL_KLINE);
+	if (i)
+		printk(KERN_ERR "sl_kline: can't unregister ldisc (err %d)\n", i);
+}
+
+module_init(sl_kline_init);
+module_exit(sl_kline_exit);
diff --git a/include/uapi/linux/can.h b/include/uapi/linux/can.h
index 9692cda..732cdc0 100644
--- a/include/uapi/linux/can.h
+++ b/include/uapi/linux/can.h
@@ -89,6 +89,10 @@ typedef __u32 can_err_mask_t;
 #define CANFD_MAX_DLC 15
 #define CANFD_MAX_DLEN 64
 
+/* KLine payload length and DLC FIXME */
+#define KLINE_MAX_DLC	15
+#define KLINE_MAX_DLEN	255
+
 /**
  * struct can_frame - basic CAN frame structure
  * @can_id:  CAN ID of the frame and CAN_*_FLAG flags, see canid_t definition
@@ -146,8 +150,37 @@ struct canfd_frame {
 	__u8    data[CANFD_MAX_DLEN] __attribute__((aligned(8)));
 };
 
+/*
+ * FIXME
+ * defined bits for kline_frame.flags
+ *
+ */
+#define KLINE_ISO9141_START 0x1  /* ISO slow start sequence */
+#define KLINE_KWP_SLOW_START 0x2 /* KWP slow start sequence */
+#define KLINE_KWP_FAST_START 0x4 /* KWP fast start sequence */
+
+/**
+ * FIXME
+ * struct canfd_frame - CAN flexible data rate frame structure
+ * @can_id: CAN ID of the frame and CAN_*_FLAG flags, see canid_t definition
+ * @len:    frame payload length in byte (0 .. CANFD_MAX_DLEN)
+ * @flags:  additional flags for CAN FD
+ * @__res0: reserved / padding
+ * @__res1: reserved / padding
+ * @data:   CAN FD frame payload (up to CANFD_MAX_DLEN byte)
+ */
+struct kline_frame {
+	canid_t can_id;  /* 32 bit KLine address + EFF/RTR/ERR flags (unused) */
+	__u8    len;     /* frame payload length in byte */
+	__u8    flags;   /* additional flags for KLine */
+	__u8    __res0;  /* reserved / padding */
+	__u8    __res1;  /* reserved / padding */
+	__u8    data[KLINE_MAX_DLEN] __attribute__((aligned(8)));
+};
+
 #define CAN_MTU		(sizeof(struct can_frame))
 #define CANFD_MTU	(sizeof(struct canfd_frame))
+#define KLINE_MTU	(sizeof(struct kline_frame))
 
 /* particular protocols of the protocol family PF_CAN */
 #define CAN_RAW		1 /* RAW sockets */
diff --git a/include/uapi/linux/tty.h b/include/uapi/linux/tty.h
index 01c4410..80b8f1e 100644
--- a/include/uapi/linux/tty.h
+++ b/include/uapi/linux/tty.h
@@ -35,5 +35,6 @@
 #define N_TRACESINK	23	/* Trace data routing for MIPI P1149.7 */
 #define N_TRACEROUTER	24	/* Trace data routing for MIPI P1149.7 */
 #define N_NCI		25	/* NFC NCI UART */
+#define N_SL_KLINE	26	/* ISO 9141-2 K-Line via SocketCAN */
 
 #endif /* _UAPI_LINUX_TTY_H */
diff --git a/net/can/af_can.c b/net/can/af_can.c
index 166d436..1a8b836 100644
--- a/net/can/af_can.c
+++ b/net/can/af_can.c
@@ -238,6 +238,10 @@ int can_send(struct sk_buff *skb, int loop)
 		skb->protocol = htons(ETH_P_CANFD);
 		if (unlikely(cfd->len > CANFD_MAX_DLEN))
 			goto inval_skb;
+	} else if (skb->len == KLINE_MTU) {
+		skb->protocol = htons(ETH_P_CAN);
+		if (unlikely(cfd->len > KLINE_MAX_DLEN))
+			goto inval_skb;
 	} else
 		goto inval_skb;
 
@@ -715,7 +719,7 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev,
 		goto drop;
 
 	if (WARN_ONCE(dev->type != ARPHRD_CAN ||
-		      skb->len != CAN_MTU ||
+		      (skb->len != CAN_MTU && skb->len != KLINE_MTU) ||
 		      cfd->len > CAN_MAX_DLEN,
 		      "PF_CAN: dropped non conform CAN skbuf: "
 		      "dev type %d, len %d, datalen %d\n",
diff --git a/net/can/raw.c b/net/can/raw.c
index 2e67b14..8a95404 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -734,7 +734,7 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
 		if (unlikely(size != CANFD_MTU && size != CAN_MTU))
 			return -EINVAL;
 	} else {
-		if (unlikely(size != CAN_MTU))
+		if (unlikely((size != CAN_MTU) && (size != KLINE_MTU)))
 			return -EINVAL;
 	}
 
-- 
2.7.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH 4/5][RFC] can: kline: Add KLine rtnl configuration options
  2016-06-09 19:21 ` [PATCH 4/5][RFC] can: kline: Add KLine rtnl configuration options Marek Vasut
@ 2016-06-09 20:21   ` Menschel.P
  2016-06-11 19:40     ` Marek Vasut
  0 siblings, 1 reply; 11+ messages in thread
From: Menschel.P @ 2016-06-09 20:21 UTC (permalink / raw)
  To: Marek Vasut, linux-can

[-- Attachment #1: Type: text/plain, Size: 559 bytes --]

Hello Marek,

these look like the timing parameters for KWP2000 protocol.
> +struct kline_timing {
> +	__u32 w0;
> +	__u32 w1;
> +	__u32 w2;
> +	__u32 w3;
> +	__u32 w4;
> +	__u32 w5;
> +	__u32 p1;
> +	__u32 p2_94;
> +	__u32 p2_08;
> +	__u32 p3;
> +	__u32 p4;
> +};
The wX parameters are the wake up timings and the pX are the response 
timings in between tester and ecu.
Imho the protocol needs to be separated from the device driver since 
there are other protocols like kwp500 and kwp1281 that use k-line.

Regards,
Patrick






[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 3709 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 4/5][RFC] can: kline: Add KLine rtnl configuration options
  2016-06-09 20:21   ` Menschel.P
@ 2016-06-11 19:40     ` Marek Vasut
  2016-06-12 15:36       ` Patrick Menschel
  0 siblings, 1 reply; 11+ messages in thread
From: Marek Vasut @ 2016-06-11 19:40 UTC (permalink / raw)
  To: Menschel.P, linux-can

On 06/09/2016 10:21 PM, Menschel.P wrote:
> Hello Marek,

Hi,

> these look like the timing parameters for KWP2000 protocol.
>> +struct kline_timing {
>> +    __u32 w0;
>> +    __u32 w1;
>> +    __u32 w2;
>> +    __u32 w3;
>> +    __u32 w4;
>> +    __u32 w5;
>> +    __u32 p1;
>> +    __u32 p2_94;
>> +    __u32 p2_08;
>> +    __u32 p3;
>> +    __u32 p4;
>> +};
> The wX parameters are the wake up timings and the pX are the response
> timings in between tester and ecu.
> Imho the protocol needs to be separated from the device driver since
> there are other protocols like kwp500 and kwp1281 that use k-line.

Do you have some idea how to design the framework ?

-- 
Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 4/5][RFC] can: kline: Add KLine rtnl configuration options
  2016-06-11 19:40     ` Marek Vasut
@ 2016-06-12 15:36       ` Patrick Menschel
  2016-06-12 17:34         ` Marek Vasut
  0 siblings, 1 reply; 11+ messages in thread
From: Patrick Menschel @ 2016-06-12 15:36 UTC (permalink / raw)
  To: Marek Vasut, linux-can

[-- Attachment #1: Type: text/plain, Size: 1291 bytes --]

Am 11.06.2016 um 21:40 schrieb Marek Vasut:
> On 06/09/2016 10:21 PM, Menschel.P wrote:
>> Hello Marek,
> 
> Hi,
> 
>> these look like the timing parameters for KWP2000 protocol.
>>> +struct kline_timing {
>>> +    __u32 w0;
>>> +    __u32 w1;
>>> +    __u32 w2;
>>> +    __u32 w3;
>>> +    __u32 w4;
>>> +    __u32 w5;
>>> +    __u32 p1;
>>> +    __u32 p2_94;
>>> +    __u32 p2_08;
>>> +    __u32 p3;
>>> +    __u32 p4;
>>> +};
>> The wX parameters are the wake up timings and the pX are the response
>> timings in between tester and ecu.
>> Imho the protocol needs to be separated from the device driver since
>> there are other protocols like kwp500 and kwp1281 that use k-line.
> 
> Do you have some idea how to design the framework ?
> 

Hi,

As I wrote before, I favor the serial port since K-Line is pure serial
communication.
Let the serial driver do the wakeup pattern in kernel space by using
pinctl to pull up/ down the line for the necessary time.
If no pinctl available use regular RTS/CTS pins with external
transistors. There is already an extension for RS485 support, e.g. RX/TX
switching of the transceiver PHY.

The protocol handler would hand the wakeup parameters to the serial
driver when Open() is called.

Regards,
Patrick


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 3709 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 4/5][RFC] can: kline: Add KLine rtnl configuration options
  2016-06-12 15:36       ` Patrick Menschel
@ 2016-06-12 17:34         ` Marek Vasut
  0 siblings, 0 replies; 11+ messages in thread
From: Marek Vasut @ 2016-06-12 17:34 UTC (permalink / raw)
  To: Patrick Menschel, linux-can

On 06/12/2016 05:36 PM, Patrick Menschel wrote:
> Am 11.06.2016 um 21:40 schrieb Marek Vasut:
>> On 06/09/2016 10:21 PM, Menschel.P wrote:
>>> Hello Marek,
>>
>> Hi,
>>
>>> these look like the timing parameters for KWP2000 protocol.
>>>> +struct kline_timing {
>>>> +    __u32 w0;
>>>> +    __u32 w1;
>>>> +    __u32 w2;
>>>> +    __u32 w3;
>>>> +    __u32 w4;
>>>> +    __u32 w5;
>>>> +    __u32 p1;
>>>> +    __u32 p2_94;
>>>> +    __u32 p2_08;
>>>> +    __u32 p3;
>>>> +    __u32 p4;
>>>> +};
>>> The wX parameters are the wake up timings and the pX are the response
>>> timings in between tester and ecu.
>>> Imho the protocol needs to be separated from the device driver since
>>> there are other protocols like kwp500 and kwp1281 that use k-line.
>>
>> Do you have some idea how to design the framework ?
>>
> 
> Hi,
> 
> As I wrote before, I favor the serial port since K-Line is pure serial
> communication.
> Let the serial driver do the wakeup pattern in kernel space by using
> pinctl to pull up/ down the line for the necessary time.

Not the serial driver, this can be all moved into a line discipline
to avoid adding cruft into the serial driver itself. But how do you
propose to configure the necessary timings, by IOCTLs ? That feels
like bloating the interface. Sysfs might also work, though I am not
sure about that.

> If no pinctl available use regular RTS/CTS pins with external
> transistors. There is already an extension for RS485 support, e.g. RX/TX
> switching of the transceiver PHY.

The RS485 bit can only ever work if the UART supports it. I have seen
some parts using GPIO for the switching and that cannot work reliably
on higher-speed links.

> The protocol handler would hand the wakeup parameters to the serial
> driver when Open() is called.

How ?

> Regards,
> Patrick
> 


-- 
Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/5][RFC] can: slcan: Replace sizeof struct can_frame with CAN_MTU
  2016-06-09 19:21 [PATCH 1/5][RFC] can: slcan: Replace sizeof struct can_frame with CAN_MTU Marek Vasut
                   ` (3 preceding siblings ...)
  2016-06-09 19:21 ` [PATCH 5/5][RFC] can: kline: Add KLine ldisc Marek Vasut
@ 2016-06-17  9:24 ` Marc Kleine-Budde
  2016-06-17  9:25   ` Marek Vasut
  4 siblings, 1 reply; 11+ messages in thread
From: Marc Kleine-Budde @ 2016-06-17  9:24 UTC (permalink / raw)
  To: Marek Vasut, linux-can; +Cc: Oliver Hartkopp


[-- Attachment #1.1: Type: text/plain, Size: 605 bytes --]

On 06/09/2016 09:21 PM, Marek Vasut wrote:
> Use CAN_MTU macro instead of sizeof(struct can_frame) just like the
> other drivers do.
> 
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Oliver Hartkopp <socketcan@hartkopp.net>
> Cc: Marc Kleine-Budde <mkl@pengutronix.de>

Added this one to can-next.

Thnaks,
Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 455 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/5][RFC] can: slcan: Replace sizeof struct can_frame with CAN_MTU
  2016-06-17  9:24 ` [PATCH 1/5][RFC] can: slcan: Replace sizeof struct can_frame with CAN_MTU Marc Kleine-Budde
@ 2016-06-17  9:25   ` Marek Vasut
  0 siblings, 0 replies; 11+ messages in thread
From: Marek Vasut @ 2016-06-17  9:25 UTC (permalink / raw)
  To: Marc Kleine-Budde, linux-can; +Cc: Oliver Hartkopp

On 06/17/2016 11:24 AM, Marc Kleine-Budde wrote:
> On 06/09/2016 09:21 PM, Marek Vasut wrote:
>> Use CAN_MTU macro instead of sizeof(struct can_frame) just like the
>> other drivers do.
>>
>> Signed-off-by: Marek Vasut <marex@denx.de>
>> Cc: Oliver Hartkopp <socketcan@hartkopp.net>
>> Cc: Marc Kleine-Budde <mkl@pengutronix.de>
> 
> Added this one to can-next.

Thnaks, at least this one was a bit helpful.

> Thnaks,
> Marc
> 


-- 
Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2016-06-17  9:26 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-09 19:21 [PATCH 1/5][RFC] can: slcan: Replace sizeof struct can_frame with CAN_MTU Marek Vasut
2016-06-09 19:21 ` [PATCH 2/5][RFC] can: Factor out alloc_socketdev() Marek Vasut
2016-06-09 19:21 ` [PATCH 3/5][RFC] can: Add register_candevice() Marek Vasut
2016-06-09 19:21 ` [PATCH 4/5][RFC] can: kline: Add KLine rtnl configuration options Marek Vasut
2016-06-09 20:21   ` Menschel.P
2016-06-11 19:40     ` Marek Vasut
2016-06-12 15:36       ` Patrick Menschel
2016-06-12 17:34         ` Marek Vasut
2016-06-09 19:21 ` [PATCH 5/5][RFC] can: kline: Add KLine ldisc Marek Vasut
2016-06-17  9:24 ` [PATCH 1/5][RFC] can: slcan: Replace sizeof struct can_frame with CAN_MTU Marc Kleine-Budde
2016-06-17  9:25   ` Marek Vasut

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.