Added basic LED stuff to libpnd pnd_device
authorskeezix <skeezix@flotsam-vm.(none)>
Thu, 18 Feb 2010 03:07:38 +0000 (22:07 -0500)
committerskeezix <skeezix@flotsam-vm.(none)>
Thu, 18 Feb 2010 03:07:38 +0000 (22:07 -0500)
Added blink-timer to evmapperd .. low battery causes blink! cute!

Makefile
apps/pndevmapperd.c
deployment/etc/pandora/conf/eventmap
include/pnd_device.h
lib/pnd_device.c
testdata/conf/eventmap

index 3fd2231..d5b018b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -21,7 +21,7 @@ LIB = libpnd.a
 SOLIB = libpnd.so.1         # canonicle name
 SOLIB1 = libpnd.so.1.0.1    # versioned name
 XMLOBJ = lib/tinyxml/tinystr.o lib/tinyxml/tinyxml.o lib/tinyxml/tinyxmlerror.o lib/tinyxml/tinyxmlparser.o
-ALLOBJ = pnd_conf.o pnd_container.o pnd_discovery.o pnd_pxml.o pnd_notify.o pnd_locate.o pnd_tinyxml.o pnd_pndfiles.o pnd_apps.o pnd_utility.o pnd_desktop.o pnd_io_gpio.o pnd_logger.o pnd_dbusnotify.o
+ALLOBJ = pnd_conf.o pnd_container.o pnd_discovery.o pnd_pxml.o pnd_notify.o pnd_locate.o pnd_tinyxml.o pnd_pndfiles.o pnd_apps.o pnd_utility.o pnd_desktop.o pnd_io_gpio.o pnd_logger.o pnd_dbusnotify.o pnd_device.o
 
 all: ${SOLIB} ${LIB} conftest discotest notifytest pndnotifyd rawpxmltest pndvalidator loggertest dbusnotifytest pnd_run pndevmapperd pnd_info evtest
 
index a9ad7b2..f09cbfe 100644 (file)
@@ -20,6 +20,7 @@
 #include <ctype.h> // for isdigit
 #include <signal.h> // for sigaction
 #include <sys/wait.h> // for wait
+#include <sys/time.h> // setitimer
 
 #include <linux/input.h> // for keys
 //#include "../../kernel-rip/input.h" // for keys
@@ -34,6 +35,7 @@
 #include "pnd_logger.h"
 #include "pnd_utility.h"
 #include "pnd_notify.h"
+#include "pnd_device.h"
 
 // daemon and logging
 //
