Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/leds/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 11 kB image not shown  

Quelle  led-class-flash.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * LED Flash class interface
 *
 * Copyright (C) 2015 Samsung Electronics Co., Ltd.
 * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
 */


#include <linux/device.h>
#include <linux/init.h>
#include <linux/led-class-flash.h>
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/slab.h>

#define has_flash_op(fled_cdev, op)    \
 (fled_cdev && fled_cdev->ops->op)

#define call_flash_op(fled_cdev, op, args...)  \
 ((has_flash_op(fled_cdev, op)) ?   \
   (fled_cdev->ops->op(fled_cdev, args)) : \
   -EINVAL)

static const char * const led_flash_fault_names[] = {
 "led-over-voltage",
 "flash-timeout-exceeded",
 "controller-over-temperature",
 "controller-short-circuit",
 "led-power-supply-over-current",
 "indicator-led-fault",
 "led-under-voltage",
 "controller-under-voltage",
 "led-over-temperature",
};

static ssize_t flash_brightness_store(struct device *dev,
  struct device_attribute *attr, const char *buf, size_t size)
{
 struct led_classdev *led_cdev = dev_get_drvdata(dev);
 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
 unsigned long state;
 ssize_t ret;

 mutex_lock(&led_cdev->led_access);

 if (led_sysfs_is_disabled(led_cdev)) {
  ret = -EBUSY;
  goto unlock;
 }

 ret = kstrtoul(buf, 10, &state);
 if (ret)
  goto unlock;

 ret = led_set_flash_brightness(fled_cdev, state);
 if (ret < 0)
  goto unlock;

 ret = size;
unlock:
 mutex_unlock(&led_cdev->led_access);
 return ret;
}

static ssize_t flash_brightness_show(struct device *dev,
  struct device_attribute *attr, char *buf)
{
 struct led_classdev *led_cdev = dev_get_drvdata(dev);
 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);

 /* no lock needed for this */
 led_update_flash_brightness(fled_cdev);

 return sprintf(buf, "%u\n", fled_cdev->brightness.val);
}
static DEVICE_ATTR_RW(flash_brightness);

static ssize_t max_flash_brightness_show(struct device *dev,
  struct device_attribute *attr, char *buf)
{
 struct led_classdev *led_cdev = dev_get_drvdata(dev);
 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);

 return sprintf(buf, "%u\n", fled_cdev->brightness.max);
}
static DEVICE_ATTR_RO(max_flash_brightness);

static ssize_t flash_strobe_store(struct device *dev,
  struct device_attribute *attr, const char *buf, size_t size)
{
 struct led_classdev *led_cdev = dev_get_drvdata(dev);
 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
 unsigned long state;
 ssize_t ret = -EBUSY;

 mutex_lock(&led_cdev->led_access);

 if (led_sysfs_is_disabled(led_cdev))
  goto unlock;

 ret = kstrtoul(buf, 10, &state);
 if (ret)
  goto unlock;

 if (state > 1) {
  ret = -EINVAL;
  goto unlock;
 }

 ret = led_set_flash_strobe(fled_cdev, state);
 if (ret < 0)
  goto unlock;
 ret = size;
unlock:
 mutex_unlock(&led_cdev->led_access);
 return ret;
}

static ssize_t flash_strobe_show(struct device *dev,
  struct device_attribute *attr, char *buf)
{
 struct led_classdev *led_cdev = dev_get_drvdata(dev);
 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
 bool state;
 int ret;

 /* no lock needed for this */
 ret = led_get_flash_strobe(fled_cdev, &state);
 if (ret < 0)
  return ret;

 return sprintf(buf, "%u\n", state);
}
static DEVICE_ATTR_RW(flash_strobe);

static ssize_t flash_timeout_store(struct device *dev,
  struct device_attribute *attr, const char *buf, size_t size)
{
 struct led_classdev *led_cdev = dev_get_drvdata(dev);
 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
 unsigned long flash_timeout;
 ssize_t ret;

 mutex_lock(&led_cdev->led_access);

 if (led_sysfs_is_disabled(led_cdev)) {
  ret = -EBUSY;
  goto unlock;
 }

 ret = kstrtoul(buf, 10, &flash_timeout);
 if (ret)
  goto unlock;

 ret = led_set_flash_timeout(fled_cdev, flash_timeout);
 if (ret < 0)
  goto unlock;

 ret = size;
unlock:
 mutex_unlock(&led_cdev->led_access);
 return ret;
}

