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