I tried wkalrm by Werner Almesberger and it works without problems. I
don't know where i found it so i attached it to this mail.

Ciao,
     Rainer

Nikita V. Youshchenko wrote:
> Hi
> 
> I see, rtcwake does not work on freerunner:
> 
> freerunner:~# rtcwake -s 30
> rtcwake: /dev/rtc0 not enabled for wakeup events
> 
> Is there any working methond to make freerunner suspend sleep and later 
> wakeup not later than at a given moment?
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> Openmoko community mailing list
> [email protected]
> http://lists.openmoko.org/mailman/listinfo/community
/*
 * wkalrm.c - Use the RTC alarm to wake us up
 *
 * Copyright (C) 2008 by OpenMoko, Inc.
 * Written by Werner Almesberger <[email protected]>
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */


#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/rtc.h>


#define DEFAULT_RTC "/dev/rtc0"


static const char *device = DEFAULT_RTC;
static int fd;


/* ----- Low-level wrappers ------------------------------------------------ */


static void read_alarm(struct rtc_wkalrm *alarm)
{
        int res;

        res = ioctl(fd, RTC_WKALM_RD, alarm);
        if (res < 0) {
                perror("ioctl(RTC_WKALM_RD)");
                exit(1);
        }
}


static void read_time(struct rtc_time *tm)
{
        int res;

        res = ioctl(fd, RTC_RD_TIME, tm);
        if (res < 0) {
                perror("ioctl(RTC_RD_TIME)");
                exit(1);
        }
}


static void write_alarm(const struct rtc_wkalrm *alarm)
{
        int res;

        res = ioctl(fd, RTC_WKALM_SET, alarm);
        if (res < 0) {
                perror("ioctl(RTC_WKALM_SET)");
                exit(1);
        }
}


/* ----- Date conversions -------------------------------------------------- */


static void show_alarm(void)
{
        struct rtc_wkalrm alarm;

        read_alarm(&alarm);
        if (!alarm.enabled)
                printf("alarm disabled%s\n",
                    alarm.pending ? " (pending)" : "");
        else
                printf("%02d:%02d:%02d %04d-%02d-%02d%s\n",
                    alarm.time.tm_hour, alarm.time.tm_min, alarm.time.tm_sec,
                    alarm.time.tm_year+1900, alarm.time.tm_mon+1,
                    alarm.time.tm_mday,
                    alarm.pending ? " (pending)" : "");
}


static void set_alarm_abs(const char *t, const char *day)
{
        fprintf(stderr, "not yet implemented :-)\n");
        exit(1);
}


static void set_alarm_delta(time_t delta)
{
        struct rtc_wkalrm alarm;
        struct tm tm, *tmp;
        time_t t;

        read_time(&alarm.time);
        memset(&tm, 0, sizeof(tm));
        tm.tm_sec = alarm.time.tm_sec;
        tm.tm_min = alarm.time.tm_min;
        tm.tm_hour = alarm.time.tm_hour;
        tm.tm_mday = alarm.time.tm_mday;
        tm.tm_mon = alarm.time.tm_mon;
        tm.tm_year = alarm.time.tm_year;
        t = mktime(&tm);
        if (t == (time_t) -1) {
                fprintf(stderr, "mktime: error\n");
                exit(1);
        }
        t += delta;
        tmp = localtime(&t);
        if (!tmp) {
                fprintf(stderr, "localtime_r: error\n");
                exit(1);
        }
        alarm.time.tm_sec = tmp->tm_sec;
        alarm.time.tm_min = tmp->tm_min;
        alarm.time.tm_hour = tmp->tm_hour;
        alarm.time.tm_mday = tmp->tm_mday;
        alarm.time.tm_mon = tmp->tm_mon;
        alarm.time.tm_year = tmp->tm_year;
        alarm.enabled = 1;
        write_alarm(&alarm);
}


static void set_alarm_rel(const char *delta)
{
        unsigned long n;
        char *end;

        n = strtoul(delta, &end, 10);
        if (!strcmp(end, "d") || !strcmp(end, "day") || !strcmp(end, "days"))
                n *= 24*3600;
        else if (!strcmp(end, "h") || !strcmp(end, "hour") ||
            !strcmp(end, "hours"))
                n *= 3600;
        else if (!strcmp(end, "m") || !strcmp(end, "min") ||
            !strcmp(end, "mins"))
                n *= 60;
        else if (strcmp(end, "s") && strcmp(end, "sec") &&
            strcmp(end, "secs")) {
                fprintf(stderr, "invalid delta time \"%s\"\n", delta);
                exit(1);
        }
        set_alarm_delta(n);
}


static void disable_alarm(void)
{
        struct rtc_wkalrm alarm;

        read_alarm(&alarm);
        alarm.enabled = 0;
        write_alarm(&alarm);
}


static void set_alarm_24h(const char *t)
{
        fprintf(stderr, "not yet implemented :-)\n");
        exit(1);
}


static void set_alarm(const char *when)
{
        if (*when == '+')
                set_alarm_rel(when+1);
        else
                set_alarm_24h(when);
}


/* ----- Command line parsing ---------------------------------------------- */


static void usage(const char *name)
{
        fprintf(stderr,
"usage: %s [-d device]\n"
"       %s [-d device] hh:mm[:ss] [[yyyy-]mm-dd]\n"
"       %s [-d device] +Nunit\n\n"
"  unit  is d[ay[s]], h[our[s]] m[in[s]], or s[ec[s]]\n\n"
"  -d device  open the specified RTC device (default: %s)\n"
    , name, name, name, DEFAULT_RTC);
        exit(1);
}


int main(int argc, char **argv)
{
        int c;

        while ((c = getopt(argc, argv, "d:")) != EOF)
                switch (c) {
                case 'd':
                        device = optarg;
                        break;
                default:
                        usage(*argv);
                }

        fd = open(device, O_RDWR);
        if (fd < 0) {
                perror(device);
                exit(1);
        }

        switch (argc-optind) {
        case 0:
                show_alarm();
                break;
        case 1:
                if (!strcmp(argv[optind], "off"))
                        disable_alarm();
                else
                        set_alarm(argv[optind]);
                break;
        case 2:
                set_alarm_abs(argv[optind], argv[optind+1]);
                break;
        default:
                usage(*argv);
        }
        return 0;
}
_______________________________________________
Openmoko community mailing list
[email protected]
http://lists.openmoko.org/mailman/listinfo/community

Reply via email to