Netgear WNR3500L: correct leds behavior
[tomato.git] / release / src / router / rc / buttons.c
blob28934682c4ec40c800818a4ef50322aa13150bfa
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 #if 0 // TOMATO_N
14 #include <linux_gpio.h>
15 #include <sys/socket.h>
16 #include <sys/ioctl.h>
17 #endif
19 // #define DEBUG_TEST
22 static int gf;
24 static int get_btn(const char *name, uint32_t *bit, uint32_t *pushed)
26 int gpio;
27 int inv;
29 if (nvget_gpio(name, &gpio, &inv)) {
30 *bit = 1 << gpio;
31 *pushed = inv ? 0 : *bit;
32 return 1;
34 return 0;
37 int buttons_main(int argc, char *argv[])
39 uint32_t gpio;
40 uint32_t mask;
41 uint32_t last;
42 uint32_t ses_mask;
43 uint32_t ses_pushed;
44 uint32_t reset_mask;
45 uint32_t reset_pushed;
46 uint32_t brau_mask;
47 uint32_t brau_state;
48 int brau_count_stable;
49 int brau_flag;
50 int count;
51 char s[16];
52 char *p;
53 int n;
54 int ses_led;
56 ses_mask = ses_pushed = 0;
57 reset_pushed = 0;
58 brau_mask = 0;
59 brau_state = ~0;
60 ses_led = LED_DIAG;
62 // moveme
63 switch (nvram_get_int("btn_override") ? MODEL_UNKNOWN : get_model()) {
64 case MODEL_WRT54G:
65 case MODEL_WRTSL54GS:
66 reset_mask = 1 << 6;
67 ses_mask = 1 << 4;
68 ses_led = LED_DMZ;
69 break;
70 /*
71 case MODEL_WRH54G:
72 reset_mask = 1 << 6;
73 break;
75 case MODEL_WTR54GS:
76 reset_mask = 1 << 3;
77 ses_mask = 1 << 2;
78 break;
79 case MODEL_WHRG54S:
80 case MODEL_WHRHPG54:
81 case MODEL_WHR2A54G54:
82 case MODEL_WHR3AG54:
83 case MODEL_WHRG125:
84 reset_mask = reset_pushed = 1 << 4;
85 ses_mask = 1 << 0;
86 brau_mask = 1 << 5;
87 break;
88 case MODEL_WBRG54:
89 reset_mask = reset_pushed = 1 << 4;
90 break;
91 case MODEL_WBR2G54:
92 reset_mask = reset_pushed = 1 << 7;
93 ses_mask = ses_pushed = 1 << 4;
94 ses_led = LED_AOSS;
95 break;
96 case MODEL_WZRG54:
97 case MODEL_WZRHPG54:
98 case MODEL_WZRRSG54:
99 case MODEL_WZRRSG54HP:
100 case MODEL_WVRG54NF:
101 reset_mask = reset_pushed = 1 << 4;
102 ses_mask = 1 << 0;
103 ses_led = LED_AOSS;
104 break;
105 case MODEL_WZRG108:
106 reset_mask = reset_pushed = 1 << 7;
107 ses_mask = 1 << 0;
108 ses_led = LED_AOSS;
109 break;
110 case MODEL_WR850GV1:
111 reset_mask = 1 << 0;
112 break;
113 case MODEL_WR850GV2:
114 case MODEL_WR100:
115 reset_mask = 1 << 5;
116 break;
117 case MODEL_WL500GP:
118 reset_mask = reset_pushed = 1 << 0;
119 ses_mask = ses_pushed = 1 << 4;
120 break;
121 case MODEL_WL500W:
122 reset_mask = reset_pushed = 1 << 6;
123 ses_mask = ses_pushed = 1 << 7;
124 break;
125 case MODEL_DIR320:
126 reset_mask = 1 << 7;
127 ses_mask = 1 << 6;
128 break;
129 case MODEL_WL500GPv2:
130 case MODEL_WL520GU:
131 reset_mask = 1 << 2;
132 ses_mask = 1 << 3;
133 break;
134 // case MODEL_MN700:
135 //? reset_mask = reset_pushed = 1 << 7;
136 // break;
137 case MODEL_WLA2G54L:
138 reset_mask = reset_pushed = 1 << 7;
139 break;
140 case MODEL_RTN10:
141 reset_mask = 1 << 3;
142 ses_mask = 1 << 2;
143 break;
144 case MODEL_RTN12:
145 reset_mask = 1 << 1;
146 ses_mask = 1 << 0;
147 brau_mask = (1 << 4) | (1 << 5) | (1 << 6);
148 break;
149 case MODEL_RTN16:
150 reset_mask = 1 << 6;
151 ses_mask = 1 << 8;
152 break;
153 case MODEL_WNR3500L:
154 reset_mask = 1 << 4;
155 ses_mask = 1 << 6;
156 ses_led = LED_WHITE;
157 break;
158 default:
159 get_btn("btn_ses", &ses_mask, &ses_pushed);
160 if (!get_btn("btn_reset", &reset_mask, &reset_pushed)) {
161 // fprintf(stderr, "Not supported.\n");
162 return 1;
164 break;
166 mask = reset_mask | ses_mask | brau_mask;
168 #ifdef DEBUG_TEST
169 cprintf("reset_mask=0x%X reset_pushed=0x%X\n", reset_mask, reset_pushed);
170 cprintf("ses_mask=0x%X\n", ses_mask);
171 cprintf("brau_mask=0x%X\n", brau_mask);
172 cprintf("ses_led=%d\n", ses_led);
173 #else
174 if (fork() != 0) return 0;
175 setsid();
176 #endif
178 signal(SIGCHLD, handle_reap);
180 #if 0 // TOMATO_N
181 // !
182 #else
183 if ((gf = gpio_open(mask)) < 0) return 1;
184 #endif
186 last = 0;
187 brau_count_stable = 0;
188 brau_flag = 0;
189 while (1) {
190 if (((gpio = _gpio_read(gf)) == ~0) || (last == (gpio &= mask) && !brau_flag) || (check_action() != ACT_IDLE)) {
191 #ifdef DEBUG_TEST
192 cprintf("gpio = %X\n", gpio);
193 #endif
194 sleep(1);
195 continue;
198 if ((gpio & reset_mask) == reset_pushed) {
199 #ifdef DEBUG_TEST
200 cprintf("reset down\n");
201 #endif
203 led(LED_DIAG, 0);
205 count = 0;
206 do {
207 sleep(1);
208 if (++count == 3) led(LED_DIAG, 1);
209 } while (((gpio = _gpio_read(gf)) != ~0) && ((gpio & reset_mask) == reset_pushed));
211 #ifdef DEBUG_TEST
212 cprintf("reset count = %d\n", count);
213 #else
214 if (count >= 3) {
215 eval("mtd-erase", "-d", "nvram");
216 //nvram_set("restore_defaults", "1");
217 //nvram_commit();
218 sync();
219 reboot(RB_AUTOBOOT);
221 else {
222 led(LED_DIAG, 1);
223 set_action(ACT_REBOOT);
224 kill(1, SIGTERM);
226 exit(0);
227 #endif
230 if ((ses_mask) && ((gpio & ses_mask) == ses_pushed)) {
231 count = 0;
232 do {
233 // syslog(LOG_DEBUG, "ses-pushed: gpio=x%X, pushed=x%X, mask=x%X, count=%d", gpio, ses_pushed, ses_mask, count);
235 led(ses_led, LED_ON);
236 usleep(500000);
237 led(ses_led, LED_OFF);
238 usleep(500000);
239 ++count;
240 } while (((gpio = _gpio_read(gf)) != ~0) && ((gpio & ses_mask) == ses_pushed));
241 gpio &= mask;
243 if ((ses_led == LED_DMZ) && (nvram_get_int("dmz_enable") > 0)) led(LED_DMZ, 1);
245 // syslog(LOG_DEBUG, "ses-released: gpio=x%X, pushed=x%X, mask=x%X, count=%d", gpio, ses_pushed, ses_mask, count);
246 syslog(LOG_INFO, "SES pushed. Count was %d.", count);
248 if ((count != 3) && (count != 7) && (count != 11)) {
249 n = count >> 2;
250 if (n > 3) n = 3;
252 0-2 = func0
253 4-6 = func1
254 8-10 = func2
255 12+ = func3
258 #ifdef DEBUG_TEST
259 cprintf("ses func=%d\n", n);
260 #else
261 sprintf(s, "sesx_b%d", n);
262 // syslog(LOG_DEBUG, "ses-func: count=%d %s='%s'", count, s, nvram_safe_get(s));
263 if ((p = nvram_get(s)) != NULL) {
264 switch (*p) {
265 case '1': // toggle wl
266 nvram_set("rrules_radio", "-1");
267 eval("radio", "toggle");
268 break;
269 case '2': // reboot
270 kill(1, SIGTERM);
271 break;
272 case '3': // shutdown
273 kill(1, SIGQUIT);
274 break;
275 case '4': // run a script
276 sprintf(s, "%d", count);
277 run_nvscript("sesx_script", s, 2);
278 break;
279 #ifdef TCONFIG_USB
280 case '5': // !!TB: unmount all USB drives
281 add_remove_usbhost("-1", 0);
282 break;
283 #endif
286 #endif
291 if (brau_mask) {
292 if (last == gpio)
293 sleep(1);
294 last = (gpio & brau_mask);
295 if (brau_state != last) {
296 brau_flag = (brau_state != ~0); // set to 1 to run at startup
297 brau_state = last;
298 brau_count_stable = 0;
300 else if (brau_flag && ++brau_count_stable > 2) { // stable for 2+ seconds
301 brau_flag = 0;
302 switch (nvram_get_int("btn_override") ? MODEL_UNKNOWN : get_model()) {
303 case MODEL_RTN12:
304 p = (brau_state & (1 << 4)) ? "ap" : (brau_state & (1 << 5)) ? "repeater" : "router";
305 break;
306 default:
307 p = brau_state ? "auto" : "bridge";
308 break;
310 nvram_set("brau_state", p);
311 #ifdef DEBUG_TEST
312 cprintf("bridge/auto state = %s\n", p);
313 #else
314 run_nvscript("script_brau", p, 2);
315 #endif
319 last = gpio;
322 return 0;