2019-06-04 10:11:33 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2006-03-31 02:31:07 -08:00
/*
* LED Kernel Timer Trigger
*
* Copyright 2005 - 2006 Openedhand Ltd .
*
* Author : Richard Purdie < rpurdie @ openedhand . com >
*/
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/device.h>
2006-05-15 09:44:17 -07:00
# include <linux/ctype.h>
2019-01-09 15:44:49 +01:00
# include <linux/slab.h>
2006-03-31 02:31:07 -08:00
# include <linux/leds.h>
2008-03-09 20:59:57 +00:00
static ssize_t led_delay_on_show ( struct device * dev ,
2007-07-08 23:19:31 +01:00
struct device_attribute * attr , char * buf )
2006-03-31 02:31:07 -08:00
{
2018-07-02 22:05:27 +02:00
struct led_classdev * led_cdev = led_trigger_get_led ( dev ) ;
2006-03-31 02:31:07 -08:00
2010-11-11 14:05:21 -08:00
return sprintf ( buf , " %lu \n " , led_cdev - > blink_delay_on ) ;
2006-03-31 02:31:07 -08:00
}
2008-03-09 20:59:57 +00:00
static ssize_t led_delay_on_store ( struct device * dev ,
2007-07-08 23:19:31 +01:00
struct device_attribute * attr , const char * buf , size_t size )
2006-03-31 02:31:07 -08:00
{
2018-07-02 22:05:27 +02:00
struct led_classdev * led_cdev = led_trigger_get_led ( dev ) ;
2012-05-29 15:07:26 -07:00
unsigned long state ;
2020-04-20 23:12:29 +01:00
ssize_t ret ;
2006-03-31 02:31:07 -08:00
2012-05-29 15:07:26 -07:00
ret = kstrtoul ( buf , 10 , & state ) ;
if ( ret )
return ret ;
2006-05-15 09:44:17 -07:00
2012-05-29 15:07:26 -07:00
led_blink_set ( led_cdev , & state , & led_cdev - > blink_delay_off ) ;
led_cdev - > blink_delay_on = state ;
2006-03-31 02:31:07 -08:00
2012-05-29 15:07:26 -07:00
return size ;
2006-03-31 02:31:07 -08:00
}
2008-03-09 20:59:57 +00:00
static ssize_t led_delay_off_show ( struct device * dev ,
2007-07-08 23:19:31 +01:00
struct device_attribute * attr , char * buf )
2006-03-31 02:31:07 -08:00
{
2018-07-02 22:05:27 +02:00
struct led_classdev * led_cdev = led_trigger_get_led ( dev ) ;
2006-03-31 02:31:07 -08:00
2010-11-11 14:05:21 -08:00
return sprintf ( buf , " %lu \n " , led_cdev - > blink_delay_off ) ;
2006-03-31 02:31:07 -08:00
}
2008-03-09 20:59:57 +00:00
static ssize_t led_delay_off_store ( struct device * dev ,
2007-07-08 23:19:31 +01:00
struct device_attribute * attr , const char * buf , size_t size )
2006-03-31 02:31:07 -08:00
{
2018-07-02 22:05:27 +02:00
struct led_classdev * led_cdev = led_trigger_get_led ( dev ) ;
2012-05-29 15:07:26 -07:00
unsigned long state ;
2020-04-20 23:12:29 +01:00
ssize_t ret ;
2006-05-15 09:44:17 -07:00
2012-05-29 15:07:26 -07:00
ret = kstrtoul ( buf , 10 , & state ) ;
if ( ret )
return ret ;
2006-03-31 02:31:07 -08:00
2012-05-29 15:07:26 -07:00
led_blink_set ( led_cdev , & led_cdev - > blink_delay_on , & state ) ;
led_cdev - > blink_delay_off = state ;
2006-03-31 02:31:07 -08:00
2012-05-29 15:07:26 -07:00
return size ;
2006-03-31 02:31:07 -08:00
}
2007-07-08 23:19:31 +01:00
static DEVICE_ATTR ( delay_on , 0644 , led_delay_on_show , led_delay_on_store ) ;
static DEVICE_ATTR ( delay_off , 0644 , led_delay_off_show , led_delay_off_store ) ;
2006-03-31 02:31:07 -08:00
2018-07-02 22:05:27 +02:00
static struct attribute * timer_trig_attrs [ ] = {
& dev_attr_delay_on . attr ,
& dev_attr_delay_off . attr ,
NULL
} ;
ATTRIBUTE_GROUPS ( timer_trig ) ;
2019-01-09 15:44:49 +01:00
static void pattern_init ( struct led_classdev * led_cdev )
{
u32 * pattern ;
unsigned int size = 0 ;
pattern = led_get_default_pattern ( led_cdev , & size ) ;
if ( ! pattern )
return ;
if ( size ! = 2 ) {
dev_warn ( led_cdev - > dev ,
" Expected 2 but got %u values for delays pattern \n " ,
size ) ;
goto out ;
}
led_cdev - > blink_delay_on = pattern [ 0 ] ;
led_cdev - > blink_delay_off = pattern [ 1 ] ;
/* led_blink_set() called by caller */
out :
kfree ( pattern ) ;
}
2018-07-02 22:05:21 +02:00
static int timer_trig_activate ( struct led_classdev * led_cdev )
2006-03-31 02:31:07 -08:00
{
2019-01-09 15:44:49 +01:00
if ( led_cdev - > flags & LED_INIT_DEFAULT_TRIGGER ) {
pattern_init ( led_cdev ) ;
/*
* Mark as initialized even on pattern_init ( ) error because
* any consecutive call to it would produce the same error .
*/
led_cdev - > flags & = ~ LED_INIT_DEFAULT_TRIGGER ;
}
2019-05-26 09:38:55 +02:00
/*
* If " set brightness to 0 " is pending in workqueue , we don ' t
* want that to be reordered after blink_set ( )
*/
flush_work ( & led_cdev - > set_brightness_work ) ;
2011-05-24 17:13:22 -07:00
led_blink_set ( led_cdev , & led_cdev - > blink_delay_on ,
& led_cdev - > blink_delay_off ) ;
2018-07-02 22:05:21 +02:00
return 0 ;
2006-03-31 02:31:07 -08:00
}
static void timer_trig_deactivate ( struct led_classdev * led_cdev )
{
2010-11-11 14:05:21 -08:00
/* Stop blinking */
2012-06-14 04:34:30 +08:00
led_set_brightness ( led_cdev , LED_OFF ) ;
2006-03-31 02:31:07 -08:00
}
static struct led_trigger timer_led_trigger = {
. name = " timer " ,
. activate = timer_trig_activate ,
. deactivate = timer_trig_deactivate ,
2018-07-02 22:05:27 +02:00
. groups = timer_trig_groups ,
2006-03-31 02:31:07 -08:00
} ;
2018-07-02 22:05:27 +02:00
module_led_trigger ( timer_led_trigger ) ;
2006-03-31 02:31:07 -08:00
MODULE_AUTHOR ( " Richard Purdie <rpurdie@openedhand.com> " ) ;
MODULE_DESCRIPTION ( " Timer LED trigger " ) ;
2018-07-02 22:05:20 +02:00
MODULE_LICENSE ( " GPL v2 " ) ;