@@ -97,11 +99,20 @@ typedef struct {
 evmap_t g_evmap [ MAXEVENTS ];
 unsigned int g_evmap_max = 0;
 
+// battery
+unsigned char b_threshold = 5;    // %battery
+unsigned int b_frequency = 300;   // frequency to check
+unsigned int b_blinkfreq = 2;     // blink every 2sec
+unsigned int b_blinkdur = 1000;   // blink duration (uSec), 0sec + uSec is assumed
+unsigned char b_active = 0;       // 0=inactive, 1=active and waiting to blink, 2=blink is on, waiting to turn off
+
 /* get to it
  */
 void dispatch_key ( int keycode, int val );
 void dispatch_event ( int code, int val );
 void sigchld_handler ( int n );
+unsigned char set_next_alarm ( unsigned int secs, unsigned int usecs );
+void sigalrm_handler ( int n );
 
 static void usage ( char *argv[] ) {
   printf ( "%s [-d]\n", argv [ 0 ] );
@@ -318,6 +329,9 @@ int main ( int argc, char *argv[] ) {
     } else if ( strncmp ( k, "pndevmapperd.", 7 ) == 0 ) {
       // not consumed here, skip silently
 
+    } else if ( strncmp ( k, "battery.", 8 ) == 0 ) {
+      // not consumed here, skip silently
+
     } else {
       // uhhh
       pnd_log ( pndn_warning, "Unknown config key '%s'; skipping.\n", k );
@@ -336,6 +350,25 @@ int main ( int argc, char *argv[] ) {
     pnd_log ( pndn_rem, "config file causes minimum_separation to change to %u", g_minimum_separation );
   }
 
+  // battery conf
+  if ( pnd_conf_get_as_int ( evmaph, "battery.threshold" ) != PND_CONF_BADNUM ) {
+    b_threshold = pnd_conf_get_as_int ( evmaph, "battery.threshold" );
+    pnd_log ( pndn_rem, "Battery threshold set to %u", b_threshold );
+  }
+  if ( pnd_conf_get_as_int ( evmaph, "battery.check_interval" ) != PND_CONF_BADNUM ) {
+    b_frequency = pnd_conf_get_as_int ( evmaph, "battery.check_interval" );
+    pnd_log ( pndn_rem, "Battery check interval set to %u", b_frequency );
+  }
+  if ( pnd_conf_get_as_int ( evmaph, "battery.blink_interval" ) != PND_CONF_BADNUM ) {
+    b_blinkfreq = pnd_conf_get_as_int ( evmaph, "battery.blink_interval" );
+    pnd_log ( pndn_rem, "Battery blink interval set to %u", b_blinkfreq );
+  }
+  if ( pnd_conf_get_as_int ( evmaph, "battery.blink_duration" ) != PND_CONF_BADNUM ) {
+    b_blinkdur = pnd_conf_get_as_int ( evmaph, "battery.blink_duration" );
+    pnd_log ( pndn_rem, "Battery blink duration set to %u", b_blinkdur );
+  }
+  b_active = 0;
+
   /* do we have anything to do?
    */
   if ( ! g_evmap_max ) {
@@ -353,9 +386,21 @@ int main ( int argc, char *argv[] ) {
   siggy.sa_handler = sigchld_handler;
   siggy.sa_mask = ss; /* implicitly blocks the origin signal */
   siggy.sa_flags = SA_RESTART; /* don't need anything */
-
   sigaction ( SIGCHLD, &siggy, NULL );
 
+  /* set up the battery level warning timers
+   */
+  siggy.sa_handler = sigalrm_handler;
+  siggy.sa_mask = ss; /* implicitly blocks the origin signal */
+  siggy.sa_flags = SA_RESTART; /* don't need anything */
+  sigaction ( SIGALRM, &siggy, NULL );
+
+  if ( set_next_alarm ( b_frequency, 0 ) ) { // check every 'frequency' seconds
+    pnd_log ( pndn_rem, "Checking for low battery every %u seconds\n", b_frequency );
+  } else {
+    pnd_log ( pndn_error, "ERROR: Couldn't set up timer for every %u seconds\n", b_frequency );
+  }
+
   /* actually try to do something useful
    */
 
@@ -419,8 +464,8 @@ int main ( int argc, char *argv[] ) {
   }
 
   if ( fds [ 0 ] == -1 && fds [ 1 ] == -1 ) {
-    pnd_log ( pndn_error, "ERROR! Couldn't find either device; exiting!\n" );
-    exit ( -2 );
+    pnd_log ( pndn_error, "ERROR! Couldn't find either device!\n" );
+    //exit ( -2 );
   }
 
   /* loop forever, watching for events
@@ -650,3 +695,93 @@ void sigchld_handler ( int n ) {
 
   return;
 }
+
+unsigned char set_next_alarm ( unsigned int secs, unsigned int usecs ) {
+
+  // assume that SIGALRM is already being caught, we just set the itimer here
+
+  struct itimerval itv;
+
+  // if no timer at all, set the 'current' one so it does something; otherwise
+  // let it continue..
+  getitimer ( ITIMER_REAL, &itv );
+
+  if ( itv.it_value.tv_sec == 0 && itv.it_value.tv_sec == 0 ) {
+    itv.it_value.tv_sec = secs;
+    itv.it_value.tv_usec = usecs;
+  }
+
+  // set the next timer
+  //bzero ( &itv, sizeof(struct itimerval) );
+
+  itv.it_interval.tv_sec = secs;
+  itv.it_interval.tv_usec = usecs;
+
+  // if next-timer is less than current, set current too
+  if ( itv.it_value.tv_sec > itv.it_interval.tv_sec ) {
+    itv.it_value.tv_sec = secs;
+    itv.it_value.tv_usec = usecs;
+  }
+
+  if ( setitimer ( ITIMER_REAL, &itv, NULL /* old value returned here */ ) < 0 ) {
+    // sucks
+    return ( 0 );
+  }
+  
+  return ( 1 );
+}
+
+void sigalrm_handler ( int n ) {
+
+  pnd_log ( pndn_debug, "---[ SIGALRM ]---\n" );
+
+  int batlevel = pnd_device_get_battery_gauge_perc();
+
+  if ( batlevel < 0 ) {
+    // couldn't read the battery level, so just assume low and make blinks?
+    batlevel = 4; // low, but not cause a shutdown
+  }
+
+  // is battery warning already active?
+  if ( b_active ) {
+    // warning is on!
+
+    // is user charging up? if so, stop blinking.
+    // perhaps we shoudl check if charger is connected, and not blink at all in that case..
+    if ( batlevel > b_threshold + 1 /* allow for error in read */ ) {
+      pnd_log ( pndn_debug, "Battery is high again, flipping to non-blinker mode\n" );
+      b_active = 0;
+      set_next_alarm ( b_frequency, 0 );
+      pnd_device_set_led_power_brightness ( 250 );
+      return;
+    }
+
+    if ( b_active == 1 ) {
+      // turn LED on
+      pnd_log ( pndn_debug, "Blink on\n" );
+      pnd_device_set_led_power_brightness ( 200 );
+      // set timer to short duration
+      b_active = 2;
+      set_next_alarm ( 0, b_blinkdur );
+    } else if ( b_active == 2 ) {
+      // turn LED off
+      pnd_log ( pndn_debug, "Blink off\n" );
+      pnd_device_set_led_power_brightness ( 10 );
+      // back to longer duration
+      b_active = 1;
+      set_next_alarm ( b_blinkfreq, 0 );
+    }
+
+    return;
+  }
+
+  // warning is off..
+  if ( batlevel <= b_threshold ) {
+    // battery seems low, go to active mode
+    pnd_log ( pndn_debug, "Battery is low, flipping to blinker mode\n" );
+    b_active = 1;
+    set_next_alarm ( b_blinkfreq, 0 );
+  } // battery level
+
+  return;
+}
index aa933c9..1025107 100644 (file)
@@ -16,3 +16,10 @@ lid-toggle   /usr/pandora/scripts/op_lid.sh
 # logging level 0 means to include debug; level 1 (regular), 2 (warnings), 3 (errors)
 loglevel       1
 minimum_separation     1       # 1 second minimum between a single event repeating
+
+[battery]
+# for LED-blinking when battery gets low
+threshold         5            # in %age; at x%, we go into blink-mode as warning
+check_interval    300          # in seconds to check threshold; should be a high 300s
+blink_interval    2            # frequency of blink
+blink_duration    50000        # how long a blink lasts, in uSecs
index 706b783..d0b32f5 100644 (file)
@@ -21,6 +21,15 @@ extern "C" {
 #define PND_DEVICE_FRAMEBUFFER "/dev/fb0"
 #define PND_DEVICE_NUB1 "/dev/input/js1"
 #define PND_DEVICE_NUB2 "/dev/input/js2"
+#define PND_DEVICE_BATTERY_GAUGE_PERC "/sys/class/power_supply/bq27500-0/capacity"
+
+#define PND_DEVICE_LED_CHARGER "/sys/class/leds/pandora::charger"
+#define PND_DEVICE_LED_POWER   "/sys/class/leds/pandora::power"
+#define PND_DEVICE_LED_SD1     "/sys/class/leds/pandora::sd1"
+#define PND_DEVICE_LED_SD2     "/sys/class/leds/pandora::sd2"
+#define PND_DEVICE_LED_WIFI    "/sys/class/leds/pandora::wifi"
+#define PND_DEVICE_LED_BT      "/sys/class/leds/pandora::bluetooth"
+#define PND_DEVICE_LED_SUFFIX_BRIGHTNESS "/brightness"
 
 /* utility
  */
@@ -34,6 +43,11 @@ unsigned char pnd_device_open_read_close ( char *name, char *r_buffer, unsigned
 unsigned char pnd_device_set_clock ( unsigned int c ); // returns >0 on success
 unsigned int pnd_device_get_clock ( void );
 
+/* return the battery current %age level; 0-100%
+ * On error, returns -1
+ */
+int pnd_device_get_battery_gauge_perc ( void );
+
 // LCD to set on/off
 
 // Backlight control
@@ -41,6 +55,7 @@ unsigned char pnd_device_set_backlight ( unsigned int v ); // value to set; 0 is
 unsigned int pnd_device_get_backlight ( void );
 
 // set one or more LEDs on
+unsigned char pnd_device_set_led_power_brightness ( unsigned char v ); // 0-255
 
 // suspend/hibernate/etc
 
index 42a17ca..df9e108 100644 (file)
 unsigned char pnd_device_open_write_close ( char *name, char *v ) {
   int f;
 
-  if ( ( f = open ( PND_DEVICE_PROC_CLOCK, O_WRONLY /*O_RDONLY*/ ) ) < 0 ) {
+  if ( ( f = open ( name, O_WRONLY /*O_RDONLY*/ ) ) < 0 ) {
     return ( 0 );
   }
 
-  if ( write ( f, buffer, strlen ( buffer ) ) < strlen ( buffer ) ) {
+  if ( write ( f, v, strlen ( v ) ) < strlen ( v ) ) {
+    close ( f );
     return ( 0 );
   }
 
@@ -48,7 +49,7 @@ unsigned char pnd_device_open_read_close ( char *name, char *r_buffer, unsigned
 unsigned char pnd_device_set_clock ( unsigned int c ) {
   char buffer [ 100 ];
 
-  sprint ( buffer, "%u", c );
+  sprintf ( buffer, "%u", c );
 
   return ( pnd_device_open_write_close ( PND_DEVICE_PROC_CLOCK, buffer ) );
 }
@@ -66,7 +67,7 @@ unsigned int pnd_device_get_clock ( void ) {
 unsigned char pnd_device_set_backlight ( unsigned int c ) {
   char buffer [ 100 ];
 
-  sprint ( buffer, "%u", c );
+  sprintf ( buffer, "%u", c );
 
   return ( pnd_device_open_write_close ( PND_DEVICE_SYS_BACKLIGHT_BRIGHTNESS, buffer ) );
 }
@@ -80,3 +81,21 @@ unsigned int pnd_device_get_backlight ( void ) {
 
   return ( 0 );
 }
+
+int pnd_device_get_battery_gauge_perc ( void ) {
+  char buffer [ 100 ];
+
+  if ( pnd_device_open_read_close ( PND_DEVICE_BATTERY_GAUGE_PERC, buffer, 100 ) ) {
+    return ( atoi ( buffer ) );
+  }
+
+  return ( -1 );
+}
+
+unsigned char pnd_device_set_led_power_brightness ( unsigned char v ) {
+  char buffer [ 100 ];
+
+  sprintf ( buffer, "%u", v );
+
+  return ( pnd_device_open_write_close ( PND_DEVICE_LED_POWER PND_DEVICE_LED_SUFFIX_BRIGHTNESS, buffer ) );
+}
index 57ef8cd..666a054 100644 (file)
@@ -12,3 +12,10 @@ lid-toggle   /usr/pandora/scripts/op_lidtoggle.sh
 # logging level 0 means to include debug; level 1 (regular), 2 (warnings), 3 (errors)
 loglevel       1
 minimum_separation     1       # 1 second minimum between a single event repeating
+
+[battery]
+# for LED-blinking when battery gets low
+threshold         5            # in %age; at x%, we go into blink-mode as warning
+check_interval    7            # in seconds to check threshold; should be a high 300s
+blink_interval    2            # frequency of blink
+blink_duration    50000        # how long a blink lasts, in uSecs