static void led_timer_function(unsigned long data) { struct led_classdev *led_cdev = (void *)data; unsigned long brightness; unsigned long delay; if (!led_cdev->blink_delay_on || !led_cdev->blink_delay_off) { __led_set_brightness(led_cdev, LED_OFF); return; } if (led_cdev->flags & LED_BLINK_ONESHOT_STOP) { led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP; return; } brightness = led_get_brightness(led_cdev); if (!brightness) { /* Time to switch the LED on. */ brightness = led_cdev->blink_brightness; delay = led_cdev->blink_delay_on; } else { /* Store the current brightness value to be able * to restore it when the delay_off period is over. */ led_cdev->blink_brightness = brightness; brightness = LED_OFF; delay = led_cdev->blink_delay_off; } __led_set_brightness(led_cdev, brightness); /* Return in next iteration if led is in one-shot mode and we are in * the final blink state so that the led is toggled each delay_on + * delay_off milliseconds in worst case. */ if (led_cdev->flags & LED_BLINK_ONESHOT) { if (led_cdev->flags & LED_BLINK_INVERT) { if (brightness) led_cdev->flags |= LED_BLINK_ONESHOT_STOP; } else { if (!brightness) led_cdev->flags |= LED_BLINK_ONESHOT_STOP; } } mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay)); }
static void transient_timer_function(unsigned long data) { struct led_classdev *led_cdev = (struct led_classdev *) data; struct transient_trig_data *transient_data = led_cdev->trigger_data; transient_data->activate = 0; __led_set_brightness(led_cdev, transient_data->restore_state); }
static void set_brightness_delayed(struct work_struct *ws) { struct led_classdev *led_cdev = container_of(ws, struct led_classdev, set_brightness_work); led_stop_software_blink(led_cdev); __led_set_brightness(led_cdev, led_cdev->delayed_set_value); }
void led_set_brightness_nopm(struct led_classdev *led_cdev, enum led_brightness value) { /* Use brightness_set op if available, it is guaranteed not to sleep */ if (!__led_set_brightness(led_cdev, value)) return; /* If brightness setting can sleep, delegate it to a work queue task */ led_cdev->delayed_set_value = value; schedule_work(&led_cdev->set_brightness_work); }
static ssize_t transient_activate_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct led_classdev *led_cdev = dev_get_drvdata(dev); struct transient_trig_data *transient_data = led_cdev->trigger_data; unsigned long state; ssize_t ret; ret = kstrtoul(buf, 10, &state); if (ret) return ret; if (state != 1 && state != 0) return -EINVAL; /* cancel the running timer */ if (state == 0 && transient_data->activate == 1) { del_timer(&transient_data->timer); transient_data->activate = state; __led_set_brightness(led_cdev, transient_data->restore_state); return size; } /* start timer if there is no active timer */ if (state == 1 && transient_data->activate == 0 && transient_data->duration != 0) { transient_data->activate = state; __led_set_brightness(led_cdev, transient_data->state); transient_data->restore_state = (transient_data->state == LED_FULL) ? LED_OFF : LED_FULL; mod_timer(&transient_data->timer, jiffies + transient_data->duration); } /* state == 0 && transient_data->activate == 0 timer is not active - just return */ /* state == 1 && transient_data->activate == 1 timer is already active - just return */ return size; }
static ssize_t led_invert_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct led_classdev *led_cdev = dev_get_drvdata(dev); struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data; unsigned long state; int ret; ret = kstrtoul(buf, 0, &state); if (ret) return ret; oneshot_data->invert = !!state; if (oneshot_data->invert) __led_set_brightness(led_cdev, LED_FULL); else __led_set_brightness(led_cdev, LED_OFF); return size; }
static void gpio_trig_work(struct work_struct *work) { struct gpio_trig_data *gpio_data = container_of(work, struct gpio_trig_data, work); int tmp; if (!gpio_data->gpio) return; tmp = gpio_get_value(gpio_data->gpio); if (gpio_data->inverted) tmp = !tmp; if (tmp) { if (gpio_data->desired_brightness) __led_set_brightness(gpio_data->led, gpio_data->desired_brightness); else __led_set_brightness(gpio_data->led, LED_FULL); } else { __led_set_brightness(gpio_data->led, LED_OFF); } }
static void transient_trig_deactivate(struct led_classdev *led_cdev) { struct transient_trig_data *transient_data = led_cdev->trigger_data; if (led_cdev->activated) { del_timer_sync(&transient_data->timer); __led_set_brightness(led_cdev, transient_data->restore_state); device_remove_file(led_cdev->dev, &dev_attr_activate); device_remove_file(led_cdev->dev, &dev_attr_duration); device_remove_file(led_cdev->dev, &dev_attr_state); led_cdev->trigger_data = NULL; led_cdev->activated = false; kfree(transient_data); } }
static ssize_t led_brightness_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct led_classdev *led_cdev = dev_get_drvdata(dev); unsigned long state; ssize_t ret = -EINVAL; ret = kstrtoul(buf, 10, &state); if (ret) return ret; __led_set_brightness(led_cdev, state); return size; }
static void set_brightness_delayed(struct work_struct *ws) { struct led_classdev *led_cdev = container_of(ws, struct led_classdev, set_brightness_work); int ret = 0; if (test_and_clear_bit(LED_BLINK_DISABLE, &led_cdev->work_flags)) { led_cdev->delayed_set_value = LED_OFF; led_stop_software_blink(led_cdev); } ret = __led_set_brightness(led_cdev, led_cdev->delayed_set_value); if (ret == -ENOTSUPP) ret = __led_set_brightness_blocking(led_cdev, led_cdev->delayed_set_value); if (ret < 0 && /* LED HW might have been unplugged, therefore don't warn */ !(ret == -ENODEV && (led_cdev->flags & LED_UNREGISTERING) && (led_cdev->flags & LED_HW_PLUGGABLE))) dev_err(led_cdev->dev, "Setting an LED's brightness failed (%d)\n", ret); }
static void defon_trig_activate(struct led_classdev *led_cdev) { __led_set_brightness(led_cdev, led_cdev->max_brightness); }