All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] leds: ledtrig-tty: add tty_led_mode xtension
@ 2023-02-17  9:44 Florian Eckert
  2023-02-17  9:44 ` [PATCH v2 1/2] tty: new helper function tty_get_mget Florian Eckert
  2023-02-17  9:44 ` [PATCH v2 2/2] trigger: ledtrig-tty: add additional modes Florian Eckert
  0 siblings, 2 replies; 4+ messages in thread
From: Florian Eckert @ 2023-02-17  9:44 UTC (permalink / raw)
  To: u.kleine-koenig, gregkh, jirislaby, pavel, lee
  Cc: linux-kernel, linux-leds, Eckert.Florian

Hello,

here commes v2 of this series to add additional tty_led_modes.
Changes compared to the initial patchset with
20230213140638.620206-1-fe@dev.tdt.de are.

Addressed review comments by Jiri Slaby are:

tty.h:
- Fix compilation error because of wrong rebaseing
- Remove empty lines
- Use new 'tty_get_mget' in 'tty_tiocmget'

ledtrg-tty.c:
- Update commit description
- Use enum for tty_led_mod in struct ledtrig_tty_date
- Rename sysfs file from 'mode' to 'tty_led_mode'
- Change tty_led_mode show function to use loop instead of switch/case
- Change tty_led_mode store function to use loop instead of switch/case
- Check return value of function tty_get_mget

Florian Eckert (2):
  tty: new helper function tty_get_mget
  trigger: ledtrig-tty: add additional modes

 .../ABI/testing/sysfs-class-led-trigger-tty   |  16 ++
 drivers/leds/trigger/ledtrig-tty.c            | 146 ++++++++++++++++--
 drivers/tty/tty_io.c                          |  30 +++-
 include/linux/tty.h                           |   1 +
 4 files changed, 171 insertions(+), 22 deletions(-)

-- 
2.30.2


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

* [PATCH v2 1/2] tty: new helper function tty_get_mget
  2023-02-17  9:44 [PATCH v2 0/2] leds: ledtrig-tty: add tty_led_mode xtension Florian Eckert
@ 2023-02-17  9:44 ` Florian Eckert
  2023-02-17  9:49   ` Greg KH
  2023-02-17  9:44 ` [PATCH v2 2/2] trigger: ledtrig-tty: add additional modes Florian Eckert
  1 sibling, 1 reply; 4+ messages in thread
From: Florian Eckert @ 2023-02-17  9:44 UTC (permalink / raw)
  To: u.kleine-koenig, gregkh, jirislaby, pavel, lee
  Cc: linux-kernel, linux-leds, Eckert.Florian

For a given struct tty_struct, this provides the appropriate tty line
state flags needed to add more modes to the ledtrig-tty trigger.

The new function is then used to get via tty_tiocmget() the different tty
line states.

Signed-off-by: Florian Eckert <fe@dev.tdt.de>
---
 drivers/tty/tty_io.c | 30 +++++++++++++++++++++++-------
 include/linux/tty.h  |  1 +
 2 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 3149114bf130..f049ab8b3362 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -2493,26 +2493,42 @@ static int send_break(struct tty_struct *tty, unsigned int duration)
 	return retval;
 }
 
+/*
+ * tty_get_mget		-	get modem status
+ * @tty: tty device
+ *
+ * Obtain the modem status bits from the tty driver if the feature
+ * is supported. Return -ENOTTY if it is not available.
+ */
+int tty_get_mget(struct tty_struct *tty)
+{
+	int retval = -ENOTTY;
+
+	if (tty->ops->tiocmget)
+		retval = tty->ops->tiocmget(tty);
+
+	return retval;
+}
+EXPORT_SYMBOL_GPL(tty_get_mget);
+
 /**
  * tty_tiocmget		-	get modem status
  * @tty: tty device
  * @p: pointer to result
  *
  * Obtain the modem status bits from the tty driver if the feature is
- * supported. Return -%ENOTTY if it is not available.
+ * supported.
  *
  * Locking: none (up to the driver)
  */
 static int tty_tiocmget(struct tty_struct *tty, int __user *p)
 {
-	int retval = -ENOTTY;
+	int retval;
 
-	if (tty->ops->tiocmget) {
-		retval = tty->ops->tiocmget(tty);
+	retval = tty_get_mget(tty);
+	if (retval >= 0)
+		retval = put_user(retval, p);
 
-		if (retval >= 0)
-			retval = put_user(retval, p);
-	}
 	return retval;
 }
 
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 730c3301d710..825186c0fec1 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -421,6 +421,7 @@ int tty_unthrottle_safe(struct tty_struct *tty);
 int tty_do_resize(struct tty_struct *tty, struct winsize *ws);
 int tty_get_icount(struct tty_struct *tty,
 		struct serial_icounter_struct *icount);
+int tty_get_mget(struct tty_struct *tty);
 int is_current_pgrp_orphaned(void);
 void tty_hangup(struct tty_struct *tty);
 void tty_vhangup(struct tty_struct *tty);
-- 
2.30.2


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

* [PATCH v2 2/2] trigger: ledtrig-tty: add additional modes
  2023-02-17  9:44 [PATCH v2 0/2] leds: ledtrig-tty: add tty_led_mode xtension Florian Eckert
  2023-02-17  9:44 ` [PATCH v2 1/2] tty: new helper function tty_get_mget Florian Eckert
