ledtrig-oneshot.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * One-shot LED Trigger
  3. *
  4. * Copyright 2012, Fabio Baltieri <fabio.baltieri@gmail.com>
  5. *
  6. * Based on ledtrig-timer.c by Richard Purdie <rpurdie@openedhand.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License version 2 as
  10. * published by the Free Software Foundation.
  11. */
  12. #include <linux/module.h>
  13. #include <linux/kernel.h>
  14. #include <linux/init.h>
  15. #include <linux/device.h>
  16. #include <linux/ctype.h>
  17. #include <linux/slab.h>
  18. #include <linux/leds.h>
  19. #include "../leds.h"
  20. #define DEFAULT_DELAY 100
  21. struct oneshot_trig_data {
  22. unsigned int invert;
  23. };
  24. static ssize_t led_shot(struct device *dev,
  25. struct device_attribute *attr, const char *buf, size_t size)
  26. {
  27. struct led_classdev *led_cdev = led_trigger_get_led(dev);
  28. struct oneshot_trig_data *oneshot_data = led_trigger_get_drvdata(dev);
  29. led_blink_set_oneshot(led_cdev,
  30. &led_cdev->blink_delay_on, &led_cdev->blink_delay_off,
  31. oneshot_data->invert);
  32. /* content is ignored */
  33. return size;
  34. }
  35. static ssize_t led_invert_show(struct device *dev,
  36. struct device_attribute *attr, char *buf)
  37. {
  38. struct oneshot_trig_data *oneshot_data = led_trigger_get_drvdata(dev);
  39. return sprintf(buf, "%u\n", oneshot_data->invert);
  40. }
  41. static ssize_t led_invert_store(struct device *dev,
  42. struct device_attribute *attr, const char *buf, size_t size)
  43. {
  44. struct led_classdev *led_cdev = led_trigger_get_led(dev);
  45. struct oneshot_trig_data *oneshot_data = led_trigger_get_drvdata(dev);
  46. unsigned long state;
  47. int ret;
  48. ret = kstrtoul(buf, 0, &state);
  49. if (ret)
  50. return ret;
  51. oneshot_data->invert = !!state;
  52. if (oneshot_data->invert)
  53. led_set_brightness_nosleep(led_cdev, LED_FULL);
  54. else
  55. led_set_brightness_nosleep(led_cdev, LED_OFF);
  56. return size;
  57. }
  58. static ssize_t led_delay_on_show(struct device *dev,
  59. struct device_attribute *attr, char *buf)
  60. {
  61. struct led_classdev *led_cdev = led_trigger_get_led(dev);
  62. return sprintf(buf, "%lu\n", led_cdev->blink_delay_on);
  63. }
  64. static ssize_t led_delay_on_store(struct device *dev,
  65. struct device_attribute *attr, const char *buf, size_t size)
  66. {
  67. struct led_classdev *led_cdev = led_trigger_get_led(dev);
  68. unsigned long state;
  69. int ret;
  70. ret = kstrtoul(buf, 0, &state);
  71. if (ret)
  72. return ret;
  73. led_cdev->blink_delay_on = state;
  74. return size;
  75. }
  76. static ssize_t led_delay_off_show(struct device *dev,
  77. struct device_attribute *attr, char *buf)
  78. {
  79. struct led_classdev *led_cdev = led_trigger_get_led(dev);
  80. return sprintf(buf, "%lu\n", led_cdev->blink_delay_off);
  81. }
  82. static ssize_t led_delay_off_store(struct device *dev,
  83. struct device_attribute *attr, const char *buf, size_t size)
  84. {
  85. struct led_classdev *led_cdev = led_trigger_get_led(dev);
  86. unsigned long state;
  87. int ret;
  88. ret = kstrtoul(buf, 0, &state);
  89. if (ret)
  90. return ret;
  91. led_cdev->blink_delay_off = state;
  92. return size;
  93. }
  94. static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store);
  95. static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store);
  96. static DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store);
  97. static DEVICE_ATTR(shot, 0200, NULL, led_shot);
  98. static struct attribute *oneshot_trig_attrs[] = {
  99. &dev_attr_delay_on.attr,
  100. &dev_attr_delay_off.attr,
  101. &dev_attr_invert.attr,
  102. &dev_attr_shot.attr,
  103. NULL
  104. };
  105. ATTRIBUTE_GROUPS(oneshot_trig);
  106. static int oneshot_trig_activate(struct led_classdev *led_cdev)
  107. {
  108. struct oneshot_trig_data *oneshot_data;
  109. oneshot_data = kzalloc(sizeof(*oneshot_data), GFP_KERNEL);
  110. if (!oneshot_data)
  111. return -ENOMEM;
  112. led_set_trigger_data(led_cdev, oneshot_data);
  113. led_cdev->blink_delay_on = DEFAULT_DELAY;
  114. led_cdev->blink_delay_off = DEFAULT_DELAY;
  115. return 0;
  116. }
  117. static void oneshot_trig_deactivate(struct led_classdev *led_cdev)
  118. {
  119. struct oneshot_trig_data *oneshot_data = led_get_trigger_data(led_cdev);
  120. kfree(oneshot_data);
  121. /* Stop blinking */
  122. led_set_brightness(led_cdev, LED_OFF);
  123. }
  124. static struct led_trigger oneshot_led_trigger = {
  125. .name = "oneshot",
  126. .activate = oneshot_trig_activate,
  127. .deactivate = oneshot_trig_deactivate,
  128. .groups = oneshot_trig_groups,
  129. };
  130. module_led_trigger(oneshot_led_trigger);
  131. MODULE_AUTHOR("Fabio Baltieri <fabio.baltieri@gmail.com>");
  132. MODULE_DESCRIPTION("One-shot LED trigger");
  133. MODULE_LICENSE("GPL v2");