root/drivers/leds/trigger/ledtrig-transient.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. transient_timer_function
  2. transient_activate_show
  3. transient_activate_store
  4. transient_duration_show
  5. transient_duration_store
  6. transient_state_show
  7. transient_state_store
  8. transient_trig_activate
  9. transient_trig_deactivate

   1 // SPDX-License-Identifier: GPL-2.0
   2 //
   3 // LED Kernel Transient Trigger
   4 //
   5 // Transient trigger allows one shot timer activation. Please refer to
   6 // Documentation/leds/ledtrig-transient.rst for details
   7 // Copyright (C) 2012 Shuah Khan <shuahkhan@gmail.com>
   8 //
   9 // Based on Richard Purdie's ledtrig-timer.c and Atsushi Nemoto's
  10 // ledtrig-heartbeat.c
  11 // Design and use-case input from Jonas Bonn <jonas@southpole.se> and
  12 // Neil Brown <neilb@suse.de>
  13 
  14 #include <linux/module.h>
  15 #include <linux/kernel.h>
  16 #include <linux/init.h>
  17 #include <linux/device.h>
  18 #include <linux/slab.h>
  19 #include <linux/timer.h>
  20 #include <linux/leds.h>
  21 #include "../leds.h"
  22 
  23 struct transient_trig_data {
  24         int activate;
  25         int state;
  26         int restore_state;
  27         unsigned long duration;
  28         struct timer_list timer;
  29         struct led_classdev *led_cdev;
  30 };
  31 
  32 static void transient_timer_function(struct timer_list *t)
  33 {
  34         struct transient_trig_data *transient_data =
  35                 from_timer(transient_data, t, timer);
  36         struct led_classdev *led_cdev = transient_data->led_cdev;
  37 
  38         transient_data->activate = 0;
  39         led_set_brightness_nosleep(led_cdev, transient_data->restore_state);
  40 }
  41 
  42 static ssize_t transient_activate_show(struct device *dev,
  43                 struct device_attribute *attr, char *buf)
  44 {
  45         struct transient_trig_data *transient_data =
  46                 led_trigger_get_drvdata(dev);
  47 
  48         return sprintf(buf, "%d\n", transient_data->activate);
  49 }
  50 
  51 static ssize_t transient_activate_store(struct device *dev,
  52                 struct device_attribute *attr, const char *buf, size_t size)
  53 {
  54         struct led_classdev *led_cdev = led_trigger_get_led(dev);
  55         struct transient_trig_data *transient_data =
  56                 led_trigger_get_drvdata(dev);
  57         unsigned long state;
  58         ssize_t ret;
  59 
  60         ret = kstrtoul(buf, 10, &state);
  61         if (ret)
  62                 return ret;
  63 
  64         if (state != 1 && state != 0)
  65                 return -EINVAL;
  66 
  67         /* cancel the running timer */
  68         if (state == 0 && transient_data->activate == 1) {
  69                 del_timer(&transient_data->timer);
  70                 transient_data->activate = state;
  71                 led_set_brightness_nosleep(led_cdev,
  72                                         transient_data->restore_state);
  73                 return size;
  74         }
  75 
  76         /* start timer if there is no active timer */
  77         if (state == 1 && transient_data->activate == 0 &&
  78             transient_data->duration != 0) {
  79                 transient_data->activate = state;
  80                 led_set_brightness_nosleep(led_cdev, transient_data->state);
  81                 transient_data->restore_state =
  82                     (transient_data->state == LED_FULL) ? LED_OFF : LED_FULL;
  83                 mod_timer(&transient_data->timer,
  84                           jiffies + msecs_to_jiffies(transient_data->duration));
  85         }
  86 
  87         /* state == 0 && transient_data->activate == 0
  88                 timer is not active - just return */
  89         /* state == 1 && transient_data->activate == 1
  90                 timer is already active - just return */
  91 
  92         return size;
  93 }
  94 
  95 static ssize_t transient_duration_show(struct device *dev,
  96                 struct device_attribute *attr, char *buf)
  97 {
  98         struct transient_trig_data *transient_data = led_trigger_get_drvdata(dev);
  99 
 100         return sprintf(buf, "%lu\n", transient_data->duration);
 101 }
 102 
 103 static ssize_t transient_duration_store(struct device *dev,
 104                 struct device_attribute *attr, const char *buf, size_t size)
 105 {
 106         struct transient_trig_data *transient_data =
 107                 led_trigger_get_drvdata(dev);
 108         unsigned long state;
 109         ssize_t ret;
 110 
 111         ret = kstrtoul(buf, 10, &state);
 112         if (ret)
 113                 return ret;
 114 
 115         transient_data->duration = state;
 116         return size;
 117 }
 118 
 119 static ssize_t transient_state_show(struct device *dev,
 120                 struct device_attribute *attr, char *buf)
 121 {
 122         struct transient_trig_data *transient_data =
 123                 led_trigger_get_drvdata(dev);
 124         int state;
 125 
 126         state = (transient_data->state == LED_FULL) ? 1 : 0;
 127         return sprintf(buf, "%d\n", state);
 128 }
 129 
 130 static ssize_t transient_state_store(struct device *dev,
 131                 struct device_attribute *attr, const char *buf, size_t size)
 132 {
 133         struct transient_trig_data *transient_data =
 134                 led_trigger_get_drvdata(dev);
 135         unsigned long state;
 136         ssize_t ret;
 137 
 138         ret = kstrtoul(buf, 10, &state);
 139         if (ret)
 140                 return ret;
 141 
 142         if (state != 1 && state != 0)
 143                 return -EINVAL;
 144 
 145         transient_data->state = (state == 1) ? LED_FULL : LED_OFF;
 146         return size;
 147 }
 148 
 149 static DEVICE_ATTR(activate, 0644, transient_activate_show,
 150                    transient_activate_store);
 151 static DEVICE_ATTR(duration, 0644, transient_duration_show,
 152                    transient_duration_store);
 153 static DEVICE_ATTR(state, 0644, transient_state_show, transient_state_store);
 154 
 155 static struct attribute *transient_trig_attrs[] = {
 156         &dev_attr_activate.attr,
 157         &dev_attr_duration.attr,
 158         &dev_attr_state.attr,
 159         NULL
 160 };
 161 ATTRIBUTE_GROUPS(transient_trig);
 162 
 163 static int transient_trig_activate(struct led_classdev *led_cdev)
 164 {
 165         struct transient_trig_data *tdata;
 166 
 167         tdata = kzalloc(sizeof(struct transient_trig_data), GFP_KERNEL);
 168         if (!tdata)
 169                 return -ENOMEM;
 170 
 171         led_set_trigger_data(led_cdev, tdata);
 172         tdata->led_cdev = led_cdev;
 173 
 174         timer_setup(&tdata->timer, transient_timer_function, 0);
 175 
 176         return 0;
 177 }
 178 
 179 static void transient_trig_deactivate(struct led_classdev *led_cdev)
 180 {
 181         struct transient_trig_data *transient_data = led_get_trigger_data(led_cdev);
 182 
 183         del_timer_sync(&transient_data->timer);
 184         led_set_brightness_nosleep(led_cdev, transient_data->restore_state);
 185         kfree(transient_data);
 186 }
 187 
 188 static struct led_trigger transient_trigger = {
 189         .name     = "transient",
 190         .activate = transient_trig_activate,
 191         .deactivate = transient_trig_deactivate,
 192         .groups = transient_trig_groups,
 193 };
 194 module_led_trigger(transient_trigger);
 195 
 196 MODULE_AUTHOR("Shuah Khan <shuahkhan@gmail.com>");
 197 MODULE_DESCRIPTION("Transient LED trigger");
 198 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */