Netgear 3500L: do not mess with gpio 0
[tomato.git] / release / src / router / shared / led.c
blob51c84817b9e859801f8762da60eea8fb458a2cfc
1 /*
3 Tomato Firmware
4 Copyright (C) 2006-2009 Jonathan Zarate
6 */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <fcntl.h>
14 #include <bcmnvram.h>
16 #include "utils.h"
17 #include "shutils.h"
18 #include "shared.h"
21 const char *led_names[] = { "wlan", "diag", "white", "amber", "dmz", "aoss", "bridge", "mystery" };
23 #ifdef LINUX26
24 #define GPIO_IOCTL
25 #endif
27 // --- move begin ---
28 #ifdef GPIO_IOCTL
30 #include <sys/ioctl.h>
31 #include <linux_gpio.h>
33 static int _gpio_ioctl(int f, int gpioreg, unsigned int mask, unsigned int val)
35 struct gpio_ioctl gpio;
37 gpio.val = val;
38 gpio.mask = mask;
40 if (ioctl(f, gpioreg, &gpio) < 0) {
41 _dprintf("Invalid gpioreg %d\n", gpioreg);
42 return -1;
44 return (gpio.val);
47 static int _gpio_open()
49 int f = open("/dev/gpio", O_RDWR);
50 if (f < 0)
51 _dprintf ("Failed to open /dev/gpio\n");
52 return f;
55 int gpio_open(uint32_t mask)
57 uint32_t bit;
58 int i;
59 int f = _gpio_open();
61 if ((f >= 0) && mask) {
62 for (i = 0; i <= 15; i++) {
63 bit = 1 << i;
64 if ((mask & bit) == bit) {
65 _gpio_ioctl(f, GPIO_IOC_RESERVE, bit, bit);
66 _gpio_ioctl(f, GPIO_IOC_OUTEN, bit, 0);
69 close(f);
70 f = _gpio_open();
73 return f;
76 void gpio_write(uint32_t bit, int en)
78 int f;
80 if ((f = gpio_open(0)) < 0) return;
82 _gpio_ioctl(f, GPIO_IOC_RESERVE, bit, bit);
83 _gpio_ioctl(f, GPIO_IOC_OUT, bit, en ? bit : 0);
84 close(f);
87 uint32_t _gpio_read(int f)
89 uint32_t r;
90 // r = _gpio_ioctl(f, GPIO_IOC_IN, 0xFFFF, 0);
91 r = _gpio_ioctl(f, GPIO_IOC_IN, 0x07FF, 0);
92 if (r < 0) r = ~0;
93 return r;
96 uint32_t gpio_read(void)
98 int f;
99 uint32_t r;
101 if ((f = gpio_open(0)) < 0) return ~0;
102 r = _gpio_read(f);
103 close(f);
104 return r;
107 #else
109 int gpio_open(uint32_t mask)
111 int f = open(DEV_GPIO(in), O_RDONLY|O_SYNC);
112 if (f < 0)
113 _dprintf ("Failed to open %s\n", DEV_GPIO(in));
114 return f;
117 void gpio_write(uint32_t bit, int en)
119 int f;
120 uint32_t r;
122 if ((f = open(DEV_GPIO(control), O_RDWR)) < 0) return;
123 read(f, &r, sizeof(r));
124 r &= ~bit;
125 write(f, &r, sizeof(r));
126 close(f);
128 if ((f = open(DEV_GPIO(outen), O_RDWR)) < 0) return;
129 read(f, &r, sizeof(r));
130 r |= bit;
131 write(f, &r, sizeof(r));
132 close(f);
134 if ((f = open(DEV_GPIO(out), O_RDWR)) < 0) return;
135 read(f, &r, sizeof(r));
136 if (en) r |= bit;
137 else r &= ~bit;
138 write(f, &r, sizeof(r));
139 close(f);
142 uint32_t _gpio_read(int f)
144 uint32_t v;
145 return (read(f, &v, sizeof(v)) == sizeof(v)) ? v : ~0;
148 uint32_t gpio_read(void)
150 int f;
151 uint32_t r;
153 if ((f = open(DEV_GPIO(in), O_RDONLY)) < 0) return ~0;
154 r = _gpio_read(f);
155 close(f);
156 return r;
159 #endif
161 int nvget_gpio(const char *name, int *gpio, int *inv)
163 char *p;
164 uint32_t n;
166 if (((p = nvram_get(name)) != NULL) && (*p)) {
167 n = strtoul(p, NULL, 0);
168 if ((n & 0xFFFFFF70) == 0) {
169 *gpio = (n & 15);
170 *inv = ((n & 0x80) != 0);
171 return 1;
174 return 0;
176 // --- move end ---
179 int led(int which, int mode)
181 // WLAN DIAG WHITE AMBER DMZ AOSS BRIDG MYST
182 // ----- ----- ----- ----- ----- ----- ----- -----
183 static int wrt54g[] = { 0, 1, 2, 3, 7, 255, 255, 255 };
184 static int wrtsl[] = { 255, 1, 5, 7, 0, 255, 255, 255 };
185 static int whrg54[] = { 2, 7, 255, 255, 255, 6, 1, 3 };
186 static int wbr2g54[] = { 255, -1, 255, 255, 255, -6, 255, 255 };
187 static int wzrg54[] = { 2, 7, 255, 255, 255, 6, 255, 255 };
188 static int wr850g1[] = { 7, 3, 255, 255, 255, 255, 255, 255 };
189 static int wr850g2[] = { 0, 1, 255, 255, 255, 255, 255, 255 };
190 static int wtr54gs[] = { 1, -1, 255, 255, 255, 255, 255, 255 };
191 static int dir320[] = { -99, 1, 4, 3, 255, 255, 255, -5 };
192 static int wnr3500[] = { 255, 255, 2, 255, 255, -1, 255, 255 };
193 static int wrt160nv3[] = { 255, 1, 4, 2, 255, 255, 255, 255 };
195 char s[16];
196 int n;
197 int b = 255, c = 255;
199 if ((which < 0) || (which >= LED_COUNT)) return 0;
201 switch (nvram_match("led_override", "1") ? MODEL_UNKNOWN : get_model()) {
202 case MODEL_WRT54G:
203 if (check_hw_type() == HW_BCM4702) {
204 // G v1.x
205 if ((which != LED_DIAG) && (which != LED_DMZ)) return 0;
206 if (mode != LED_PROBE) {
207 if (f_read_string("/proc/sys/diag", s, sizeof(s)) > 0) {
208 b = (which == LED_DMZ) ? 1 : 4;
209 n = atoi(s);
210 sprintf(s, "%u", mode ? (n | b) : (n & ~b));
211 f_write_string("/proc/sys/diag", s, 0, 0);
214 return 1;
216 switch (which) {
217 case LED_AMBER:
218 case LED_WHITE:
219 if (!supports(SUP_WHAM_LED)) return 0;
220 break;
222 b = wrt54g[which];
223 break;
224 case MODEL_WTR54GS:
225 b = wtr54gs[which];
226 break;
227 case MODEL_WRTSL54GS:
228 b = wrtsl[which];
229 break;
230 case MODEL_WHRG54S:
231 case MODEL_WHRHPG54:
232 case MODEL_WHRG125:
233 b = whrg54[which];
234 break;
235 case MODEL_WZRG54:
236 case MODEL_WZRHPG54:
237 case MODEL_WZRRSG54:
238 case MODEL_WZRRSG54HP:
239 case MODEL_WVRG54NF:
240 case MODEL_WHR2A54G54:
241 case MODEL_WHR3AG54:
242 case MODEL_WZRG108:
243 b = wzrg54[which];
244 break;
246 case MODEL_WHR2A54G54:
247 if (which != LED_DIAG) return 0;
248 b = 7;
249 break;
251 case MODEL_WBRG54:
252 if (which != LED_DIAG) return 0;
253 b = 7;
254 break;
255 case MODEL_WBR2G54:
256 b = wbr2g54[which];
257 break;
258 case MODEL_WR850GV1:
259 b = wr850g1[which];
260 break;
261 case MODEL_WR850GV2:
262 case MODEL_WR100:
263 b = wr850g2[which];
264 break;
265 case MODEL_WL500GP:
266 if (which != LED_DIAG) return 0;
267 b = -1; // power light
268 break;
269 case MODEL_WL500W:
270 if (which != LED_DIAG) return 0;
271 b = -5; // power light
272 break;
273 case MODEL_DIR320:
274 b = dir320[which];
275 break;
276 case MODEL_WL500GPv2:
277 case MODEL_WL520GU:
278 if (which != LED_DIAG) return 0;
279 b = -99; // Invert power light as diag indicator
280 break;
281 case MODEL_RTN12:
282 if (which != LED_DIAG) return 0;
283 b = -2; // power light
284 break;
285 case MODEL_RTN10:
286 case MODEL_RTN16:
287 if (which != LED_DIAG) return 0;
288 b = -1; // power light
289 break;
290 case MODEL_WNR3500L:
291 if (which == LED_DIAG) {
292 // power led gpio: 0x03 - green, 0x07 - amber
293 b = (mode) ? 7 : 3;
294 c = (mode) ? 3 : 7;
295 } else
296 b = wnr3500[which];
297 break;
298 case MODEL_WRT160Nv3:
299 b = wrt160nv3[which];
300 break;
302 case MODEL_RT390W:
303 break;
305 case MODEL_MN700:
306 if (which != LED_DIAG) return 0;
307 b = 6;
308 break;
309 case MODEL_WLA2G54L:
310 if (which != LED_DIAG) return 0;
311 b = 1;
312 break;
313 default:
314 sprintf(s, "led_%s", led_names[which]);
315 if (nvget_gpio(s, &b, &n)) {
316 if ((mode != LED_PROBE) && (n)) mode = !mode;
317 goto SET;
319 return 0;
322 if (b < 0) {
323 if (b == -99) b = 0; // -0 substitute
324 else b = -b;
326 else if (mode != LED_PROBE) {
327 mode = !mode;
330 SET:
331 if (b < 16) {
332 if (mode != LED_PROBE) {
333 gpio_write(1 << b, mode);
335 if (c < 0) {
336 if (c == -99) c = 0;
337 else c = -c;
339 else mode = !mode;
340 if (c < 16) gpio_write(1 << c, mode);
342 return 1;
345 return 0;