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 write_lock_irqsave(&led_cdev->trigger->leddev_list_lock, flags); 171 list_del(&led_cdev->trig_list); 172 write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, flags); 173 led_cdev->trigger = NULL; 174 led_cdev->trigger_data = NULL; 175 led_set_brightness(led_cdev, LED_OFF); 176 kfree(event); 177 178 return ret; 179 } 180 EXPORT_SYMBOL_GPL(led_trigger_set); 181 182 void led_trigger_remove(struct led_classdev *led_cdev) 183 { 184 down_write(&led_cdev->trigger_lock); 185 led_trigger_set(led_cdev, NULL); 186 up_write(&led_cdev->trigger_lock); 187 } 188 EXPORT_SYMBOL_GPL(led_trigger_remove); 189 190 void led_trigger_set_default(struct led_classdev *led_cdev) 191 { 192 struct led_trigger *trig; 193 194 if (!led_cdev->default_trigger) 195 return; 196 197 down_read(&triggers_list_lock); 198 down_write(&led_cdev->trigger_lock); 199 list_for_each_entry(trig, &trigger_list, next_trig) { 200 if (!strcmp(led_cdev->default_trigger, trig->name)) { 201 led_cdev->flags |= LED_INIT_DEFAULT_TRIGGER; 202 led_trigger_set(led_cdev, trig); 203 break; 204 } 205 } 206 up_write(&led_cdev->trigger_lock); 207 up_read(&triggers_list_lock); 208 } 209 EXPORT_SYMBOL_GPL(led_trigger_set_default); 210 211 void led_trigger_rename_static(const char *name, struct led_trigger *trig) 212 { 213 /* new name must be on a temporary string to prevent races */ 214 BUG_ON(name == trig->name); 215 216 down_write(&triggers_list_lock); 217 /* this assumes that trig->name was originaly allocated to 218 * non constant storage */ 219 strcpy((char *)trig->name, name); 220 up_write(&triggers_list_lock); 221 } 222 EXPORT_SYMBOL_GPL(led_trigger_rename_static); 223 224 /* LED Trigger Interface */ 225 226 int led_trigger_register(struct led_trigger *trig) 227 { 228 struct led_classdev *led_cdev; 229 struct led_trigger *_trig; 230 231 rwlock_init(&trig->leddev_list_lock); 232 INIT_LIST_HEAD(&trig->led_cdevs); 233 234 down_write(&triggers_list_lock); 235 /* Make sure the trigger's name isn't already in use */ 236 list_for_each_entry(_trig, &trigger_list, next_trig) { 237 if (!strcmp(_trig->name, trig->name)) { 238 up_write(&triggers_list_lock); 239 return -EEXIST; 240 } 241 } 242 /* Add to the list of led triggers */ 243 list_add_tail(&trig->next_trig, &trigger_list); 244 up_write(&triggers_list_lock); 245 246 /* Register with any LEDs that have this as a default trigger */ 247 down_read(&leds_list_lock); 248 list_for_each_entry(led_cdev, &leds_list, node) { 249 down_write(&led_cdev->trigger_lock); 250 if (!led_cdev->trigger && led_cdev->default_trigger && 251 !strcmp(led_cdev->default_trigger, trig->name)) { 252 led_cdev->flags |= LED_INIT_DEFAULT_TRIGGER; 253 led_trigger_set(led_cdev, trig); 254 } 255 up_write(&led_cdev->trigger_lock); 256 } 257 up_read(&leds_list_lock); 258 259 return 0; 260 } 261 EXPORT_SYMBOL_GPL(led_trigger_register); 262 263 void led_trigger_unregister(struct led_trigger *trig) 264 { 265 struct led_classdev *led_cdev; 266 267 if (list_empty_careful(&trig->next_trig)) 268 return; 269 270 /* Remove from the list of led triggers */ 271 down_write(&triggers_list_lock); 272 list_del_init(&trig->next_trig); 273 up_write(&triggers_list_lock); 274 275 /* Remove anyone actively using this trigger */ 276 down_read(&leds_list_lock); 277 list_for_each_entry(led_cdev, &leds_list, node) { 278 down_write(&led_cdev->trigger_lock); 279 if (led_cdev->trigger == trig) 280 led_trigger_set(led_cdev, NULL); 281 up_write(&led_cdev->trigger_lock); 282 } 283 up_read(&leds_list_lock); 284 } 285 EXPORT_SYMBOL_GPL(led_trigger_unregister); 286 287 static void devm_led_trigger_release(struct device *dev, void *res) 288 { 289 led_trigger_unregister(*(struct led_trigger **)res); 290 } 291 292 int devm_led_trigger_register(struct device *dev, 293 struct led_trigger *trig) 294 { 295 struct led_trigger **dr; 296 int rc; 297 298 dr = devres_alloc(devm_led_trigger_release, sizeof(*dr), 299 GFP_KERNEL); 300 if (!dr) 301 return -ENOMEM; 302 303 *dr = trig; 304 305 rc = led_trigger_register(trig); 306 if (rc) 307 devres_free(dr); 308 else 309 devres_add(dev, dr); 310 311 return rc; 312 } 313 EXPORT_SYMBOL_GPL(devm_led_trigger_register); 314 315 /* Simple LED Tigger Interface */ 316 317 void led_trigger_event(struct led_trigger *trig, 318 enum led_brightness brightness) 319 { 320 struct led_classdev *led_cdev; 321 322 if (!trig) 323 return; 324 325 read_lock(&trig->leddev_list_lock); 326 list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list) 327 led_set_brightness(led_cdev, brightness); 328 read_unlock(&trig->leddev_list_lock); 329 } 330 EXPORT_SYMBOL_GPL(led_trigger_event); 331 332 static void led_trigger_blink_setup(struct led_trigger *trig, 333 unsigned long *delay_on, 334 unsigned long *delay_off, 335 int oneshot, 336 int invert) 337 { 338 struct led_classdev *led_cdev; 339 340 if (!trig) 341 return; 342 343 read_lock(&trig->leddev_list_lock); 344 list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list) { 345 if (oneshot) 346 led_blink_set_oneshot(led_cdev, delay_on, delay_off, 347 invert); 348 else 349 led_blink_set(led_cdev, delay_on, delay_off); 350 } 351 read_unlock(&trig->leddev_list_lock); 352 } 353 354 void led_trigger_blink(struct led_trigger *trig, 355 unsigned long *delay_on, 356 unsigned long *delay_off) 357 { 358 led_trigger_blink_setup(trig, delay_on, delay_off, 0, 0); 359 } 360 EXPORT_SYMBOL_GPL(led_trigger_blink); 361 362 void led_trigger_blink_oneshot(struct led_trigger *trig, 363 unsigned long *delay_on, 364 unsigned long *delay_off, 365 int invert) 366 { 367 led_trigger_blink_setup(trig, delay_on, delay_off, 1, invert); 368 } 369 EXPORT_SYMBOL_GPL(led_trigger_blink_oneshot); 370 371 void led_trigger_register_simple(const char *name, struct led_trigger **tp) 372 { 373 struct led_trigger *trig; 374 int err; 375 376 trig = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); 377 378 if (trig) { 379 trig->name = name; 380 err = led_trigger_register(trig); 381 if (err < 0) { 382 kfree(trig); 383 trig = NULL; 384 pr_warn("LED trigger %s failed to register (%d)\n", 385 name, err); 386 } 387 } else { 388 pr_warn("LED trigger %s failed to register (no memory)\n", 389 name); 390 } 391 *tp = trig; 392 } 393 EXPORT_SYMBOL_GPL(led_trigger_register_simple); 394 395 void led_trigger_unregister_simple(struct led_trigger *trig) 396 { 397 if (trig) 398 led_trigger_unregister(trig); 399 kfree(trig); 400 } 401 EXPORT_SYMBOL_GPL(led_trigger_unregister_simple); 402