openwrt/target/linux/generic/hack-5.15/820-led-netdev-trigger-invert.patch
James Haggerty 9b6f83e336 linux: (APP-3627, PR #315) add invert ability to LED netdev trigger
When you have an RGB LED with every colour mapped individually,
it's useful to have a different colour for link on vs link off,
particularly in the case where the LED has multiple meanings
(i.e. it's a generic status/power LED as well, so shouldn't just be
turned off in the absence of a link).

This invert code is largely copied from similar code
in other triggers which already support invert.


Approved-by: Sophronia Koilpillai
Approved-by: Evan Benn
2024-11-26 10:03:34 +11:00

94 lines
2.6 KiB
Diff

--- a/drivers/leds/trigger/ledtrig-netdev.c 2024-10-23 12:18:22.727984995 +1100
+++ b/drivers/leds/trigger/ledtrig-netdev.c 2024-10-23 12:40:17.985584090 +1100
@@ -49,6 +49,7 @@
char device_name[IFNAMSIZ];
atomic_t interval;
+ int invert;
unsigned int last_activity;
unsigned long mode;
@@ -75,9 +76,9 @@
led_cdev->blink_brightness = led_cdev->max_brightness;
if (!trigger_data->carrier_link_up) {
- led_set_brightness(led_cdev, LED_OFF);
+ led_set_brightness(led_cdev, trigger_data->invert ? led_cdev->blink_brightness : LED_OFF);
} else {
- if (test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode))
+ if (trigger_data->invert ^ test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode))
led_set_brightness(led_cdev,
led_cdev->blink_brightness);
else
@@ -126,6 +127,9 @@
struct led_classdev *led_cdev = trigger_data->led_cdev;
int ret;
+ if (trigger_data->invert)
+ return false;
+
if (!supports_hw_control(led_cdev))
return false;
@@ -335,12 +339,40 @@
static DEVICE_ATTR_RW(interval);
+static ssize_t invert_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct led_netdev_data *netdev_data = led_trigger_get_drvdata(dev);
+
+ return sprintf(buf, "%u\n", netdev_data->invert);
+}
+
+static ssize_t invert_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct led_netdev_data *netdev_data = led_trigger_get_drvdata(dev);
+ unsigned long state;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &state);
+ if (ret)
+ return ret;
+
+ netdev_data->invert = !!state;
+
+ return size;
+}
+
+static DEVICE_ATTR_RW(invert);
+
static struct attribute *netdev_trig_attrs[] = {
&dev_attr_device_name.attr,
&dev_attr_link.attr,
&dev_attr_rx.attr,
&dev_attr_tx.attr,
&dev_attr_interval.attr,
+ &dev_attr_invert.attr,
NULL
};
ATTRIBUTE_GROUPS(netdev_trig);
@@ -406,9 +438,9 @@
unsigned long interval;
int invert;
- /* If we dont have a device, insure we are off */
+ /* If we don't have a device, ensure we are in the baseline state */
if (!trigger_data->net_dev) {
- led_set_brightness(trigger_data->led_cdev, LED_OFF);
+ set_baseline_state(trigger_data);
return;
}
@@ -427,7 +459,7 @@
if (trigger_data->last_activity != new_activity) {
led_stop_software_blink(trigger_data->led_cdev);
- invert = test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode);
+ invert = trigger_data->invert ^ test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode);
interval = jiffies_to_msecs(
atomic_read(&trigger_data->interval));
/* base state is ON (link present) */