forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-31 f70575805708cabdedea7498aaa3f710fde4d920
kernel/drivers/leds/led-triggers.c
....@@ -1,14 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * LED Triggers Core
34 *
45 * Copyright 2005-2007 Openedhand Ltd.
56 *
67 * Author: Richard Purdie <rpurdie@openedhand.com>
7
- *
8
- * This program is free software; you can redistribute it and/or modify
9
- * it under the terms of the GNU General Public License version 2 as
10
- * published by the Free Software Foundation.
11
- *
128 */
139
1410 #include <linux/export.h>
....@@ -20,6 +16,7 @@
2016 #include <linux/rwsem.h>
2117 #include <linux/leds.h>
2218 #include <linux/slab.h>
19
+#include <linux/mm.h>
2320 #include "leds.h"
2421
2522 /*
....@@ -30,9 +27,17 @@
3027
3128 /* Used by LED Class */
3229
33
-ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
34
- const char *buf, size_t count)
30
+static inline bool
31
+trigger_relevant(struct led_classdev *led_cdev, struct led_trigger *trig)
3532 {
33
+ return !trig->trigger_type || trig->trigger_type == led_cdev->trigger_type;
34
+}
35
+
36
+ssize_t led_trigger_write(struct file *filp, struct kobject *kobj,
37
+ struct bin_attribute *bin_attr, char *buf,
38
+ loff_t pos, size_t count)
39
+{
40
+ struct device *dev = kobj_to_dev(kobj);
3641 struct led_classdev *led_cdev = dev_get_drvdata(dev);
3742 struct led_trigger *trig;
3843 int ret = count;
....@@ -51,7 +56,7 @@
5156
5257 down_read(&triggers_list_lock);
5358 list_for_each_entry(trig, &trigger_list, next_trig) {
54
- if (sysfs_streq(buf, trig->name)) {
59
+ if (sysfs_streq(buf, trig->name) && trigger_relevant(led_cdev, trig)) {
5560 down_write(&led_cdev->trigger_lock);
5661 led_trigger_set(led_cdev, trig);
5762 up_write(&led_cdev->trigger_lock);
....@@ -68,39 +73,86 @@
6873 mutex_unlock(&led_cdev->led_access);
6974 return ret;
7075 }
71
-EXPORT_SYMBOL_GPL(led_trigger_store);
76
+EXPORT_SYMBOL_GPL(led_trigger_write);
7277
73
-ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr,
74
- char *buf)
78
+__printf(3, 4)
79
+static int led_trigger_snprintf(char *buf, ssize_t size, const char *fmt, ...)
7580 {
76
- struct led_classdev *led_cdev = dev_get_drvdata(dev);
81
+ va_list args;
82
+ int i;
83
+
84
+ va_start(args, fmt);
85
+ if (size <= 0)
86
+ i = vsnprintf(NULL, 0, fmt, args);
87
+ else
88
+ i = vscnprintf(buf, size, fmt, args);
89
+ va_end(args);
90
+
91
+ return i;
92
+}
93
+
94
+static int led_trigger_format(char *buf, size_t size,
95
+ struct led_classdev *led_cdev)
96
+{
7797 struct led_trigger *trig;
78
- int len = 0;
98
+ int len = led_trigger_snprintf(buf, size, "%s",
99
+ led_cdev->trigger ? "none" : "[none]");
100
+
101
+ list_for_each_entry(trig, &trigger_list, next_trig) {
102
+ bool hit;
103
+
104
+ if (!trigger_relevant(led_cdev, trig))
105
+ continue;
106
+
107
+ hit = led_cdev->trigger && !strcmp(led_cdev->trigger->name, trig->name);
108
+
109
+ len += led_trigger_snprintf(buf + len, size - len,
110
+ " %s%s%s", hit ? "[" : "",
111
+ trig->name, hit ? "]" : "");
112
+ }
113
+
114
+ len += led_trigger_snprintf(buf + len, size - len, "\n");
115
+
116
+ return len;
117
+}
118
+
119
+/*
120
+ * It was stupid to create 10000 cpu triggers, but we are stuck with it now.
121
+ * Don't make that mistake again. We work around it here by creating binary
122
+ * attribute, which is not limited by length. This is _not_ good design, do not
123
+ * copy it.
124
+ */
125
+ssize_t led_trigger_read(struct file *filp, struct kobject *kobj,
126
+ struct bin_attribute *attr, char *buf,
127
+ loff_t pos, size_t count)
128
+{
129
+ struct device *dev = kobj_to_dev(kobj);
130
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
131
+ void *data;
132
+ int len;
79133
80134 down_read(&triggers_list_lock);
81135 down_read(&led_cdev->trigger_lock);
82136
83
- if (!led_cdev->trigger)
84
- len += scnprintf(buf+len, PAGE_SIZE - len, "[none] ");
85
- else
86
- len += scnprintf(buf+len, PAGE_SIZE - len, "none ");
87
-
88
- list_for_each_entry(trig, &trigger_list, next_trig) {
89
- if (led_cdev->trigger && !strcmp(led_cdev->trigger->name,
90
- trig->name))
91
- len += scnprintf(buf+len, PAGE_SIZE - len, "[%s] ",
92
- trig->name);
93
- else
94
- len += scnprintf(buf+len, PAGE_SIZE - len, "%s ",
95
- trig->name);
137
+ len = led_trigger_format(NULL, 0, led_cdev);
138
+ data = kvmalloc(len + 1, GFP_KERNEL);
139
+ if (!data) {
140
+ up_read(&led_cdev->trigger_lock);
141
+ up_read(&triggers_list_lock);
142
+ return -ENOMEM;
96143 }
144
+ len = led_trigger_format(data, len + 1, led_cdev);
145
+
97146 up_read(&led_cdev->trigger_lock);
98147 up_read(&triggers_list_lock);
99148
100
- len += scnprintf(len+buf, PAGE_SIZE - len, "\n");
149
+ len = memory_read_from_buffer(buf, count, &pos, data, len);
150
+
151
+ kvfree(data);
152
+
101153 return len;
102154 }
103
-EXPORT_SYMBOL_GPL(led_trigger_show);
155
+EXPORT_SYMBOL_GPL(led_trigger_read);
104156
105157 /* Caller must ensure led_cdev->trigger_lock held */
106158 int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
....@@ -201,8 +253,12 @@
201253 down_read(&triggers_list_lock);
202254 down_write(&led_cdev->trigger_lock);
203255 list_for_each_entry(trig, &trigger_list, next_trig) {
204
- if (!strcmp(led_cdev->default_trigger, trig->name))
256
+ if (!strcmp(led_cdev->default_trigger, trig->name) &&
257
+ trigger_relevant(led_cdev, trig)) {
258
+ led_cdev->flags |= LED_INIT_DEFAULT_TRIGGER;
205259 led_trigger_set(led_cdev, trig);
260
+ break;
261
+ }
206262 }
207263 up_write(&led_cdev->trigger_lock);
208264 up_read(&triggers_list_lock);
....@@ -235,7 +291,9 @@
235291 down_write(&triggers_list_lock);
236292 /* Make sure the trigger's name isn't already in use */
237293 list_for_each_entry(_trig, &trigger_list, next_trig) {
238
- if (!strcmp(_trig->name, trig->name)) {
294
+ if (!strcmp(_trig->name, trig->name) &&
295
+ (trig->trigger_type == _trig->trigger_type ||
296
+ !trig->trigger_type || !_trig->trigger_type)) {
239297 up_write(&triggers_list_lock);
240298 return -EEXIST;
241299 }
....@@ -249,8 +307,11 @@
249307 list_for_each_entry(led_cdev, &leds_list, node) {
250308 down_write(&led_cdev->trigger_lock);
251309 if (!led_cdev->trigger && led_cdev->default_trigger &&
252
- !strcmp(led_cdev->default_trigger, trig->name))
310
+ !strcmp(led_cdev->default_trigger, trig->name) &&
311
+ trigger_relevant(led_cdev, trig)) {
312
+ led_cdev->flags |= LED_INIT_DEFAULT_TRIGGER;
253313 led_trigger_set(led_cdev, trig);
314
+ }
254315 up_write(&led_cdev->trigger_lock);
255316 }
256317 up_read(&leds_list_lock);
....@@ -311,7 +372,7 @@
311372 }
312373 EXPORT_SYMBOL_GPL(devm_led_trigger_register);
313374
314
-/* Simple LED Tigger Interface */
375
+/* Simple LED Trigger Interface */
315376
316377 void led_trigger_event(struct led_trigger *trig,
317378 enum led_brightness brightness)