1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * LED Triggers Core 4 * 5 * Copyright 2005-2007 Openedhand Ltd. 6 * 7 * Author: Richard Purdie <rpurdie@openedhand.com> 8 */ 9 10 #include <linux/export.h> 11 #include <linux/kernel.h> 12 #include <linux/list.h> 13 #include <linux/spinlock.h> 14 #include <linux/device.h> 15 #include <linux/timer.h> 16 #include <linux/rwsem.h> 17 #include <linux/leds.h> 18 #include <linux/slab.h> 19 #include "leds.h" 20 21 /* 22 * Nests outside led_cdev->trigger_lock 23 */ 24 static DECLARE_RWSEM(triggers_list_lock); 25 LIST_HEAD(trigger_list); 26 27 /* Used by LED Class */ 28 29 ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr, 30 const char *buf, size_t count) 31 { 32 struct led_classdev *led_cdev = dev_get_drvdata(dev); 33 struct led_trigger *trig; 34 int ret = count; 35 36 mutex_lock(&led_cdev->led_access); 37 38 if (led_sysfs_is_disabled(led_cdev)) { 39 ret = -EBUSY; 40 goto unlock; 41 } 42 43 if (sysfs_streq(buf, "none")) { 44 led_trigger_remove(led_cdev); 45 goto unlock; 46 } 47 48 down_read(&triggers_list_lock); 49 list_for_each_entry(trig, &trigger_list, next_trig) { 50 if (sysfs_streq(buf, trig->name)) { 51 down_write(&led_cdev->trigger_lock); 52 led_trigger_set(led_cdev, trig); 53 up_write(&led_cdev->trigger_lock); 54 55 up_read(&triggers_list_lock); 56 goto unlock; 57 } 58 } 59 /* we come here only if buf matches no trigger */ 60 ret = -EINVAL; 61 up_read(&triggers_list_lock); 62 63 unlock: 64 mutex_unlock(&led_cdev->led_access); 65 return ret; 66 } 67 EXPORT_SYMBOL_GPL(led_trigger_store); 68 69 ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr, 70 char *buf) 71 { 72 struct led_classdev *led_cdev = dev_get_drvdata(dev); 73 struct led_trigger *trig; 74 int len = 0; 75 76 down_read(&triggers_list_lock); 77 down_read(&led_cdev->trigger_lock); 78 79 if (!led_cdev->trigger) 80 len += scnprintf(buf+len, PAGE_SIZE - len, "[none] "); 81 else 82 len += scnprintf(buf+len, PAGE_SIZE - len, "none "); 83 84 list_for_each_entry(trig, &trigger_list, next_trig) { 85 if (led_cdev->trigger && !strcmp(led_cdev->trigger->name, 86 trig->name)) 87 len += scnprintf(buf+len, PAGE_SIZE - len, "[%s] ", 88 trig->name); 89 else 90 len += scnprintf(buf+len, PAGE_SIZE - len, "%s ", 91 trig->name); 92 } 93 up_read(&led_cdev->trigger_lock); 94 up_read(&triggers_list_lock); 95 96 len += scnprintf(len+buf, PAGE_SIZE - len, "\n"); 97 return len; 98 } 99 EXPORT_SYMBOL_GPL(led_trigger_show); 100 101 /* Caller must ensure led_cdev->trigger_lock held */ 102 int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) 103 { 104 unsigned long flags; 105 char *event = NULL; 106 char *envp[2]; 107 const char *name; 108 int ret; 109 110 if (!led_cdev->trigger && !trig) 111 return 0; 112 113 name = trig ? trig->name : "none"; 114 event = kasprintf(GFP_KERNEL, "TRIGGER=%s", name); 115 116 /* Remove any existing trigger */ 117 if (led_cdev->trigger) { 118 write_lock_irqsave(&led_cdev->trigger->leddev_list_lock, flags); 119 list_del(&led_cdev->trig_list); 120 write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, 121 flags); 122 cancel_work_sync(&led_cdev->set_brightness_work); 123 led_stop_software_blink(led_cdev); 124 if (led_cdev->trigger->deactivate) 125 led_cdev->trigger->deactivate(led_cdev); 126 device_remove_groups(led_cdev->dev, led_cdev->trigger->groups); 127 led_cdev->trigger = NULL; 128 led_cdev->trigger_data = NULL; 129 led_cdev->activated = false; 130 led_set_brightness(led_cdev, LED_OFF); 131 } 132 if (trig) { 133 write_lock_irqsave(&trig->leddev_list_lock, flags); 134 list_add_tail(&led_cdev->trig_list, &trig->led_cdevs); 135 write_unlock_irqrestore(&trig->leddev_list_lock, flags); 136 led_cdev->trigger = trig; 137 138 if (trig->activate) 139 ret = trig->activate(led_cdev); 140 else 141 ret = 0; 142 143 if (ret) 144 goto err_activate; 145 146 ret = device_add_groups(led_cdev->dev, trig->groups); 147 if (ret) { 148 dev_err(led_cdev->dev, "Failed to add trigger attributes\n"); 149 goto err_add_groups; 150 } 151 } 152 153 if (event) { 154 envp[0] = event; 155 envp[1] = NULL; 156 if (kobject_uevent_env(&led_cdev->dev->kobj, KOBJ_CHANGE, envp)) 157 dev_err(led_cdev->dev, 158 "%s: Error sending uevent\n", __func__); 159 kfree(event); 160 } 161 162 return 0; 163 164 err_add_groups: 165 166 if (trig->deactivate) 167 trig->deactivate(led_cdev); 168 err_activate: 169 170 led_cdev->trigger = NULL; 171 led_cdev->trigger_data = NULL; 172 write_lock_irqsave(&led_cdev->trigger->leddev_list_lock, flags); 173 list_del(&led_cdev->trig_list); 174 write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, flags); 175 led_set_brightness(led_cdev, LED_OFF); 176 177 return ret; 178 } 179 EXPORT_SYMBOL_GPL(led_trigger_set); 180 181 void led_trigger_remove(struct led_classdev *led_cdev) 182 { 183 down_write(&led_cdev->trigger_lock); 184 led_trigger_set(led_cdev, NULL); 185 up_write(&led_cdev->trigger_lock); 186 } 187 EXPORT_SYMBOL_GPL(led_trigger_remove); 188 189 void led_trigger_set_default(struct led_classdev *led_cdev) 190 { 191 struct led_trigger *trig; 192 193 if (!led_cdev->default_trigger) 194 return; 195 196 down_read(&triggers_list_lock); 197 down_write(&led_cdev->trigger_lock); 198 list_for_each_entry(trig, &trigger_list, next_trig) { 199 if (!strcmp(led_cdev->default_trigger, trig->name)) { 200 led_cdev->flags |= LED_INIT_DEFAULT_TRIGGER; 201 led_trigger_set(led_cdev, trig); 202 break; 203 } 204 } 205 up_write(&led_cdev->trigger_lock); 206 up_read(&triggers_list_lock); 207 } 208 EXPORT_SYMBOL_GPL(led_trigger_set_default); 209 210 void led_trigger_rename_static(const char *name, struct led_trigger *trig) 211 { 212 /* new name must be on a temporary string to prevent races */ 213 BUG_ON(name == trig->name); 214 215 down_write(&triggers_list_lock); 216 /* this assumes that trig->name was originaly allocated to 217 * non constant storage */ 218 strcpy((char *)trig->name, name); 219 up_write(&triggers_list_lock); 220 } 221 EXPORT_SYMBOL_GPL(led_trigger_rename_static); 222 223 /* LED Trigger Interface */ 224 225 int led_trigger_register(struct led_trigger *trig) 226 { 227 struct led_classdev *led_cdev; 228 struct led_trigger *_trig; 229 230 rwlock_init(&trig->leddev_list_lock); 231 INIT_LIST_HEAD(&trig->led_cdevs); 232 233 down_write(&triggers_list_lock); 234 /* Make sure the trigger's name isn't already in use */ 235 list_for_each_entry(_trig, &trigger_list, next_trig) { 236 if (!strcmp(_trig->name, trig->name)) { 237 up_write(&triggers_list_lock); 238 return -EEXIST; 239 } 240 } 241 /* Add to the list of led triggers */ 242 list_add_tail(&trig->next_trig, &trigger_list); 243 up_write(&triggers_list_lock); 244 245 /* Register with any LEDs that have this as a default trigger */ 246 down_read(&leds_list_lock); 247 list_for_each_entry(led_cdev, &leds_list, node) { 248 down_write(&led_cdev->trigger_lock); 249 if (!led_cdev->trigger && led_cdev->default_trigger && 250 !strcmp(led_cdev->default_trigger, trig->name)) { 251 led_cdev->flags |= LED_INIT_DEFAULT_TRIGGER; 252 led_trigger_set(led_cdev, trig); 253 } 254 up_write(&led_cdev->trigger_lock); 255 } 256 up_read(&leds_list_lock); 257 258 return 0; 259 } 260 EXPORT_SYMBOL_GPL(led_trigger_register); 261 262 void led_trigger_unregister(struct led_trigger *trig) 263 { 264 struct led_classdev *led_cdev; 265 266 if (list_empty_careful(&trig->next_trig)) 267 return; 268 269 /* Remove from the list of led triggers */ 270 down_write(&triggers_list_lock); 271 list_del_init(&trig->next_trig); 272 up_write(&triggers_list_lock); 273 274 /* Remove anyone actively using this trigger */ 275 down_read(&leds_list_lock); 276 list_for_each_entry(led_cdev, &leds_list, node) { 277 down_write(&led_cdev->trigger_lock); 278 if (led_cdev->trigger == trig) 279 led_trigger_set(led_cdev, NULL); 280 up_write(&led_cdev->trigger_lock); 281 } 282 up_read(&leds_list_lock); 283 } 284 EXPORT_SYMBOL_GPL(led_trigger_unregister); 285 286 static void devm_led_trigger_release(struct device *dev, void *res) 287 { 288 led_trigger_unregister(*(struct led_trigger **)res); 289 } 290 291 int devm_led_trigger_register(struct device *dev, 292 struct led_trigger *trig) 293 { 294 struct led_trigger **dr; 295 int rc; 296 297 dr = devres_alloc(devm_led_trigger_release, sizeof(*dr), 298 GFP_KERNEL); 299 if (!dr) 300 return -ENOMEM; 301 302 *dr = trig; 303 304 rc = led_trigger_register(trig); 305 if (rc) 306 devres_free(dr); 307 else 308 devres_add(dev, dr); 309 310 return rc; 311 } 312 EXPORT_SYMBOL_GPL(devm_led_trigger_register); 313 314 /* Simple LED Tigger Interface */ 315 316 void led_trigger_event(struct led_trigger *trig, 317 enum led_brightness brightness) 318 { 319 struct led_classdev *led_cdev; 320 321 if (!trig) 322 return; 323 324 read_lock(&trig->leddev_list_lock); 325 list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list) 326 led_set_brightness(led_cdev, brightness); 327 read_unlock(&trig->leddev_list_lock); 328 } 329 EXPORT_SYMBOL_GPL(led_trigger_event); 330 331 static void led_trigger_blink_setup(struct led_trigger *trig, 332 unsigned long *delay_on, 333 unsigned long *delay_off, 334 int oneshot, 335 int invert) 336 { 337 struct led_classdev *led_cdev; 338 339 if (!trig) 340 return; 341 342 read_lock(&trig->leddev_list_lock); 343 list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list) { 344 if (oneshot) 345 led_blink_set_oneshot(led_cdev, delay_on, delay_off, 346 invert); 347 else 348 led_blink_set(led_cdev, delay_on, delay_off); 349 } 350 read_unlock(&trig->leddev_list_lock); 351 } 352 353 void led_trigger_blink(struct led_trigger *trig, 354 unsigned long *delay_on, 355 unsigned long *delay_off) 356 { 357 led_trigger_blink_setup(trig, delay_on, delay_off, 0, 0); 358 } 359 EXPORT_SYMBOL_GPL(led_trigger_blink); 360 361 void led_trigger_blink_oneshot(struct led_trigger *trig, 362 unsigned long *delay_on, 363 unsigned long *delay_off, 364 int invert) 365 { 366 led_trigger_blink_setup(trig, delay_on, delay_off, 1, invert); 367 } 368 EXPORT_SYMBOL_GPL(led_trigger_blink_oneshot); 369 370 void led_trigger_register_simple(const char *name, struct led_trigger **tp) 371 { 372 struct led_trigger *trig; 373 int err; 374 375 trig = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); 376 377 if (trig) { 378 trig->name = name; 379 err = led_trigger_register(trig); 380 if (err < 0) { 381 kfree(trig); 382 trig = NULL; 383 pr_warn("LED trigger %s failed to register (%d)\n", 384 name, err); 385 } 386 } else { 387 pr_warn("LED trigger %s failed to register (no memory)\n", 388 name); 389 } 390 *tp = trig; 391 } 392 EXPORT_SYMBOL_GPL(led_trigger_register_simple); 393 394 void led_trigger_unregister_simple(struct led_trigger *trig) 395 { 396 if (trig) 397 led_trigger_unregister(trig); 398 kfree(trig); 399 } 400 EXPORT_SYMBOL_GPL(led_trigger_unregister_simple); 401