Netgear R6400 support
[tomato.git] / release / src-rt-6.x.4708 / router / shared / led.c
blob70349fb209db915c89390f2efc215bace5bfee39
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", "usb", "usb3", "5g"};
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_OUTEN, bit, bit);
84 _gpio_ioctl(f, GPIO_IOC_OUT, bit, en ? bit : 0);
85 close(f);
88 uint32_t _gpio_read(int f)
90 uint32_t r;
91 // r = _gpio_ioctl(f, GPIO_IOC_IN, 0xFFFF, 0);
92 r = _gpio_ioctl(f, GPIO_IOC_IN, 0x07FF, 0);
93 if (r < 0) r = ~0;
94 return r;
97 uint32_t gpio_read(void)
99 int f;
100 uint32_t r;
102 if ((f = gpio_open(0)) < 0) return ~0;
103 r = _gpio_read(f);
104 close(f);
105 return r;
108 #else
110 int gpio_open(uint32_t mask)
112 int f = open(DEV_GPIO(in), O_RDONLY|O_SYNC);
113 if (f < 0)
114 _dprintf ("Failed to open %s\n", DEV_GPIO(in));
115 return f;
118 void gpio_write(uint32_t bit, int en)
120 int f;
121 uint32_t r;
123 if ((f = open(DEV_GPIO(control), O_RDWR)) < 0) return;
124 read(f, &r, sizeof(r));
125 r &= ~bit;
126 write(f, &r, sizeof(r));
127 close(f);
129 if ((f = open(DEV_GPIO(outen), O_RDWR)) < 0) return;
130 read(f, &r, sizeof(r));
131 r |= bit;
132 write(f, &r, sizeof(r));
133 close(f);
135 if ((f = open(DEV_GPIO(out), O_RDWR)) < 0) return;
136 read(f, &r, sizeof(r));
137 if (en) r |= bit;
138 else r &= ~bit;
139 write(f, &r, sizeof(r));
140 close(f);
143 uint32_t _gpio_read(int f)
145 uint32_t v;
146 return (read(f, &v, sizeof(v)) == sizeof(v)) ? v : ~0;
149 uint32_t gpio_read(void)
151 int f;
152 uint32_t r;
154 if ((f = open(DEV_GPIO(in), O_RDONLY)) < 0) return ~0;
155 r = _gpio_read(f);
156 close(f);
157 return r;
160 #endif
162 int nvget_gpio(const char *name, int *gpio, int *inv)
164 char *p;
165 uint32_t n;
167 if (((p = nvram_get(name)) != NULL) && (*p)) {
168 n = strtoul(p, NULL, 0);
169 if ((n & 0xFFFFFF70) == 0) {
170 *gpio = (n & 15);
171 *inv = ((n & 0x80) != 0);
172 return 1;
175 return 0;
177 // --- move end ---
180 int do_led(int which, int mode)
182 // WLAN DIAG WHITE AMBER DMZ AOSS BRIDG USB2 USB3 5G
183 // ----- ----- ----- ----- --- ---- ----- ---- ---- --
184 static int wrt54g[] = { 255, 1, 2, 3, 7, 255, 255, 255, 255, 255};
185 static int wrtsl[] = { 255, 1, 5, 7, 0, 255, 255, 255, 255, 255};
186 static int whrg54[] = { 2, 7, 255, 255, 255, 6, 1, 3, 255, 255};
187 static int wbr2g54[] = { 255, -1, 255, 255, 255, -6, 255, 255, 255, 255};
188 static int wzrg54[] = { 2, 7, 255, 255, 255, 6, 255, 255, 255, 255};
189 static int wr850g1[] = { 7, 3, 255, 255, 255, 255, 255, 255, 255, 255};
190 static int wr850g2[] = { 0, 1, 255, 255, 255, 255, 255, 255, 255, 255};
191 static int wtr54gs[] = { 1, -1, 255, 255, 255, 255, 255, 255, 255, 255};
192 static int dir320[] = { -99, 1, 4, 3, 255, 255, 255, -5, 255, 255};
193 static int h618b[] = { 255, -1, 255, 255, 255, -5, -3, -4, 255, 255};
194 static int wl1600gl[] = { 1, -5, 0, 255, 255, 2, 255, 255, 255, 255};
195 static int wrt310nv1[] = { 255, 1, 9, 3, 255, 255, 255, 255, 255, 255};
196 static int wrt160nv1[] = { 255, 1, 5, 3, 255, 255, 255, 255, 255, 255};
197 #ifdef CONFIG_BCMWL5
198 static int wnr3500[] = { 255, 255, 2, 255, 255, -1, 255, 255, 255, 255};
199 static int wnr2000v2[] = { 255, 255, 255, 255, 255, -7, 255, 255, 255, 255};
200 static int f7d[] = { 255, 255, 255, 255, 12, 13, 255, 14, 255, 255};
201 static int wrt160nv3[] = { 255, 1, 4, 2, 255, 255, 255, 255, 255, 255};
202 static int e900[] = { 255, -6, 8, 255, 255, 255, 255, 255, 255, 255};
203 static int e1000v2[] = { 255, -6, 8, 7, 255, 255, 255, 255, 255, 255};
204 static int e3200[] = { 255, -3, 255, 255, 255, 255, 255, 255, 255, 255};
205 static int wrt320n[] = { 255, 2, 3, 4, 255, 255, 255, 255, 255, 255};
206 static int wrt610nv2[] = { 255, 5, 3, 0, 255, 255, 255, -7, 255, 255};
207 static int e4200[] = { 255, 5, -3, 255, 255, 255, 255, 255, 255, 255};
208 static int rtn10u[] = { 255, 255, 255, 255, 255, -7, 255, -8, 255, 255};
209 static int rtn10p[] = { 255, -6, 255, 255, 255, -7, 255, 255, 255, 255};
210 static int rtn12b1[] = { -5, 255, 255, 255, 255, 255, 255, 225, 255, 255};
211 static int rtn15u[] = { 1, 255, 3, 255, 255, 255, 255, -9, 255, 255};
212 static int rtn53[] = { 0, -17, 255, 255, 255, 255, 255, 255, 255, 255};
213 static int l600n[] = { 255, 255, 255, 255, 255, -7, 255, -8, 255, 255};
214 static int dir620c1[] = { -6, -8, 255, 255, 255, -7, 255, 255, 255, 255};
215 static int rtn66u[] = { 255, -12, 255, 255, 255, 255, 255, 15, 255, 13};
216 static int w1800r[] = { 255, -13, 255, 255, 255, 255, 255, -12, 255, -5};
217 static int d1800h[] = { -12, -13, 8, 255, 255, -10, 255, 15, 255, 11};
218 static int tdn6[] = { 255, -6, 8, 255, 255, 255, 255, 255, 255, 255};
219 #endif
220 #ifdef CONFIG_BCMWL6A
221 static int ac68u[] = { 255, 255, 255, 255, 255, -4, 255, -0, -14, 255};
222 static int ac56u[] = { 255, 255, 255, 255, 255, -3, 255, -0, -14, 255};
223 static int n18u[] = { 255, 255, 6, 255, 255, 255, 255, 3, 14, 255};
224 static int r6250[] = { 11, 255, 15, 255, 255, 1, 255, 8, 8, 255};
225 static int r6300v2[] = { 11, 255, 10, 255, 255, 1, 255, 8, 8, 255};
226 static int r6400[] = { 9, -2, 255, 255, 255, -11, 255, 12, 13, 8};
227 static int r7000[] = { 13, 255, 255, 255, 255, -15, 255, -17, -18, 12};
228 static int dir868[] = { 255, 255, 3, 255, 255, -0, 255, 255, 255, 255};
229 static int ea6700[] = { 255, 255, -6, -6, 255, 255, 255, 255, 255, 255};
230 static int ea6900[] = { 255, 255, 8, 255, 255, 6, 255, 255, 255, 255};
231 static int ws880[] = { 0, 255, -12, 255, 255, 6, 1, 14, 14, 6};
232 static int r1d[] = { 255, 255, 255, 255, 255, 1, -8, 255, 255, 255};
233 static int wzr1750[] = { 255, 255, 255, 255, 255, -5, 255, 255, 255, 255};
235 #endif
236 // WLAN DIAG WHITE AMBER DMZ AOSS BRIDG USB2 USB3 5G
239 char s[16];
240 int n;
241 int b = 255, c = 255;
242 int ret = 255;
244 if ((which < 0) || (which >= LED_COUNT)) return ret;
246 switch (nvram_match("led_override", "1") ? MODEL_UNKNOWN : get_model()) {
247 case MODEL_WRT54G:
248 if (check_hw_type() == HW_BCM4702) {
249 // G v1.x
250 if ((which != LED_DIAG) && (which != LED_DMZ)) return ret;
251 b = (which == LED_DMZ) ? 1 : 4;
252 if (mode != LED_PROBE) {
253 if (f_read_string("/proc/sys/diag", s, sizeof(s)) > 0) {
254 n = atoi(s);
255 sprintf(s, "%u", mode ? (n | b) : (n & ~b));
256 f_write_string("/proc/sys/diag", s, 0, 0);
259 return b;
261 switch (which) {
262 case LED_AMBER:
263 case LED_WHITE:
264 if (!supports(SUP_WHAM_LED)) return ret;
265 break;
267 b = wrt54g[which];
268 break;
269 case MODEL_WTR54GS:
270 b = wtr54gs[which];
271 break;
272 case MODEL_WRTSL54GS:
273 b = wrtsl[which];
274 break;
275 case MODEL_WHRG54S:
276 case MODEL_WHRHPG54:
277 case MODEL_WHRG125:
278 b = whrg54[which];
279 break;
280 case MODEL_WZRG54:
281 case MODEL_WZRHPG54:
282 case MODEL_WZRRSG54:
283 case MODEL_WZRRSG54HP:
284 case MODEL_WVRG54NF:
285 case MODEL_WHR2A54G54:
286 case MODEL_WHR3AG54:
287 case MODEL_WZRG108:
288 b = wzrg54[which];
289 break;
291 case MODEL_WHR2A54G54:
292 if (which != LED_DIAG) return ret;
293 b = 7;
294 break;
296 case MODEL_WBRG54:
297 if (which != LED_DIAG) return ret;
298 b = 7;
299 break;
300 case MODEL_WBR2G54:
301 b = wbr2g54[which];
302 break;
303 case MODEL_WR850GV1:
304 b = wr850g1[which];
305 break;
306 case MODEL_WR850GV2:
307 case MODEL_WR100:
308 b = wr850g2[which];
309 break;
310 case MODEL_WL500GP:
311 if (which != LED_DIAG) return ret;
312 b = -1; // power light
313 break;
314 case MODEL_WL500W:
315 if (which != LED_DIAG) return ret;
316 b = -5; // power light
317 break;
318 case MODEL_DIR320:
319 b = dir320[which];
320 break;
321 case MODEL_H618B:
322 b = h618b[which];
323 break;
324 case MODEL_WL1600GL:
325 b = wl1600gl[which];
326 break;
327 case MODEL_WL500GPv2:
328 case MODEL_WL500GD:
329 case MODEL_WL520GU:
330 case MODEL_WL330GE:
331 if (which != LED_DIAG) return ret;
332 b = -99; // Invert power light as diag indicator
333 break;
334 #ifdef CONFIG_BCMWL5
335 case MODEL_RTN12:
336 if (which != LED_DIAG) return ret;
337 b = -2; // power light
338 break;
339 case MODEL_RTN10:
340 case MODEL_RTN16:
341 if (which != LED_DIAG) return ret;
342 b = -1; // power light
343 break;
344 case MODEL_RTN15U:
345 b = rtn15u[which];
346 break;
347 case MODEL_RTN53:
348 case MODEL_RTN53A1:
349 b = rtn53[which];
350 break;
351 case MODEL_RTN66U:
352 b = rtn66u[which];
353 break;
354 case MODEL_W1800R:
355 b = w1800r[which];
356 break;
357 case MODEL_D1800H:
358 if (which == LED_DIAG) {
359 // power led gpio: 0x02 - white, 0x13 - red
360 b = (mode) ? 13 : 2;
361 c = (mode) ? 2 : 13;
362 } else
363 b = d1800h[which];
364 break;
365 case MODEL_WNR3500L:
366 case MODEL_WNR3500LV2:
367 if (which == LED_DIAG) {
368 // power led gpio: 0x03 - green, 0x07 - amber
369 b = (mode) ? 7 : 3;
370 c = (mode) ? 3 : 7;
371 } else
372 b = wnr3500[which];
373 break;
374 case MODEL_WNR2000v2:
375 if (which == LED_DIAG) {
376 // power led gpio: 0x01 - green, 0x02 - amber
377 b = (mode) ? 2 : 1;
378 c = (mode) ? 1 : 2;
379 } else
380 b = wnr2000v2[which];
381 break;
382 case MODEL_F7D3301:
383 case MODEL_F7D3302:
384 case MODEL_F7D4301:
385 case MODEL_F7D4302:
386 case MODEL_F5D8235v3:
387 if (which == LED_DIAG) {
388 // power led gpio: 10 - green, 11 - red
389 b = (mode) ? 11 : -10;
390 c = (mode) ? -10 : 11;
391 } else
392 b = f7d[which];
393 break;
394 case MODEL_E1000v2:
395 b = e1000v2[which];
396 break;
397 case MODEL_E900:
398 case MODEL_E1500:
399 case MODEL_E1550:
400 case MODEL_E2500:
401 b = e900[which];
402 break;
403 case MODEL_E3200:
404 b = e3200[which];
405 break;
406 case MODEL_WRT160Nv3:
407 b = wrt160nv3[which];
408 break;
409 case MODEL_WRT320N:
410 b = wrt320n[which];
411 break;
412 case MODEL_WRT610Nv2:
413 b = wrt610nv2[which];
414 break;
415 case MODEL_E4200:
416 b = e4200[which];
417 break;
418 case MODEL_RTN10U:
419 b = rtn10u[which];
420 break;
421 case MODEL_RTN10P:
422 b = rtn10p[which];
423 break;
424 case MODEL_RTN12B1:
425 b = rtn12b1[which];
426 break;
427 case MODEL_L600N:
428 b = l600n[which];
429 break;
430 case MODEL_DIR620C1:
431 b = dir620c1[which];
432 case MODEL_TDN60: //bwq518
433 case MODEL_TDN6:
434 b = tdn6[which];
435 break;
436 #endif
437 #ifdef CONFIG_BCMWL6A
438 case MODEL_RTAC68U:
439 b = ac68u[which];
440 break;
441 case MODEL_RTAC56U:
442 b = ac56u[which];
443 break;
444 case MODEL_RTN18U:
445 b = n18u[which];
446 break;
447 case MODEL_R6250:
448 if (which == LED_DIAG) {
449 // power led gpio: -3 - orange, -2 - green
450 b = (mode) ? 2 : 3;
451 c = (mode) ? 3 : 2;
452 } else
453 b = r6250[which];
454 break;
455 case MODEL_R6300v2:
456 if (which == LED_DIAG) {
457 // power led gpio: -3 - orange, -2 - green
458 b = (mode) ? 2 : 3;
459 c = (mode) ? 3 : 2;
460 } else
461 b = r6300v2[which];
462 break;
463 case MODEL_R6400:
464 if (which == LED_DIAG) {
465 // power led gpio: -2 - orange, -1 - white
466 b = (mode) ? 1 : 2;
467 c = (mode) ? 2 : 1;
468 } else
469 b = r6400[which];
470 break;
471 case MODEL_R7000:
472 if (which == LED_DIAG) {
473 // power led gpio: -3 - orange, -2 - white
474 b = (mode) ? 2 : 3;
475 c = (mode) ? 3 : 2;
476 } else
477 b = r7000[which];
478 break;
479 case MODEL_DIR868L:
480 if (which == LED_DIAG) {
481 // power led gpio: -0 - orange, -2 - white
482 b = (mode) ? 2 : 0;
483 c = (mode) ? 0 : 2;
484 } else
485 b = dir868[which];
486 break;
487 case MODEL_WS880:
488 b = ws880[which];
489 break;
490 case MODEL_R1D:
491 if (which == LED_DIAG) {
492 // power led gpio: -2 - orange, -3 - blue
493 b = (mode) ? 3 : 2;
494 c = (mode) ? 2 : 3;
495 } else
496 b = r1d[which];
497 break;
498 case MODEL_EA6700:
499 case MODEL_EA6900: //need to be verified
500 b = ea6700[which];
501 break;
502 case MODEL_WZR1750:
503 b = wzr1750[which];
504 break;
506 #endif
508 case MODEL_RT390W:
509 break;
511 case MODEL_MN700:
512 if (which != LED_DIAG) return ret;
513 b = 6;
514 break;
515 case MODEL_WLA2G54L:
516 if (which != LED_DIAG) return ret;
517 b = 1;
518 break;
519 case MODEL_WRT300N:
520 if (which != LED_DIAG) return ret;
521 b = 1;
522 break;
523 case MODEL_WRT310Nv1:
524 b = wrt310nv1[which];
525 break;
526 case MODEL_WRT160Nv1:
527 b = wrt160nv1[which];
528 break;
529 default:
530 sprintf(s, "led_%s", led_names[which]);
531 if (nvget_gpio(s, &b, &n)) {
532 if ((mode != LED_PROBE) && (n)) mode = !mode;
533 ret = (n) ? b : ((b) ? -b : -99);
534 goto SET;
536 return ret;
539 ret = b;
540 if (b < 0) {
541 if (b == -99) b = 0; // -0 substitute
542 else b = -b;
544 else if (mode != LED_PROBE) {
545 mode = !mode;
548 SET:
549 if (b < 16) {
550 if (mode != LED_PROBE) {
551 gpio_write(1 << b, mode);
553 if (c < 0) {
554 if (c == -99) c = 0;
555 else c = -c;
557 else mode = !mode;
558 if (c < 16) gpio_write(1 << c, mode);
562 return ret;