Netgear R6400 support
[tomato.git] / release / src-rt-6.x.4708 / router / rc / buttons.c
blob9c5b62e085e3eb3c34f89e96ef7074c34e3891cb
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_RTN10P:
151 reset_mask = 1 << 20;
152 ses_mask = 1 << 21;
153 ses_led = LED_AOSS;
154 break;
155 case MODEL_RTN12:
156 reset_mask = 1 << 1;
157 ses_mask = 1 << 0;
158 brau_mask = (1 << 4) | (1 << 5) | (1 << 6);
159 break;
160 case MODEL_RTN15U:
161 reset_mask = 1 << 5;
162 ses_mask = 1 << 8;
163 break;
164 case MODEL_RTN16:
165 reset_mask = 1 << 6;
166 ses_mask = 1 << 8;
167 break;
168 case MODEL_RTN53:
169 reset_mask = 1 << 3;
170 ses_mask = 1 << 7;
171 break;
172 case MODEL_RTN53A1:
173 reset_mask = 1 << 7;
174 ses_mask = 1 << 3;
175 break;
176 case MODEL_RTN66U:
177 reset_mask = 1 << 9;
178 ses_mask = 1 << 4;
179 break;
180 case MODEL_RTN18U:
181 reset_mask = 1 << 7;
182 ses_mask = 1 << 11;
183 break;
184 case MODEL_RTAC56U:
185 reset_mask = 1 << 11;
186 ses_mask = 1 << 15;
187 ses_led = LED_AOSS;
188 break;
189 case MODEL_RTAC68U:
190 case MODEL_DIR868L:
191 reset_mask = 1 << 11;
192 ses_mask = 1 << 7;
193 ses_led = LED_AOSS;
194 break;
195 case MODEL_WS880:
196 reset_mask = 1 << 2;
197 ses_mask = 1 << 3;
198 ses_led = LED_AOSS;
199 break;
200 case MODEL_EA6500V1:
201 reset_mask = 1 << 3;
202 ses_mask = 1 << 4;
203 break;
204 case MODEL_EA6700:
205 ses_mask = 1 << 7;
206 reset_mask = 1 << 11;
207 ses_led = LED_AOSS;
208 break;
209 case MODEL_EA6900:
210 ses_mask = 1 << 7;
211 reset_mask = 1 << 11;
212 ses_led = LED_AOSS;
213 break;
214 case MODEL_R1D:
215 reset_mask = 1 << 17;
216 ses_led = LED_AOSS;
217 break;
218 case MODEL_W1800R:
219 reset_mask = 1 << 14;
220 break;
221 case MODEL_D1800H:
222 reset_mask = 1 << 5;
223 break;
224 case MODEL_R6400:
225 reset_mask = 1 << 5;
226 ses_mask = 1 << 4;
227 ses_led = LED_AOSS;
228 break;
229 case MODEL_R6250:
230 case MODEL_R6300v2:
231 case MODEL_R7000:
232 reset_mask = 1 << 6;
233 ses_mask = 1 << 5;
234 ses_led = LED_AOSS;
235 break;
236 case MODEL_WZR1750:
237 // reset_mask = 1 << 6;
238 ses_mask = 1 << 12;
239 ses_led = LED_AOSS;
240 break;
241 case MODEL_WNR3500L:
242 case MODEL_WNR3500LV2:
243 reset_mask = 1 << 4;
244 ses_mask = 1 << 6;
245 ses_led = LED_AOSS;
246 break;
247 case MODEL_WNR2000v2:
248 reset_mask = 1 << 1;
249 ses_mask = 1 << 0;
250 ses_led = LED_AOSS;
251 break;
252 case MODEL_F7D3301:
253 case MODEL_F7D3302:
254 case MODEL_F7D4301:
255 case MODEL_F7D4302:
256 case MODEL_F5D8235v3:
257 reset_mask = 1 << 6;
258 ses_mask = 1 << 8;
259 ses_led = LED_AOSS;
260 break;
261 case MODEL_E900:
262 case MODEL_E1000v2:
263 case MODEL_E1500:
264 case MODEL_E1550:
265 case MODEL_E2500:
266 reset_mask = 1 << 10;
267 ses_mask = 1 << 9;
268 break;
269 case MODEL_E3200:
270 reset_mask = 1 << 5;
271 ses_mask = 1 << 8;
272 break;
273 case MODEL_WRT160Nv3:
274 reset_mask = 1 << 6;
275 ses_mask = 1 << 5;
276 break;
277 case MODEL_WRT320N:
278 reset_mask = 1 << 8;
279 ses_mask = 1 << 5;
280 ses_led = LED_AMBER;
281 break;
282 case MODEL_WRT610Nv2:
283 reset_mask = 1 << 6;
284 ses_mask = 1 << 4;
285 ses_led = LED_AMBER;
286 break;
287 case MODEL_E4200:
288 reset_mask = 1 << 6;
289 ses_mask = 1 << 4;
290 ses_led = LED_WHITE;
291 break;
292 case MODEL_L600N:
293 reset_mask = 1 << 21;
294 ses_mask = 1 << 20;
295 //wlan button = 1 >> 10
296 break;
297 case MODEL_DIR620C1:
298 reset_mask = 1 << 21;
299 ses_mask = 1 << 20;
300 break;
301 #endif
302 case MODEL_WRT160Nv1:
303 case MODEL_WRT300N:
304 reset_mask = 1 << 6;
305 ses_mask = 1 << 4;
306 break;
307 case MODEL_WRT310Nv1:
308 reset_mask = 1 << 6;
309 ses_mask = 1 << 8;
310 break;
311 // Added by BWQ
312 case MODEL_RG200E_CA:
313 case MODEL_H218N:
314 reset_mask = 1 << 30;
315 ses_mask = 1 << 28;
316 break;
317 case MODEL_HG320:
318 reset_mask = 1 << 30;
319 ses_mask = 1 << 29;
320 break;
321 case MODEL_TDN60:
322 reset_mask = 1 << 8;
323 break;
324 case MODEL_TDN6:
325 reset_mask = 1 << 20;
326 break;
327 // BWQ end
328 default:
329 get_btn("btn_ses", &ses_mask, &ses_pushed);
330 if (!get_btn("btn_reset", &reset_mask, &reset_pushed)) {
331 // fprintf(stderr, "Not supported.\n");
332 return 1;
334 break;
336 mask = reset_mask | ses_mask | brau_mask;
338 #ifdef DEBUG_TEST
339 cprintf("reset_mask=0x%X reset_pushed=0x%X\n", reset_mask, reset_pushed);
340 cprintf("ses_mask=0x%X\n", ses_mask);
341 cprintf("brau_mask=0x%X\n", brau_mask);
342 cprintf("ses_led=%d\n", ses_led);
343 #else
344 if (fork() != 0) return 0;
345 setsid();
346 #endif
348 signal(SIGCHLD, chld_reap);
350 if ((gf = gpio_open(mask)) < 0) return 1;
352 last = 0;
353 brau_count_stable = 0;
354 brau_flag = 0;
355 while (1) {
356 if (((gpio = _gpio_read(gf)) == ~0) || (last == (gpio &= mask) && !brau_flag) || (check_action() != ACT_IDLE)) {
357 #ifdef DEBUG_TEST
358 cprintf("gpio = %X\n", gpio);
359 #endif
360 sleep(1);
361 continue;
364 if ((gpio & reset_mask) == reset_pushed) {
365 #ifdef DEBUG_TEST
366 cprintf("reset down\n");
367 #endif
369 led(LED_DIAG, 0);
371 count = 0;
372 do {
373 sleep(1);
374 if (++count == 3) led(LED_DIAG, 1);
375 } while (((gpio = _gpio_read(gf)) != ~0) && ((gpio & reset_mask) == reset_pushed));
377 #ifdef DEBUG_TEST
378 cprintf("reset count = %d\n", count);
379 #else
380 if (count >= 3) {
381 eval("mtd-erase2", "nvram");
382 //nvram_set("restore_defaults", "1");
383 //nvram_commit();
384 sync();
385 reboot(RB_AUTOBOOT);
387 else {
388 led(LED_DIAG, 1);
389 set_action(ACT_REBOOT);
390 kill(1, SIGTERM);
392 exit(0);
393 #endif
396 if ((ses_mask) && ((gpio & ses_mask) == ses_pushed)) {
397 count = 0;
398 do {
399 // syslog(LOG_DEBUG, "ses-pushed: gpio=x%X, pushed=x%X, mask=x%X, count=%d", gpio, ses_pushed, ses_mask, count);
401 led(ses_led, LED_ON);
402 usleep(500000);
403 led(ses_led, LED_OFF);
404 usleep(500000);
405 ++count;
406 } while (((gpio = _gpio_read(gf)) != ~0) && ((gpio & ses_mask) == ses_pushed));
407 gpio &= mask;
409 if ((ses_led == LED_DMZ) && (nvram_get_int("dmz_enable") > 0)) led(LED_DMZ, 1);
411 // syslog(LOG_DEBUG, "ses-released: gpio=x%X, pushed=x%X, mask=x%X, count=%d", gpio, ses_pushed, ses_mask, count);
412 syslog(LOG_INFO, "SES pushed. Count was %d.", count);
414 if ((count != 3) && (count != 7) && (count != 11)) {
415 n = count >> 2;
416 if (n > 3) n = 3;
418 0-2 = func0
419 4-6 = func1
420 8-10 = func2
421 12+ = func3
424 #ifdef DEBUG_TEST
425 cprintf("ses func=%d\n", n);
426 #else
427 sprintf(s, "sesx_b%d", n);
428 // syslog(LOG_DEBUG, "ses-func: count=%d %s='%s'", count, s, nvram_safe_get(s));
429 if ((p = nvram_get(s)) != NULL) {
430 switch (*p) {
431 case '1': // toggle wl
432 nvram_set("rrules_radio", "-1");
433 eval("radio", "toggle");
434 break;
435 case '2': // reboot
436 kill(1, SIGTERM);
437 break;
438 case '3': // shutdown
439 kill(1, SIGQUIT);
440 break;
441 case '4': // run a script
442 sprintf(s, "%d", count);
443 run_nvscript("sesx_script", s, 2);
444 break;
445 #ifdef TCONFIG_USB
446 case '5': // !!TB: unmount all USB drives
447 add_remove_usbhost("-2", 0);
448 break;
449 #endif
452 #endif
457 if (brau_mask) {
458 if (last == gpio)
459 sleep(1);
460 last = (gpio & brau_mask);
461 if (brau_state != last) {
462 brau_flag = (brau_state != ~0); // set to 1 to run at startup
463 brau_state = last;
464 brau_count_stable = 0;
466 else if (brau_flag && ++brau_count_stable > 2) { // stable for 2+ seconds
467 brau_flag = 0;
468 switch (nvram_get_int("btn_override") ? MODEL_UNKNOWN : get_model()) {
469 #ifdef CONFIG_BCMWL5
470 case MODEL_RTN12:
471 p = (brau_state & (1 << 4)) ? "ap" : (brau_state & (1 << 5)) ? "repeater" : "router";
472 break;
473 #endif
474 default:
475 p = brau_state ? "auto" : "bridge";
476 break;
478 nvram_set("brau_state", p);
479 #ifdef DEBUG_TEST
480 cprintf("bridge/auto state = %s\n", p);
481 #else
482 run_nvscript("script_brau", p, 2);
483 #endif
487 last = gpio;
490 return 0;