author | sandman <sandman> | 2002-06-17 02:19:40 (UTC) |
---|---|---|
committer | sandman <sandman> | 2002-06-17 02:19:40 (UTC) |
commit | b646eee10051aa1065f60113066eb0028d17efc4 (patch) (side-by-side diff) | |
tree | a079377b12b97bc54a7a960a36d7453716d1f497 /core/opiealarm/opiealarm.c | |
parent | 0d9911023b9a5c70916c0354ca3358c90b601f32 (diff) | |
download | opie-b646eee10051aa1065f60113066eb0028d17efc4.zip opie-b646eee10051aa1065f60113066eb0028d17efc4.tar.gz opie-b646eee10051aa1065f60113066eb0028d17efc4.tar.bz2 |
Added a new switch (-f) to opiealarm. When enabled the RTC is 'fixed'
on suspend, if system and RTC time differ more than 5 seconds. This
works both with a installed /etc/localtime and without.
This should fix many reported problems regarding ipaqalarm/opiealarm.
-rw-r--r-- | core/opiealarm/opiealarm.c | 55 |
1 files changed, 42 insertions, 13 deletions
diff --git a/core/opiealarm/opiealarm.c b/core/opiealarm/opiealarm.c index ac98832..128929e 100644 --- a/core/opiealarm/opiealarm.c +++ b/core/opiealarm/opiealarm.c @@ -28,13 +28,13 @@ #define PIDFILE "/var/run/opiealarm.pid" #define APMFILE "/proc/apm" FILE *log; // debug only int resume ( int resuspend ); -int suspend ( void ); +int suspend ( int fix_rtc ); int main ( int argc, char **argv ); int fork_with_pidfile ( void ); int kill_with_pidfile ( void ); void remove_pidfile ( void ); void usage ( void ); void sig_handler ( int sig ); @@ -70,14 +70,15 @@ void sig_handler ( int sig ) remove_pidfile ( ); exit ( 0 ); } void usage ( void ) { - fprintf ( stderr, "Usage: opiealarm -r|-s [-a]\n\n" ); + fprintf ( stderr, "Usage: opiealarm -s [-f] | -r [-a]\n\n" ); fprintf ( stderr, "\t-s\tSuspend mode: set RTC alarm\n" ); + fprintf ( stderr, "\t-f \tFix RTC, if RTC and system have more than 5sec difference (suspend mode)\n" ); fprintf ( stderr, "\t-r\tResume mode: kill running opiealarm\n" ); fprintf ( stderr, "\t-a <x>\tResuspend in <x> seconds (resume mode)\n\n" ); exit ( 1 ); } int fork_with_pidfile ( void ) @@ -140,15 +141,16 @@ void remove_pidfile ( void ) int main ( int argc, char **argv ) { int mode = 0; int ac_resusp = 0; + int fix_rtc = 0; int opt; - while (( opt = getopt ( argc, argv, "a:rs" )) != EOF ) { + while (( opt = getopt ( argc, argv, "a:frs" )) != EOF ) { switch ( opt ) { case 's': mode = 's'; break; case 'r': mode = 'r'; @@ -158,12 +160,15 @@ int main ( int argc, char **argv ) if ( ac_resusp < 30 ) { ac_resusp = 120; fprintf ( stderr, "Warning: resuspend timeout must be >= 30 sec. -- now set to 120 sec\n" ); } break; + case 'f': + fix_rtc = 1; + break; default: usage ( ); } } if ( geteuid ( ) != 0 ) { @@ -178,25 +183,26 @@ int main ( int argc, char **argv ) opiealarm_was_running = kill_with_pidfile ( ); remove_pidfile ( ); switch ( mode ) { case 'r': return resume ( ac_resusp ); case 's': - default : return suspend ( ); + default : return suspend ( fix_rtc ); } return 0; } -int suspend ( void ) +int suspend ( int fix_rtc ) { FILE *fp; char buf [64]; - time_t t; - struct tm *tm; + time_t alrt, syst, rtct; + struct tm alr, sys, rtc; int fd; + int rtc_sys_diff; if ( !fork_with_pidfile ( )) return 3; log = fopen ( "/tmp/opiealarm.log", "w" ); @@ -209,30 +215,53 @@ int suspend ( void ) if ( !fgets ( buf, sizeof( buf ) - 1, fp )) error_msg_and_die ( 1, "/etc/resumeat" ); fclose ( fp ); - t = atoi ( buf ); + alrt = atoi ( buf ); - if ( t == 0 ) + if ( alrt == 0 ) error_msg_and_die ( 0, "/etc/resumeat contains an invalid time description" ); /* subtract 5 sec from event time... */ - t -= 5; + alrt -= 5; if ( log ) - fprintf ( log, "Setting RTC alarm to %d\n", t ); + fprintf ( log, "Setting RTC alarm to %d\n", alrt ); + + alr = *gmtime ( &alrt ); - tm = gmtime ( &t ); + // get system time + time ( &syst ); + sys = *localtime ( &syst ); // Write alarm time to RTC if (( fd = open ( "/dev/misc/rtc", O_RDWR )) < 0 ) error_msg_and_die ( 1, "/dev/misc/rtc" ); + + // get RTC time + if ( ioctl ( fd, RTC_ALM_SET, &rtc ) < 0 ) + error_msg_and_die ( 1, "ioctl RTC_RD_TIME" ); + rtct = mktime ( &rtc ); + + rtc_sys_diff = ( syst - rtct ) - sys. tm_gmtoff; + + if ( fix_rtc && (( rtc_sys_diff < -4 ) || ( rtc_sys_diff > 4 ))) { + struct tm set; + + set = *gmtime ( &syst ); + + fprintf ( log, "Correcting RTC: %d seconds\n", rtc_sys_diff ); + + if ( ioctl ( fd, RTC_SET_TIME, &set ) < 0 ) + error_msg_and_die ( 1, "ioctl RTC_SET_TIME" ); + } + // set alarm time - if ( ioctl ( fd, RTC_ALM_SET, tm ) < 0 ) + if ( ioctl ( fd, RTC_ALM_SET, &alr ) < 0 ) error_msg_and_die ( 1, "ioctl RTC_ALM_SET" ); // enable alarm irq if ( ioctl ( fd, RTC_AIE_ON, 0 ) < 0 ) error_msg_and_die ( 1, "ioctl RTC_AIE_ON" ); log_msg ( "SLEEPING\n" ); |