New routers supported
[tomato.git] / release / src / router / rc / buttons.c
blob576b408bdc76f3a140af4a9c7e63566fae67f502
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_W1800R:
181 reset_mask = 1 << 14;
182 break;
183 case MODEL_WNR3500L:
184 case MODEL_WNR3500LV2:
185 reset_mask = 1 << 4;
186 ses_mask = 1 << 6;
187 ses_led = LED_AOSS;
188 break;
189 case MODEL_WNR2000v2:
190 reset_mask = 1 << 1;
191 ses_mask = 1 << 0;
192 ses_led = LED_AOSS;
193 break;
194 case MODEL_F7D3301:
195 case MODEL_F7D3302:
196 case MODEL_F7D4301:
197 case MODEL_F7D4302:
198 case MODEL_F5D8235v3:
199 reset_mask = 1 << 6;
200 ses_mask = 1 << 8;
201 ses_led = LED_AOSS;
202 break;
203 case MODEL_E900:
204 case MODEL_E1000v2:
205 case MODEL_E1500:
206 case MODEL_E1550:
207 case MODEL_E2500:
208 reset_mask = 1 << 10;
209 ses_mask = 1 << 9;
210 break;
211 case MODEL_E3200:
212 reset_mask = 1 << 5;
213 ses_mask = 1 << 8;
214 break;
215 case MODEL_WRT160Nv3:
216 reset_mask = 1 << 6;
217 ses_mask = 1 << 5;
218 break;
219 case MODEL_WRT320N:
220 reset_mask = 1 << 8;
221 ses_mask = 1 << 5;
222 ses_led = LED_AMBER;
223 break;
224 case MODEL_WRT610Nv2:
225 reset_mask = 1 << 6;
226 ses_mask = 1 << 4;
227 ses_led = LED_AMBER;
228 break;
229 case MODEL_E4200:
230 reset_mask = 1 << 6;
231 ses_mask = 1 << 4;
232 ses_led = LED_WHITE;
233 break;
234 case MODEL_L600N:
235 reset_mask = 1 << 21;
236 ses_mask = 1 << 20;
237 //wlan button = 1 >> 10
238 break;
239 case MODEL_DIR620C1:
240 reset_mask = 1 << 21;
241 ses_mask = 1 << 20;
242 break;
243 #endif
244 case MODEL_WRT160Nv1:
245 case MODEL_WRT300N:
246 reset_mask = 1 << 6;
247 ses_mask = 1 << 4;
248 break;
249 case MODEL_WRT310Nv1:
250 reset_mask = 1 << 6;
251 ses_mask = 1 << 8;
252 break;
253 // Added by BWQ
254 case MODEL_RG200E_CA:
255 case MODEL_H218N:
256 reset_mask = 1 << 30;
257 ses_mask = 1 << 28;
258 break;
259 case MODEL_HG320:
260 reset_mask = 1 << 30;
261 ses_mask = 1 << 29;
262 break;
263 // BWQ end.
264 default:
265 get_btn("btn_ses", &ses_mask, &ses_pushed);
266 if (!get_btn("btn_reset", &reset_mask, &reset_pushed)) {
267 // fprintf(stderr, "Not supported.\n");
268 return 1;
270 break;
272 mask = reset_mask | ses_mask | brau_mask;
274 #ifdef DEBUG_TEST
275 cprintf("reset_mask=0x%X reset_pushed=0x%X\n", reset_mask, reset_pushed);
276 cprintf("ses_mask=0x%X\n", ses_mask);
277 cprintf("brau_mask=0x%X\n", brau_mask);
278 cprintf("ses_led=%d\n", ses_led);
279 #else
280 if (fork() != 0) return 0;
281 setsid();
282 #endif
284 signal(SIGCHLD, chld_reap);
286 if ((gf = gpio_open(mask)) < 0) return 1;
288 last = 0;
289 brau_count_stable = 0;
290 brau_flag = 0;
291 while (1) {
292 if (((gpio = _gpio_read(gf)) == ~0) || (last == (gpio &= mask) && !brau_flag) || (check_action() != ACT_IDLE)) {
293 #ifdef DEBUG_TEST
294 cprintf("gpio = %X\n", gpio);
295 #endif
296 sleep(1);
297 continue;
300 if ((gpio & reset_mask) == reset_pushed) {
301 #ifdef DEBUG_TEST
302 cprintf("reset down\n");
303 #endif
305 led(LED_DIAG, 0);
307 count = 0;
308 do {
309 sleep(1);
310 if (++count == 3) led(LED_DIAG, 1);
311 } while (((gpio = _gpio_read(gf)) != ~0) && ((gpio & reset_mask) == reset_pushed));
313 #ifdef DEBUG_TEST
314 cprintf("reset count = %d\n", count);
315 #else
316 if (count >= 3) {
317 eval("mtd-erase", "-d", "nvram");
318 //nvram_set("restore_defaults", "1");
319 //nvram_commit();
320 sync();
321 reboot(RB_AUTOBOOT);
323 else {
324 led(LED_DIAG, 1);
325 set_action(ACT_REBOOT);
326 kill(1, SIGTERM);
328 exit(0);
329 #endif
332 if ((ses_mask) && ((gpio & ses_mask) == ses_pushed)) {
333 count = 0;
334 do {
335 // syslog(LOG_DEBUG, "ses-pushed: gpio=x%X, pushed=x%X, mask=x%X, count=%d", gpio, ses_pushed, ses_mask, count);
337 led(ses_led, LED_ON);
338 usleep(500000);
339 led(ses_led, LED_OFF);
340 usleep(500000);
341 ++count;
342 } while (((gpio = _gpio_read(gf)) != ~0) && ((gpio & ses_mask) == ses_pushed));
343 gpio &= mask;
345 if ((ses_led == LED_DMZ) && (nvram_get_int("dmz_enable") > 0)) led(LED_DMZ, 1);
347 // syslog(LOG_DEBUG, "ses-released: gpio=x%X, pushed=x%X, mask=x%X, count=%d", gpio, ses_pushed, ses_mask, count);
348 syslog(LOG_INFO, "SES pushed. Count was %d.", count);
350 if ((count != 3) && (count != 7) && (count != 11)) {
351 n = count >> 2;
352 if (n > 3) n = 3;
354 0-2 = func0
355 4-6 = func1
356 8-10 = func2
357 12+ = func3
360 #ifdef DEBUG_TEST
361 cprintf("ses func=%d\n", n);
362 #else
363 sprintf(s, "sesx_b%d", n);
364 // syslog(LOG_DEBUG, "ses-func: count=%d %s='%s'", count, s, nvram_safe_get(s));
365 if ((p = nvram_get(s)) != NULL) {
366 switch (*p) {
367 case '1': // toggle wl
368 nvram_set("rrules_radio", "-1");
369 eval("radio", "toggle");
370 break;
371 case '2': // reboot
372 kill(1, SIGTERM);
373 break;
374 case '3': // shutdown
375 kill(1, SIGQUIT);
376 break;
377 case '4': // run a script
378 sprintf(s, "%d", count);
379 run_nvscript("sesx_script", s, 2);
380 break;
381 #ifdef TCONFIG_USB
382 case '5': // !!TB: unmount all USB drives
383 add_remove_usbhost("-2", 0);
384 break;
385 #endif
388 #endif
393 if (brau_mask) {
394 if (last == gpio)
395 sleep(1);
396 last = (gpio & brau_mask);
397 if (brau_state != last) {
398 brau_flag = (brau_state != ~0); // set to 1 to run at startup
399 brau_state = last;
400 brau_count_stable = 0;
402 else if (brau_flag && ++brau_count_stable > 2) { // stable for 2+ seconds
403 brau_flag = 0;
404 switch (nvram_get_int("btn_override") ? MODEL_UNKNOWN : get_model()) {
405 #ifdef CONFIG_BCMWL5
406 case MODEL_RTN12:
407 p = (brau_state & (1 << 4)) ? "ap" : (brau_state & (1 << 5)) ? "repeater" : "router";
408 break;
409 #endif
410 default:
411 p = brau_state ? "auto" : "bridge";
412 break;
414 nvram_set("brau_state", p);
415 #ifdef DEBUG_TEST
416 cprintf("bridge/auto state = %s\n", p);
417 #else
418 run_nvscript("script_brau", p, 2);
419 #endif
423 last = gpio;
426 return 0;