ledtrig-oneshot.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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. */
  13. #include <linux/module.h>
  14. #include <linux/kernel.h>
  15. #include <linux/init.h>
  16. #include <linux/device.h>
  17. #include <linux/ctype.h>
  18. #include <linux/slab.h>
  19. #include <linux/leds.h>
  20. #include "../leds.h"
  21. #define DEFAULT_DELAY 100
  22. struct oneshot_trig_data {
  23. unsigned int invert;
  24. };
  25. static ssize_t led_shot(struct device *dev,
  26. struct device_attribute *attr, const char *buf, size_t size)
  27. {
  28. struct led_classdev *led_cdev = dev_get_drvdata(dev);
  29. struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data;
  30. led_blink_set_oneshot(led_cdev,
  31. &led_cdev->blink_delay_on, &led_cdev->blink_delay_off,
  32. oneshot_data->invert);
  33. /* content is ignored */
  34. return size;
  35. }
  36. static ssize_t led_invert_show(struct device *dev,
  37. struct device_attribute *attr, char *buf)
  38. {
  39. struct led_classdev *led_cdev = dev_get_drvdata(dev);
  40. struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data;
  41. return sprintf(buf, "%u\n", oneshot_data->invert);
  42. }
  43. static ssize_t led_invert_store(struct device *dev,
  44. struct device_attribute *attr, const char *buf, size_t size)
  45. {
  46. struct led_classdev *led_cdev = dev_get_drvdata(dev);
  47. struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data;
  48. unsigned long state;
  49. int ret;
  50. ret = kstrtoul(buf, 0, &state);
  51. if (ret)
  52. return ret;
  53. oneshot_data->invert = !!state;
  54. if (oneshot_data->invert)
  55. led_set_brightness_async(led_cdev, LED_FULL);
  56. else
  57. led_set_brightness_async(led_cdev, LED_OFF);
  58. return size;
  59. }
  60. static ssize_t led_delay_on_show(struct device *dev,
  61. struct device_attribute *attr, char *buf)
  62. {
  63. struct led_classdev *led_cdev = dev_get_drvdata(dev);
  64. return sprintf(buf, "%lu\n", led_cdev->blink_delay_on);
  65. }
  66. static ssize_t led_delay_on_store(struct device *dev,
  67. struct device_attribute *attr, const char *buf, size_t size)
  68. {
  69. struct led_classdev *led_cdev = dev_get_drvdata(dev);
  70. unsigned long state;
  71. int ret;
  72. ret = kstrtoul(buf, 0, &state);
  73. if (ret)
  74. return ret;
  75. led_cdev->blink_delay_on = state;
  76. return size;
  77. }
  78. static ssize_t led_delay_off_show(struct device *dev,
  79. struct device_attribute *attr, char *buf)
  80. {
  81. struct led_classdev *led_cdev = dev_get_drvdata(dev);
  82. return sprintf(buf, "%lu\n", led_cdev->blink_delay_off);
  83. }
  84. static ssize_t led_delay_off_store(struct device *dev,
  85. struct device_attribute *attr, const char *buf, size_t size)
  86. {
  87. struct led_classdev *led_cdev = dev_get_drvdata(dev);
  88. unsigned long state;
  89. int ret;
  90. ret = kstrtoul(buf, 0, &state);
  91. if (ret)
  92. return ret;
  93. led_cdev->blink_delay_off = state;
  94. return size;
  95. }
  96. static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store);
  97. static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store);
  98. static DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store);
  99. static DEVICE_ATTR(shot, 0200, NULL, led_shot);
  100. static void oneshot_trig_activate(struct led_classdev *led_cdev)
  101. {
  102. struct oneshot_trig_data *oneshot_data;
  103. int rc;
  104. oneshot_data = kzalloc(sizeof(*oneshot_data), GFP_KERNEL);
  105. if (!oneshot_data)
  106. return;
  107. led_cdev->trigger_data = oneshot_data;
  108. rc = device_create_file(led_cdev->dev, &dev_attr_delay_on);
  109. if (rc)
  110. goto err_out_trig_data;
  111. rc = device_create_file(led_cdev->dev, &dev_attr_delay_off);
  112. if (rc)
  113. goto err_out_delayon;
  114. rc = device_create_file(led_cdev->dev, &dev_attr_invert);
  115. if (rc)
  116. goto err_out_delayoff;
  117. rc = device_create_file(led_cdev->dev, &dev_attr_shot);
  118. if (rc)
  119. goto err_out_invert;
  120. led_cdev->blink_delay_on = DEFAULT_DELAY;
  121. led_cdev->blink_delay_off = DEFAULT_DELAY;
  122. led_cdev->activated = true;
  123. return;
  124. err_out_invert:
  125. device_remove_file(led_cdev->dev, &dev_attr_invert);
  126. err_out_delayoff:
  127. device_remove_file(led_cdev->dev, &dev_attr_delay_off);
  128. err_out_delayon:
  129. device_remove_file(led_cdev->dev, &dev_attr_delay_on);
  130. err_out_trig_data:
  131. kfree(led_cdev->trigger_data);
  132. }
  133. static void oneshot_trig_deactivate(struct led_classdev *led_cdev)
  134. {
  135. struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data;
  136. if (led_cdev->activated) {
  137. device_remove_file(led_cdev->dev, &dev_attr_delay_on);
  138. device_remove_file(led_cdev->dev, &dev_attr_delay_off);
  139. device_remove_file(led_cdev->dev, &dev_attr_invert);
  140. device_remove_file(led_cdev->dev, &dev_attr_shot);
  141. kfree(oneshot_data);
  142. led_cdev->activated = false;
  143. }
  144. /* Stop blinking */
  145. led_set_brightness(led_cdev, LED_OFF);
  146. }
  147. static struct led_trigger oneshot_led_trigger = {
  148. .name = "oneshot",
  149. .activate = oneshot_trig_activate,
  150. .deactivate = oneshot_trig_deactivate,
  151. };
  152. static int __init oneshot_trig_init(void)
  153. {
  154. return led_trigger_register(&oneshot_led_trigger);
  155. }
  156. static void __exit oneshot_trig_exit(void)
  157. {
  158. led_trigger_unregister(&oneshot_led_trigger);
  159. }
  160. module_init(oneshot_trig_init);
  161. module_exit(oneshot_trig_exit);
  162. MODULE_AUTHOR("Fabio Baltieri <fabio.baltieri@gmail.com>");
  163. MODULE_DESCRIPTION("One-shot LED trigger");
  164. MODULE_LICENSE("GPL");