8d82fef8bb
When using the timer trigger and setting delay_on to 0, the led will stay in whatever state is was in, while intuitively one would expect it to turn off. This patch changes the behaviour to turn it off. Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com> Signed-off-by: Bryan Wu <cooloney@gmail.com>
128 lines
3.2 KiB
C
128 lines
3.2 KiB
C
/*
|
|
* LED Class Core
|
|
*
|
|
* Copyright 2005-2006 Openedhand Ltd.
|
|
*
|
|
* Author: Richard Purdie <rpurdie@openedhand.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/list.h>
|
|
#include <linux/module.h>
|
|
#include <linux/rwsem.h>
|
|
#include <linux/leds.h>
|
|
#include "leds.h"
|
|
|
|
DECLARE_RWSEM(leds_list_lock);
|
|
EXPORT_SYMBOL_GPL(leds_list_lock);
|
|
|
|
LIST_HEAD(leds_list);
|
|
EXPORT_SYMBOL_GPL(leds_list);
|
|
|
|
static void led_set_software_blink(struct led_classdev *led_cdev,
|
|
unsigned long delay_on,
|
|
unsigned long delay_off)
|
|
{
|
|
int current_brightness;
|
|
|
|
current_brightness = led_get_brightness(led_cdev);
|
|
if (current_brightness)
|
|
led_cdev->blink_brightness = current_brightness;
|
|
if (!led_cdev->blink_brightness)
|
|
led_cdev->blink_brightness = led_cdev->max_brightness;
|
|
|
|
led_cdev->blink_delay_on = delay_on;
|
|
led_cdev->blink_delay_off = delay_off;
|
|
|
|
/* never on - just set to off */
|
|
if (!delay_on) {
|
|
__led_set_brightness(led_cdev, LED_OFF);
|
|
return;
|
|
}
|
|
|
|
/* never off - just set to brightness */
|
|
if (!delay_off) {
|
|
__led_set_brightness(led_cdev, led_cdev->blink_brightness);
|
|
return;
|
|
}
|
|
|
|
mod_timer(&led_cdev->blink_timer, jiffies + 1);
|
|
}
|
|
|
|
|
|
static void led_blink_setup(struct led_classdev *led_cdev,
|
|
unsigned long *delay_on,
|
|
unsigned long *delay_off)
|
|
{
|
|
if (!(led_cdev->flags & LED_BLINK_ONESHOT) &&
|
|
led_cdev->blink_set &&
|
|
!led_cdev->blink_set(led_cdev, delay_on, delay_off))
|
|
return;
|
|
|
|
/* blink with 1 Hz as default if nothing specified */
|
|
if (!*delay_on && !*delay_off)
|
|
*delay_on = *delay_off = 500;
|
|
|
|
led_set_software_blink(led_cdev, *delay_on, *delay_off);
|
|
}
|
|
|
|
void led_blink_set(struct led_classdev *led_cdev,
|
|
unsigned long *delay_on,
|
|
unsigned long *delay_off)
|
|
{
|
|
del_timer_sync(&led_cdev->blink_timer);
|
|
|
|
led_cdev->flags &= ~LED_BLINK_ONESHOT;
|
|
led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
|
|
|
|
led_blink_setup(led_cdev, delay_on, delay_off);
|
|
}
|
|
EXPORT_SYMBOL(led_blink_set);
|
|
|
|
void led_blink_set_oneshot(struct led_classdev *led_cdev,
|
|
unsigned long *delay_on,
|
|
unsigned long *delay_off,
|
|
int invert)
|
|
{
|
|
if ((led_cdev->flags & LED_BLINK_ONESHOT) &&
|
|
timer_pending(&led_cdev->blink_timer))
|
|
return;
|
|
|
|
led_cdev->flags |= LED_BLINK_ONESHOT;
|
|
led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
|
|
|
|
if (invert)
|
|
led_cdev->flags |= LED_BLINK_INVERT;
|
|
else
|
|
led_cdev->flags &= ~LED_BLINK_INVERT;
|
|
|
|
led_blink_setup(led_cdev, delay_on, delay_off);
|
|
}
|
|
EXPORT_SYMBOL(led_blink_set_oneshot);
|
|
|
|
void led_stop_software_blink(struct led_classdev *led_cdev)
|
|
{
|
|
del_timer_sync(&led_cdev->blink_timer);
|
|
led_cdev->blink_delay_on = 0;
|
|
led_cdev->blink_delay_off = 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(led_stop_software_blink);
|
|
|
|
void led_set_brightness(struct led_classdev *led_cdev,
|
|
enum led_brightness brightness)
|
|
{
|
|
/* delay brightness setting if need to stop soft-blink timer */
|
|
if (led_cdev->blink_delay_on || led_cdev->blink_delay_off) {
|
|
led_cdev->delayed_set_value = brightness;
|
|
schedule_work(&led_cdev->set_brightness_work);
|
|
return;
|
|
}
|
|
|
|
__led_set_brightness(led_cdev, brightness);
|
|
}
|
|
EXPORT_SYMBOL(led_set_brightness);
|