drivers/leds/led-triggers.c
Source file repositories/reference/linux-study-clean/drivers/leds/led-triggers.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/leds/led-triggers.c- Extension
.c- Size
- 12606 bytes
- Lines
- 515
- Domain
- Driver Families
- Bucket
- drivers/leds
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/export.hlinux/kernel.hlinux/list.hlinux/spinlock.hlinux/device.hlinux/timer.hlinux/rwsem.hlinux/leds.hlinux/slab.hlinux/mm.hleds.h
Detected Declarations
function trigger_relevantfunction led_trigger_writefunction led_trigger_snprintffunction led_trigger_formatfunction list_for_each_entryfunction led_trigger_readfunction led_trigger_setfunction led_trigger_removefunction led_match_default_triggerfunction led_trigger_set_defaultfunction led_trigger_registerfunction led_trigger_unregisterfunction devm_led_trigger_releasefunction devm_led_trigger_registerfunction led_trigger_eventfunction led_mc_trigger_eventfunction led_trigger_blink_setupfunction led_trigger_blinkfunction led_trigger_blink_oneshotfunction led_trigger_register_simplefunction led_trigger_unregister_simpleexport led_trigger_writeexport led_trigger_readexport led_trigger_setexport led_trigger_removeexport led_trigger_set_defaultexport led_trigger_registerexport led_trigger_unregisterexport devm_led_trigger_registerexport led_trigger_eventexport led_mc_trigger_eventexport led_trigger_blinkexport led_trigger_blink_oneshotexport led_trigger_register_simpleexport led_trigger_unregister_simple
Annotated Snippet
if (sysfs_streq(buf, trig->name) && trigger_relevant(led_cdev, trig)) {
down_write(&led_cdev->trigger_lock);
led_trigger_set(led_cdev, trig);
up_write(&led_cdev->trigger_lock);
up_read(&triggers_list_lock);
goto unlock;
}
}
/* we come here only if buf matches no trigger */
ret = -EINVAL;
up_read(&triggers_list_lock);
unlock:
mutex_unlock(&led_cdev->led_access);
return ret;
}
EXPORT_SYMBOL_GPL(led_trigger_write);
__printf(3, 4)
static int led_trigger_snprintf(char *buf, ssize_t size, const char *fmt, ...)
{
va_list args;
int i;
va_start(args, fmt);
if (size <= 0)
i = vsnprintf(NULL, 0, fmt, args);
else
i = vscnprintf(buf, size, fmt, args);
va_end(args);
return i;
}
static int led_trigger_format(char *buf, size_t size,
struct led_classdev *led_cdev)
{
struct led_trigger *trig;
int len = led_trigger_snprintf(buf, size, "%s",
led_cdev->trigger ? "none" : "[none]");
if (led_cdev->default_trigger)
len += led_trigger_snprintf(buf + len, size - len, " default");
list_for_each_entry(trig, &trigger_list, next_trig) {
bool hit;
if (!trigger_relevant(led_cdev, trig))
continue;
hit = led_cdev->trigger && !strcmp(led_cdev->trigger->name, trig->name);
len += led_trigger_snprintf(buf + len, size - len,
" %s%s%s", hit ? "[" : "",
trig->name, hit ? "]" : "");
}
len += led_trigger_snprintf(buf + len, size - len, "\n");
return len;
}
/*
* It was stupid to create 10000 cpu triggers, but we are stuck with it now.
* Don't make that mistake again. We work around it here by creating binary
* attribute, which is not limited by length. This is _not_ good design, do not
* copy it.
*/
ssize_t led_trigger_read(struct file *filp, struct kobject *kobj,
const struct bin_attribute *attr, char *buf,
loff_t pos, size_t count)
{
struct device *dev = kobj_to_dev(kobj);
struct led_classdev *led_cdev = dev_get_drvdata(dev);
void *data;
int len;
down_read(&triggers_list_lock);
down_read(&led_cdev->trigger_lock);
len = led_trigger_format(NULL, 0, led_cdev);
data = kvmalloc(len + 1, GFP_KERNEL);
if (!data) {
up_read(&led_cdev->trigger_lock);
up_read(&triggers_list_lock);
return -ENOMEM;
}
len = led_trigger_format(data, len + 1, led_cdev);
Annotation
- Immediate include surface: `linux/export.h`, `linux/kernel.h`, `linux/list.h`, `linux/spinlock.h`, `linux/device.h`, `linux/timer.h`, `linux/rwsem.h`, `linux/leds.h`.
- Detected declarations: `function trigger_relevant`, `function led_trigger_write`, `function led_trigger_snprintf`, `function led_trigger_format`, `function list_for_each_entry`, `function led_trigger_read`, `function led_trigger_set`, `function led_trigger_remove`, `function led_match_default_trigger`, `function led_trigger_set_default`.
- Atlas domain: Driver Families / drivers/leds.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.