@ 2023-02-17  9:44 ` Florian Eckert
  1 sibling, 0 replies; 4+ messages in thread
From: Florian Eckert @ 2023-02-17  9:44 UTC (permalink / raw)
  To: u.kleine-koenig, gregkh, jirislaby, pavel, lee
  Cc: linux-kernel, linux-leds, Eckert.Florian

Until now, the LED is flashed when data is transmitted. With a
legacy serial interface there are additional input signal lines.

CTS: Clear To Send       -> DCE is ready to accept data from the DTE
DSR: Data Set Ready      -> DCE is ready to receive and send data.
CAR: Data Carrier Detect -> DCE is receiving a carrier from a remote DCE.
RNG: Ring Indicator      -> DCE has detected an incoming ring on the line.

Add additional modes to trigger the selected LED.
The following modes are supported:

Tx/Rx:	Flash LED on data transmission (default)
CTS:	DCE Ready to accept data from the DTE.
DSR:	DCE is ready to receive and send data.
CAR:	DCE is receiving a carrier from a remote DTE.
RNG:	DCE has detected an incoming ring signal.

The mode can be changed for example with the following command:
echo "CTS" > /sys/class/leds/<led>/tty_led_mode

This would turn on the LED, when the DTE(modem) signals the DCE that it
is ready to accept data.

Signed-off-by: Florian Eckert <fe@dev.tdt.de>
---
 .../ABI/testing/sysfs-class-led-trigger-tty   |  16 ++
 drivers/leds/trigger/ledtrig-tty.c            | 146 ++++++++++++++++--
 2 files changed, 147 insertions(+), 15 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-led-trigger-tty b/Documentation/ABI/testing/sysfs-class-led-trigger-tty
index 2bf6b24e781b..31d62a5ae095 100644
--- a/Documentation/ABI/testing/sysfs-class-led-trigger-tty
+++ b/Documentation/ABI/testing/sysfs-class-led-trigger-tty
@@ -4,3 +4,19 @@ KernelVersion:	5.10
 Contact:	linux-leds@vger.kernel.org
 Description:
 		Specifies the tty device name of the triggering tty
+
+What:		/sys/class/leds/<led>/mode
+Date:		January 2023
+KernelVersion:	6.3
+Description:
+		Specifies the operating to trigger the LED.
+		The following operating modes are supported:
+		Tx/Rx: Flash LED on data transmission (default)
+		CTS:   DCE Ready to accept data from the DTE.
+		       LED on if line is high.
+		DSR:   DCE is ready to receive and send data.
+		       LED on if line is high.
+		CAR:   DCE is receiving a carrier from a remote DTE.
+		       LED on if line is high.
+		RNG:   DCE has detected an incoming ring signal.
+		       LED on if line is high.
diff --git a/drivers/leds/trigger/ledtrig-tty.c b/drivers/leds/trigger/ledtrig-tty.c
index f62db7e520b5..09d1be7b8ffb 100644
--- a/drivers/leds/trigger/ledtrig-tty.c
+++ b/drivers/leds/trigger/ledtrig-tty.c
@@ -7,6 +7,15 @@
 #include <linux/tty.h>
 #include <uapi/linux/serial.h>
 
+enum tty_led_mode {
+	TTY_LED_CNT,
+	TTY_LED_CTS,
+	TTY_LED_DSR,
+	TTY_LED_CAR,
+	TTY_LED_RNG,
+	__TTY_LED_MAX
+};
+
 struct ledtrig_tty_data {
 	struct led_classdev *led_cdev;
 	struct delayed_work dwork;
@@ -14,6 +23,15 @@ struct ledtrig_tty_data {
 	const char *ttyname;
 	struct tty_struct *tty;
 	int rx, tx;
+	enum tty_led_mode mode;
+};
+
+static const char * const mode[] = {
+	[TTY_LED_CNT] = "Tx/Rx", // Trasmit Data / Receive Data
+	[TTY_LED_CTS] = "CTS", // CTS Clear To Send
+	[TTY_LED_DSR] = "DSR", // DSR Data Set Ready
+	[TTY_LED_CAR] = "CAR", // CAR Data Carrier Detect (DCD)
+	[TTY_LED_RNG] = "RNG", // RNG Ring Indicator (RI)
 };
 
 static void ledtrig_tty_restart(struct ledtrig_tty_data *trigger_data)
@@ -21,6 +39,71 @@ static void ledtrig_tty_restart(struct ledtrig_tty_data *trigger_data)
 	schedule_delayed_work(&trigger_data->dwork, 0);
 }
 
+static ssize_t ledtrig_tty_mode_show(char *buf, enum tty_led_mode tty_mode)
+{
+	int len = 0;
+	int i;
+
+	for (i = 0; i < __TTY_LED_MAX; i++) {
+		bool hit;
+
+		hit = tty_mode == i;
+		len += sysfs_emit_at(buf, len, "%s%s%s",
+				  hit ? "[" : "",
+				  mode[i],
+				  hit ? "]" : "");
+
+		if (i < __TTY_LED_MAX - 1)
+			len += sysfs_emit_at(buf, len, " ");
+	}
+
+	len += sysfs_emit_at(buf, len, "\n");
+
+	return len;
+}
+
+static ssize_t tty_led_mode_show(struct device *dev,
+			 struct device_attribute *attr, char *buf)
+{
+	struct ledtrig_tty_data *trigger_data = led_trigger_get_drvdata(dev);
+	enum tty_led_mode tty_mode;
+
+	mutex_lock(&trigger_data->mutex);
+	tty_mode = trigger_data->mode;
+	mutex_unlock(&trigger_data->mutex);
+
+	return ledtrig_tty_mode_show(buf, tty_mode);
+}
+
+static ssize_t tty_led_mode_store(struct device *dev,
+			  struct device_attribute *attr, const char *buf,
+			  size_t size)
+{
+	struct ledtrig_tty_data *trigger_data = led_trigger_get_drvdata(dev);
+	ssize_t ret = size;
+	enum tty_led_mode tty_mode = __TTY_LED_MAX;
+	int i;
+
+	/* Check for new line in string*/
+	if (size > 0 && buf[size - 1] == '\n')
+		size -= 1;
+
+	for (i = 0; i < __TTY_LED_MAX; i++) {
+		if (strncmp(buf, mode[i], size) == 0)
+			tty_mode = i;
+	}
+
+	if (tty_mode == __TTY_LED_MAX)
+		return -EINVAL;
+
+	mutex_lock(&trigger_data->mutex);
+	trigger_data->mode = tty_mode;
+	mutex_unlock(&trigger_data->mutex);
+
+	return ret;
+}
+static DEVICE_ATTR_RW(tty_led_mode);
+
 static ssize_t ttyname_show(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
@@ -76,6 +159,18 @@ static ssize_t ttyname_store(struct device *dev,
 }
 static DEVICE_ATTR_RW(ttyname);
 
+static void ledtrig_tty_flags(struct ledtrig_tty_data *trigger_data,
+		unsigned int flag)
+{
+	unsigned int status;
+
+	status = tty_get_mget(trigger_data->tty);
+	if (status & flag)
+		led_set_brightness_sync(trigger_data->led_cdev, LED_ON);
+	else
+		led_set_brightness_sync(trigger_data->led_cdev, LED_OFF);
+}
+
 static void ledtrig_tty_work(struct work_struct *work)
 {
 	struct ledtrig_tty_data *trigger_data =
@@ -113,21 +208,38 @@ static void ledtrig_tty_work(struct work_struct *work)
 		trigger_data->tty = tty;
 	}
 
-	ret = tty_get_icount(trigger_data->tty, &icount);
-	if (ret) {
-		dev_info(trigger_data->tty->dev, "Failed to get icount, stopped polling\n");
-		mutex_unlock(&trigger_data->mutex);
-		return;
-	}
-
-	if (icount.rx != trigger_data->rx ||
-	    icount.tx != trigger_data->tx) {
-		led_set_brightness_sync(trigger_data->led_cdev, LED_ON);
-
-		trigger_data->rx = icount.rx;
-		trigger_data->tx = icount.tx;
-	} else {
-		led_set_brightness_sync(trigger_data->led_cdev, LED_OFF);
+	switch (trigger_data->mode) {
+	case TTY_LED_CTS:
+		ledtrig_tty_flags(trigger_data, TIOCM_CTS);
+		break;
+	case TTY_LED_DSR:
+		ledtrig_tty_flags(trigger_data, TIOCM_DSR);
+		break;
+	case TTY_LED_CAR:
+		ledtrig_tty_flags(trigger_data, TIOCM_CAR);
+		break;
+	case TTY_LED_RNG:
+		ledtrig_tty_flags(trigger_data, TIOCM_RNG);
+		break;
+	case TTY_LED_CNT:
+	default:
+		ret = tty_get_icount(trigger_data->tty, &icount);
+		if (ret) {
+			dev_info(trigger_data->tty->dev, "Failed to get icount, stopped polling\n");
+			mutex_unlock(&trigger_data->mutex);
+			return;
+		}
+
+		if (icount.rx != trigger_data->rx ||
+		    icount.tx != trigger_data->tx) {
+			led_set_brightness_sync(trigger_data->led_cdev, LED_ON);
+
+			trigger_data->rx = icount.rx;
+			trigger_data->tx = icount.tx;
+		} else {
+			led_set_brightness_sync(trigger_data->led_cdev, LED_OFF);
+		}
+		break;
 	}
 
 out:
@@ -137,6 +249,7 @@ static void ledtrig_tty_work(struct work_struct *work)
 
 static struct attribute *ledtrig_tty_attrs[] = {
 	&dev_attr_ttyname.attr,
+	&dev_attr_tty_led_mode.attr,
 	NULL
 };
 ATTRIBUTE_GROUPS(ledtrig_tty);
@@ -149,6 +262,9 @@ static int ledtrig_tty_activate(struct led_classdev *led_cdev)
 	if (!trigger_data)
 		return -ENOMEM;
 
+	/* set default mode */
+	trigger_data->mode = TTY_LED_CNT;
+
 	led_set_trigger_data(led_cdev, trigger_data);
 
 	INIT_DELAYED_WORK(&trigger_data->dwork, ledtrig_tty_work);
-- 
2.30.2


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

* Re: [PATCH v2 1/2] tty: new helper function tty_get_mget
  2023-02-17  9:44 ` [PATCH v2 1/2] tty: new helper function tty_get_mget Florian Eckert
