[trunk/include/autotools.mk] disable libtool fixups in trunk globally
[openwrt/svn-archive/archive.git] / package / mac80211 / patches / 560-led_blink_backport.patch
1 --- a/compat/compat-2.6.37.c
2 +++ b/compat/compat-2.6.37.c
3 @@ -152,3 +152,175 @@ int compat_genl_unregister_family(struct
4 }
5 EXPORT_SYMBOL(compat_genl_unregister_family);
6
7 +#ifdef CONFIG_LEDS_CLASS
8 +
9 +#undef led_brightness_set
10 +#undef led_classdev_unregister
11 +
12 +spinlock_t led_lock;
13 +static LIST_HEAD(led_timers);
14 +
15 +struct led_timer {
16 + struct list_head list;
17 + struct led_classdev *cdev;
18 + struct timer_list blink_timer;
19 + unsigned long blink_delay_on;
20 + unsigned long blink_delay_off;
21 + int blink_brightness;
22 +};
23 +
24 +static void led_brightness_set(struct led_classdev *led_cdev,
25 + enum led_brightness brightness)
26 +{
27 + led_cdev->brightness = brightness;
28 + led_cdev->brightness_set(led_cdev, brightness);
29 +}
30 +
31 +static struct led_timer *led_get_timer(struct led_classdev *led_cdev)
32 +{
33 + struct led_timer *p;
34 + unsigned long flags;
35 +
36 + spin_lock_irqsave(&led_lock, flags);
37 + list_for_each_entry(p, &led_timers, list) {
38 + if (p->cdev == led_cdev)
39 + goto found;
40 + }
41 + p = NULL;
42 +found:
43 + spin_unlock_irqrestore(&led_lock, flags);
44 + return p;
45 +}
46 +
47 +static void led_stop_software_blink(struct led_timer *led)
48 +{
49 + del_timer_sync(&led->blink_timer);
50 + led->blink_delay_on = 0;
51 + led->blink_delay_off = 0;
52 +}
53 +
54 +static void led_timer_function(unsigned long data)
55 +{
56 + struct led_timer *led = (struct led_timer *)data;
57 + unsigned long brightness;
58 + unsigned long delay;
59 +
60 + if (!led->blink_delay_on || !led->blink_delay_off) {
61 + led->cdev->brightness_set(led->cdev, LED_OFF);
62 + return;
63 + }
64 +
65 + brightness = led->cdev->brightness;
66 + if (!brightness) {
67 + /* Time to switch the LED on. */
68 + brightness = led->blink_brightness;
69 + delay = led->blink_delay_on;
70 + } else {
71 + /* Store the current brightness value to be able
72 + * to restore it when the delay_off period is over.
73 + */
74 + led->blink_brightness = brightness;
75 + brightness = LED_OFF;
76 + delay = led->blink_delay_off;
77 + }
78 +
79 + led_brightness_set(led->cdev, brightness);
80 + mod_timer(&led->blink_timer, jiffies + msecs_to_jiffies(delay));
81 +}
82 +
83 +static struct led_timer *led_new_timer(struct led_classdev *led_cdev)
84 +{
85 + struct led_timer *led;
86 + unsigned long flags;
87 +
88 + led = kzalloc(sizeof(struct led_timer), GFP_ATOMIC);
89 + if (!led)
90 + return NULL;
91 +
92 + led->cdev = led_cdev;
93 + init_timer(&led->blink_timer);
94 + led->blink_timer.function = led_timer_function;
95 + led->blink_timer.data = (unsigned long) led;
96 +
97 + spin_lock_irqsave(&led_lock, flags);
98 + list_add(&led->list, &led_timers);
99 + spin_unlock_irqrestore(&led_lock, flags);
100 +
101 + return led;
102 +}
103 +
104 +void led_blink_set(struct led_classdev *led_cdev,
105 + unsigned long *delay_on,
106 + unsigned long *delay_off)
107 +{
108 + struct led_timer *led = led_get_timer(led_cdev);
109 + int current_brightness;
110 +
111 + if (!led) {
112 + led = led_new_timer(led_cdev);
113 + if (!led)
114 + return;
115 + }
116 +
117 + /* blink with 1 Hz as default if nothing specified */
118 + if (!*delay_on && !*delay_off)
119 + *delay_on = *delay_off = 500;
120 +
121 + if (led->blink_delay_on == *delay_on &&
122 + led->blink_delay_off == *delay_off)
123 + return;
124 +
125 + current_brightness = led_cdev->brightness;
126 + if (current_brightness)
127 + led->blink_brightness = current_brightness;
128 + if (!led->blink_brightness)
129 + led->blink_brightness = led_cdev->max_brightness;
130 +
131 + led_stop_software_blink(led);
132 + led->blink_delay_on = *delay_on;
133 + led->blink_delay_off = *delay_off;
134 +
135 + /* never on - don't blink */
136 + if (!*delay_on)
137 + return;
138 +
139 + /* never off - just set to brightness */
140 + if (!*delay_off) {
141 + led_brightness_set(led_cdev, led->blink_brightness);
142 + return;
143 + }
144 +
145 + mod_timer(&led->blink_timer, jiffies + 1);
146 +}
147 +EXPORT_SYMBOL(led_blink_set);
148 +
149 +void compat_led_brightness_set(struct led_classdev *led_cdev,
150 + enum led_brightness brightness)
151 +{
152 + struct led_timer *led = led_get_timer(led_cdev);
153 +
154 + if (led)
155 + led_stop_software_blink(led);
156 +
157 + return led_cdev->brightness_set(led_cdev, brightness);
158 +}
159 +EXPORT_SYMBOL(compat_led_brightness_set);
160 +
161 +void compat_led_classdev_unregister(struct led_classdev *led_cdev)
162 +{
163 + struct led_timer *led = led_get_timer(led_cdev);
164 + unsigned long flags;
165 +
166 + if (led) {
167 + del_timer_sync(&led->blink_timer);
168 + spin_lock_irqsave(&led_lock, flags);
169 + list_del(&led->list);
170 + spin_unlock_irqrestore(&led_lock, flags);
171 + kfree(led);
172 + }
173 +
174 + led_classdev_unregister(led_cdev);
175 +}
176 +EXPORT_SYMBOL(compat_led_classdev_unregister);
177 +
178 +#endif
179 --- a/include/linux/compat-2.6.37.h
180 +++ b/include/linux/compat-2.6.37.h
181 @@ -6,6 +6,7 @@
182 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37))
183
184 #include <linux/skbuff.h>
185 +#include <linux/leds.h>
186
187 #define SDIO_CLASS_BT_AMP 0x09 /* Type-A Bluetooth AMP interface */
188
189 @@ -93,6 +94,18 @@ int genl_unregister_family(struct genl_f
190 #define genl_register_mc_group(_fam, _grp) genl_register_mc_group(&(_fam)->family, _grp)
191 #define genl_unregister_mc_group(_fam, _grp) genl_unregister_mc_group(&(_fam)->family, _grp)
192
193 +
194 +extern void led_blink_set(struct led_classdev *led_cdev,
195 + unsigned long *delay_on,
196 + unsigned long *delay_off);
197 +
198 +#define led_classdev_unregister compat_led_classdev_unregister
199 +extern void led_classdev_unregister(struct led_classdev *led_cdev);
200 +
201 +#define led_brightness_set compat_led_brightness_set
202 +extern void led_brightness_set(struct led_classdev *led_cdev,
203 + enum led_brightness brightness);
204 +
205 #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)) */
206
207 #endif /* LINUX_26_37_COMPAT_H */