0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/export.h>
0011 #include <linux/kernel.h>
0012 #include <linux/list.h>
0013 #include <linux/spinlock.h>
0014 #include <linux/device.h>
0015 #include <linux/timer.h>
0016 #include <linux/rwsem.h>
0017 #include <linux/leds.h>
0018 #include <linux/slab.h>
0019 #include <linux/mm.h>
0020 #include "leds.h"
0021
0022
0023
0024
0025 static DECLARE_RWSEM(triggers_list_lock);
0026 LIST_HEAD(trigger_list);
0027
0028
0029
0030 static inline bool
0031 trigger_relevant(struct led_classdev *led_cdev, struct led_trigger *trig)
0032 {
0033 return !trig->trigger_type || trig->trigger_type == led_cdev->trigger_type;
0034 }
0035
0036 ssize_t led_trigger_write(struct file *filp, struct kobject *kobj,
0037 struct bin_attribute *bin_attr, char *buf,
0038 loff_t pos, size_t count)
0039 {
0040 struct device *dev = kobj_to_dev(kobj);
0041 struct led_classdev *led_cdev = dev_get_drvdata(dev);
0042 struct led_trigger *trig;
0043 int ret = count;
0044
0045 mutex_lock(&led_cdev->led_access);
0046
0047 if (led_sysfs_is_disabled(led_cdev)) {
0048 ret = -EBUSY;
0049 goto unlock;
0050 }
0051
0052 if (sysfs_streq(buf, "none")) {
0053 led_trigger_remove(led_cdev);
0054 goto unlock;
0055 }
0056
0057 down_read(&triggers_list_lock);
0058 list_for_each_entry(trig, &trigger_list, next_trig) {
0059 if (sysfs_streq(buf, trig->name) && trigger_relevant(led_cdev, trig)) {
0060 down_write(&led_cdev->trigger_lock);
0061 led_trigger_set(led_cdev, trig);
0062 up_write(&led_cdev->trigger_lock);
0063
0064 up_read(&triggers_list_lock);
0065 goto unlock;
0066 }
0067 }
0068
0069 ret = -EINVAL;
0070 up_read(&triggers_list_lock);
0071
0072 unlock:
0073 mutex_unlock(&led_cdev->led_access);
0074 return ret;
0075 }
0076 EXPORT_SYMBOL_GPL(led_trigger_write);
0077
0078 __printf(3, 4)
0079 static int led_trigger_snprintf(char *buf, ssize_t size, const char *fmt, ...)
0080 {
0081 va_list args;
0082 int i;
0083
0084 va_start(args, fmt);
0085 if (size <= 0)
0086 i = vsnprintf(NULL, 0, fmt, args);
0087 else
0088 i = vscnprintf(buf, size, fmt, args);
0089 va_end(args);
0090
0091 return i;
0092 }
0093
0094 static int led_trigger_format(char *buf, size_t size,
0095 struct led_classdev *led_cdev)
0096 {
0097 struct led_trigger *trig;
0098 int len = led_trigger_snprintf(buf, size, "%s",
0099 led_cdev->trigger ? "none" : "[none]");
0100
0101 list_for_each_entry(trig, &trigger_list, next_trig) {
0102 bool hit;
0103
0104 if (!trigger_relevant(led_cdev, trig))
0105 continue;
0106
0107 hit = led_cdev->trigger && !strcmp(led_cdev->trigger->name, trig->name);
0108
0109 len += led_trigger_snprintf(buf + len, size - len,
0110 " %s%s%s", hit ? "[" : "",
0111 trig->name, hit ? "]" : "");
0112 }
0113
0114 len += led_trigger_snprintf(buf + len, size - len, "\n");
0115
0116 return len;
0117 }
0118
0119
0120
0121
0122
0123
0124
0125 ssize_t led_trigger_read(struct file *filp, struct kobject *kobj,
0126 struct bin_attribute *attr, char *buf,
0127 loff_t pos, size_t count)
0128 {
0129 struct device *dev = kobj_to_dev(kobj);
0130 struct led_classdev *led_cdev = dev_get_drvdata(dev);
0131 void *data;
0132 int len;
0133
0134 down_read(&triggers_list_lock);
0135 down_read(&led_cdev->trigger_lock);
0136
0137 len = led_trigger_format(NULL, 0, led_cdev);
0138 data = kvmalloc(len + 1, GFP_KERNEL);
0139 if (!data) {
0140 up_read(&led_cdev->trigger_lock);
0141 up_read(&triggers_list_lock);
0142 return -ENOMEM;
0143 }
0144 len = led_trigger_format(data, len + 1, led_cdev);
0145
0146 up_read(&led_cdev->trigger_lock);
0147 up_read(&triggers_list_lock);
0148
0149 len = memory_read_from_buffer(buf, count, &pos, data, len);
0150
0151 kvfree(data);
0152
0153 return len;
0154 }
0155 EXPORT_SYMBOL_GPL(led_trigger_read);
0156
0157
0158 int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
0159 {
0160 char *event = NULL;
0161 char *envp[2];
0162 const char *name;
0163 int ret;
0164
0165 if (!led_cdev->trigger && !trig)
0166 return 0;
0167
0168 name = trig ? trig->name : "none";
0169 event = kasprintf(GFP_KERNEL, "TRIGGER=%s", name);
0170
0171
0172 if (led_cdev->trigger) {
0173 spin_lock(&led_cdev->trigger->leddev_list_lock);
0174 list_del_rcu(&led_cdev->trig_list);
0175 spin_unlock(&led_cdev->trigger->leddev_list_lock);
0176
0177
0178 synchronize_rcu();
0179
0180 cancel_work_sync(&led_cdev->set_brightness_work);
0181 led_stop_software_blink(led_cdev);
0182 if (led_cdev->trigger->deactivate)
0183 led_cdev->trigger->deactivate(led_cdev);
0184 device_remove_groups(led_cdev->dev, led_cdev->trigger->groups);
0185 led_cdev->trigger = NULL;
0186 led_cdev->trigger_data = NULL;
0187 led_cdev->activated = false;
0188 led_set_brightness(led_cdev, LED_OFF);
0189 }
0190 if (trig) {
0191 spin_lock(&trig->leddev_list_lock);
0192 list_add_tail_rcu(&led_cdev->trig_list, &trig->led_cdevs);
0193 spin_unlock(&trig->leddev_list_lock);
0194 led_cdev->trigger = trig;
0195
0196 if (trig->activate)
0197 ret = trig->activate(led_cdev);
0198 else
0199 ret = 0;
0200
0201 if (ret)
0202 goto err_activate;
0203
0204 ret = device_add_groups(led_cdev->dev, trig->groups);
0205 if (ret) {
0206 dev_err(led_cdev->dev, "Failed to add trigger attributes\n");
0207 goto err_add_groups;
0208 }
0209 }
0210
0211 if (event) {
0212 envp[0] = event;
0213 envp[1] = NULL;
0214 if (kobject_uevent_env(&led_cdev->dev->kobj, KOBJ_CHANGE, envp))
0215 dev_err(led_cdev->dev,
0216 "%s: Error sending uevent\n", __func__);
0217 kfree(event);
0218 }
0219
0220 return 0;
0221
0222 err_add_groups:
0223
0224 if (trig->deactivate)
0225 trig->deactivate(led_cdev);
0226 err_activate:
0227
0228 spin_lock(&led_cdev->trigger->leddev_list_lock);
0229 list_del_rcu(&led_cdev->trig_list);
0230 spin_unlock(&led_cdev->trigger->leddev_list_lock);
0231 synchronize_rcu();
0232 led_cdev->trigger = NULL;
0233 led_cdev->trigger_data = NULL;
0234 led_set_brightness(led_cdev, LED_OFF);
0235 kfree(event);
0236
0237 return ret;
0238 }
0239 EXPORT_SYMBOL_GPL(led_trigger_set);
0240
0241 void led_trigger_remove(struct led_classdev *led_cdev)
0242 {
0243 down_write(&led_cdev->trigger_lock);
0244 led_trigger_set(led_cdev, NULL);
0245 up_write(&led_cdev->trigger_lock);
0246 }
0247 EXPORT_SYMBOL_GPL(led_trigger_remove);
0248
0249 void led_trigger_set_default(struct led_classdev *led_cdev)
0250 {
0251 struct led_trigger *trig;
0252
0253 if (!led_cdev->default_trigger)
0254 return;
0255
0256 down_read(&triggers_list_lock);
0257 down_write(&led_cdev->trigger_lock);
0258 list_for_each_entry(trig, &trigger_list, next_trig) {
0259 if (!strcmp(led_cdev->default_trigger, trig->name) &&
0260 trigger_relevant(led_cdev, trig)) {
0261 led_cdev->flags |= LED_INIT_DEFAULT_TRIGGER;
0262 led_trigger_set(led_cdev, trig);
0263 break;
0264 }
0265 }
0266 up_write(&led_cdev->trigger_lock);
0267 up_read(&triggers_list_lock);
0268 }
0269 EXPORT_SYMBOL_GPL(led_trigger_set_default);
0270
0271 void led_trigger_rename_static(const char *name, struct led_trigger *trig)
0272 {
0273
0274 BUG_ON(name == trig->name);
0275
0276 down_write(&triggers_list_lock);
0277
0278
0279 strcpy((char *)trig->name, name);
0280 up_write(&triggers_list_lock);
0281 }
0282 EXPORT_SYMBOL_GPL(led_trigger_rename_static);
0283
0284
0285
0286 int led_trigger_register(struct led_trigger *trig)
0287 {
0288 struct led_classdev *led_cdev;
0289 struct led_trigger *_trig;
0290
0291 spin_lock_init(&trig->leddev_list_lock);
0292 INIT_LIST_HEAD(&trig->led_cdevs);
0293
0294 down_write(&triggers_list_lock);
0295
0296 list_for_each_entry(_trig, &trigger_list, next_trig) {
0297 if (!strcmp(_trig->name, trig->name) &&
0298 (trig->trigger_type == _trig->trigger_type ||
0299 !trig->trigger_type || !_trig->trigger_type)) {
0300 up_write(&triggers_list_lock);
0301 return -EEXIST;
0302 }
0303 }
0304
0305 list_add_tail(&trig->next_trig, &trigger_list);
0306 up_write(&triggers_list_lock);
0307
0308
0309 down_read(&leds_list_lock);
0310 list_for_each_entry(led_cdev, &leds_list, node) {
0311 down_write(&led_cdev->trigger_lock);
0312 if (!led_cdev->trigger && led_cdev->default_trigger &&
0313 !strcmp(led_cdev->default_trigger, trig->name) &&
0314 trigger_relevant(led_cdev, trig)) {
0315 led_cdev->flags |= LED_INIT_DEFAULT_TRIGGER;
0316 led_trigger_set(led_cdev, trig);
0317 }
0318 up_write(&led_cdev->trigger_lock);
0319 }
0320 up_read(&leds_list_lock);
0321
0322 return 0;
0323 }
0324 EXPORT_SYMBOL_GPL(led_trigger_register);
0325
0326 void led_trigger_unregister(struct led_trigger *trig)
0327 {
0328 struct led_classdev *led_cdev;
0329
0330 if (list_empty_careful(&trig->next_trig))
0331 return;
0332
0333
0334 down_write(&triggers_list_lock);
0335 list_del_init(&trig->next_trig);
0336 up_write(&triggers_list_lock);
0337
0338
0339 down_read(&leds_list_lock);
0340 list_for_each_entry(led_cdev, &leds_list, node) {
0341 down_write(&led_cdev->trigger_lock);
0342 if (led_cdev->trigger == trig)
0343 led_trigger_set(led_cdev, NULL);
0344 up_write(&led_cdev->trigger_lock);
0345 }
0346 up_read(&leds_list_lock);
0347 }
0348 EXPORT_SYMBOL_GPL(led_trigger_unregister);
0349
0350 static void devm_led_trigger_release(struct device *dev, void *res)
0351 {
0352 led_trigger_unregister(*(struct led_trigger **)res);
0353 }
0354
0355 int devm_led_trigger_register(struct device *dev,
0356 struct led_trigger *trig)
0357 {
0358 struct led_trigger **dr;
0359 int rc;
0360
0361 dr = devres_alloc(devm_led_trigger_release, sizeof(*dr),
0362 GFP_KERNEL);
0363 if (!dr)
0364 return -ENOMEM;
0365
0366 *dr = trig;
0367
0368 rc = led_trigger_register(trig);
0369 if (rc)
0370 devres_free(dr);
0371 else
0372 devres_add(dev, dr);
0373
0374 return rc;
0375 }
0376 EXPORT_SYMBOL_GPL(devm_led_trigger_register);
0377
0378
0379
0380 void led_trigger_event(struct led_trigger *trig,
0381 enum led_brightness brightness)
0382 {
0383 struct led_classdev *led_cdev;
0384
0385 if (!trig)
0386 return;
0387
0388 rcu_read_lock();
0389 list_for_each_entry_rcu(led_cdev, &trig->led_cdevs, trig_list)
0390 led_set_brightness(led_cdev, brightness);
0391 rcu_read_unlock();
0392 }
0393 EXPORT_SYMBOL_GPL(led_trigger_event);
0394
0395 static void led_trigger_blink_setup(struct led_trigger *trig,
0396 unsigned long *delay_on,
0397 unsigned long *delay_off,
0398 int oneshot,
0399 int invert)
0400 {
0401 struct led_classdev *led_cdev;
0402
0403 if (!trig)
0404 return;
0405
0406 rcu_read_lock();
0407 list_for_each_entry_rcu(led_cdev, &trig->led_cdevs, trig_list) {
0408 if (oneshot)
0409 led_blink_set_oneshot(led_cdev, delay_on, delay_off,
0410 invert);
0411 else
0412 led_blink_set(led_cdev, delay_on, delay_off);
0413 }
0414 rcu_read_unlock();
0415 }
0416
0417 void led_trigger_blink(struct led_trigger *trig,
0418 unsigned long *delay_on,
0419 unsigned long *delay_off)
0420 {
0421 led_trigger_blink_setup(trig, delay_on, delay_off, 0, 0);
0422 }
0423 EXPORT_SYMBOL_GPL(led_trigger_blink);
0424
0425 void led_trigger_blink_oneshot(struct led_trigger *trig,
0426 unsigned long *delay_on,
0427 unsigned long *delay_off,
0428 int invert)
0429 {
0430 led_trigger_blink_setup(trig, delay_on, delay_off, 1, invert);
0431 }
0432 EXPORT_SYMBOL_GPL(led_trigger_blink_oneshot);
0433
0434 void led_trigger_register_simple(const char *name, struct led_trigger **tp)
0435 {
0436 struct led_trigger *trig;
0437 int err;
0438
0439 trig = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
0440
0441 if (trig) {
0442 trig->name = name;
0443 err = led_trigger_register(trig);
0444 if (err < 0) {
0445 kfree(trig);
0446 trig = NULL;
0447 pr_warn("LED trigger %s failed to register (%d)\n",
0448 name, err);
0449 }
0450 } else {
0451 pr_warn("LED trigger %s failed to register (no memory)\n",
0452 name);
0453 }
0454 *tp = trig;
0455 }
0456 EXPORT_SYMBOL_GPL(led_trigger_register_simple);
0457
0458 void led_trigger_unregister_simple(struct led_trigger *trig)
0459 {
0460 if (trig)
0461 led_trigger_unregister(trig);
0462 kfree(trig);
0463 }
0464 EXPORT_SYMBOL_GPL(led_trigger_unregister_simple);