From 9a9fe7352a0687d1604b5cc01c18a3ae29abb756 Mon Sep 17 00:00:00 2001 From: skeezix Date: Wed, 17 Feb 2010 22:07:38 -0500 Subject: [PATCH] Added basic LED stuff to libpnd pnd_device Added blink-timer to evmapperd .. low battery causes blink! cute! --- Makefile | 2 +- apps/pndevmapperd.c | 141 ++++++++++++++++++++++++++- deployment/etc/pandora/conf/eventmap | 7 ++ include/pnd_device.h | 15 +++ lib/pnd_device.c | 27 ++++- testdata/conf/eventmap | 7 ++ 6 files changed, 191 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 3fd2231..d5b018b 100644 --- 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 diff --git a/apps/pndevmapperd.c b/apps/pndevmapperd.c index a9ad7b2..f09cbfe 100644 --- a/apps/pndevmapperd.c +++ b/apps/pndevmapperd.c @@ -20,6 +20,7 @@ #include // for isdigit #include // for sigaction #include // for wait +#include // setitimer #include // 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; +} diff --git a/deployment/etc/pandora/conf/eventmap b/deployment/etc/pandora/conf/eventmap index aa933c9..1025107 100644 --- a/deployment/etc/pandora/conf/eventmap +++ b/deployment/etc/pandora/conf/eventmap @@ -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 diff --git a/include/pnd_device.h b/include/pnd_device.h index 706b783..d0b32f5 100644 --- a/include/pnd_device.h +++ b/include/pnd_device.h @@ -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 diff --git a/lib/pnd_device.c b/lib/pnd_device.c index 42a17ca..df9e108 100644 --- a/lib/pnd_device.c +++ b/lib/pnd_device.c @@ -13,11 +13,12 @@ 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 ) ); +} diff --git a/testdata/conf/eventmap b/testdata/conf/eventmap index 57ef8cd..666a054 100644 --- a/testdata/conf/eventmap +++ b/testdata/conf/eventmap @@ -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 -- 2.39.2