source: src/router/rc/resetbutton.c @ 7535

Last change on this file since 7535 was 7535, checked in by eko, 6 years ago

update for current WHR branch

File size: 12.9 KB
Line 
1/*
2 */
3
4#include <stdio.h>
5#include <signal.h>
6#include <sys/time.h>
7#include <unistd.h>
8#include <stdlib.h>
9#include <sys/types.h>
10#include <string.h>
11#include <bcmnvram.h>
12#include <shutils.h>
13#include <utils.h>
14#include <rc.h>
15#include <stdarg.h>
16#include <dirent.h>
17#include <syslog.h>
18
19
20
21#define SES_LED_CHECK_TIMES     "9999"  /* How many times to check? */
22#define SES_LED_CHECK_INTERVAL  "1"     /* Wait interval seconds */
23#define RESET_WAIT              1       /* seconds */
24#define RESET_WAIT_COUNT        RESET_WAIT * 10 /* 10 times a second */
25
26#define NORMAL_INTERVAL         1       /* second */
27#define URGENT_INTERVAL         100 * 1000      /* microsecond */
28
29#ifndef HAVE_GATEWORX           /* 1/10 second */
30#define GPIO_FILE               "/dev/gpio/in"
31#endif
32#if 0
33#define DEBUG printf
34#else
35#define DEBUG(format, args...)
36#endif
37
38
39
40#ifdef HAVE_MAGICBOX
41#include <sys/mman.h>
42
43#define GPIO0_OR   0x0700       /* rw, output */
44#define GPIO0_TCR  0x0704       /* rw, three-state control */
45#define GPIO0_ODR  0x0718       /* rw, open drain */
46#define GPIO0_IR   0x071c       /* ro, input */
47#define GPIO0_BASE 0xef600000   /* page */
48
49#define GPIO_LED    0x20000000  /* GPIO1 */
50#define GPIO_BUTTON 0x40000000  /* GPIO2 */
51
52#define REG(buf, offset) ((unsigned int *)((void *)buf + offset))
53
54static unsigned int *page;
55static int fd;
56
57void
58init_gpio ()
59{
60  void *start = 0;
61
62  fd = open ("/dev/mem", O_RDWR);
63  if (fd < 0)
64    {
65//        syslog(LOG_ERR, "Can't open /dev/mem: %s", strerror(errno));
66      exit (1);
67    }
68
69  page = mmap (start, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
70               (off_t) GPIO0_BASE);
71  if (page == MAP_FAILED)
72    {
73//        syslog(LOG_ERR, "Can't mmap GPIO memory space: %s", strerror(errno));
74      exit (1);
75    }
76
77  /* disable */
78  *REG (page, GPIO0_TCR) &= ~(GPIO_LED | GPIO_BUTTON);
79  /* enable led */
80  *REG (page, GPIO0_TCR) |= GPIO_LED | GPIO_BUTTON;
81  /* enable/disable(?) button */
82  *REG (page, GPIO0_TCR) &= ~GPIO_BUTTON;
83
84  *REG (page, GPIO0_IR) & GPIO_BUTTON;
85  *REG (page, GPIO0_IR) & GPIO_BUTTON;
86
87}
88
89int
90getbuttonstate ()
91{
92  return (*REG (page, GPIO0_IR) & GPIO_BUTTON) == 0;
93
94}
95#endif
96
97#if defined(HAVE_FONERA) || defined(HAVE_WHRAG108) || defined(HAVE_LS2) || defined(HAVE_CA8)
98int
99getbuttonstate ()
100{
101  FILE *in;
102  int ret;
103  in = fopen ("/proc/gpio/6_in", "rb");
104  if (in == NULL)
105    return 0;
106  fscanf (in, "%d", &ret);
107  fclose (in);
108  return ret;
109}
110#endif
111#if defined(HAVE_GATEWORX)
112
113#define u8 unsigned char
114#define u32 unsigned long
115
116//#include <linux/ixp425-gpio.h>
117
118#include <include/asm/hardware.h>
119#include <include/asm-arm/arch-ixp4xx/ixp4xx-regs.h>
120
121#define IXP4XX_GPIO_OUT                 0x1
122#define IXP4XX_GPIO_IN                  0x2
123
124struct gpio_bit
125{
126  unsigned char bit;
127  unsigned char state;
128};
129
130
131
132char *filename = "/dev/gpio";
133
134
135int
136read_bit (int bit)
137{
138  int file;
139  struct gpio_bit _bit;
140
141  /* open device */
142  if ((file = open (filename, O_RDONLY)) == -1)
143    {
144      /* ERROR HANDLING; you can check errno to see what went wrong */
145      return 1;
146    }
147
148  /* Config pin as input */
149  _bit.bit = bit;
150  _bit.state = IXP4XX_GPIO_IN;
151  if (ioctl (file, GPIO_SET_CONFIG, (long) &_bit) < 0)
152    {
153      /* ERROR HANDLING; you can check errno to see what went wrong */
154      return 1;
155    }
156
157  /* Read data */
158  _bit.bit = bit;
159  if (ioctl (file, GPIO_GET_BIT, (long) &_bit) < 0)
160    {
161      /* ERROR HANDLING; you can check errno to see what went wrong */
162      return 1;
163    }
164
165  close (file);
166  return _bit.state;
167}
168
169int
170getbuttonstate ()
171{
172  FILE *in;
173  int ret = read_bit (4);
174  return ret == 0 ? 1 : 0;
175}
176#endif
177
178
179static int mode = 0;            /* mode 1 : pushed */
180static int ses_mode = 0;        /* mode 1 : pushed */
181static int count = 0;
182
183static int brand;
184
185static void
186alarmtimer (unsigned long sec, unsigned long usec)
187{
188  struct itimerval itv;
189
190  itv.it_value.tv_sec = sec;
191  itv.it_value.tv_usec = usec;
192
193  itv.it_interval = itv.it_value;
194  setitimer (ITIMER_REAL, &itv, NULL);
195}
196
197int
198endswith (char *str, char *cmp)
199{
200  int cmp_len, str_len, i;
201  cmp_len = strlen (cmp);
202  str_len = strlen (str);
203  if (cmp_len > str_len)
204    return (0);
205  for (i = 0; i < cmp_len; i++)
206    {
207      if (str[(str_len - 1) - i] != cmp[(cmp_len - 1) - i])
208        return (0);
209    }
210  return (1);
211}
212
213void
214runStartup (char *folder, char *extension)
215{
216  struct dirent *entry;
217  DIR *directory;
218  unsigned char buf[128];
219  directory = opendir (folder);
220  if (directory == NULL)
221    {
222      return;
223    }
224//list all files in this directory
225  while ((entry = readdir (directory)) != NULL)
226    {
227      if (endswith (entry->d_name, extension))
228        {
229          sprintf (buf, "%s/%s&\n", folder, entry->d_name);
230          //execute script     
231          system (buf);
232        }
233    }
234  closedir (directory);
235}
236
237/*
238void system_reboot(void)
239{
240        DEBUG("resetbutton: reboot\n");
241        alarmtimer(0, 0);
242        eval("reboot");
243}
244*/
245
246void
247service_restart (void)
248{
249  DEBUG ("resetbutton: restart\n");
250  /* Stop the timer alarm */
251  alarmtimer (0, 0);
252  /* Reset the Diagnostic LED */
253  diag_led (DIAG, START_LED);   /* call from service.c */
254  /* Restart all of services */
255  eval ("rc", "restart");
256}
257
258
259void
260period_check (int sig)
261{
262  FILE *fp;
263  unsigned int val = 0;
264//      time_t t;
265
266//      time(&t);
267//      DEBUG("resetbutton: now time=%d\n", t);
268
269#if defined(HAVE_MAGICBOX) || defined(HAVE_FONERA) || defined(HAVE_WHRAG108) || defined(HAVE_GATEWORX) || defined(HAVE_LS2) || defined(HAVE_CA8)
270  val = getbuttonstate ();
271#else
272  if ((fp = fopen (GPIO_FILE, "r")))
273    {
274#ifdef HAVE_XSCALE
275      fscanf (fp, "%d", &val);
276#else
277      fread (&val, 4, 1, fp);
278#endif
279      fclose (fp);
280    }
281  else
282    perror (GPIO_FILE);
283#endif
284  DEBUG ("resetbutton: GPIO = 0x%x\n", val);
285
286  int gpio = 0;
287
288  int state = 0;
289#if defined(HAVE_XSCALE) || defined(HAVE_MAGICBOX) || defined(HAVE_FONERA) || defined(HAVE_WHRAG108) || defined(HAVE_GATEWORX) || defined(HAVE_LS2) || defined(HAVE_CA8)
290  state = val;
291#else
292  if ((brand & 0x000f) != 0x000f)
293    gpio = 1 << (brand & 0x000f);       //calculate gpio value.
294
295  if ((brand & 0x0010) == 0)    //check reset button polarity: 0 normal, 1 inversed
296    state = (val & gpio);
297  else
298    state = !(val & gpio);
299
300/* 1 byte router's SES (AOSS) button gpio number and polarity; Eko 25.nov.06
301
302  R R R P N N N N   = 0xXX
303  ----- - -------
304    |   | gpio num (1111 = f = disable SES (AOSS) button)
305    |   |
306    |   |--- SES - AOSS button polarity (0: normal, 1 inversed)
307    |
308    |-------- reserved for future use
309*/
310  int push;
311  int sesgpio;
312  switch (brand)
313    {
314    case ROUTER_BUFFALO_WHRG54S:
315    case ROUTER_BUFFALO_WZRRSG54:
316    case ROUTER_BUFFALO_WLI_TX4_G54HP:
317      sesgpio = 0x10;           //gpio 0, inversed
318      break;
319    case ROUTER_BUFFALO_WLA2G54C:
320      sesgpio = 0x12;           //gpio 2, inversed
321      break;
322    case ROUTER_BUFFALO_WBR2G54S:     
323      sesgpio = 0x04;           //gpio 4, normal
324      break;     
325#ifndef HAVE_BUFFALO     
326    case ROUTER_WRT54G:
327    case ROUTER_WRT300N:
328      sesgpio = 0x14;           //gpio 4, inversed
329      break;
330    case ROUTER_ASUS_WL500G_PRE:
331    case ROUTER_WRT150N:
332      sesgpio = 0x04;           //gpio 4, normal
333      break;
334    case ROUTER_WRT350N:
335      sesgpio = 0x18;           //gpio 8, inversed
336      break;
337#endif
338    default:
339      sesgpio = 0x0f;           //gpio unknown, disabled
340    }
341
342  push = 1 << (sesgpio & 0x0f); //calculate push value from ses gpio pin no.
343
344#endif
345  /*  The value is zero during button-pushed. */
346  if (state)
347    {
348      DEBUG ("resetbutton: mode=%d, count=%d\n", mode, count);
349
350      if (mode == 0)
351        {
352          /* We detect button pushed first time */
353          alarmtimer (0, URGENT_INTERVAL);
354          mode = 1;
355        }
356      {                         /* Whenever it is pushed steady */
357        if (++count > RESET_WAIT_COUNT)
358          {
359            if (check_action () != ACT_IDLE)
360              {                 // Don't execute during upgrading
361                fprintf (stderr, "resetbutton: nothing to do...\n");
362                alarmtimer (0, 0);      /* Stop the timer alarm */
363                return;
364              }
365            if ((brand & 0x000f) != 0x000f)
366              {
367                printf ("resetbutton: factory default.\n");
368                syslog (LOG_DEBUG,
369                        "Reset button: restoring factory defaults now!\n");
370#if !defined(HAVE_XSCALE) && !defined(HAVE_MAGICBOX) && !defined(HAVE_FONERA) && !defined(HAVE_WHRAG108) && !defined(HAVE_GATEWORX) && !defined(HAVE_LS2) && !defined(HAVE_CA8)
371                led_control (LED_DIAG, LED_ON);
372#endif
373                ACTION ("ACT_HW_RESTORE");
374                alarmtimer (0, 0);      /* Stop the timer alarm */
375#ifdef HAVE_X86
376                eval ("mount", "/usr/local", "-o", "remount,rw");
377                eval ("rm", "-f", "/tmp/nvram/*");      // delete nvram database
378                eval ("rm", "-f", "/tmp/nvram/.lock");  // delete nvram database
379                eval ("rm", "-f", "/usr/local/nvram/*");        // delete nvram database
380                eval ("mount", "/usr/local", "-o", "remount,ro");
381#elif HAVE_RB500
382                eval ("rm", "-f", "/tmp/nvram/*");      // delete nvram database
383                eval ("rm", "-f", "/tmp/nvram/.lock");  // delete nvram database
384                eval ("rm", "-f", "/etc/nvram/*");      // delete nvram database
385#elif HAVE_MAGICBOX
386                eval ("rm", "-f", "/tmp/nvram/*");      // delete nvram database
387                eval ("rm", "-f", "/tmp/nvram/.lock");  // delete nvram database
388                eval ("erase", "nvram");
389#else
390                nvram_set ("sv_restore_defaults", "1");
391                nvram_commit ();
392                eval ("erase", "nvram");
393#endif
394
395
396//                nvram_set ("sv_restore_defaults", "1");
397//                nvram_commit ();
398
399
400
401                kill (1, SIGTERM);
402              }
403          }
404      }
405    }
406#if !defined(HAVE_XSCALE) && !defined(HAVE_MAGICBOX) && !defined(HAVE_FONERA) && !defined(HAVE_WHRAG108) && !defined(HAVE_GATEWORX) && !defined(HAVE_LS2) && !defined(HAVE_CA8)
407
408  else if ((sesgpio != 0x0f)
409           && (((sesgpio & 0x10) == 0 && (val & push))
410               || ((sesgpio & 0x10) == 0x10 && !(val & push))))
411    {
412      runStartup ("/etc/config", ".sesbutton");
413      runStartup ("/jffs/etc/config", ".sesbutton");    //if available
414      runStartup ("/mmc/etc/config", ".sesbutton");     //if available
415      runStartup ("/tmp/etc/config", ".sesbutton");     //if available
416
417      if (ses_mode == 1)
418        {
419#ifdef HAVE_RADIOOFF
420          if (nvram_match ("radiooff_button", "1"))
421            {
422              eval ("wl", "radio", "on");
423              syslog (LOG_DEBUG,
424                      "SES /AOSS /EZ-setup button: turning radio on\n");
425            }
426#endif
427
428//              led_control (LED_SES, LED_OFF);         
429//              led_control (LED_SES2, LED_ON);         //enable orange led
430          led_control (LED_SES, LED_FLASH);     //when pressed, blink white SES (AOSS) led
431
432//      switch (brand)
433//              {
434//              case ROUTER_WRT54G:
435//              case ROUTER_WRTSL54GS:
436//                      ses_mode = 2;
437//              break;
438//              default:
439          ses_mode = 0;
440//              }
441
442        }
443      else if (ses_mode == 0)
444        {
445#ifdef HAVE_RADIOOFF
446          if (nvram_match ("radiooff_button", "1"))
447            {
448              eval ("wl", "radio", "off");
449              syslog (LOG_DEBUG,
450                      "SES /AOSS /EZ-setup button: turning radio off\n");
451            }
452#endif
453//              led_control (LED_SES, LED_ON);          //enable white led
454//              led_control (LED_SES2, LED_OFF);
455          led_control (LED_SES, LED_FLASH);     //when pressed, blink white SES (AOSS) led
456
457          ses_mode = 1;
458
459        }
460/*      else if (ses_mode == 2)
461        {
462#ifdef HAVE_RADIOOFF
463          if (nvram_match ("radiooff_button", "1"))
464            eval ("wl", "radio", "on");
465#endif
466
467                led_control (LED_SES, LED_ON);          //both leds on
468                led_control (LED_SES2, LED_ON);
469
470                ses_mode = 3;
471               
472        }
473      else if (ses_mode == 3)
474        {
475#ifdef HAVE_RADIOOFF
476          if (nvram_match ("radiooff_button", "1"))
477            eval ("wl", "radio", "off");
478#endif
479                led_control (LED_SES, LED_OFF);         //both leds off
480                led_control (LED_SES2, LED_OFF);
481
482                ses_mode = 0;
483               
484        }
485*/
486
487      /*
488         char *led_argv[] = { "check_ses_led",
489         SES_LED_CHECK_TIMES,
490         SES_LED_CHECK_INTERVAL,
491         NULL
492         };
493         pid_t pid;
494
495         if(!is_exist("/tmp/EnablePushButton"))       
496         return;
497
498         ses_mode = 1;
499         eval("killall", "check_ses_led");
500         _eval(led_argv, NULL, 0, &pid); */
501
502    }
503#endif
504  else
505    {
506
507      /* Although it's unpushed now, it had ever been pushed */
508      if (mode == 1)
509        {
510          if (check_action () != ACT_IDLE)
511            {                   // Don't execute during upgrading
512              fprintf (stderr, "resetbutton: nothing to do...\n");
513              alarmtimer (0, 0);        /* Stop the timer alarm */
514              return;
515            }
516          service_restart ();
517        }
518      /*
519         if( ses_mode == 1 ){
520         cprintf("Release SES push button\n");
521         eval("sendudp", "-i", nvram_safe_get("lan_ifname"),
522         "-s", nvram_safe_get("lan_ipaddr"),
523         "-d", nvram_safe_get("http_client_ip"),
524         "-m", nvram_safe_get("lan_hwaddr"),
525         "-p", "9999",
526         "LED TEST FINISH");
527         ses_mode = 0;
528         } */
529    }
530}
531
532int
533resetbutton_main (int argc, char *argv[])
534{
535
536  brand = getRouterBrand ();
537
538  if ((brand & 0x000f) == 0x000f)
539
540    {
541      puts ("sorry, your unit does not support resetbutton feature\n");
542      return 0;
543    }
544#ifdef HAVE_MAGICBOX
545  init_gpio ();
546#endif
547  /* Run it under background */
548  switch (fork ())
549    {
550    case -1:
551      DEBUG ("can't fork\n");
552      exit (0);
553      break;
554    case 0:
555      /* child process */
556      DEBUG ("fork ok\n");
557      (void) setsid ();
558      break;
559    default:
560      /* parent process should just die */
561      _exit (0);
562    }
563
564  /* set the signal handler */
565  signal (SIGALRM, period_check);
566
567  /* set timer */
568  alarmtimer (NORMAL_INTERVAL, 0);
569
570  /* Most of time it goes to sleep */
571  while (1)
572    pause ();
573
574  return 0;
575}
Note: See TracBrowser for help on using the repository browser.