static ssize_t flash_timeout_show(struct device *dev,
  struct device_attribute *attr, char *buf)
{
 struct led_classdev *led_cdev = dev_get_drvdata(dev);
 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);

 return sprintf(buf, "%u\n", fled_cdev->timeout.val);
}
static DEVICE_ATTR_RW(flash_timeout);

static ssize_t max_flash_timeout_show(struct device *dev,
  struct device_attribute *attr, char *buf)
{
 struct led_classdev *led_cdev = dev_get_drvdata(dev);
 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);

 return sprintf(buf, "%u\n", fled_cdev->timeout.max);
}
static DEVICE_ATTR_RO(max_flash_timeout);

static ssize_t flash_fault_show(struct device *dev,
  struct device_attribute *attr, char *buf)
{
 struct led_classdev *led_cdev = dev_get_drvdata(dev);
 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
 u32 fault, mask = 0x1;
 char *pbuf = buf;
 int i, ret, buf_len;

 ret = led_get_flash_fault(fled_cdev, &fault);
 if (ret < 0)
  return -EINVAL;

 *buf = '\0';

 for (i = 0; i < LED_NUM_FLASH_FAULTS; ++i) {
  if (fault & mask) {
   buf_len = sprintf(pbuf, "%s ",
       led_flash_fault_names[i]);
   pbuf += buf_len;
  }
  mask <<= 1;
 }

 return strlen(strcat(buf, "\n"));
}
static DEVICE_ATTR_RO(flash_fault);

static struct attribute *led_flash_strobe_attrs[] = {
 &dev_attr_flash_strobe.attr,
 NULL,
};

static struct attribute *led_flash_timeout_attrs[] = {
 &dev_attr_flash_timeout.attr,
 &dev_attr_max_flash_timeout.attr,
 NULL,
};

static struct attribute *led_flash_brightness_attrs[] = {
 &dev_attr_flash_brightness.attr,
 &dev_attr_max_flash_brightness.attr,
 NULL,
};

static struct attribute *led_flash_fault_attrs[] = {
 &dev_attr_flash_fault.attr,
 NULL,
};

static const struct attribute_group led_flash_strobe_group = {
 .attrs = led_flash_strobe_attrs,
};

static const struct attribute_group led_flash_timeout_group = {
 .attrs = led_flash_timeout_attrs,
};

static const struct attribute_group led_flash_brightness_group = {
 .attrs = led_flash_brightness_attrs,
};

static const struct attribute_group led_flash_fault_group = {
 .attrs = led_flash_fault_attrs,
};

static void led_flash_resume(struct led_classdev *led_cdev)
{
 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);

 call_flash_op(fled_cdev, flash_brightness_set,
     fled_cdev->brightness.val);
 call_flash_op(fled_cdev, timeout_set, fled_cdev->timeout.val);
}

static void led_flash_init_sysfs_groups(struct led_classdev_flash *fled_cdev)
{
 struct led_classdev *led_cdev = &fled_cdev->led_cdev;
 const struct led_flash_ops *ops = fled_cdev->ops;
 const struct attribute_group **flash_groups = fled_cdev->sysfs_groups;

 int num_sysfs_groups = 0;

 flash_groups[num_sysfs_groups++] = &led_flash_strobe_group;

 if (ops->flash_brightness_set)
  flash_groups[num_sysfs_groups++] = &led_flash_brightness_group;

 if (ops->timeout_set)
  flash_groups[num_sysfs_groups++] = &led_flash_timeout_group;

 if (ops->fault_get)
  flash_groups[num_sysfs_groups++] = &led_flash_fault_group;

 led_cdev->groups = flash_groups;
}

int led_classdev_flash_register_ext(struct device *parent,
        struct led_classdev_flash *fled_cdev,
        struct led_init_data *init_data)
{
 struct led_classdev *led_cdev;
 const struct led_flash_ops *ops;
 int ret;

 if (!fled_cdev)
  return -EINVAL;

 led_cdev = &fled_cdev->led_cdev;

 if (led_cdev->flags & LED_DEV_CAP_FLASH) {
  if (!led_cdev->brightness_set_blocking)
   return -EINVAL;

  ops = fled_cdev->ops;
  if (!ops || !ops->strobe_set)
   return -EINVAL;

  led_cdev->flash_resume = led_flash_resume;

  /* Select the sysfs attributes to be created for the device */
  led_flash_init_sysfs_groups(fled_cdev);
 }

 /* Register led class device */
 ret = led_classdev_register_ext(parent, led_cdev, init_data);
 if (ret < 0)
  return ret;

 return 0;
}
EXPORT_SYMBOL_GPL(led_classdev_flash_register_ext);

void led_classdev_flash_unregister(struct led_classdev_flash *fled_cdev)
{
 if (!fled_cdev)
  return;

 led_classdev_unregister(&fled_cdev->led_cdev);
}
EXPORT_SYMBOL_GPL(led_classdev_flash_unregister);

static void devm_led_classdev_flash_release(struct device *dev, void *res)
{
 led_classdev_flash_unregister(*(struct led_classdev_flash **)res);
}

int devm_led_classdev_flash_register_ext(struct device *parent,
         struct led_classdev_flash *fled_cdev,
         struct led_init_data *init_data)
{
 struct led_classdev_flash **dr;
 int ret;

 dr = devres_alloc(devm_led_classdev_flash_release, sizeof(*dr),
     GFP_KERNEL);
 if (!dr)
  return -ENOMEM;

 ret = led_classdev_flash_register_ext(parent, fled_cdev, init_data);
 if (ret) {
  devres_free(dr);
  return ret;
 }

 *dr = fled_cdev;
 devres_add(parent, dr);

 return 0;
}
EXPORT_SYMBOL_GPL(devm_led_classdev_flash_register_ext);

static int devm_led_classdev_flash_match(struct device *dev,
           void *res, void *data)
{
 struct led_classdev_flash **p = res;

 if (WARN_ON(!p || !*p))
  return 0;

 return *p == data;
}

void devm_led_classdev_flash_unregister(struct device *dev,
     struct led_classdev_flash *fled_cdev)
{
 WARN_ON(devres_release(dev,
          devm_led_classdev_flash_release,
          devm_led_classdev_flash_match, fled_cdev));
}
EXPORT_SYMBOL_GPL(devm_led_classdev_flash_unregister);

static void led_clamp_align(struct led_flash_setting *s)
{
 u32 v, offset;

 v = s->val + s->step / 2;
 v = clamp(v, s->min, s->max);
 offset = v - s->min;
 offset = s->step * (offset / s->step);
 s->val = s->min + offset;
}

int led_set_flash_timeout(struct led_classdev_flash *fled_cdev, u32 timeout)
{
 struct led_classdev *led_cdev = &fled_cdev->led_cdev;
 struct led_flash_setting *s = &fled_cdev->timeout;

 s->val = timeout;
 led_clamp_align(s);

 if (!(led_cdev->flags & LED_SUSPENDED))
  return call_flash_op(fled_cdev, timeout_set, s->val);

 return 0;
}
EXPORT_SYMBOL_GPL(led_set_flash_timeout);

int led_get_flash_fault(struct led_classdev_flash *fled_cdev, u32 *fault)
{
 return call_flash_op(fled_cdev, fault_get, fault);
}
EXPORT_SYMBOL_GPL(led_get_flash_fault);

int led_set_flash_brightness(struct led_classdev_flash *fled_cdev,
    u32 brightness)
{
 struct led_classdev *led_cdev = &fled_cdev->led_cdev;
 struct led_flash_setting *s = &fled_cdev->brightness;

 s->val = brightness;
 led_clamp_align(s);

 if (!(led_cdev->flags & LED_SUSPENDED))
  return call_flash_op(fled_cdev, flash_brightness_set, s->val);

 return 0;
}
EXPORT_SYMBOL_GPL(led_set_flash_brightness);

int led_update_flash_brightness(struct led_classdev_flash *fled_cdev)
{
 struct led_flash_setting *s = &fled_cdev->brightness;
 u32 brightness;

 if (has_flash_op(fled_cdev, flash_brightness_get)) {
  int ret = call_flash_op(fled_cdev, flash_brightness_get,
      &brightness);
  if (ret < 0)
   return ret;

  s->val = brightness;
 }

 return 0;
}
EXPORT_SYMBOL_GPL(led_update_flash_brightness);

int led_set_flash_duration(struct led_classdev_flash *fled_cdev, u32 duration)
{
 struct led_classdev *led_cdev = &fled_cdev->led_cdev;
 struct led_flash_setting *s = &fled_cdev->duration;

 s->val = duration;
 led_clamp_align(s);

 if (!(led_cdev->flags & LED_SUSPENDED))
  return call_flash_op(fled_cdev, duration_set, s->val);

 return 0;
}
EXPORT_SYMBOL_GPL(led_set_flash_duration);

MODULE_AUTHOR("Jacek Anaszewski ");
MODULE_DESCRIPTION("LED Flash class interface");
MODULE_LICENSE("GPL v2");

Messung V0.5
C=97 H=97 G=96

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.