1/*
2 * Copyright 2004, ASUSTek Inc.
3 * All Rights Reserved.
4 *
5 * THIS SOFTWARE IS OFFERED "AS IS", AND ASUS GRANTS NO WARRANTIES OF ANY
6 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
7 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
8 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
9 *
10 * $Id: watchdog.c,v 1.3 2009/03/03 02:39:54 james26_jang Exp $
11 */
12
13
14#include <stdio.h>
15#include <signal.h>
16#include <time.h>
17#include <sys/time.h>
18#include <unistd.h>
19#include <stdlib.h>
20#include <sys/types.h>
21#include <shutils.h>
22#include <rc.h>
23#include <stdarg.h>
24#include <wlioctl.h>
25#include <syslog.h>
26#include <bcmnvram.h>
27#include <fcntl.h>
28#include <linux_gpio.h>
29#include <sys/stat.h>
30#include <math.h>
31
32
33/* +++ Cherry Cho added in 2007/1/4. +++ */
34#include <sys/types.h>
35#include <sys/socket.h>
36#include <time.h>
37/* --- Cherry Cho added in 2007/1/4. --- */
38
39#define BCM47XX_SOFTWARE_RESET  0x40		/* GPIO 6 */
40#define RESET_WAIT		3		/* seconds */
41#define RESET_WAIT_COUNT	RESET_WAIT * 10 /* 10 times a second */
42
43#define NORMAL_PERIOD		1		/* second */
44#define URGENT_PERIOD		100 * 1000	/* microsecond */
45#define RUSHURGENT_PERIOD	50 * 1000	/* microsecond */
46						/* 1/10 second */
47#define STACHECK_PERIOD_CONNECT 60/5		/* 30 seconds */
48#define STACHECK_PERIOD_DISCONNECT 5/5		/* 5 seconds */
49
50#ifdef WCN
51#define QUICK_PERIOD		100 * 1000	/* microsecond */
52int wcn_on=0;
53int wcn_led=0;
54int wcn_led_state=0;
55int wcn_timer=2;
56int reboot_WCN_count=0;
57#endif
58
59#define GPIO0 0x0001
60#define GPIO1 0x0002
61#define GPIO2 0x0004
62#define GPIO3 0x0008
63#define GPIO4 0x0010
64#define GPIO5 0x0020
65#define GPIO6 0x0040
66#define GPIO7 0x0080
67#define GPIO15 0x8000
68
69#define LED_ON 	0
70#define LED_OFF 1
71
72#define LED_POWER	GPIO0
73#define BTN_RESET	GPIO2
74#define BTN_SETUP	GPIO3
75
76#ifdef BTN_SETUP
77#define SETUP_WAIT		3		/* seconds */
78#define SETUP_WAIT_COUNT	100 /* The real waiting time depends on the alarm timer. Cherry Cho modified in 2008/7/4. */
79#define SETUP_TIMEOUT		60 		/* seconds */
80#define SETUP_TIMEOUT_COUNT	SETUP_TIMEOUT * 10 /* 60 times a second */
81#endif //BTN_SETUP
82
83
84/* Global containing the file descriptor of the GPIO kernel drivers */
85static int bcmgpio_fd;
86
87/* Global containing information about each GPIO pin */
88
89/* Static function prototypes */
90
91/* Generic functions to read/write Chip Common core's GPIO registers on the AP */
92int tgpio_drvinit ();
93void tgpio_drvcleanup ();
94
95int tgpio_ioctl(int gpioreg, unsigned int mask , unsigned int val);
96
97/* GPIO registers */
98#define BCMGPIO_REG_IN          0
99#define BCMGPIO_REG_OUT         1
100#define BCMGPIO_REG_OUTEN       2
101#define BCMGPIO_REG_RESERVE     3
102#define BCMGPIO_REG_RELEASE     4
103
104
105#define LED_CONTROL(led,flag) gpio_write("/dev/gpio/out", led, flag)
106
107
108struct itimerval itv;
109int watchdog_period=0;
110static int btn_pressed=0;
111static int btn_count = 0;
112long sync_interval=-1; // every 30 seconds a unit
113int sync_flag=0;
114long timestamp_g=0;
115int stacheck_interval=-1;
116#ifdef BTN_SETUP
117int btn_pressed_setup=0;
118int btn_pressed_flag=0;
119int btn_count_setup=0;
120int btn_count_timeout=0;
121int btn_stage=0;
122#endif
123#ifdef WSC
124int btn_addER = 0;
125/* +++ Cherry Cho added in 2008/7/16. +++ */
126int WSC_ENABLED;
127int wsc_success = 1;
128int led_count = 0;
129int led_count_timeout = 100;
130extern int start_wsc(void);
131/* --- Cherry Cho added in 2008/7/16. --- */
132#endif
133
134#ifdef CDMA
135int cdma_down=0;
136int cdma_connect=0;
137#endif
138
139int reboot_count=0;
140static int int_nas_enable=0;
141static int nas_check_interval=0;
142
143int tgpio_fd_init ();
144void tgpio_fd_cleanup ();
145int tgpio_ioctl(int gpioreg, unsigned int mask , unsigned int val);
146void gpio_write(char *dev, int gpio, int val);
147
148void wl_led_ctrl(int ctrl);/* Cherry Cho added in 2008/7/16. */
149
150
151int
152tgpio_fd_init ()
153{
154        bcmgpio_fd = open("/dev/gpio", O_RDWR);
155        if (bcmgpio_fd == -1) {
156                printf ("Failed to open /dev/gpio\n");
157                return -1;
158        }
159        return 0;
160}
161
162void
163tgpio_fd_cleanup ()
164{
165        if (bcmgpio_fd!= -1) {
166                close (bcmgpio_fd);
167                bcmgpio_fd = -1;
168        }
169}
170
171int
172tgpio_ioctl(int gpioreg, unsigned int mask , unsigned int val)
173{
174        struct gpio_ioctl gpio;
175        int type;
176
177        gpio.val = val;
178        gpio.mask = mask;
179
180        switch (gpioreg) {
181                case BCMGPIO_REG_IN:
182                        type = GPIO_IOC_IN;
183                        break;
184                case BCMGPIO_REG_OUT:
185                        type = GPIO_IOC_OUT;
186                        break;
187                case BCMGPIO_REG_OUTEN:
188                        type = GPIO_IOC_OUTEN;
189                        break;
190                case BCMGPIO_REG_RESERVE:
191                        type = GPIO_IOC_RESERVE;
192                        break;
193                case BCMGPIO_REG_RELEASE:
194                        type = GPIO_IOC_RELEASE;
195                        break;
196                default:
197                        printf ("invalid gpioreg %d\n", gpioreg);
198                        return -1;
199        }
200        if (ioctl(bcmgpio_fd, type, &gpio) < 0) {
201                printf ("invalid gpioreg %d\n", gpioreg);
202                return -1;
203        }
204        return (gpio.val);
205}
206
207void gpio_write(char *dev, int gpio, int val)
208{
209	unsigned int gpio_type;
210	unsigned long bitmask;
211	unsigned long gpio_val;
212//	int gpio_pin;
213
214	if( strcmp (dev, "/dev/gpio/in") == 0)
215		gpio_type = BCMGPIO_REG_IN;
216	else if ( strcmp (dev, "/dev/gpio/out") == 0)
217		gpio_type = BCMGPIO_REG_OUT;
218	else if ( strcmp (dev, "/dev/gpio/outen") == 0)
219		gpio_type = BCMGPIO_REG_OUTEN;
220	else
221		printf("ERROR GPIO NAME %s\n", dev);
222
223	//sscanf(argv[3], "%x", &val);
224	tgpio_fd_init();
225	tgpio_ioctl(BCMGPIO_REG_RESERVE, gpio, gpio);
226	if (val > 0)
227	tgpio_ioctl(gpio_type, gpio, gpio);
228	else
229	tgpio_ioctl(gpio_type, gpio, 0);
230	tgpio_fd_cleanup();
231}
232
233int gpio_read (char *dev, int gpio)
234{
235	unsigned int gpio_type;
236	int ret;
237	unsigned long bitmask;
238        if( strcmp (dev, "/dev/gpio/in") == 0)
239                gpio_type = BCMGPIO_REG_IN;
240        else if ( strcmp (dev, "/dev/gpio/out") == 0)
241                gpio_type = BCMGPIO_REG_OUT;
242        else if ( strcmp (dev, "/dev/gpio/outen") == 0)
243                gpio_type = BCMGPIO_REG_OUTEN;
244        else
245                printf("ERROR GPIO NAME %s\n", dev);
246
247	tgpio_fd_init();
248
249	/* read the value of GPIO*/
250	ret = (tgpio_ioctl(gpio_type, gpio, 0));
251	tgpio_fd_cleanup();
252
253	return (ret&gpio);
254}
255
256/* Functions used to control led and button */
257void gpio_init()
258{
259	gpio_write("/dev/gpio/outen", LED_POWER, 1);
260	gpio_write("/dev/gpio/outen", BTN_RESET, 0);
261#ifdef BTN_SETUP
262	gpio_write("/dev/gpio/outen", BTN_SETUP, 0);
263#endif
264	gpio_write("/dev/gpio/out", LED_POWER, 0);
265}
266
267static void
268alarmtimer(unsigned long sec,unsigned long usec)
269{
270	itv.it_value.tv_sec  = sec;
271	itv.it_value.tv_usec = usec;
272	itv.it_interval = itv.it_value;
273	setitimer(ITIMER_REAL, &itv, NULL);
274}
275
276void btn_check(void)
277{
278#ifdef WCN
279	if(wcn_on==1)
280	{
281		++wcn_led;
282		wcn_led%=wcn_timer;
283		wcn_led_state=(wcn_led==0?1:0);
284
285		if(wcn_led_state)
286			LED_CONTROL(LED_POWER, LED_ON);
287		else
288			LED_CONTROL(LED_POWER, LED_OFF);
289
290		return;
291	}
292#endif
293
294#ifdef BTN_SETUP
295#if 0/* Cherry Cho marked for stoping using EZsetup in 2007/2/12. */
296	if (btn_pressed_flag)
297	{
298		++btn_pressed_flag;
299
300		if(btn_pressed_flag==8)
301		{
302			start_ots();
303		}
304		else if(btn_pressed_flag==10)
305		{
306			btn_pressed_flag=0;
307			btn_pressed_setup=BTNSETUP_START;
308			btn_count_setup=0;
309			alarmtimer(0, RUSHURGENT_PERIOD);
310		}
311	}
312#endif
313	if (btn_pressed_setup==BTNSETUP_NONE)
314	{
315#endif
316		if(!gpio_read("/dev/gpio/in", BTN_RESET)){
317			/*--------------- Add BTN_RST MFG test ------------------------*/
318			if(!nvram_match("asus_mfg", "")){
319				nvram_set("btn_rst", "1");
320			}
321			else{
322				if(!btn_pressed){
323					btn_pressed = 1;
324					btn_count = 0;
325					alarmtimer(0, URGENT_PERIOD); /* URGENT_PERIOD = 100*1000 microseconds */
326				}
327				else{	/* Whenever it is pushed steady */
328					if(++btn_count > RESET_WAIT_COUNT){
329						btn_pressed = 2;
330					}
331
332					if(btn_pressed == 2){
333						/* 0123456789 */
334						/* 0011100111 */
335						if((btn_count%10) < 1 ||
336								((btn_count%10) > 4 && (btn_count%10) < 7)){
337							LED_CONTROL(LED_POWER, LED_OFF);
338						}
339						else{
340							LED_CONTROL(LED_POWER, LED_ON);
341						}
342					}
343				}
344			} //end BTN_RST MFG test
345		}
346		else{
347			if(btn_pressed == 1){
348				btn_count = 0;
349				btn_pressed = 0;
350				LED_CONTROL(LED_POWER, LED_ON);
351				alarmtimer(NORMAL_PERIOD, 0);
352			}
353			else if(btn_pressed == 2){
354				LED_CONTROL(LED_POWER, LED_OFF);
355				alarmtimer(0, 0);
356				eval("erase", "/dev/mtd/3");
357				kill(1, SIGTERM);
358			}
359		}
360#ifdef BTN_SETUP
361	}
362
363	if (btn_pressed!=0) return;
364
365	if (btn_pressed_setup<BTNSETUP_START)
366	{
367		if (!gpio_read("/dev/gpio/in", BTN_SETUP))
368		{
369		   /* Add BTN_EZ MFG test */
370		   if (!nvram_match("asus_mfg", "")){
371			nvram_set("btn_ez", "1");
372		   }
373		   else{
374			if (btn_pressed_setup==BTNSETUP_NONE)
375			{
376				btn_pressed_setup=BTNSETUP_DETECT;
377				btn_count_setup=0;
378				alarmtimer(0, RUSHURGENT_PERIOD);/* RUSHURGENT_PERIOD = 50*1000 microseconds */
379			}
380			else {	/* Whenever it is pushed steady */
381				if( ++btn_count_setup > SETUP_WAIT_COUNT )//User must press button for more than 5 seconds.
382				{
383				   #ifdef WSC/* Cherry Cho modified in 2008/6/24. */
384				   if(WSC_ENABLED){
385						if(nvram_match("wsc_waiting", "1")
386						   && nvram_match("wsc_timer_start", "1")
387						   && nvram_match("wsc_method", "1")){
388							/* When PIN configuration is running, PBC can interrupt PIN.*/
389							nvram_set("wsc_config_command", "2");//Timeout PIN process immediately
390						}
391						else{
392							/* Run WSC Push Button to Get Configuration */
393							if(nvram_match("wsc_waiting", "0")
394							   &&nvram_match("wsc_timer_start", "0")){
395								nvram_set("wsc_method", "2");
396								nvram_set("wsc_pbc_force", "1");
397								nvram_set("wsc_proc_status", "0");//Reset value of wsc_proc_status
398								if(nvram_match("wsc_config_state", "0"))
399									nvram_set("wsc_asus_mode", "1");
400								else
401									btn_addER = 1;
402
403								btn_pressed_setup=BTNSETUP_START;
404								btn_count_setup=0;
405								alarmtimer(0, RUSHURGENT_PERIOD);
406							}
407						}
408				   }
409				   #endif
410				}
411			}
412		   } //end BTN_EZ MFG test
413		}
414		else if(btn_pressed_setup==BTNSETUP_DETECT)/* Cherry Cho modified in 2008/6/24. */
415		{
416			#ifdef WSC
417			if(WSC_ENABLED){/* Cherry Cho added in 2008/7/21. */
418				if(nvram_match("wsc_waiting", "1")//The PIN process is running.
419	   	   	   		&& nvram_match("wsc_timer_start", "1")
420	   	   	   		&& nvram_match("wsc_method", "1"))
421	   	   		{
422					nvram_set("wsc_config_command", "2");
423				}
424				else if(nvram_match("wsc_waiting", "0")
425						&& nvram_match("wsc_timer_start", "0"))
426				{
427					nvram_set("wsc_method", "2");
428					nvram_set("wsc_pbc_force", "1");
429					nvram_set("wsc_proc_status", "0");
430					btn_addER = 1;
431					btn_pressed_setup=BTNSETUP_START;
432					btn_count_setup=0;
433					alarmtimer(0, RUSHURGENT_PERIOD);
434				}
435			}
436			else/* WSC is not enabled. Cherry Cho added in 2008/7/21. */
437			{
438				btn_pressed_setup = BTNSETUP_START;
439				btn_count_setup = 0;
440			}
441			#endif
442		}
443	}
444	else /* Cherry Cho modified in 2008/1/15. */
445	{
446	    #ifdef WSC
447	    if(WSC_ENABLED){
448	    	if( !btn_addER && nvram_match("wsc_method","2")
449	    		&& nvram_match("wsc_config_state","0"))
450	    	{
451				++btn_count_setup;
452				btn_count_setup = btn_count_setup%20;
453
454				/* 0123456789 */
455				if ((btn_count_setup%2)==0&&(btn_count_setup>10)) LED_CONTROL(LED_POWER, LED_ON);
456				else LED_CONTROL(LED_POWER, LED_OFF);
457    		}
458   			else if( btn_addER && nvram_match("wsc_method","2") )
459   			{
460				++btn_count_setup;
461				btn_count_setup = btn_count_setup%6;
462
463	        	/* RUSHURGENT_PERIOD = 0.05 seconds
464			      	WPS in process: LED ON 0.2 seconds  LED OFF 0.1 seconds
465		  		   	LED: 0123 ON  45 OFF */
466				if (btn_count_setup<=3) LED_CONTROL(LED_POWER, LED_ON);
467				else LED_CONTROL(LED_POWER, LED_OFF);
468	    	}
469	    	else
470	    	{
471	    		/* Cherry Cho added in 2008/7/16. */
472	    		if( !wsc_success )//WPS process fails to complete.
473	    		{
474	    			if( led_count < led_count_timeout )
475	    			{
476	    				++btn_count_setup;
477	    				btn_count_setup = btn_count_setup%4;
478	    				if (btn_count_setup<=1) LED_CONTROL(LED_POWER, LED_ON);
479						else LED_CONTROL(LED_POWER, LED_OFF);
480						++led_count;
481					}
482					else
483					{
484						btn_pressed_setup = BTNSETUP_NONE;
485						btn_count_setup = 0;
486						LED_CONTROL(LED_POWER, LED_ON);
487						alarmtimer(NORMAL_PERIOD, 0);
488						led_count = 0;
489						wsc_success = 1;
490					}
491	    		}
492	    	}
493
494	    	/* +++ Cherry Cho added for PBC overlap in 2008/2/25. +++ */
495	    	if ((btn_pressed_setup==BTNSETUP_START) && !gpio_read("/dev/gpio/in", BTN_SETUP)
496	    	   	&& nvram_match("wsc_timer_start", "1")
497		    	&& nvram_match("wsc_waiting", "1")){
498	    		nvram_set("pbc_overlap", "1");
499	    	}
500	    	/* --- Cherry Cho added for PBC overlap in 2008/2/25. --- */
501	    }
502	    else /* WSC is not enabled. Cherry Cho added in 2008/7/21. */
503	    {
504	    	if( led_count < led_count_timeout )
505	    	{
506	    		++btn_count_setup;
507	    		btn_count_setup = btn_count_setup%2;
508	    		if (btn_count_setup ==1) LED_CONTROL(LED_POWER, LED_ON);
509				else LED_CONTROL(LED_POWER, LED_OFF);
510				++led_count;
511			}
512			else
513			{
514				btn_pressed_setup = BTNSETUP_NONE;
515				btn_count_setup = 0;
516				LED_CONTROL(LED_POWER, LED_ON);
517				alarmtimer(NORMAL_PERIOD, 0);
518				led_count = 0;
519			}
520	    }
521	    #endif
522	}
523#endif
524}
525
526void refresh_ntpc(void)
527{
528	eval("killall","ntpclient");
529	kill_pidfile_s("/var/run/ntp.pid", SIGUSR1);
530	//printf("Sync time %d.\n", sync_interval);
531}
532
533int ntp_timesync(void)
534{
535	time_t now;
536	struct tm tm;
537	struct tm gm, local;
538	struct timezone tz;
539
540	//if (nvram_match("router_disable", "1")) return 0;
541
542	if (sync_interval!=-1)
543	{
544        	sync_interval--;
545
546	    	if (sync_interval==0)
547		{
548			/* Update kernel timezone */
549			setenv("TZ", nvram_safe_get("time_zone_x"), 1);
550			time(&now);
551			gmtime_r(&now, &gm);
552			localtime_r(&now, &local);
553			tz.tz_minuteswest = (mktime(&gm) - mktime(&local)) / 60;
554			settimeofday(NULL, &tz);
555		   	memcpy(&tm, localtime(&now), sizeof(struct tm));
556
557		   	if (tm.tm_year>100) // More than 2000
558		   	{
559		      		sync_interval=60*60/5;
560			  	logmessage("ntp client", "time is synchronized to %s", nvram_safe_get("ntp_servers"));
561				stop_upnp();
562				start_upnp();
563		   	}
564		  	else sync_interval=1;
565
566			refresh_ntpc();
567		}
568	}
569}
570
571enum
572{
573	URLACTIVE=0,
574	WEBACTIVE,
575	RADIOACTIVE,
576	ACTIVEITEMS
577} ACTIVE;
578
579int svcStatus[ACTIVEITEMS] = { -1, -1, -1};
580int extStatus[ACTIVEITEMS] = { 0, 0, 0};
581char svcDate[ACTIVEITEMS][10];
582char *svcTime[ACTIVEITEMS][20];
583
584int timecheck_item(char *activeDate, char *activeTime)
585{
586	#define DAYSTART (0)
587	#define DAYEND (60*60*23+60*59+59) //86399
588	int current, active, activeTimeStart, activeTimeEnd, i;
589	time_t now;
590	struct tm *tm;
591
592	time(&now);
593	tm = localtime(&now);
594	current = tm->tm_hour*60 + tm->tm_min;
595
596	active=0;
597
598	//printf("active: %s %s\n", activeDate, activeTime);
599
600	activeTimeStart=((activeTime[0]-'0')*10+(activeTime[1]-'0'))*60 + (activeTime[2]-'0')*10 + (activeTime[3]-'0');
601
602	activeTimeEnd=((activeTime[4]-'0')*10+(activeTime[5]-'0'))*60 + (activeTime[6]-'0')*10 + (activeTime[7]-'0');
603
604	if (activeDate[tm->tm_wday] == '1')
605	{
606		if (activeTimeEnd<activeTimeStart)
607		{
608			if ((current>=activeTimeStart && current<=DAYEND) ||
609			   (current>=DAYSTART && current<=activeTimeEnd))
610			{
611				active = 1;
612			}
613			else
614			{
615				active = 0;
616			}
617		}
618		else
619		{
620			if (current>=activeTimeStart &&
621		     	current<=activeTimeEnd)
622			{
623				active = 1;
624			}
625			else
626			{
627				active = 0;
628			}
629		}
630	}
631	return(active);
632}
633
634/* Check for time-dependent service 	*/
635/* 1. URL filter 			*/
636/* 2. WEB Camera Security filter 	*/
637int svc_timecheck(void)
638{
639	int activeFlag, activeNow;
640
641	activeFlag = 0;
642
643	/* Initialize */
644	if (svcStatus[URLACTIVE]==-1 && nvram_invmatch("url_enable_x", "0"))
645	{
646		strcpy(svcDate[URLACTIVE], nvram_safe_get("url_date_x"));
647		strcpy(svcTime[URLACTIVE], nvram_safe_get("url_time_x"));
648		svcStatus[URLACTIVE] = -2;
649	}
650
651	if (svcStatus[URLACTIVE]!=-1)
652	{
653		activeNow = timecheck_item(svcDate[URLACTIVE], svcTime[URLACTIVE]);
654		if (activeNow!=svcStatus[URLACTIVE])
655		{
656			//printf("url time change: %d\n", activeNow);
657			svcStatus[URLACTIVE] = activeNow;
658			stop_dns();
659			start_dns();
660		}
661	}
662
663	if (svcStatus[WEBACTIVE]==-1 &&
664		nvram_invmatch("usb_webenable_x", "0") &&
665		nvram_invmatch("usb_websecurity_x", "0"))
666	{
667		strcpy(svcDate[WEBACTIVE], nvram_safe_get("usb_websecurity_date_x"));
668		strcpy(svcTime[WEBACTIVE], nvram_safe_get("usb_websecurity_time_x"));
669		svcStatus[WEBACTIVE] = -2;
670	}
671
672	if (svcStatus[WEBACTIVE]!=-1)
673	{
674		activeNow = timecheck_item(svcDate[WEBACTIVE], svcTime[WEBACTIVE]);
675		if (activeNow!=svcStatus[WEBACTIVE])
676		{
677			svcStatus[WEBACTIVE] = activeNow;
678
679			if (!notice_rcamd(svcStatus[WEBACTIVE])) svcStatus[WEBACTIVE]=-1;
680		}
681	}
682
683	if (svcStatus[RADIOACTIVE]==-1 && nvram_invmatch("wl_radio_x", "0"))
684	{
685		strcpy(svcDate[RADIOACTIVE], nvram_safe_get("wl_radio_date_x"));
686		strcpy(svcTime[RADIOACTIVE], nvram_safe_get("wl_radio_time_x"));
687		svcStatus[RADIOACTIVE] = -2;
688	}
689
690	if (svcStatus[RADIOACTIVE]!=-1)
691	{
692		activeNow = timecheck_item(svcDate[RADIOACTIVE], svcTime[RADIOACTIVE]);
693		if (activeNow!=svcStatus[RADIOACTIVE])
694		{
695			svcStatus[RADIOACTIVE] = activeNow;
696
697			if (activeNow)
698			{
699				eval("wl", "radio", "on");
700				wl_led_ctrl(1);
701			}
702			else
703			{
704				eval("wl", "radio", "off");
705				wl_led_ctrl(0);
706			}
707		}
708	}
709
710	return 0;
711}
712
713/* Sometimes, httpd becomes inaccessible, try to re-run it */
714int http_processcheck(void)
715{
716	//char http_cmd[32];
717	char buf[256];
718
719	//sprintf(http_cmd, "http://127.0.0.1/");
720	if(
721#ifdef DLM
722			!nvram_match("usb_storage_busy2", "1") &&
723#endif
724#ifdef ASUS_DDNS //2007.03.27 Yau add for prevent httpd die when doing hostname check
725			!nvram_match("httpd_check_ddns", "1") &&
726#endif
727			//!http_check(http_cmd, buf, sizeof(buf), 0))
728			!http_check(NULL, buf, sizeof(buf), 0))
729	{
730		dprintf("http rerun\n");
731		kill_pidfile("/var/run/httpd.pid");
732		if(nvram_match("httpd_die_reboot", "1")){
733			nvram_set("httpd_die_reboot", "");
734			eval("reboot");
735
736			return 0;
737		}
738		//stop_httpd();
739		start_httpd();
740	}
741
742	/*if(nvram_invmatch("usb_webdriver_x", "") &&
743			nvram_invmatch("usb_webdriver_x", "0"))
744	{
745		//sprintf(http_cmd, "http://127.0.0.1:%s/", nvram_safe_get("usb_webhttpport_x"));
746		//logmessage("webcam", "webcam httpd die checking %s\n", http_cmd);
747
748		if(
749#ifdef DLM
750				!nvram_match("usb_storage_busy2", "1") &&
751#endif
752#ifdef ASUS_DDNS //2007.03.27 Yau add for prevent httpd die when doing hostname check
753				!nvram_match("httpd_check_ddns", "1") &&
754#endif
755				//!http_check(http_cmd, buf, sizeof(buf), 0))
756				!http_check(NULL, buf, sizeof(buf), 0))
757		{
758			dprintf("http rerun\n");
759			sprintf(buf, "/var/run/httpd-%s.pid", nvram_safe_get("usb_webhttpport_x"));
760			kill_pidfile(buf);
761			//logmessage("webcam", "webcam httpd rerun\n");
762
763			chdir("/tmp/webcam");
764			eval("httpd", nvram_safe_get("wan0_ifname"), nvram_safe_get("usb_webhttpport_x"));
765			chdir("/");
766		}
767	}*/
768
769	return 0;
770}
771
772/* While radius auth fails, wireless is down. We need to retry the auth */
773int nas_processcheck()
774{
775	FILE *fp;
776	char cfgfile[64];
777	char pidfile[64];
778
779	snprintf(cfgfile, sizeof(cfgfile), "/tmp/nas.%s.conf", "lan");
780	snprintf(pidfile, sizeof(pidfile), "/tmp/nas.%s.pid", "lan");
781
782	fp = fopen(pidfile, "r");
783	if(fp != NULL){
784		fclose(fp);
785		return 0;
786	}
787
788	char *argv[] = {"nas", cfgfile, pidfile, "lan", NULL};
789	pid_t pid;
790
791	syslog(LOG_NOTICE, "Radius server authentication failed.");
792	syslog(LOG_NOTICE, "Please check the settings of radius server are correct and the radius server is available.");
793	syslog(LOG_NOTICE, "Router would try to authenticate again in seconds.");
794	sleep(5);
795	_eval(argv, NULL, 0, &pid);
796
797	return 0;
798}
799
800
801#ifdef USB_SUPPORT
802char usbinterrupt[128];
803
804int rcamd_processcheck()
805{
806	FILE *fp;
807	char buf[128];
808	int flag=1;
809
810	fp = fopen("/proc/interrupts", "r");
811
812	if (fp!=NULL)
813	{
814		while(fgets(buf, sizeof(buf), fp))
815		{
816#ifdef WL500GX
817			if (strstr(buf, "ehci"))
818#else
819			if (strstr(buf, "ohci"))
820#endif
821			{
822				//logmessage("web camera", buf);
823
824//				if (strcmp(usbinterrupt, buf)==0) flag=0;
825//				strcpy(usbinterrupt, buf);
826//				break;
827			}
828		}
829		fclose(fp);
830	}
831	return flag;
832}
833#endif
834
835int notice_rcamd(int flag)
836{
837	 int rcamdpid=-1;
838	 //printf("Send signal : %d %d\n", rcamdpid, flag);
839	 if (rcamdpid==-1)
840	 {
841			FILE *fp;
842
843			if ((fp=fopen("/var/run/rcamd.pid","r"))!=NULL)
844			{
845				fscanf(fp,"%d", &rcamdpid);
846				fclose(fp);
847			}
848	 }
849	 if (rcamdpid!=-1)
850	 {
851		 if (flag)
852			kill(rcamdpid, SIGUSR1);
853		 else
854			kill(rcamdpid, SIGUSR2);
855
856		 return 1;
857	 }
858	 return 0;
859}
860
861int refresh_rcamd(void)
862{
863	FILE *fp;
864	int rcamdpid=-1;
865
866	if ((fp=fopen("/var/run/rcamd.pid","r"))!=NULL)
867	{
868		fscanf(fp,"%d", &rcamdpid);
869		fclose(fp);
870		unlink("/var/run/rcamd.pid");
871		kill(rcamdpid, SIGUSR1);
872	}
873	else
874	{
875		eval("killall", "rcamd");
876	}
877
878	if ((fp=fopen("/var/run/rcamdmain.pid","r"))!=NULL)
879	{
880		fscanf(fp,"%d", &rcamdpid);
881		fclose(fp);
882		kill(rcamdpid, SIGUSR1);
883	}
884	return 0;
885}
886
887int refresh_wave(void)
888{
889	FILE *fp;
890	int wavepid=-1;
891
892	eval("killall", "waveserver");
893
894	if ((fp=fopen("/var/run/waveservermain.pid","r"))!=NULL)
895	{
896		fscanf(fp,"%d", &wavepid);
897		fclose(fp);
898		kill(wavepid, SIGUSR1);
899	}
900	return 0;
901}
902
903static void catch_sig(int sig)
904{
905	if (sig == SIGUSR1)
906	{
907		dprintf("Catch Reset to Default Signal\n");
908		//sys_default();
909		//set_pid(getpid());
910	}
911	else if (sig == SIGUSR2)
912	{
913		FILE *fp;
914		char command[256], *cmd_ptr;
915
916		dprintf("Get Signal: %d %d %d\n", svcStatus[WEBACTIVE], extStatus[WEBACTIVE], sig);
917
918		if (!svcStatus[WEBACTIVE]) return;
919
920		if (extStatus[WEBACTIVE]==0)
921		{
922			fp = fopen("/var/tmp/runshell", "r+");
923			if (fp!=NULL)
924			{
925				cmd_ptr = fgets(command, 256, fp);
926
927				if (cmd_ptr!=NULL) system(command);
928			}
929			fclose(fp);
930			unlink("/tmp/runshell");
931			notice_rcamd(0);
932			extStatus[WEBACTIVE]=1;
933		}
934		else if (svcStatus[WEBACTIVE]==1)
935		{
936			notice_rcamd(1);
937			extStatus[WEBACTIVE] = 0;
938		}
939	}
940#ifdef WSC
941	else if (sig == SIGTSTP)
942	{
943		switch(atoi(nvram_safe_get("wsc_sigtstp_case"))){
944			case 1:/* Cherry Cho added in 2008/7/2. */
945				if( btn_pressed_setup!=BTNSETUP_START &&
946					nvram_match("wsc_client_role", "enrollee") &&
947					!strcmp(nvram_safe_get("wsc_method"), "2") )
948				{
949					btn_pressed_setup=BTNSETUP_START;
950					btn_count_setup=0;
951					alarmtimer(0, RUSHURGENT_PERIOD);
952					btn_addER = 1;
953				}
954				break;
955
956			case 2:/* WPS process successfully completes. Added for stopping LED twinkle. Cherry Cho added in 2008/2/12. */
957				if( ( btn_pressed_setup==BTNSETUP_START )/* Reset variables when WSC process terminates. */
958	 	   	     	&& nvram_match("wsc_proc_status","2") )
959	 	   	    {
960					btn_pressed_setup = BTNSETUP_NONE;
961					btn_count_setup = 0;
962					LED_CONTROL(LED_POWER, LED_ON);
963					alarmtimer(NORMAL_PERIOD, 0);
964					if(btn_addER)
965						btn_addER = 0;
966					wsc_success = 1;
967				}
968				break;
969
970			case 3:/* Restart nas. Cherry Cho added in 2008/7/8. */
971				syslog(LOG_NOTICE, "WSC: send signal to watchdog and restart nas.");
972				eval("wlconf", "eth1", "up");
973				start_wsc();
974				start_nas("lan");
975				break;
976
977			case 4:/* WPS process fails to complete. Cherry Cho added in 2008/7/16.*/
978				if(( btn_pressed_setup==BTNSETUP_START )/* Reset variables when WSC process terminates. */
979	 	   	     	&& ( nvram_match("wsc_proc_status","3") || nvram_match("wsc_proc_status","4") ))
980	 	   	    {
981	 	   	    	if(btn_addER)
982						btn_addER = 0;
983					wsc_success = 0;
984	 	   		}
985	 	   		break;
986
987			default:
988				break;
989		}
990	}
991#endif
992}
993
994void sta_check(void)
995{
996	int ret;
997	char *wl_ifname=nvram_safe_get("wl0_ifname");
998	char bssid[32];
999
1000	if (stacheck_interval==-1)
1001	{
1002		if (nvram_invmatch("wl0_mode", "sta") &&
1003            		nvram_invmatch("wl0_mode", "wet")) return;
1004
1005		stacheck_interval=STACHECK_PERIOD_DISCONNECT;
1006	}
1007
1008	stacheck_interval--;
1009
1010	if (stacheck_interval)
1011		return;
1012
1013	// Get bssid
1014	ret=wl_ioctl(wl_ifname, WLC_GET_BSSID, bssid, sizeof(bssid));
1015	if (ret==0 && !(bssid[0]==0&&bssid[1]==0&&bssid[2]==0
1016		&&bssid[3]==0&&bssid[4]==0&&bssid[5]==0))
1017	{
1018		dprintf("connected\n");
1019		stacheck_interval=STACHECK_PERIOD_CONNECT;
1020	}
1021	else
1022	{
1023		dprintf("disconnected\n");
1024		stacheck_interval=STACHECK_PERIOD_DISCONNECT;
1025		dprintf("connect: [%s]\n", nvram_safe_get("wl0_join"));
1026		system(nvram_safe_get("wl0_join"));
1027		//eval("wl", "join", nvram_safe_get("wl0_ssid"));
1028	}
1029	return;
1030}
1031
1032// 2009.12 James. {
1033#ifdef WSC
1034#define MAX_PIN_INTERVAL 120	// almost 2 mins.
1035int wps_pin_interval = 0;
1036#endif
1037// 2009.12 James. }
1038
1039/* wathchdog is runned in NORMAL_PERIOD, 1 seconds
1040 * check in each NORMAL_PERIOD
1041 *	1. button
1042 *
1043 * check in each NORAML_PERIOD*5
1044 *
1045 *      1. ntptime,
1046 *      2. time-dependent service
1047 *      3. http-process
1048 *      4. usb hotplug status
1049 */
1050void watchdog(void)
1051{
1052	time_t now;
1053
1054	/* handle button */
1055	btn_check();
1056
1057// 2009.12 James. {
1058#ifdef WSC
1059	if(nvram_match("wsc_method", "1") && nvram_match("wsc_proc_status", "1")){
1060		if(wps_pin_interval < MAX_PIN_INTERVAL)
1061			++wps_pin_interval;
1062		else{
1063			wps_pin_interval = 0;
1064			nvram_set("wsc_config_command", "2"); // Be timeout and turned off PIN process immediately.
1065		}
1066	}
1067#endif
1068// 2009.12 James. }
1069
1070#ifdef WCN
1071	if(nvram_match("reboot_WCN", "1"))
1072	{
1073		++reboot_WCN_count;
1074
1075		if(reboot_WCN_count>=50)
1076			kill(1, SIGTERM);
1077		else
1078			return;
1079	}
1080	else if(nvram_match("reboot_WCN", "2"))
1081	{
1082		nvram_commit();
1083		alarmtimer(0, QUICK_PERIOD);
1084		wcn_on=1;
1085		nvram_set("reboot_WCN", "1");
1086		return;
1087	}
1088#endif
1089
1090	/* if timer is set to less than 1 sec, then bypass the following */
1091	if (itv.it_value.tv_sec==0) return;
1092
1093#if 0
1094	if (nvram_match("eject_from_web", "1"))
1095	{
1096		nvram_set("eject_from_web", "0");
1097		eval("run_ftpsamba");
1098	}
1099#endif
1100	// reboot signal checking
1101	if(nvram_match("reboot", "1"))
1102	{
1103		++reboot_count;
1104		if(reboot_count>=2) kill(1, SIGTERM);
1105	}
1106	else if(nvram_match("reboot", "0")) return;
1107
1108	watchdog_period = (watchdog_period+1)%10;
1109
1110	if(watchdog_period) return;
1111
1112	time(&now);
1113
1114#ifdef BTN_SETUP
1115	if (btn_pressed_setup>=BTNSETUP_START) return;
1116#endif
1117	//printf("now: %d\n", (long )now);
1118	/* sync time to ntp server if necessary */
1119	ntp_timesync();
1120
1121	/* check for time-dependent services */
1122	svc_timecheck();
1123
1124	/* http server check */
1125#ifdef DLM
1126	if (!nvram_match("usb_storage_busy2", "1"))
1127#endif
1128		http_processcheck();
1129
1130	/* nas check for radius fail auth */
1131	if (int_nas_enable){
1132		if(nas_check_interval > 7){
1133			nas_check_interval = 0;
1134			nas_processcheck();
1135		}
1136		else
1137			++nas_check_interval;
1138	}
1139
1140#ifdef USB_SUPPORT
1141
1142	/* web cam process */
1143	if (!nvram_match("usb_web_device", ""))
1144	{
1145		if (!nvram_match("usb_webdriver_x", ""))
1146		{
1147			if (!rcamd_processcheck())
1148			{
1149				refresh_rcamd();
1150			}
1151		}
1152		else
1153		{
1154			//hotplug_usb_webcam(nvram_safe_get("usb_web_device"),
1155			//	   atoi(nvram_safe_get("usb_web_flag")));
1156			//nvram_set("usb_web_device", "");
1157			//nvram_set("usb_web_flag", "");
1158			// reset WEBCAM status
1159			refresh_rcamd();
1160			svcStatus[WEBACTIVE] = -1;
1161		}
1162	}
1163
1164	/* storage process */
1165// 2007.12 James {
1166	char *remove_disk = nvram_safe_get("usb_storage_device_remove");
1167	char *add_disk = nvram_safe_get("usb_storage_device");
1168
1169	if(strlen(remove_disk) > 0){
1170printf("*** start to remove usb disk. ***\n");
1171		nvram_set("usb_storage_busy", "1");	// 2007.12 James
1172		remove_usb_mass(remove_disk);
1173		nvram_set("usb_storage_busy", "0");	// 2007.12 James
1174printf("*** end to remove usb disk. ***\n");
1175	}
1176	else if(strlen(add_disk) > 0){
1177printf("*** start to add usb disk. ***\n");
1178		nvram_set("usb_storage_busy", "1");	// 2007.12 James
1179		hotplug_usb_mass(add_disk);
1180		nvram_set("usb_storage_busy", "0");	// 2007.12 James
1181printf("*** end to add usb disk. ***\n");
1182	}
1183// 2007.12 James }
1184
1185#endif
1186
1187	/* station or ethernet bridge handler */
1188	sta_check();
1189
1190#ifdef CDMA
1191	if(!nvram_match("hsdpa_product", "")){
1192		/*
1193		 * cdma_down = 99, none
1194		 * cdma_down = 1, currently down
1195		 * cdma_down = 2, currently up
1196		 * cdma_down = 3, Stop
1197		 * cdma_down = 0, currently trying to connect
1198		 */
1199		if (nvram_match("cdma_down", "1"))
1200		{
1201			logmessage("CDMA client", "USB Modem was down(%d)!", cdma_down); // HSDPA
1202
1203			++cdma_down;
1204			cdma_connect=0;
1205
1206			//if(cdma_down==2)
1207			if(cdma_down==1)
1208			{
1209				stop_wan();
1210				start_wan();
1211			}
1212			else if(cdma_down >= 2) // 20 seconds timeout for retry
1213			{
1214				cdma_down=0;
1215			}
1216		}
1217		else if(nvram_match("cdma_down", "0"))
1218		{
1219			//if(cdma_connect%3==0) // HSDPA
1220				logmessage("CDMA client", "USB Modem: Try to connect(%d)!", cdma_connect+1); // HSDPA
1221			cdma_down=0;
1222			++cdma_connect;
1223
1224			if(cdma_connect >= 2) /* 20 seconds timeout for connecting */ // HSDPA
1225			{
1226				nvram_set("cdma_down", "1");
1227			}
1228		}
1229		else if (nvram_match("cdma_down", "3"))
1230		{
1231			//logmessage("CDMA client", "USB Modem is down(%d)!", cdma_down); // HSDPA
1232			eval("killall", "chat");
1233			eval("killall", "pppd");
1234		}
1235		else
1236		{
1237			cdma_down=0;
1238			cdma_connect=0;
1239		}
1240	} // 2009.09 James.
1241#endif
1242}
1243
1244int
1245gpio_main(int ledin)
1246{
1247#ifdef BTN_SETUP
1248	printf("BTN:%d,%d\n", gpio_read("/dev/gpio/in", BTN_RESET), gpio_read("/dev/gpio/in", BTN_SETUP));
1249#else
1250	printf("BTN:%d,0\n", gpio_read("/dev/gpio/in", BTN_RESET));
1251#endif
1252}
1253
1254int
1255watchdog_main(int argc, char *argv[])
1256{
1257	FILE *fp;
1258#ifdef WSC/* Cherry Cho added in 2008/7/16. */
1259	WSC_ENABLED = nvram_match("wsc_mode", "enabled");
1260#endif
1261
1262#ifdef REMOVE
1263	/* Run it under background */
1264	switch (fork()) {
1265	case -1:
1266		exit(0);
1267		break;
1268	case 0:
1269		// start in a new session
1270		(void) setsid();
1271		break;
1272	default:
1273		/* parent process should just die */
1274		_exit(0);
1275	}
1276#endif
1277
1278	/* write pid */
1279	if ((fp=fopen("/var/run/watchdog.pid", "w"))!=NULL)
1280	{
1281		fprintf(fp, "%d", getpid());
1282		fclose(fp);
1283	}
1284
1285	/* set the signal handler */
1286	signal(SIGUSR1, catch_sig);
1287	signal(SIGUSR2, catch_sig);
1288	signal(SIGTSTP, catch_sig);/* Cherry Cho added in 2008/2/12 */
1289	signal(SIGALRM, watchdog);
1290
1291	/* Start GPIO function */
1292	gpio_init();
1293
1294	/* Start POWER LED */
1295	LED_CONTROL(LED_POWER, LED_ON);
1296// MFG test LED off for MFG USB test
1297//	LED_CONTROL(LED_POWER, LED_OFF);
1298//end MFG
1299
1300	/* Start sync time */
1301	sync_interval=1;
1302	start_ntpc();
1303
1304#ifdef BTN_SETUP
1305	if (!nvram_match("sharedkeystr", ""))
1306	{
1307		printf("Debug::sharedkeystr=%s\n", nvram_get("sharedkeystr"));
1308		++btn_pressed_flag;
1309		btn_stage=1;
1310	}
1311	nvram_set("bs_mode", "");
1312#endif
1313
1314	/* nas check for radius fail auth */
1315	if(nvram_match("wl0_akm", "wpa" )	// WPA-Enterprise
1316			|| nvram_match("wl0_akm", "wpa2" )	// WPA2-Enterprise
1317			|| nvram_match("wl0_akm", "wpa wpa2" )	// WPA-Auto-Enterprise
1318			|| nvram_match("wl0_auth_mode", "radius" ) // Radius with 802.1x
1319			)
1320		int_nas_enable = 1;
1321
1322	/* set timer */
1323	alarmtimer(NORMAL_PERIOD, 0);
1324
1325	/* Most of time it goes to sleep */
1326	while(1)
1327	{
1328		pause();
1329	}
1330
1331	return 0;
1332}
1333
1334#define LED_RADIO GPIO1
1335
1336void wl_led_ctrl(int ctrl)
1337{
1338	int led;
1339	if (!ctrl)
1340	{
1341		gpio_write("/dev/gpio/out", LED_RADIO, !ctrl);
1342		led=0;
1343		wl_ioctl("eth2", WLC_SET_LED, &led, sizeof(led));
1344	}
1345	else
1346	{
1347		tgpio_fd_init();
1348		tgpio_ioctl(BCMGPIO_REG_RELEASE, LED_RADIO, LED_RADIO);
1349		tgpio_fd_cleanup();
1350	}
1351}
1352
1353int radio_main(int ctrl)
1354{
1355	if (ctrl)
1356	{
1357		eval("wl", "radio", "on");
1358		wl_led_ctrl(1);
1359	}
1360	else
1361	{
1362		eval("wl", "radio", "off");
1363		wl_led_ctrl(0);
1364	}
1365}
1366