Merge branch 'tomato-ND-fixes' into tomato-ND-USBmod
[tomato.git] / release / src / router / shared / led.c
blobc5b1f11cf8e66fb1b0e8eae6c8380458f655e781
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 int gpio_open()
35 int f = open("/dev/gpio", O_RDWR);
36 if (f < 0)
37 _dprintf ("Failed to open /dev/gpio\n");
38 return f;
41 static int _gpio_ioctl(int f, int gpioreg, unsigned int mask, unsigned int val)
43 struct gpio_ioctl gpio;
45 gpio.val = val;
46 gpio.mask = mask;
48 if (ioctl(f, gpioreg, &gpio) < 0) {
49 _dprintf("Invalid gpioreg %d\n", gpioreg);
50 return -1;
52 return (gpio.val);
55 void gpio_write(uint32_t bit, int en)
57 int f;
59 if ((f = gpio_open()) < 0) return;
61 _gpio_ioctl(f, GPIO_IOC_RESERVE, bit, bit);
62 _gpio_ioctl(f, GPIO_IOC_OUTEN, bit, bit);
64 _gpio_ioctl(f, GPIO_IOC_OUT, bit, en ? bit : 0);
65 close(f);
68 uint32_t gpio_read(void)
70 int f;
71 uint32_t r;
73 if ((f = gpio_open()) < 0) return ~0;
74 r = _gpio_ioctl(f, GPIO_IOC_IN, 0xffff, 0);
75 if (r < 0) r = ~0;
76 close(f);
77 return r;
80 uint32_t _gpio_read(int f)
82 uint32_t r;
83 r = _gpio_ioctl(f, GPIO_IOC_IN, 0xffff, 0);
84 if (r < 0) r = ~0;
85 return r;
88 #else
90 int gpio_open()
92 int f = open(DEV_GPIO(in), O_RDONLY|O_SYNC);
93 if (f < 0)
94 _dprintf ("Failed to open %s\n", DEV_GPIO(in));
95 return f;
98 void gpio_write(uint32_t bit, int en)
100 int f;
101 uint32_t r;
103 if ((f = open(DEV_GPIO(control), O_RDWR)) < 0) return;
104 read(f, &r, sizeof(r));
105 r &= ~bit;
106 write(f, &r, sizeof(r));
107 close(f);
109 if ((f = open(DEV_GPIO(outen), O_RDWR)) < 0) return;
110 read(f, &r, sizeof(r));
111 r |= bit;
112 write(f, &r, sizeof(r));
113 close(f);
115 if ((f = open(DEV_GPIO(out), O_RDWR)) < 0) return;
116 read(f, &r, sizeof(r));
117 if (en) r |= bit;
118 else r &= ~bit;
119 write(f, &r, sizeof(r));
120 close(f);
123 uint32_t gpio_read(void)
125 int f;
126 uint32_t r;
128 if ((f = open(DEV_GPIO(in), O_RDONLY)) < 0) return ~0;
129 if (read(f, &r, sizeof(r)) != sizeof(r)) r = ~0;
130 close(f);
131 return r;
134 uint32_t _gpio_read(int f)
136 uint32_t v;
137 return (read(f, &v, sizeof(v)) == sizeof(v)) ? v : ~0;
140 #endif
142 int nvget_gpio(const char *name, int *gpio, int *inv)
144 char *p;
145 uint32_t n;
147 if (((p = nvram_get(name)) != NULL) && (*p)) {
148 n = strtoul(p, NULL, 0);
149 if ((n & 0xFFFFFF70) == 0) {
150 *gpio = (n & 15);
151 *inv = ((n & 0x80) != 0);
152 return 1;
155 return 0;
157 // --- move end ---
160 int led(int which, int mode)
162 // WLAN DIAG WHITE AMBER DMZ AOSS BRIDG MYST
163 // ----- ----- ----- ----- ----- ----- ----- -----
164 static int wrt54g[] = { 0, 1, 2, 3, 7, 255, 255, 255 };
165 static int wrtsl[] = { 255, 1, 5, 7, 0, 255, 255, 255 };
166 static int whrg54[] = { 2, 7, 255, 255, 255, 6, 1, 3 };
167 static int wbr2g54[] = { 255, -1, 255, 255, 255, -6, 255, 255 };
168 static int wzrg54[] = { 2, 7, 255, 255, 255, 6, 255, 255 };
169 static int wr850g1[] = { 7, 3, 255, 255, 255, 255, 255, 255 };
170 static int wr850g2[] = { 0, 1, 255, 255, 255, 255, 255, 255 };
171 static int wtr54gs[] = { 1, -1, 255, 255, 255, 255, 255, 255 };
172 static int dir320[] = { -99, 1, 4, 3, 255, 255, 255, -5 };
173 char s[16];
174 int n;
175 int b;
177 if ((which < 0) || (which >= LED_COUNT)) return 0;
179 switch (nvram_match("led_override", "1") ? MODEL_UNKNOWN : get_model()) {
180 case MODEL_WRT54G:
181 if (check_hw_type() == HW_BCM4702) {
182 // G v1.x
183 if ((which != LED_DIAG) && (which != LED_DMZ)) return 0;
184 if (mode != LED_PROBE) {
185 if (f_read_string("/proc/sys/diag", s, sizeof(s)) > 0) {
186 b = (which == LED_DMZ) ? 1 : 4;
187 n = atoi(s);
188 sprintf(s, "%u", mode ? (n | b) : (n & ~b));
189 f_write_string("/proc/sys/diag", s, 0, 0);
192 return 1;
194 switch (which) {
195 case LED_AMBER:
196 case LED_WHITE:
197 if (!supports(SUP_WHAM_LED)) return 0;
198 break;
200 b = wrt54g[which];
201 break;
202 case MODEL_WTR54GS:
203 b = wtr54gs[which];
204 break;
205 case MODEL_WRTSL54GS:
206 b = wrtsl[which];
207 break;
208 case MODEL_WHRG54S:
209 case MODEL_WHRHPG54:
210 case MODEL_WHRG125:
211 b = whrg54[which];
212 break;
213 case MODEL_WZRG54:
214 case MODEL_WZRHPG54:
215 case MODEL_WZRRSG54:
216 case MODEL_WZRRSG54HP:
217 case MODEL_WVRG54NF:
218 case MODEL_WHR2A54G54:
219 case MODEL_WHR3AG54:
220 case MODEL_WZRG108:
221 b = wzrg54[which];
222 break;
224 case MODEL_WHR2A54G54:
225 if (which != LED_DIAG) return 0;
226 b = 7;
227 break;
229 case MODEL_WBRG54:
230 if (which != LED_DIAG) return 0;
231 b = 7;
232 break;
233 case MODEL_WBR2G54:
234 b = wbr2g54[which];
235 break;
236 case MODEL_WR850GV1:
237 b = wr850g1[which];
238 break;
239 case MODEL_WR850GV2:
240 case MODEL_WR100:
241 b = wr850g2[which];
242 break;
243 case MODEL_WL500GP:
244 if (which != LED_DIAG) return 0;
245 b = -1; // power light
246 break;
247 case MODEL_WL500W:
248 if (which != LED_DIAG) return 0;
249 b = -5; // power light
250 break;
251 case MODEL_DIR320:
252 b = dir320[which];
253 break;
254 case MODEL_WL500GPv2:
255 case MODEL_WL520GU:
256 if (which != LED_DIAG) return 0;
257 b = 0; // Invert power light as diag indicator
258 if (mode != LED_PROBE) mode = !mode;
259 break;
260 case MODEL_RTN12:
261 if (which != LED_DIAG) return 0;
262 b = -2; // power light
263 break;
264 case MODEL_RTN10:
265 case MODEL_RTN16:
266 if (which != LED_DIAG) return 0;
267 b = -1; // power light
268 break;
270 case MODEL_RT390W:
271 break;
273 case MODEL_MN700:
274 if (which != LED_DIAG) return 0;
275 b = 6;
276 break;
277 case MODEL_WLA2G54L:
278 if (which != LED_DIAG) return 0;
279 b = 1;
280 break;
281 default:
282 sprintf(s, "led_%s", led_names[which]);
283 if (nvget_gpio(s, &b, &n)) {
284 if ((mode != LED_PROBE) && (n)) mode = !mode;
285 goto SET;
287 return 0;
290 if (b < 0) {
291 if (b == -99) b = 0; // -0 substitute
292 else b = -b;
294 else if (mode != LED_PROBE) {
295 mode = !mode;
298 SET:
299 if (b < 16) {
300 if (mode != LED_PROBE) {
301 gpio_write(1 << b, mode);
303 return 1;
306 return 0;