Merge commit 'origin/tomato-RT' into tomato-shibby
[tomato.git] / release / src / router / rc / buttons.c
blobf019e2e96a23b205d7807fce019e9b39a1668866
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 reset_mask = 1 << 2;
126 ses_mask = 1 << 3;
127 break;
128 // case MODEL_MN700:
129 //? reset_mask = reset_pushed = 1 << 7;
130 // break;
131 case MODEL_WLA2G54L:
132 reset_mask = reset_pushed = 1 << 7;
133 break;
134 case MODEL_WL1600GL:
135 reset_mask = 1 << 3;
136 ses_mask = 1 << 4;
137 ses_led = LED_AOSS;
138 break;
139 #ifdef CONFIG_BCMWL5
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_AOSS;
157 break;
158 case MODEL_WNR2000v2:
159 reset_mask = 1 << 1;
160 ses_mask = 1 << 0;
161 ses_led = LED_AOSS;
162 break;
163 case MODEL_F7D3301:
164 case MODEL_F7D3302:
165 case MODEL_F7D4301:
166 case MODEL_F7D4302:
167 case MODEL_F5D8235v3:
168 reset_mask = 1 << 6;
169 ses_mask = 1 << 8;
170 ses_led = LED_AOSS;
171 break;
172 case MODEL_WRT160Nv3:
173 reset_mask = 1 << 6;
174 ses_mask = 1 << 5;
175 break;
176 case MODEL_WRT320N:
177 reset_mask = 1 << 8;
178 ses_mask = 1 << 5;
179 ses_led = LED_AMBER;
180 break;
181 case MODEL_WRT610Nv2:
182 reset_mask = 1 << 6;
183 ses_mask = 1 << 4;
184 ses_led = LED_AMBER;
185 break;
186 case MODEL_E4200:
187 reset_mask = 1 << 6;
188 ses_mask = 1 << 4;
189 ses_led = LED_WHITE;
190 break;
191 #endif
192 case MODEL_WRT160Nv1:
193 case MODEL_WRT300N:
194 reset_mask = 1 << 6;
195 ses_mask = 1 << 4;
196 break;
197 case MODEL_WRT310Nv1:
198 reset_mask = 1 << 6;
199 ses_mask = 1 << 8;
200 break;
201 default:
202 get_btn("btn_ses", &ses_mask, &ses_pushed);
203 if (!get_btn("btn_reset", &reset_mask, &reset_pushed)) {
204 // fprintf(stderr, "Not supported.\n");
205 return 1;
207 break;
209 mask = reset_mask | ses_mask | brau_mask;
211 #ifdef DEBUG_TEST
212 cprintf("reset_mask=0x%X reset_pushed=0x%X\n", reset_mask, reset_pushed);
213 cprintf("ses_mask=0x%X\n", ses_mask);
214 cprintf("brau_mask=0x%X\n", brau_mask);
215 cprintf("ses_led=%d\n", ses_led);
216 #else
217 if (fork() != 0) return 0;
218 setsid();
219 #endif
221 signal(SIGCHLD, chld_reap);
223 if ((gf = gpio_open(mask)) < 0) return 1;
225 last = 0;
226 brau_count_stable = 0;
227 brau_flag = 0;
228 while (1) {
229 if (((gpio = _gpio_read(gf)) == ~0) || (last == (gpio &= mask) && !brau_flag) || (check_action() != ACT_IDLE)) {
230 #ifdef DEBUG_TEST
231 cprintf("gpio = %X\n", gpio);
232 #endif
233 sleep(1);
234 continue;
237 if ((gpio & reset_mask) == reset_pushed) {
238 #ifdef DEBUG_TEST
239 cprintf("reset down\n");
240 #endif
242 led(LED_DIAG, 0);
244 count = 0;
245 do {
246 sleep(1);
247 if (++count == 3) led(LED_DIAG, 1);
248 } while (((gpio = _gpio_read(gf)) != ~0) && ((gpio & reset_mask) == reset_pushed));
250 #ifdef DEBUG_TEST
251 cprintf("reset count = %d\n", count);
252 #else
253 if (count >= 3) {
254 eval("mtd-erase", "-d", "nvram");
255 //nvram_set("restore_defaults", "1");
256 //nvram_commit();
257 sync();
258 reboot(RB_AUTOBOOT);
260 else {
261 led(LED_DIAG, 1);
262 set_action(ACT_REBOOT);
263 kill(1, SIGTERM);
265 exit(0);
266 #endif
269 if ((ses_mask) && ((gpio & ses_mask) == ses_pushed)) {
270 count = 0;
271 do {
272 // syslog(LOG_DEBUG, "ses-pushed: gpio=x%X, pushed=x%X, mask=x%X, count=%d", gpio, ses_pushed, ses_mask, count);
274 led(ses_led, LED_ON);
275 usleep(500000);
276 led(ses_led, LED_OFF);
277 usleep(500000);
278 ++count;
279 } while (((gpio = _gpio_read(gf)) != ~0) && ((gpio & ses_mask) == ses_pushed));
280 gpio &= mask;
282 if ((ses_led == LED_DMZ) && (nvram_get_int("dmz_enable") > 0)) led(LED_DMZ, 1);
284 // syslog(LOG_DEBUG, "ses-released: gpio=x%X, pushed=x%X, mask=x%X, count=%d", gpio, ses_pushed, ses_mask, count);
285 syslog(LOG_INFO, "SES pushed. Count was %d.", count);
287 if ((count != 3) && (count != 7) && (count != 11)) {
288 n = count >> 2;
289 if (n > 3) n = 3;
291 0-2 = func0
292 4-6 = func1
293 8-10 = func2
294 12+ = func3
297 #ifdef DEBUG_TEST
298 cprintf("ses func=%d\n", n);
299 #else
300 sprintf(s, "sesx_b%d", n);
301 // syslog(LOG_DEBUG, "ses-func: count=%d %s='%s'", count, s, nvram_safe_get(s));
302 if ((p = nvram_get(s)) != NULL) {
303 switch (*p) {
304 case '1': // toggle wl
305 nvram_set("rrules_radio", "-1");
306 eval("radio", "toggle");
307 break;
308 case '2': // reboot
309 kill(1, SIGTERM);
310 break;
311 case '3': // shutdown
312 kill(1, SIGQUIT);
313 break;
314 case '4': // run a script
315 sprintf(s, "%d", count);
316 run_nvscript("sesx_script", s, 2);
317 break;
318 #ifdef TCONFIG_USB
319 case '5': // !!TB: unmount all USB drives
320 add_remove_usbhost("-2", 0);
321 break;
322 #endif
325 #endif
330 if (brau_mask) {
331 if (last == gpio)
332 sleep(1);
333 last = (gpio & brau_mask);
334 if (brau_state != last) {
335 brau_flag = (brau_state != ~0); // set to 1 to run at startup
336 brau_state = last;
337 brau_count_stable = 0;
339 else if (brau_flag && ++brau_count_stable > 2) { // stable for 2+ seconds
340 brau_flag = 0;
341 switch (nvram_get_int("btn_override") ? MODEL_UNKNOWN : get_model()) {
342 #ifdef CONFIG_BCMWL5
343 case MODEL_RTN12:
344 p = (brau_state & (1 << 4)) ? "ap" : (brau_state & (1 << 5)) ? "repeater" : "router";
345 break;
346 #endif
347 default:
348 p = brau_state ? "auto" : "bridge";
349 break;
351 nvram_set("brau_state", p);
352 #ifdef DEBUG_TEST
353 cprintf("bridge/auto state = %s\n", p);
354 #else
355 run_nvscript("script_brau", p, 2);
356 #endif
360 last = gpio;
363 return 0;