BW Limiter: Restore BW limiter broken.
[tomato.git] / release / src / router / rc / buttons.c
blob0858cb69a54860d03f24c41b68afa406beb21c5e
1 /*
3 Tomato Firmware
4 Copyright (C) 2006-2009 Jonathan Zarate
6 */
7 #include "rc.h"
9 #include <sys/reboot.h>
10 #include <wlutils.h>
11 #include <wlioctl.h>
13 // #define DEBUG_TEST
15 static int gf;
17 static int get_btn(const char *name, uint32_t *bit, uint32_t *pushed)
19 int gpio;
20 int inv;
22 if (nvget_gpio(name, &gpio, &inv)) {
23 *bit = 1 << gpio;
24 *pushed = inv ? 0 : *bit;
25 return 1;
27 return 0;
30 int buttons_main(int argc, char *argv[])
32 uint32_t gpio;
33 uint32_t mask;
34 uint32_t last;
35 uint32_t ses_mask;
36 uint32_t ses_pushed;
37 uint32_t reset_mask;
38 uint32_t reset_pushed;
39 uint32_t brau_mask;
40 uint32_t brau_state;
41 int brau_count_stable;
42 int brau_flag;
43 int count;
44 char s[16];
45 char *p;
46 int n;
47 int ses_led;
49 ses_mask = ses_pushed = 0;
50 reset_pushed = 0;
51 brau_mask = 0;
52 brau_state = ~0;
53 ses_led = LED_DIAG;
55 // moveme
56 switch (nvram_get_int("btn_override") ? MODEL_UNKNOWN : get_model()) {
57 case MODEL_WRT54G:
58 case MODEL_WRTSL54GS:
59 reset_mask = 1 << 6;
60 ses_mask = 1 << 4;
61 ses_led = LED_DMZ;
62 break;
63 /*
64 case MODEL_WRH54G:
65 reset_mask = 1 << 6;
66 break;
68 case MODEL_WTR54GS:
69 reset_mask = 1 << 3;
70 ses_mask = 1 << 2;
71 break;
72 case MODEL_WHRG54S:
73 case MODEL_WHRHPG54:
74 case MODEL_WHR2A54G54:
75 case MODEL_WHR3AG54:
76 case MODEL_WHRG125:
77 reset_mask = reset_pushed = 1 << 4;
78 ses_mask = 1 << 0;
79 brau_mask = 1 << 5;
80 break;
81 case MODEL_WBRG54:
82 reset_mask = reset_pushed = 1 << 4;
83 break;
84 case MODEL_WBR2G54:
85 reset_mask = reset_pushed = 1 << 7;
86 ses_mask = ses_pushed = 1 << 4;
87 ses_led = LED_AOSS;
88 break;
89 case MODEL_WZRG54:
90 case MODEL_WZRHPG54:
91 case MODEL_WZRRSG54:
92 case MODEL_WZRRSG54HP:
93 case MODEL_WVRG54NF:
94 reset_mask = reset_pushed = 1 << 4;
95 ses_mask = 1 << 0;
96 ses_led = LED_AOSS;
97 break;
98 case MODEL_WZRG108:
99 reset_mask = reset_pushed = 1 << 7;
100 ses_mask = 1 << 0;
101 ses_led = LED_AOSS;
102 break;
103 case MODEL_WR850GV1:
104 reset_mask = 1 << 0;
105 break;
106 case MODEL_WR850GV2:
107 case MODEL_WR100:
108 reset_mask = 1 << 5;
109 break;
110 case MODEL_WL500GP:
111 reset_mask = reset_pushed = 1 << 0;
112 ses_mask = ses_pushed = 1 << 4;
113 break;
114 case MODEL_WL500W:
115 reset_mask = reset_pushed = 1 << 6;
116 ses_mask = ses_pushed = 1 << 7;
117 break;
118 case MODEL_DIR320:
119 case MODEL_H618B:
120 reset_mask = 1 << 7;
121 ses_mask = 1 << 6; // WLAN button on H618B
122 break;
123 case MODEL_WL500GPv2:
124 case MODEL_WL520GU:
125 case MODEL_WL330GE:
126 reset_mask = 1 << 2;
127 ses_mask = 1 << 3;
128 break;
129 // case MODEL_MN700:
130 //? reset_mask = reset_pushed = 1 << 7;
131 // break;
132 case MODEL_WLA2G54L:
133 reset_mask = reset_pushed = 1 << 7;
134 break;
135 case MODEL_WL1600GL:
136 reset_mask = 1 << 3;
137 ses_mask = 1 << 4;
138 ses_led = LED_AOSS;
139 break;
140 #ifdef CONFIG_BCMWL5
141 case MODEL_RTN10:
142 reset_mask = 1 << 3;
143 ses_mask = 1 << 2;
144 break;
145 case MODEL_RTN10U:
146 reset_mask = 1 << 21;
147 ses_mask = 1 << 20;
148 ses_led = LED_AOSS;
149 break;
150 case MODEL_RTN12:
151 reset_mask = 1 << 1;
152 ses_mask = 1 << 0;
153 brau_mask = (1 << 4) | (1 << 5) | (1 << 6);
154 break;
155 case MODEL_RTN15U:
156 reset_mask = 1 << 5;
157 ses_mask = 1 << 8;
158 break;
159 case MODEL_RTN16:
160 reset_mask = 1 << 6;
161 ses_mask = 1 << 8;
162 break;
163 case MODEL_RTN53:
164 reset_mask = 1 << 3;
165 ses_mask = 1 << 7;
166 break;
167 case MODEL_RTN66U:
168 reset_mask = 1 << 9;
169 ses_mask = 1 << 4;
170 break;
171 case MODEL_W1800R:
172 reset_mask = 1 << 14;
173 break;
174 case MODEL_WNR3500L:
175 case MODEL_WNR3500LV2:
176 reset_mask = 1 << 4;
177 ses_mask = 1 << 6;
178 ses_led = LED_AOSS;
179 break;
180 case MODEL_WNR2000v2:
181 reset_mask = 1 << 1;
182 ses_mask = 1 << 0;
183 ses_led = LED_AOSS;
184 break;
185 case MODEL_WNDR3700v3:
186 reset_mask = 1 << 3;
187 ses_mask = 1 << 2;
188 ses_led = LED_AOSS;
189 break;
190 case MODEL_F7D3301:
191 case MODEL_F7D3302:
192 case MODEL_F7D4301:
193 case MODEL_F7D4302:
194 case MODEL_F5D8235v3:
195 reset_mask = 1 << 6;
196 ses_mask = 1 << 8;
197 ses_led = LED_AOSS;
198 break;
199 case MODEL_E800:
200 case MODEL_E900:
201 case MODEL_E1000v2:
202 case MODEL_E1500:
203 case MODEL_E1550:
204 case MODEL_E2500:
205 reset_mask = 1 << 10;
206 ses_mask = 1 << 9;
207 break;
208 case MODEL_E3200:
209 reset_mask = 1 << 5;
210 ses_mask = 1 << 8;
211 break;
212 case MODEL_WRT160Nv3:
213 reset_mask = 1 << 6;
214 ses_mask = 1 << 5;
215 break;
216 case MODEL_WRT320N:
217 reset_mask = 1 << 8;
218 ses_mask = 1 << 5;
219 ses_led = LED_AMBER;
220 break;
221 case MODEL_WRT610Nv2:
222 reset_mask = 1 << 6;
223 ses_mask = 1 << 4;
224 ses_led = LED_AMBER;
225 break;
226 case MODEL_E4200:
227 reset_mask = 1 << 6;
228 ses_mask = 1 << 4;
229 ses_led = LED_WHITE;
230 break;
231 case MODEL_L600N:
232 reset_mask = 1 << 21;
233 ses_mask = 1 << 20;
234 //wlan button = 1 >> 10
235 break;
236 case MODEL_DIR620C1:
237 reset_mask = 1 << 21;
238 ses_mask = 1 << 20;
239 break;
240 #endif
241 case MODEL_WRT160Nv1:
242 case MODEL_WRT300N:
243 reset_mask = 1 << 6;
244 ses_mask = 1 << 4;
245 break;
246 case MODEL_WRT310Nv1:
247 reset_mask = 1 << 6;
248 ses_mask = 1 << 8;
249 break;
250 // Added by BWQ
251 case MODEL_RG200E_CA:
252 case MODEL_H218N:
253 reset_mask = 1 << 30;
254 ses_mask = 1 << 28;
255 break;
256 case MODEL_HG320:
257 reset_mask = 1 << 30;
258 ses_mask = 1 << 29;
259 break;
260 // BWQ end.
261 default:
262 get_btn("btn_ses", &ses_mask, &ses_pushed);
263 if (!get_btn("btn_reset", &reset_mask, &reset_pushed)) {
264 // fprintf(stderr, "Not supported.\n");
265 return 1;
267 break;
269 mask = reset_mask | ses_mask | brau_mask;
271 #ifdef DEBUG_TEST
272 cprintf("reset_mask=0x%X reset_pushed=0x%X\n", reset_mask, reset_pushed);
273 cprintf("ses_mask=0x%X\n", ses_mask);
274 cprintf("brau_mask=0x%X\n", brau_mask);
275 cprintf("ses_led=%d\n", ses_led);
276 #else
277 if (fork() != 0) return 0;
278 setsid();
279 #endif
281 signal(SIGCHLD, chld_reap);
283 if ((gf = gpio_open(mask)) < 0) return 1;
285 last = 0;
286 brau_count_stable = 0;
287 brau_flag = 0;
288 while (1) {
289 if (((gpio = _gpio_read(gf)) == ~0) || (last == (gpio &= mask) && !brau_flag) || (check_action() != ACT_IDLE)) {
290 #ifdef DEBUG_TEST
291 cprintf("gpio = %X\n", gpio);
292 #endif
293 sleep(1);
294 continue;
297 if ((gpio & reset_mask) == reset_pushed) {
298 #ifdef DEBUG_TEST
299 cprintf("reset down\n");
300 #endif
302 led(LED_DIAG, 0);
304 count = 0;
305 do {
306 sleep(1);
307 if (++count == 3) led(LED_DIAG, 1);
308 } while (((gpio = _gpio_read(gf)) != ~0) && ((gpio & reset_mask) == reset_pushed));
310 #ifdef DEBUG_TEST
311 cprintf("reset count = %d\n", count);
312 #else
313 if (count >= 3) {
314 eval("mtd-erase", "-d", "nvram");
315 //nvram_set("restore_defaults", "1");
316 //nvram_commit();
317 sync();
318 reboot(RB_AUTOBOOT);
320 else {
321 led(LED_DIAG, 1);
322 set_action(ACT_REBOOT);
323 kill(1, SIGTERM);
325 exit(0);
326 #endif
329 if ((ses_mask) && ((gpio & ses_mask) == ses_pushed)) {
330 count = 0;
331 do {
332 // syslog(LOG_DEBUG, "ses-pushed: gpio=x%X, pushed=x%X, mask=x%X, count=%d", gpio, ses_pushed, ses_mask, count);
334 led(ses_led, LED_ON);
335 usleep(500000);
336 led(ses_led, LED_OFF);
337 usleep(500000);
338 ++count;
339 } while (((gpio = _gpio_read(gf)) != ~0) && ((gpio & ses_mask) == ses_pushed));
340 gpio &= mask;
342 if ((ses_led == LED_DMZ) && (nvram_get_int("dmz_enable") > 0)) led(LED_DMZ, 1);
344 // syslog(LOG_DEBUG, "ses-released: gpio=x%X, pushed=x%X, mask=x%X, count=%d", gpio, ses_pushed, ses_mask, count);
345 syslog(LOG_INFO, "SES pushed. Count was %d.", count);
347 if ((count != 3) && (count != 7) && (count != 11)) {
348 n = count >> 2;
349 if (n > 3) n = 3;
351 0-2 = func0
352 4-6 = func1
353 8-10 = func2
354 12+ = func3
357 #ifdef DEBUG_TEST
358 cprintf("ses func=%d\n", n);
359 #else
360 sprintf(s, "sesx_b%d", n);
361 // syslog(LOG_DEBUG, "ses-func: count=%d %s='%s'", count, s, nvram_safe_get(s));
362 if ((p = nvram_get(s)) != NULL) {
363 switch (*p) {
364 case '1': // toggle wl
365 nvram_set("rrules_radio", "-1");
366 eval("radio", "toggle");
367 break;
368 case '2': // reboot
369 kill(1, SIGTERM);
370 break;
371 case '3': // shutdown
372 kill(1, SIGQUIT);
373 break;
374 case '4': // run a script
375 sprintf(s, "%d", count);
376 run_nvscript("sesx_script", s, 2);
377 break;
378 #ifdef TCONFIG_USB
379 case '5': // !!TB: unmount all USB drives
380 add_remove_usbhost("-2", 0);
381 break;
382 #endif
385 #endif
390 if (brau_mask) {
391 if (last == gpio)
392 sleep(1);
393 last = (gpio & brau_mask);
394 if (brau_state != last) {
395 brau_flag = (brau_state != ~0); // set to 1 to run at startup
396 brau_state = last;
397 brau_count_stable = 0;
399 else if (brau_flag && ++brau_count_stable > 2) { // stable for 2+ seconds
400 brau_flag = 0;
401 switch (nvram_get_int("btn_override") ? MODEL_UNKNOWN : get_model()) {
402 #ifdef CONFIG_BCMWL5
403 case MODEL_RTN12:
404 p = (brau_state & (1 << 4)) ? "ap" : (brau_state & (1 << 5)) ? "repeater" : "router";
405 break;
406 #endif
407 default:
408 p = brau_state ? "auto" : "bridge";
409 break;
411 nvram_set("brau_state", p);
412 #ifdef DEBUG_TEST
413 cprintf("bridge/auto state = %s\n", p);
414 #else
415 run_nvscript("script_brau", p, 2);
416 #endif
420 last = gpio;
423 return 0;