@ 2023-02-17  9:49   ` Greg KH
  0 siblings, 0 replies; 4+ messages in thread
From: Greg KH @ 2023-02-17  9:49 UTC (permalink / raw)
  To: Florian Eckert
  Cc: u.kleine-koenig, jirislaby, pavel, lee, linux-kernel, linux-leds,
	Eckert.Florian

On Fri, Feb 17, 2023 at 10:44:02AM +0100, Florian Eckert wrote:
> For a given struct tty_struct, this provides the appropriate tty line
> state flags needed to add more modes to the ledtrig-tty trigger.
> 
> The new function is then used to get via tty_tiocmget() the different tty
> line states.
> 
> Signed-off-by: Florian Eckert <fe@dev.tdt.de>
> ---
>  drivers/tty/tty_io.c | 30 +++++++++++++++++++++++-------
>  include/linux/tty.h  |  1 +
>  2 files changed, 24 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
> index 3149114bf130..f049ab8b3362 100644
> --- a/drivers/tty/tty_io.c
> +++ b/drivers/tty/tty_io.c
> @@ -2493,26 +2493,42 @@ static int send_break(struct tty_struct *tty, unsigned int duration)
>  	return retval;
>  }
>  
> +/*
> + * tty_get_mget		-	get modem status
> + * @tty: tty device
> + *
> + * Obtain the modem status bits from the tty driver if the feature
> + * is supported. Return -ENOTTY if it is not available.

Please make this proper kernel doc, the first comment line has to be /**

And you didn't mark -ENOTTY properly here either :(

> + */
> +int tty_get_mget(struct tty_struct *tty)
> +{
> +	int retval = -ENOTTY;
> +
> +	if (tty->ops->tiocmget)
> +		retval = tty->ops->tiocmget(tty);
> +
> +	return retval;
> +}
> +EXPORT_SYMBOL_GPL(tty_get_mget);
> +
>  /**
>   * tty_tiocmget		-	get modem status
>   * @tty: tty device
>   * @p: pointer to result
>   *
>   * Obtain the modem status bits from the tty driver if the feature is
> - * supported. Return -%ENOTTY if it is not available.
> + * supported.

Why did you remove the return value statement from the documentation
here?  It's still true, right?

thanks,

greg k-h

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

end of thread, other threads:[~2023-02-17  9:49 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-02-17  9:44 [PATCH v2 0/2] leds: ledtrig-tty: add tty_led_mode xtension Florian Eckert
2023-02-17  9:44 ` [PATCH v2 1/2] tty: new helper function tty_get_mget Florian Eckert
2023-02-17  9:49   ` Greg KH
2023-02-17  9:44 ` [PATCH v2 2/2] trigger: ledtrig-tty: add additional modes Florian Eckert

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.