linux/drivers/leds/trigger/ledtrig-timer.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * LED Kernel Timer Trigger
   4 *
   5 * Copyright 2005-2006 Openedhand Ltd.
   6 *
   7 * Author: Richard Purdie <rpurdie@openedhand.com>
   8 */
   9
  10#include <linux/module.h>
  11#include <linux/kernel.h>
  12#include <linux/init.h>
  13#include <linux/device.h>
  14#include <linux/ctype.h>
  15#include <linux/slab.h>
  16#include <linux/leds.h>
  17
  18static ssize_t led_delay_on_show(struct device *dev,
  19                struct device_attribute *attr, char *buf)
  20{
  21        struct led_classdev *led_cdev = led_trigger_get_led(dev);
  22
  23        return sprintf(buf, "%lu\n", led_cdev->blink_delay_on);
  24}
  25
  26static ssize_t led_delay_on_store(struct device *dev,
  27                struct device_attribute *attr, const char *buf, size_t size)
  28{
  29        struct led_classdev *led_cdev = led_trigger_get_led(dev);
  30        unsigned long state;
  31        ssize_t ret;
  32
  33        ret = kstrtoul(buf, 10, &state);
  34        if (ret)
  35                return ret;
  36
  37        led_blink_set(led_cdev, &state, &led_cdev->blink_delay_off);
  38        led_cdev->blink_delay_on = state;
  39
  40        return size;
  41}
  42
  43static ssize_t led_delay_off_show(struct device *dev,
  44                struct device_attribute *attr, char *buf)
  45{
  46        struct led_classdev *led_cdev = led_trigger_get_led(dev);
  47
  48        return sprintf(buf, "%lu\n", led_cdev->blink_delay_off);
  49}
  50
  51static ssize_t led_delay_off_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        unsigned long state;
  56        ssize_t ret;
  57
  58        ret = kstrtoul(buf, 10, &state);
  59        if (ret)
  60                return ret;
  61
  62        led_blink_set(led_cdev, &led_cdev->blink_delay_on, &state);
  63        led_cdev->blink_delay_off = state;
  64
  65        return size;
  66}
  67
  68static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store);
  69static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store);
  70
  71static struct attribute *timer_trig_attrs[] = {
  72        &dev_attr_delay_on.attr,
  73        &dev_attr_delay_off.attr,
  74        NULL
  75};
  76ATTRIBUTE_GROUPS(timer_trig);
  77
  78static void pattern_init(struct led_classdev *led_cdev)
  79{
  80        u32 *pattern;
  81        unsigned int size = 0;
  82
  83        pattern = led_get_default_pattern(led_cdev, &size);
  84        if (!pattern)
  85                return;
  86
  87        if (size != 2) {
  88                dev_warn(led_cdev->dev,
  89                         "Expected 2 but got %u values for delays pattern\n",
  90                         size);
  91                goto out;
  92        }
  93
  94        led_cdev->blink_delay_on = pattern[0];
  95        led_cdev->blink_delay_off = pattern[1];
  96        /* led_blink_set() called by caller */
  97
  98out:
  99        kfree(pattern);
 100}
 101
 102static int timer_trig_activate(struct led_classdev *led_cdev)
 103{
 104        if (led_cdev->flags & LED_INIT_DEFAULT_TRIGGER) {
 105                pattern_init(led_cdev);
 106                /*
 107                 * Mark as initialized even on pattern_init() error because
 108                 * any consecutive call to it would produce the same error.
 109                 */
 110                led_cdev->flags &= ~LED_INIT_DEFAULT_TRIGGER;
 111        }
 112
 113        /*
 114         * If "set brightness to 0" is pending in workqueue, we don't
 115         * want that to be reordered after blink_set()
 116         */
 117        flush_work(&led_cdev->set_brightness_work);
 118        led_blink_set(led_cdev, &led_cdev->blink_delay_on,
 119                      &led_cdev->blink_delay_off);
 120
 121        return 0;
 122}
 123
 124static void timer_trig_deactivate(struct led_classdev *led_cdev)
 125{
 126        /* Stop blinking */
 127        led_set_brightness(led_cdev, LED_OFF);
 128}
 129
 130static struct led_trigger timer_led_trigger = {
 131        .name     = "timer",
 132        .activate = timer_trig_activate,
 133        .deactivate = timer_trig_deactivate,
 134        .groups = timer_trig_groups,
 135};
 136module_led_trigger(timer_led_trigger);
 137
 138MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
 139MODULE_DESCRIPTION("Timer LED trigger");
 140MODULE_LICENSE("GPL v2");
 141