Allow leds to work in early user space by getting the
authorJohn Bowler <jbowler@nslu2-linux.org>
Mon, 23 May 2005 16:19:43 +0000 (16:19 +0000)
committerJohn Bowler <jbowler@nslu2-linux.org>
Mon, 23 May 2005 16:19:43 +0000 (16:19 +0000)
device entry in /dev, allow leds to be set to different
settings using 'leds'.

BKrev: 4292029fJdJ4KZzDf8ka7UNhpcVhkQ

files/device_table-openslug.txt
packages/openslug-init/openslug-init-0.10/leds.c
packages/openslug-init/openslug-init-0.10/leds.h

index e69de29..b3ee0cb 100644 (file)
@@ -0,0 +1,41 @@
+# <path>       <type> <mode>   <uid>   <gid>   <major> <minor> <start> <inc>   <count>
+# /dev/mem     c      640      0       0       1       1       0        0        -
+#      f       A regular file
+#      d       Directory
+#      c       Character special device file
+#      b       Block special device file
+#      p       Fifo (named pipe)
+/dev           d       755     0       0       -       -       -       -       -
+/dev/buzzer    c       660     0       0       62      0       -       -       -
+/dev/console   c       622     0       0       5       1       -       -       -
+/dev/cua       c       622     0       0       5       64      0       1       2
+/dev/flash     d       755     0       0       -       -       -       -       -
+/dev/flash/config c    644     0       0       90      6       -       -       -
+/dev/ipsec     c       644     0       0       36      10      -       -       -
+/dev/kmem      c       640     0       0       1       2       -       -       -
+/dev/leds      c       660     0       0       126     0       -       -       -
+/dev/mem       c       640     0       0       1       1       -       -       -
+/dev/mtd       c       664     0       0       90      0       0       2       4
+/dev/mtdblock  b       644     0       0       31      0       0       1       4
+/dev/mtdr      c       664     0       0       90      0       1       2       4
+/dev/null      c       666     0       0       1       3       -       -       -
+/dev/pbuttons  c       660     0       0       61      0       -       -       -
+/dev/ppp       c       644     0       0       108     0       -       -       -
+/dev/ptyp      c       644     0       0       2       0       0       1       10
+/dev/ram       b       644     0       0       1       0       0       1       4
+/dev/random    c       644     0       0       1       8       -       -       -
+/dev/rbuttons  c       660     0       0       60      0       -       -       -
+/dev/rtc       c       644     0       0       10      135     -       -       -
+/dev/sda       b       664     0       0       8       0       -       -       -
+/dev/sda       b       664     0       0       8       1       1       1       5
+/dev/sdb       b       664     0       0       8       16      -       -       -
+/dev/sdb       b       664     0       0       8       17      1       1       5
+/dev/sdc       b       664     0       0       8       32      -       -       -
+/dev/sdc       b       664     0       0       8       33      1       1       5
+/dev/tty       c       666     0       0       5       0       -       -       -
+/dev/tty       c       644     0       0       4       0       0       1       10
+/dev/ttyS      c       644     0       0       4       64      0       1       2
+/dev/ttyp      c       644     0       0       3       0       0       1       10
+/dev/urandom   c       644     0       0       1       9       -       -       -
+/dev/zero      c       666     0       0       1       5       -       -       -
+/bin/tinylogin f       6755    0       0       -       -       -       -       -
index e69de29..e2120ae 100644 (file)
@@ -0,0 +1,190 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <math.h>
+ #include <errno.h>
+ #include <string.h>
+ #include <endian.h>
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <sys/ioctl.h>
+ #include "leds.h"
+
+ static int leds;
+ static int reset;
+ static int verbose = 0;
+ enum {
+   off=0, on=1, blink, unknown, transition=unknown
+ };
+
+
+ void init_leds(void)
+ {
+   int i;
+   if ((leds = open("/dev/leds", O_RDWR)) < 0) {
+     int e1 = errno;
+     if (e1 != ENOENT) {
+
+       fprintf(stderr,"Error: Could not open LEDS device file '/dev/leds' : %s\n",
+               strerror(e1));
+       if(e1 == EACCES)
+         fprintf(stderr,"Run as root\n");
+       exit(1);
+     }
+   }
+
+   if (verbose)
+     printf("leds: initialized.\n");
+ }
+
+ void led_ioctl( int cmd, int num )
+ {
+   int i, st;
+
+   if (ioctl(leds, cmd, num) < 0) {
+     int e1 = errno;
+     fprintf(stderr, "leds: ioctl(%d,%d): failed to set leds: %s\n",
+        cmd, num, strerror(e1));
+     exit(1);
+   }
+ }
+
+ void led_set( int led, int state )
+ {
+   switch (state) {
+   case off:   if (!reset) led_ioctl(N2_LM_OFF, led); break;
+   case on:    led_ioctl(N2_LM_ON, led); break;
+   case blink: /* Ensure any previous timer gets deleted first and that
+               * the LED is in a well known state.
+               */
+              if (!reset) led_ioctl(N2_LM_OFF, led);
+              led_ioctl(N2_LM_BLINK, led); break;
+   }
+ }
+
+ int led( int ch ) {
+   switch (ch) {
+   case 'r': return LED_RS_RED;
+   case 'g': return LED_RS_GRN;
+   case '1': return LED_DISK1;
+   case '2': return LED_DISK2;
+   case 'A': reset = 1; return LED_ALL;
+   default:  fprintf(stderr, "leds: %c: unknown LED (use r,g,0,1 or A)\n", ch);
+            exit(1);
+   }
+ }
+
+ int main( int argc, char **argv ) 
+ {
+       /* Default: switch green on, red off (-A +g). */
+       if (argc == 1) {
+         verbose = 1;
+         init_leds();
+         led_ioctl(N2_LM_ALL_OFF, 0);
+         led_ioctl(N2_LM_ON, LED_RS_GRN);
+       } else {
+         int i, alt=0, state[PHYS_LEDS];
+         for(i=0; i<PHYS_LEDS; ++i)
+           state[i] = unknown;
+         reset = 0;
+
+         while (--argc > 0) {
+           char *arg = *++argv;
+           int st;
+           if (strcmp(arg, "-v") == 0) {
+             ++verbose;
+             continue;
+           }
+
+           switch (*arg) {
+           case '+': st = on; break;
+           case '-': st = off; break;
+           case '!': st = blink; break;
+           case '/': st = transition; break;
+           default:  fprintf(stderr, "leds: %c: unknown option\n", *arg);
+                     exit(1);
+           }
+
+           if (st != transition) {
+             while (*++arg) {
+               i = led(*arg);
+               if (i == LED_ALL)
+                 for (i=0; i<PHYS_LEDS; ++i) state[i] = st;
+               else
+                 state[i] = st;
+             }
+           } else {
+             int done, newstate[PHYS_LEDS];
+             for(i=0; i<PHYS_LEDS; ++i)
+               newstate[i] = off;
+             while (*++arg) {
+               i = led(*arg);
+               if (i == LED_ALL)
+                 for (i=0; i<PHYS_LEDS; ++i) newstate[i] = on;
+               else
+                 newstate[i] = on;
+             }
+
+             /* Merge the newstate back in.  This sets 'alt' if going
+              * from an old state of just red to a new of just green
+              * or vice versa (and this is the only way of getting
+              * 'alt')
+              */
+             /* Blink anything which changes from off to on or from
+              * on to off (this ignores anything already blinking).
+              */
+             for (done=i=0; i<PHYS_LEDS; ++i) {
+               if (state[i] == !newstate[i]) {
+                 done = 1;
+                 state[i] = blink;
+               }
+             }
+
+             /* Is anything (new) blinking?  If it is then deal
+              * with the red/green case - blinking red,green is
+              * amber, is that what we want?  This could be
+              * improved by a better kernel interface - it would
+              * be nice just to specify on/off times and a start
+              * time for each LED.
+              */
+             if (done) {
+               if (state[LED_RS_RED] == blink && state[LED_RS_GRN] == blink &&
+                   newstate[LED_RS_RED] == !newstate[LED_RS_GRN]) {
+                 /* Kernel bug: must switch off r and g first. */
+                 alt = 1;
+               }
+             } else {
+               for (i=0; i<PHYS_LEDS; ++i) {
+                 if (newstate[i] == on) {
+                   state[i] = blink;
+                 }
+               }
+             }
+           }
+         }
+
+         /* Go through the list making the required settings.  'alt' is
+          * special.  'reset' means A was given and all the settings are
+          * known.
+          */
+         init_leds();
+         if (reset)
+           led_ioctl(N2_LM_ALL_OFF, 0);
+         if (alt) {
+           /* Turn the leds off first to get to a known state. */
+           led_set(LED_RS_GRN, off);
+           led_set(LED_RS_RED, off);
+           led_ioctl(N2_LM_ALT, LED_RS_RED);
+         } else {
+           /* KERNEL BUG: setting the green timer zaps the red behaviour
+            * to toggle the green, therefore if red blink is set before
+            * green blink no blink will happen!
+            */
+           led_set(LED_RS_GRN, state[LED_RS_GRN]);
+           led_set(LED_RS_RED, state[LED_RS_RED]);
+         }
+         led_set(LED_DISK1, state[LED_DISK1]);
+         led_set(LED_DISK2, state[LED_DISK2]);
+       }
+
+       return 0;
+ }
index e69de29..0b236dd 100644 (file)
@@ -0,0 +1,21 @@
+ void init_leds(void);
+ void led_on(int);
+ void led_off( int );
+ void led_toggle(int num);
+
+ // ioctls -- 'M" is used for sound cards...we don't got one so it seems safe
+ #define N2_LM_OFF               _IOW('M',32,long)
+ #define N2_LM_ON                _IOW('M',33,long)
+ #define N2_LM_BLINK             _IOW('M',34,long)
+ #define N2_LM_ALT               _IOW('M',35,long)
+ #define N2_LM_ALL_ON            _IO('M',36)
+ #define N2_LM_ALL_OFF           _IO('M',37)
+
+ // The LED names for switches
+ #define LED_RS_RED              0
+ #define LED_RS_GRN              1
+ #define LED_DISK1               2
+ #define LED_DISK2               3
+ #define LED_ALL                 4
+
+ #define PHYS_LEDS               4