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;
28         
29         if (nvget_gpio(name, &gpio, &inv)) {
30                 *bit = 1 << gpio;
31                 *pushed = inv ? 0 : *bit;
32                 return 1;
33         }
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;
163                 }
164                 break;
165         }
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;
196                 }
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);
220                         }
221                         else {
222                                 led(LED_DIAG, 1);
223                                 set_action(ACT_REBOOT);
224                                 kill(1, SIGTERM);
225                         }
226                         exit(0);
227 #endif
228                 }
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;
251                                 /*
252                                         0-2  = func0
253                                         4-6  = func1
254                                         8-10 = func2
255                                         12+  = func3
256                                 */
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
284                                         }
285                                 }
286 #endif
288                         }
289                 }
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;
299                         }
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;
309                                 }
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
316                         }
317                 }
319                 last = gpio;
320         }
322         return 0;