Tomato 1.28
[tomato.git] / release / src / router / rc / buttons.c
blob6207aca359593ecd8694ba6aa0cb383004a92aeb
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 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 uint32_t _gpio_read(void)
26 #if TOMATO_N
27 // !
28 #else
29 uint32_t v;
30 return (read(gf, &v, sizeof(v)) == sizeof(v)) ? v : ~0;
31 #endif
34 static int get_btn(const char *name, uint32_t *bit, uint32_t *pushed)
36 int gpio;
37 int inv;
39 if (nvget_gpio(name, &gpio, &inv)) {
40 *bit = 1 << gpio;
41 *pushed = inv ? 0 : *bit;
42 return 1;
44 return 0;
47 int buttons_main(int argc, char *argv[])
49 uint32_t gpio;
50 uint32_t mask;
51 uint32_t last;
52 uint32_t ses_mask;
53 uint32_t ses_pushed;
54 uint32_t reset_mask;
55 uint32_t reset_pushed;
56 uint32_t brau_mask;
57 uint32_t brau_state;
58 int count;
59 char s[16];
60 char *p;
61 int n;
62 int ses_led;
64 ses_mask = ses_pushed = 0;
65 reset_pushed = 0;
66 brau_mask = 0;
67 brau_state = ~0;
68 ses_led = LED_DIAG;
70 // moveme
71 switch (nvram_get_int("btn_override") ? MODEL_UNKNOWN : get_model()) {
72 case MODEL_WRT54G:
73 case MODEL_WRTSL54GS:
74 reset_mask = 1 << 6;
75 ses_mask = 1 << 4;
76 ses_led = LED_DMZ;
77 break;
78 /*
79 case MODEL_WRH54G:
80 reset_mask = 1 << 6;
81 break;
83 case MODEL_WTR54GS:
84 reset_mask = 1 << 3;
85 ses_mask = 1 << 2;
86 break;
87 case MODEL_WHRG54S:
88 case MODEL_WHRHPG54:
89 case MODEL_WHR2A54G54:
90 case MODEL_WHR3AG54:
91 case MODEL_WHRG125:
92 reset_mask = reset_pushed = 1 << 4;
93 ses_mask = 1 << 0;
94 brau_mask = 1 << 5;
95 break;
96 case MODEL_WBRG54:
97 reset_mask = reset_pushed = 1 << 4;
98 break;
99 case MODEL_WBR2G54:
100 reset_mask = reset_pushed = 1 << 7;
101 ses_mask = ses_pushed = 1 << 4;
102 ses_led = LED_AOSS;
103 break;
104 case MODEL_WZRG54:
105 case MODEL_WZRHPG54:
106 case MODEL_WZRRSG54:
107 case MODEL_WZRRSG54HP:
108 case MODEL_WVRG54NF:
109 reset_mask = reset_pushed = 1 << 4;
110 ses_mask = 1 << 0;
111 ses_led = LED_AOSS;
112 break;
113 case MODEL_WZRG108:
114 reset_mask = reset_pushed = 1 << 7;
115 ses_mask = 1 << 0;
116 ses_led = LED_AOSS;
117 break;
118 case MODEL_WR850GV1:
119 reset_mask = 1 << 0;
120 break;
121 case MODEL_WR850GV2:
122 case MODEL_WR100:
123 reset_mask = 1 << 5;
124 break;
125 case MODEL_WL500GP:
126 reset_mask = reset_pushed = 1 << 0;
127 ses_mask = ses_pushed = 1 << 4;
128 break;
129 case MODEL_WL520GU:
130 reset_mask = 1 << 2;
131 ses_mask = 1 << 3;
132 break;
133 // case MODEL_MN700:
134 //? reset_mask = reset_pushed = 1 << 7;
135 // break;
136 case MODEL_WLA2G54L:
137 reset_mask = reset_pushed = 1 << 7;
138 break;
139 default:
140 get_btn("btn_ses", &ses_mask, &ses_pushed);
141 if (!get_btn("btn_reset", &reset_mask, &reset_pushed)) {
142 // fprintf(stderr, "Not supported.\n");
143 return 1;
145 break;
147 mask = reset_mask | ses_mask | brau_mask;
149 #ifdef DEBUG_TEST
150 cprintf("reset_mask=0x%X reset_pushed=0x%X\n", reset_mask, reset_pushed);
151 cprintf("ses_mask=0x%X\n", ses_mask);
152 cprintf("brau_mask=0x%X\n", brau_mask);
153 cprintf("ses_led=%d\n", ses_led);
154 #else
155 if (fork() != 0) return 0;
156 setsid();
157 #endif
159 signal(SIGCHLD, handle_reap);
161 #if TOMATO_N
162 // !
163 #else
164 if ((gf = open("/dev/gpio/in", O_RDONLY|O_SYNC)) < 0) return 1;
165 #endif
167 last = 0;
168 while (1) {
169 if (((gpio = _gpio_read()) == ~0) || (last == (gpio &= mask)) || (check_action() != ACT_IDLE)) {
170 #ifdef DEBUG_TEST
171 cprintf("gpio = %X\n", gpio);
172 #endif
173 sleep(1);
174 continue;
177 if ((gpio & reset_mask) == reset_pushed) {
178 #ifdef DEBUG_TEST
179 cprintf("reset down\n");
180 #endif
182 led(LED_DIAG, 0);
184 count = 0;
185 do {
186 sleep(1);
187 if (++count == 3) led(LED_DIAG, 1);
188 } while (((gpio = _gpio_read()) != ~0) && ((gpio & reset_mask) == reset_pushed));
190 #ifdef DEBUG_TEST
191 cprintf("reset count = %d\n", count);
192 #else
193 if (count >= 3) {
194 nvram_set("restore_defaults", "1");
195 nvram_commit();
196 sync();
197 reboot(RB_AUTOBOOT);
199 else {
200 led(LED_DIAG, 1);
201 set_action(ACT_REBOOT);
202 kill(1, SIGTERM);
204 exit(0);
205 #endif
208 if ((ses_mask) && ((gpio & ses_mask) == ses_pushed)) {
209 count = 0;
210 do {
211 // syslog(LOG_DEBUG, "ses-pushed: gpio=x%X, pushed=x%X, mask=x%X, count=%d", gpio, ses_pushed, ses_mask, count);
213 led(ses_led, LED_ON);
214 usleep(500000);
215 led(ses_led, LED_OFF);
216 usleep(500000);
217 ++count;
218 } while (((gpio = _gpio_read()) != ~0) && ((gpio & ses_mask) == ses_pushed));
219 gpio &= mask;
221 if ((ses_led == LED_DMZ) && (nvram_get_int("dmz_enable") > 0)) led(LED_DMZ, 1);
223 // syslog(LOG_DEBUG, "ses-released: gpio=x%X, pushed=x%X, mask=x%X, count=%d", gpio, ses_pushed, ses_mask, count);
224 syslog(LOG_INFO, "SES pushed. Count was %d.", count);
226 if ((count != 3) && (count != 7) && (count != 11)) {
227 n = count >> 2;
228 if (n > 3) n = 3;
230 0-2 = func0
231 4-6 = func1
232 8-10 = func2
233 12+ = func3
236 #ifdef DEBUG_TEST
237 cprintf("ses func=%d\n", n);
238 #else
239 sprintf(s, "sesx_b%d", n);
240 // syslog(LOG_DEBUG, "ses-func: count=%d %s='%s'", count, s, nvram_safe_get(s));
241 if ((p = nvram_get(s)) != NULL) {
242 switch (*p) {
243 case '1': // toggle wl
244 nvram_set("rrules_radio", "-1");
245 eval("radio", "toggle");
246 break;
247 case '2': // reboot
248 kill(1, SIGTERM);
249 break;
250 case '3': // shutdown
251 kill(1, SIGQUIT);
252 break;
253 case '4': // run a script
254 sprintf(s, "%d", count);
255 run_nvscript("sesx_script", s, 2);
256 break;
259 #endif
264 if (brau_mask) {
265 last = (gpio & brau_mask);
266 if (brau_state != last) {
267 brau_state = last;
268 p = brau_state ? "auto" : "bridge";
269 nvram_set("brau_state", p);
270 #ifdef DEBUG_TEST
271 cprintf("bridge/auto state = %s\n", p);
272 #else
273 run_nvscript("script_brau", p, 2);
274 #endif
278 last = gpio;
281 return 0;