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