Message ID | 1382982135-2835-1-git-send-email-colin.king@canonical.com |
---|---|
State | Accepted |
Headers | show |
On 10/29/2013 01:42 AM, Colin King wrote: > From: Colin Ian King <colin.king@canonical.com> > > This test fails on non-x86 architectures, so use the more generic ioctl > alarm interface instead. > > Signed-off-by: Colin Ian King <colin.king@canonical.com> > --- > src/acpi/wakealarm/wakealarm.c | 18 ++--- > src/lib/include/fwts_wakealarm.h | 5 +- > src/lib/src/fwts_wakealarm.c | 159 ++++++++++++++++++++++++++++++--------- > 3 files changed, 132 insertions(+), 50 deletions(-) > > diff --git a/src/acpi/wakealarm/wakealarm.c b/src/acpi/wakealarm/wakealarm.c > index 7f4886a..1176be0 100644 > --- a/src/acpi/wakealarm/wakealarm.c > +++ b/src/acpi/wakealarm/wakealarm.c > @@ -25,27 +25,23 @@ > #include <unistd.h> > #include <string.h> > > -static const char *wkalarm = WAKEALARM; > - > static int wakealarm_test1(fwts_framework *fw) > { > - struct stat buf; > - > - if (stat(wkalarm, &buf) == 0) > - fwts_passed(fw, WAKEALARM " found."); > + if (fwts_wakealarm_exits(fw) == FWTS_OK) > + fwts_passed(fw, "RTC with a RTC alarm ioctl() interface found."); > else { > fwts_failed(fw, LOG_LEVEL_MEDIUM, "NoWakeAlarmTest1", > - "Could not find " WAKEALARM "."); > + "Could not find an RTC with an alarm ioctl() interface."); > #ifdef FWTS_ARCH_INTEL > /* For x86 devices, this is considered a failure */ > fwts_advice(fw, > "x86 devices generally should have an RTC wake alarm that " > - "is normally controlled by the " WAKEALARM " interface. This interface " > + "is normally controlled by the RTC alarm ioctl() interface. This interface " > "does not exist, so the wake alarm tests will be aborted."); > #else > fwts_advice(fw, > "non-x86 devices sometimes do not have an RTC wake alarm that " > - "is normally controlled by the " WAKEALARM " interface. This " > + "is normally controlled by the RTC alarm ioctl() interface. This " > "interface does not exist, so the wake alarm tests will be aborted."); > #endif > return FWTS_ABORTED; > @@ -64,6 +60,8 @@ static int wakealarm_test2(fwts_framework *fw) > return FWTS_OK; > } > > + (void)fwts_wakealarm_cancel(fw); > + > fwts_passed(fw, "RTC wakealarm was triggered successfully."); > > return FWTS_OK; > @@ -122,7 +120,7 @@ static int wakealarm_test4(fwts_framework *fw) > } > > static fwts_framework_minor_test wakealarm_tests[] = { > - { wakealarm_test1, "Check existence of " WAKEALARM "." }, > + { wakealarm_test1, "Check existence of RTC with alarm interface." }, > { wakealarm_test2, "Trigger wakealarm for 1 seconds in the future." }, > { wakealarm_test3, "Check if wakealarm is fired." }, > { wakealarm_test4, "Multiple wakealarm firing tests." }, > diff --git a/src/lib/include/fwts_wakealarm.h b/src/lib/include/fwts_wakealarm.h > index df95e41..b4994fd 100644 > --- a/src/lib/include/fwts_wakealarm.h > +++ b/src/lib/include/fwts_wakealarm.h > @@ -22,10 +22,9 @@ > > #include "fwts_framework.h" > > -#define WAKEALARM "/sys/class/rtc/rtc0/wakealarm" > - > -int fwts_wakealarm_get_irq_state(void); > +int fwts_wakealarm_exits(fwts_framework *fw); > int fwts_wakealarm_test_firing(fwts_framework *fw, const int sleep); > int fwts_wakealarm_trigger(fwts_framework *fw, const int seconds); > +int fwts_wakealarm_cancel(fwts_framework *fw); > > #endif > diff --git a/src/lib/src/fwts_wakealarm.c b/src/lib/src/fwts_wakealarm.c > index f22ce4c..a2573b3 100644 > --- a/src/lib/src/fwts_wakealarm.c > +++ b/src/lib/src/fwts_wakealarm.c > @@ -18,38 +18,42 @@ > */ > #include <stdlib.h> > #include <stdio.h> > +#include <stdint.h> > +#include <errno.h> > #include <sys/types.h> > #include <sys/stat.h> > +#include <sys/ioctl.h> > #include <unistd.h> > #include <string.h> > +#include <fcntl.h> > +#include <linux/rtc.h> > > #include "fwts.h" > > -static char *fwts_wkalarm = "/sys/class/rtc/rtc0/wakealarm"; > +static char *fwts_rtc = "/dev/rtc0"; > > /* > - * fwts_wakealarm_get_irq_state() > - * get wakealarm IRQ state. checks if alarm_IRQ exists and if > - * it is set. > + * fwts_wakealarm_exits() > + * check that a RTC exists that supports minimal RTC alarm ioctl > */ > -int fwts_wakealarm_get_irq_state(void) > +int fwts_wakealarm_exits(fwts_framework *fw) > { > - FILE *fp; > - char field[32]; > - char value[32]; > + int fd; > + int ret = FWTS_OK; > + struct rtc_time rtc_tm; > > - if ((fp = fopen("/proc/driver/rtc", "r")) == NULL) > + if ((fd = open(fwts_rtc, O_RDWR)) < 0) { > + fwts_log_error(fw, "Cannot access Real Time Clock device %s.", fwts_rtc); > return FWTS_ERROR; > + } > > - while (fscanf(fp, "%s : %s\n", field, value) != EOF) { > - if (!strcmp(field, "alarm_IRQ")) { > - fclose(fp); > - return strcmp(value, "no"); > - } > + if (ioctl(fd, RTC_ALM_READ, &rtc_tm) < 0) { > + fwts_log_error(fw, "Cannot read Real Time Clock with ioctl RTC_RD_TIME %s.", fwts_rtc); > + ret = FWTS_ERROR; > } > - fclose(fp); > + (void)close(fd); > > - return FWTS_ERROR; > + return ret; > } > > /* > @@ -58,29 +62,110 @@ int fwts_wakealarm_get_irq_state(void) > */ > int fwts_wakealarm_trigger(fwts_framework *fw, const int seconds) > { > - char buffer[32]; > - int ret; > - > - snprintf(buffer, sizeof(buffer), "+%d", seconds); > + int fd, ret = FWTS_OK; > + struct rtc_time rtc_tm; > > - if (fwts_set("0", fwts_wkalarm)) { > - fwts_log_error(fw, "Cannot write '0' to %s", fwts_wkalarm); > + if ((fd = open(fwts_rtc, O_RDWR)) < 0) { > + fwts_log_error(fw, "Cannot access Real Time Clock device %s.", fwts_rtc); > return FWTS_ERROR; > } > - if (fwts_set(buffer, fwts_wkalarm)) { > - fwts_log_error(fw, "Cannot write '%s' to %s", buffer, fwts_wkalarm); > - return FWTS_ERROR; > + > + if (ioctl(fd, RTC_RD_TIME, &rtc_tm) < 0) { > + fwts_log_error(fw, "Cannot read Real Time Clock with ioctl RTC_RD_TIME %s.", fwts_rtc); > + ret = FWTS_ERROR; > + goto out; > } > - if ((ret = fwts_wakealarm_get_irq_state()) == FWTS_ERROR) > + > + rtc_tm.tm_sec += seconds; > + if (rtc_tm.tm_sec >= 60) { > + rtc_tm.tm_min += rtc_tm.tm_sec / 60; > + rtc_tm.tm_sec %= 60; > + } > + if (rtc_tm.tm_min >= 60) { > + rtc_tm.tm_hour += rtc_tm.tm_min / 60; > + rtc_tm.tm_min %= 60; > + } > + if (rtc_tm.tm_hour >= 24) { > + rtc_tm.tm_hour %= 24; > + } > + errno = 0; > + if (ioctl(fd, RTC_ALM_SET, &rtc_tm) < 0) { > + if (errno == ENOTTY) { > + fwts_log_error(fw, "Real Time Clock device %s does not support alarm interrupts.", fwts_rtc); > + ret = FWTS_ERROR; > + goto out; > + } > + } > + if (ioctl(fd, RTC_AIE_ON, 0) < 0) { > + fwts_log_error(fw, "Cannot enable alarm interrupts on Real Time Clock device %s.", fwts_rtc); > + ret = FWTS_ERROR; > + } > +out: > + (void)close(fd); > + > + return ret; > +} > + > +int fwts_wakealarm_cancel(fwts_framework *fw) > +{ > + int fd, ret = FWTS_OK; > + > + if ((fd = open(fwts_rtc, O_RDWR)) < 0) { > + fwts_log_error(fw, "Cannot access Real Time Clock device %s.", fwts_rtc); > return FWTS_ERROR; > + } > + > + if (ioctl(fd, RTC_AIE_OFF, 0) < 0) { > + fwts_log_error(fw, "Cannot read Real Time Clock with ioctl RTC_RD_TIME %s.", fwts_rtc); > + ret = FWTS_ERROR; > + } > + (void)close(fd); > + > + return ret; > +} > + > +/* > + * fwts_wakealarm_check_fired() > + * check if wakealarm fires > + */ > +int fwts_wakealarm_check_fired(fwts_framework *fw, const int seconds) > +{ > + int fd, rc, ret = FWTS_OK; > + fd_set rfds; > + struct timeval tv; > > - if (!fwts_wakealarm_get_irq_state()) { > - fwts_log_error(fw, "Wakealarm %s did not get set", fwts_wkalarm); > + if ((fd = open(fwts_rtc, O_RDWR)) < 0) { > + fwts_log_error(fw, "Cannot access Real Time Clock device %s.", fwts_rtc); > return FWTS_ERROR; > } > - return FWTS_OK; > + > + FD_ZERO(&rfds); > + FD_SET(fd, &rfds); > + > + /* Wait for 1 second longer than the alarm */ > + tv.tv_sec = seconds + 1; > + tv.tv_usec = 0; > + > + /* Wait for data to be available or timeout */ > + rc = select(fd + 1, &rfds, NULL, NULL, &tv); > + if (rc == -1) { > + fwts_log_error(fw, "Select failed waitin for Real Time Clock device %s to fire.\n", fwts_rtc); > + ret = FWTS_ERROR; > + goto out; > + } > + > + /* Timed out, no data available, so alarm did not fire */ > + if (rc == 0) { > + fwts_log_error(fw, "Wakealarm Real Time Clock device %s did not fire", fwts_rtc); > + ret = FWTS_ERROR; > + } > +out: > + (void)close(fd); > + > + return ret; > } > > + > /* > * fwts_wakealarm_test_firing() > * test RTC wakealarm trigger and firing from 'seconds' seconds time > @@ -88,15 +173,15 @@ int fwts_wakealarm_trigger(fwts_framework *fw, const int seconds) > */ > int fwts_wakealarm_test_firing(fwts_framework *fw, const int seconds) > { > - int ret; > + int ret = FWTS_OK; > > - if ((ret = fwts_wakealarm_trigger(fw, seconds)) != FWTS_OK) > + if (fwts_wakealarm_trigger(fw, seconds + 2) != FWTS_OK) > return FWTS_ERROR; > > - sleep(seconds+1); > - if (fwts_wakealarm_get_irq_state() != FWTS_OK) { > - fwts_log_error(fw, "Wakealarm %s did not fire", fwts_wkalarm); > - return FWTS_ERROR; > - } > - return FWTS_OK; > + if (fwts_wakealarm_check_fired(fw, seconds + 2) != FWTS_OK) > + ret = FWTS_ERROR; > + > + fwts_wakealarm_cancel(fw); > + > + return ret; > } > Acked-by: Alex Hung <alex.hung@canonical.com>
On 10/29/2013 01:42 AM, Colin King wrote: > From: Colin Ian King <colin.king@canonical.com> > > This test fails on non-x86 architectures, so use the more generic ioctl > alarm interface instead. > > Signed-off-by: Colin Ian King <colin.king@canonical.com> > --- > src/acpi/wakealarm/wakealarm.c | 18 ++--- > src/lib/include/fwts_wakealarm.h | 5 +- > src/lib/src/fwts_wakealarm.c | 159 ++++++++++++++++++++++++++++++--------- > 3 files changed, 132 insertions(+), 50 deletions(-) > > diff --git a/src/acpi/wakealarm/wakealarm.c b/src/acpi/wakealarm/wakealarm.c > index 7f4886a..1176be0 100644 > --- a/src/acpi/wakealarm/wakealarm.c > +++ b/src/acpi/wakealarm/wakealarm.c > @@ -25,27 +25,23 @@ > #include <unistd.h> > #include <string.h> > > -static const char *wkalarm = WAKEALARM; > - > static int wakealarm_test1(fwts_framework *fw) > { > - struct stat buf; > - > - if (stat(wkalarm, &buf) == 0) > - fwts_passed(fw, WAKEALARM " found."); > + if (fwts_wakealarm_exits(fw) == FWTS_OK) > + fwts_passed(fw, "RTC with a RTC alarm ioctl() interface found."); > else { > fwts_failed(fw, LOG_LEVEL_MEDIUM, "NoWakeAlarmTest1", > - "Could not find " WAKEALARM "."); > + "Could not find an RTC with an alarm ioctl() interface."); > #ifdef FWTS_ARCH_INTEL > /* For x86 devices, this is considered a failure */ > fwts_advice(fw, > "x86 devices generally should have an RTC wake alarm that " > - "is normally controlled by the " WAKEALARM " interface. This interface " > + "is normally controlled by the RTC alarm ioctl() interface. This interface " > "does not exist, so the wake alarm tests will be aborted."); > #else > fwts_advice(fw, > "non-x86 devices sometimes do not have an RTC wake alarm that " > - "is normally controlled by the " WAKEALARM " interface. This " > + "is normally controlled by the RTC alarm ioctl() interface. This " > "interface does not exist, so the wake alarm tests will be aborted."); > #endif > return FWTS_ABORTED; > @@ -64,6 +60,8 @@ static int wakealarm_test2(fwts_framework *fw) > return FWTS_OK; > } > > + (void)fwts_wakealarm_cancel(fw); > + > fwts_passed(fw, "RTC wakealarm was triggered successfully."); > > return FWTS_OK; > @@ -122,7 +120,7 @@ static int wakealarm_test4(fwts_framework *fw) > } > > static fwts_framework_minor_test wakealarm_tests[] = { > - { wakealarm_test1, "Check existence of " WAKEALARM "." }, > + { wakealarm_test1, "Check existence of RTC with alarm interface." }, > { wakealarm_test2, "Trigger wakealarm for 1 seconds in the future." }, > { wakealarm_test3, "Check if wakealarm is fired." }, > { wakealarm_test4, "Multiple wakealarm firing tests." }, > diff --git a/src/lib/include/fwts_wakealarm.h b/src/lib/include/fwts_wakealarm.h > index df95e41..b4994fd 100644 > --- a/src/lib/include/fwts_wakealarm.h > +++ b/src/lib/include/fwts_wakealarm.h > @@ -22,10 +22,9 @@ > > #include "fwts_framework.h" > > -#define WAKEALARM "/sys/class/rtc/rtc0/wakealarm" > - > -int fwts_wakealarm_get_irq_state(void); > +int fwts_wakealarm_exits(fwts_framework *fw); > int fwts_wakealarm_test_firing(fwts_framework *fw, const int sleep); > int fwts_wakealarm_trigger(fwts_framework *fw, const int seconds); > +int fwts_wakealarm_cancel(fwts_framework *fw); > > #endif > diff --git a/src/lib/src/fwts_wakealarm.c b/src/lib/src/fwts_wakealarm.c > index f22ce4c..a2573b3 100644 > --- a/src/lib/src/fwts_wakealarm.c > +++ b/src/lib/src/fwts_wakealarm.c > @@ -18,38 +18,42 @@ > */ > #include <stdlib.h> > #include <stdio.h> > +#include <stdint.h> > +#include <errno.h> > #include <sys/types.h> > #include <sys/stat.h> > +#include <sys/ioctl.h> > #include <unistd.h> > #include <string.h> > +#include <fcntl.h> > +#include <linux/rtc.h> > > #include "fwts.h" > > -static char *fwts_wkalarm = "/sys/class/rtc/rtc0/wakealarm"; > +static char *fwts_rtc = "/dev/rtc0"; > > /* > - * fwts_wakealarm_get_irq_state() > - * get wakealarm IRQ state. checks if alarm_IRQ exists and if > - * it is set. > + * fwts_wakealarm_exits() > + * check that a RTC exists that supports minimal RTC alarm ioctl > */ > -int fwts_wakealarm_get_irq_state(void) > +int fwts_wakealarm_exits(fwts_framework *fw) > { > - FILE *fp; > - char field[32]; > - char value[32]; > + int fd; > + int ret = FWTS_OK; > + struct rtc_time rtc_tm; > > - if ((fp = fopen("/proc/driver/rtc", "r")) == NULL) > + if ((fd = open(fwts_rtc, O_RDWR)) < 0) { > + fwts_log_error(fw, "Cannot access Real Time Clock device %s.", fwts_rtc); > return FWTS_ERROR; > + } > > - while (fscanf(fp, "%s : %s\n", field, value) != EOF) { > - if (!strcmp(field, "alarm_IRQ")) { > - fclose(fp); > - return strcmp(value, "no"); > - } > + if (ioctl(fd, RTC_ALM_READ, &rtc_tm) < 0) { > + fwts_log_error(fw, "Cannot read Real Time Clock with ioctl RTC_RD_TIME %s.", fwts_rtc); > + ret = FWTS_ERROR; > } > - fclose(fp); > + (void)close(fd); > > - return FWTS_ERROR; > + return ret; > } > > /* > @@ -58,29 +62,110 @@ int fwts_wakealarm_get_irq_state(void) > */ > int fwts_wakealarm_trigger(fwts_framework *fw, const int seconds) > { > - char buffer[32]; > - int ret; > - > - snprintf(buffer, sizeof(buffer), "+%d", seconds); > + int fd, ret = FWTS_OK; > + struct rtc_time rtc_tm; > > - if (fwts_set("0", fwts_wkalarm)) { > - fwts_log_error(fw, "Cannot write '0' to %s", fwts_wkalarm); > + if ((fd = open(fwts_rtc, O_RDWR)) < 0) { > + fwts_log_error(fw, "Cannot access Real Time Clock device %s.", fwts_rtc); > return FWTS_ERROR; > } > - if (fwts_set(buffer, fwts_wkalarm)) { > - fwts_log_error(fw, "Cannot write '%s' to %s", buffer, fwts_wkalarm); > - return FWTS_ERROR; > + > + if (ioctl(fd, RTC_RD_TIME, &rtc_tm) < 0) { > + fwts_log_error(fw, "Cannot read Real Time Clock with ioctl RTC_RD_TIME %s.", fwts_rtc); > + ret = FWTS_ERROR; > + goto out; > } > - if ((ret = fwts_wakealarm_get_irq_state()) == FWTS_ERROR) > + > + rtc_tm.tm_sec += seconds; > + if (rtc_tm.tm_sec >= 60) { > + rtc_tm.tm_min += rtc_tm.tm_sec / 60; > + rtc_tm.tm_sec %= 60; > + } > + if (rtc_tm.tm_min >= 60) { > + rtc_tm.tm_hour += rtc_tm.tm_min / 60; > + rtc_tm.tm_min %= 60; > + } > + if (rtc_tm.tm_hour >= 24) { > + rtc_tm.tm_hour %= 24; > + } > + errno = 0; > + if (ioctl(fd, RTC_ALM_SET, &rtc_tm) < 0) { > + if (errno == ENOTTY) { > + fwts_log_error(fw, "Real Time Clock device %s does not support alarm interrupts.", fwts_rtc); > + ret = FWTS_ERROR; > + goto out; > + } > + } > + if (ioctl(fd, RTC_AIE_ON, 0) < 0) { > + fwts_log_error(fw, "Cannot enable alarm interrupts on Real Time Clock device %s.", fwts_rtc); > + ret = FWTS_ERROR; > + } > +out: > + (void)close(fd); > + > + return ret; > +} > + > +int fwts_wakealarm_cancel(fwts_framework *fw) > +{ > + int fd, ret = FWTS_OK; > + > + if ((fd = open(fwts_rtc, O_RDWR)) < 0) { > + fwts_log_error(fw, "Cannot access Real Time Clock device %s.", fwts_rtc); > return FWTS_ERROR; > + } > + > + if (ioctl(fd, RTC_AIE_OFF, 0) < 0) { > + fwts_log_error(fw, "Cannot read Real Time Clock with ioctl RTC_RD_TIME %s.", fwts_rtc); > + ret = FWTS_ERROR; > + } > + (void)close(fd); > + > + return ret; > +} > + > +/* > + * fwts_wakealarm_check_fired() > + * check if wakealarm fires > + */ > +int fwts_wakealarm_check_fired(fwts_framework *fw, const int seconds) > +{ > + int fd, rc, ret = FWTS_OK; > + fd_set rfds; > + struct timeval tv; > > - if (!fwts_wakealarm_get_irq_state()) { > - fwts_log_error(fw, "Wakealarm %s did not get set", fwts_wkalarm); > + if ((fd = open(fwts_rtc, O_RDWR)) < 0) { > + fwts_log_error(fw, "Cannot access Real Time Clock device %s.", fwts_rtc); > return FWTS_ERROR; > } > - return FWTS_OK; > + > + FD_ZERO(&rfds); > + FD_SET(fd, &rfds); > + > + /* Wait for 1 second longer than the alarm */ > + tv.tv_sec = seconds + 1; > + tv.tv_usec = 0; > + > + /* Wait for data to be available or timeout */ > + rc = select(fd + 1, &rfds, NULL, NULL, &tv); > + if (rc == -1) { > + fwts_log_error(fw, "Select failed waitin for Real Time Clock device %s to fire.\n", fwts_rtc); > + ret = FWTS_ERROR; > + goto out; > + } > + > + /* Timed out, no data available, so alarm did not fire */ > + if (rc == 0) { > + fwts_log_error(fw, "Wakealarm Real Time Clock device %s did not fire", fwts_rtc); > + ret = FWTS_ERROR; > + } > +out: > + (void)close(fd); > + > + return ret; > } > > + > /* > * fwts_wakealarm_test_firing() > * test RTC wakealarm trigger and firing from 'seconds' seconds time > @@ -88,15 +173,15 @@ int fwts_wakealarm_trigger(fwts_framework *fw, const int seconds) > */ > int fwts_wakealarm_test_firing(fwts_framework *fw, const int seconds) > { > - int ret; > + int ret = FWTS_OK; > > - if ((ret = fwts_wakealarm_trigger(fw, seconds)) != FWTS_OK) > + if (fwts_wakealarm_trigger(fw, seconds + 2) != FWTS_OK) > return FWTS_ERROR; > > - sleep(seconds+1); > - if (fwts_wakealarm_get_irq_state() != FWTS_OK) { > - fwts_log_error(fw, "Wakealarm %s did not fire", fwts_wkalarm); > - return FWTS_ERROR; > - } > - return FWTS_OK; > + if (fwts_wakealarm_check_fired(fw, seconds + 2) != FWTS_OK) > + ret = FWTS_ERROR; > + > + fwts_wakealarm_cancel(fw); > + > + return ret; > } > Acked-by: Alex Hung <alex.hung@canonical.com>
On 10/29/2013 01:42 AM, Colin King wrote: > From: Colin Ian King <colin.king@canonical.com> > > This test fails on non-x86 architectures, so use the more generic ioctl > alarm interface instead. > > Signed-off-by: Colin Ian King <colin.king@canonical.com> > --- > src/acpi/wakealarm/wakealarm.c | 18 ++--- > src/lib/include/fwts_wakealarm.h | 5 +- > src/lib/src/fwts_wakealarm.c | 159 ++++++++++++++++++++++++++++++--------- > 3 files changed, 132 insertions(+), 50 deletions(-) > > diff --git a/src/acpi/wakealarm/wakealarm.c b/src/acpi/wakealarm/wakealarm.c > index 7f4886a..1176be0 100644 > --- a/src/acpi/wakealarm/wakealarm.c > +++ b/src/acpi/wakealarm/wakealarm.c > @@ -25,27 +25,23 @@ > #include <unistd.h> > #include <string.h> > > -static const char *wkalarm = WAKEALARM; > - > static int wakealarm_test1(fwts_framework *fw) > { > - struct stat buf; > - > - if (stat(wkalarm, &buf) == 0) > - fwts_passed(fw, WAKEALARM " found."); > + if (fwts_wakealarm_exits(fw) == FWTS_OK) > + fwts_passed(fw, "RTC with a RTC alarm ioctl() interface found."); > else { > fwts_failed(fw, LOG_LEVEL_MEDIUM, "NoWakeAlarmTest1", > - "Could not find " WAKEALARM "."); > + "Could not find an RTC with an alarm ioctl() interface."); > #ifdef FWTS_ARCH_INTEL > /* For x86 devices, this is considered a failure */ > fwts_advice(fw, > "x86 devices generally should have an RTC wake alarm that " > - "is normally controlled by the " WAKEALARM " interface. This interface " > + "is normally controlled by the RTC alarm ioctl() interface. This interface " > "does not exist, so the wake alarm tests will be aborted."); > #else > fwts_advice(fw, > "non-x86 devices sometimes do not have an RTC wake alarm that " > - "is normally controlled by the " WAKEALARM " interface. This " > + "is normally controlled by the RTC alarm ioctl() interface. This " > "interface does not exist, so the wake alarm tests will be aborted."); > #endif > return FWTS_ABORTED; > @@ -64,6 +60,8 @@ static int wakealarm_test2(fwts_framework *fw) > return FWTS_OK; > } > > + (void)fwts_wakealarm_cancel(fw); > + > fwts_passed(fw, "RTC wakealarm was triggered successfully."); > > return FWTS_OK; > @@ -122,7 +120,7 @@ static int wakealarm_test4(fwts_framework *fw) > } > > static fwts_framework_minor_test wakealarm_tests[] = { > - { wakealarm_test1, "Check existence of " WAKEALARM "." }, > + { wakealarm_test1, "Check existence of RTC with alarm interface." }, > { wakealarm_test2, "Trigger wakealarm for 1 seconds in the future." }, > { wakealarm_test3, "Check if wakealarm is fired." }, > { wakealarm_test4, "Multiple wakealarm firing tests." }, > diff --git a/src/lib/include/fwts_wakealarm.h b/src/lib/include/fwts_wakealarm.h > index df95e41..b4994fd 100644 > --- a/src/lib/include/fwts_wakealarm.h > +++ b/src/lib/include/fwts_wakealarm.h > @@ -22,10 +22,9 @@ > > #include "fwts_framework.h" > > -#define WAKEALARM "/sys/class/rtc/rtc0/wakealarm" > - > -int fwts_wakealarm_get_irq_state(void); > +int fwts_wakealarm_exits(fwts_framework *fw); > int fwts_wakealarm_test_firing(fwts_framework *fw, const int sleep); > int fwts_wakealarm_trigger(fwts_framework *fw, const int seconds); > +int fwts_wakealarm_cancel(fwts_framework *fw); > > #endif > diff --git a/src/lib/src/fwts_wakealarm.c b/src/lib/src/fwts_wakealarm.c > index f22ce4c..a2573b3 100644 > --- a/src/lib/src/fwts_wakealarm.c > +++ b/src/lib/src/fwts_wakealarm.c > @@ -18,38 +18,42 @@ > */ > #include <stdlib.h> > #include <stdio.h> > +#include <stdint.h> > +#include <errno.h> > #include <sys/types.h> > #include <sys/stat.h> > +#include <sys/ioctl.h> > #include <unistd.h> > #include <string.h> > +#include <fcntl.h> > +#include <linux/rtc.h> > > #include "fwts.h" > > -static char *fwts_wkalarm = "/sys/class/rtc/rtc0/wakealarm"; > +static char *fwts_rtc = "/dev/rtc0"; > > /* > - * fwts_wakealarm_get_irq_state() > - * get wakealarm IRQ state. checks if alarm_IRQ exists and if > - * it is set. > + * fwts_wakealarm_exits() > + * check that a RTC exists that supports minimal RTC alarm ioctl > */ > -int fwts_wakealarm_get_irq_state(void) > +int fwts_wakealarm_exits(fwts_framework *fw) > { > - FILE *fp; > - char field[32]; > - char value[32]; > + int fd; > + int ret = FWTS_OK; > + struct rtc_time rtc_tm; > > - if ((fp = fopen("/proc/driver/rtc", "r")) == NULL) > + if ((fd = open(fwts_rtc, O_RDWR)) < 0) { > + fwts_log_error(fw, "Cannot access Real Time Clock device %s.", fwts_rtc); > return FWTS_ERROR; > + } > > - while (fscanf(fp, "%s : %s\n", field, value) != EOF) { > - if (!strcmp(field, "alarm_IRQ")) { > - fclose(fp); > - return strcmp(value, "no"); > - } > + if (ioctl(fd, RTC_ALM_READ, &rtc_tm) < 0) { > + fwts_log_error(fw, "Cannot read Real Time Clock with ioctl RTC_RD_TIME %s.", fwts_rtc); > + ret = FWTS_ERROR; > } > - fclose(fp); > + (void)close(fd); > > - return FWTS_ERROR; > + return ret; > } > > /* > @@ -58,29 +62,110 @@ int fwts_wakealarm_get_irq_state(void) > */ > int fwts_wakealarm_trigger(fwts_framework *fw, const int seconds) > { > - char buffer[32]; > - int ret; > - > - snprintf(buffer, sizeof(buffer), "+%d", seconds); > + int fd, ret = FWTS_OK; > + struct rtc_time rtc_tm; > > - if (fwts_set("0", fwts_wkalarm)) { > - fwts_log_error(fw, "Cannot write '0' to %s", fwts_wkalarm); > + if ((fd = open(fwts_rtc, O_RDWR)) < 0) { > + fwts_log_error(fw, "Cannot access Real Time Clock device %s.", fwts_rtc); > return FWTS_ERROR; > } > - if (fwts_set(buffer, fwts_wkalarm)) { > - fwts_log_error(fw, "Cannot write '%s' to %s", buffer, fwts_wkalarm); > - return FWTS_ERROR; > + > + if (ioctl(fd, RTC_RD_TIME, &rtc_tm) < 0) { > + fwts_log_error(fw, "Cannot read Real Time Clock with ioctl RTC_RD_TIME %s.", fwts_rtc); > + ret = FWTS_ERROR; > + goto out; > } > - if ((ret = fwts_wakealarm_get_irq_state()) == FWTS_ERROR) > + > + rtc_tm.tm_sec += seconds; > + if (rtc_tm.tm_sec >= 60) { > + rtc_tm.tm_min += rtc_tm.tm_sec / 60; > + rtc_tm.tm_sec %= 60; > + } > + if (rtc_tm.tm_min >= 60) { > + rtc_tm.tm_hour += rtc_tm.tm_min / 60; > + rtc_tm.tm_min %= 60; > + } > + if (rtc_tm.tm_hour >= 24) { > + rtc_tm.tm_hour %= 24; > + } > + errno = 0; > + if (ioctl(fd, RTC_ALM_SET, &rtc_tm) < 0) { > + if (errno == ENOTTY) { > + fwts_log_error(fw, "Real Time Clock device %s does not support alarm interrupts.", fwts_rtc); > + ret = FWTS_ERROR; > + goto out; > + } > + } > + if (ioctl(fd, RTC_AIE_ON, 0) < 0) { > + fwts_log_error(fw, "Cannot enable alarm interrupts on Real Time Clock device %s.", fwts_rtc); > + ret = FWTS_ERROR; > + } > +out: > + (void)close(fd); > + > + return ret; > +} > + > +int fwts_wakealarm_cancel(fwts_framework *fw) > +{ > + int fd, ret = FWTS_OK; > + > + if ((fd = open(fwts_rtc, O_RDWR)) < 0) { > + fwts_log_error(fw, "Cannot access Real Time Clock device %s.", fwts_rtc); > return FWTS_ERROR; > + } > + > + if (ioctl(fd, RTC_AIE_OFF, 0) < 0) { > + fwts_log_error(fw, "Cannot read Real Time Clock with ioctl RTC_RD_TIME %s.", fwts_rtc); > + ret = FWTS_ERROR; > + } > + (void)close(fd); > + > + return ret; > +} > + > +/* > + * fwts_wakealarm_check_fired() > + * check if wakealarm fires > + */ > +int fwts_wakealarm_check_fired(fwts_framework *fw, const int seconds) > +{ > + int fd, rc, ret = FWTS_OK; > + fd_set rfds; > + struct timeval tv; > > - if (!fwts_wakealarm_get_irq_state()) { > - fwts_log_error(fw, "Wakealarm %s did not get set", fwts_wkalarm); > + if ((fd = open(fwts_rtc, O_RDWR)) < 0) { > + fwts_log_error(fw, "Cannot access Real Time Clock device %s.", fwts_rtc); > return FWTS_ERROR; > } > - return FWTS_OK; > + > + FD_ZERO(&rfds); > + FD_SET(fd, &rfds); > + > + /* Wait for 1 second longer than the alarm */ > + tv.tv_sec = seconds + 1; > + tv.tv_usec = 0; > + > + /* Wait for data to be available or timeout */ > + rc = select(fd + 1, &rfds, NULL, NULL, &tv); > + if (rc == -1) { > + fwts_log_error(fw, "Select failed waitin for Real Time Clock device %s to fire.\n", fwts_rtc); > + ret = FWTS_ERROR; > + goto out; > + } > + > + /* Timed out, no data available, so alarm did not fire */ > + if (rc == 0) { > + fwts_log_error(fw, "Wakealarm Real Time Clock device %s did not fire", fwts_rtc); > + ret = FWTS_ERROR; > + } > +out: > + (void)close(fd); > + > + return ret; > } > > + > /* > * fwts_wakealarm_test_firing() > * test RTC wakealarm trigger and firing from 'seconds' seconds time > @@ -88,15 +173,15 @@ int fwts_wakealarm_trigger(fwts_framework *fw, const int seconds) > */ > int fwts_wakealarm_test_firing(fwts_framework *fw, const int seconds) > { > - int ret; > + int ret = FWTS_OK; > > - if ((ret = fwts_wakealarm_trigger(fw, seconds)) != FWTS_OK) > + if (fwts_wakealarm_trigger(fw, seconds + 2) != FWTS_OK) > return FWTS_ERROR; > > - sleep(seconds+1); > - if (fwts_wakealarm_get_irq_state() != FWTS_OK) { > - fwts_log_error(fw, "Wakealarm %s did not fire", fwts_wkalarm); > - return FWTS_ERROR; > - } > - return FWTS_OK; > + if (fwts_wakealarm_check_fired(fw, seconds + 2) != FWTS_OK) > + ret = FWTS_ERROR; > + > + fwts_wakealarm_cancel(fw); > + > + return ret; > } > Acked-by: Ivan Hu <ivan.hu@canonical.com>
diff --git a/src/acpi/wakealarm/wakealarm.c b/src/acpi/wakealarm/wakealarm.c index 7f4886a..1176be0 100644 --- a/src/acpi/wakealarm/wakealarm.c +++ b/src/acpi/wakealarm/wakealarm.c @@ -25,27 +25,23 @@ #include <unistd.h> #include <string.h> -static const char *wkalarm = WAKEALARM; - static int wakealarm_test1(fwts_framework *fw) { - struct stat buf; - - if (stat(wkalarm, &buf) == 0) - fwts_passed(fw, WAKEALARM " found."); + if (fwts_wakealarm_exits(fw) == FWTS_OK) + fwts_passed(fw, "RTC with a RTC alarm ioctl() interface found."); else { fwts_failed(fw, LOG_LEVEL_MEDIUM, "NoWakeAlarmTest1", - "Could not find " WAKEALARM "."); + "Could not find an RTC with an alarm ioctl() interface."); #ifdef FWTS_ARCH_INTEL /* For x86 devices, this is considered a failure */ fwts_advice(fw, "x86 devices generally should have an RTC wake alarm that " - "is normally controlled by the " WAKEALARM " interface. This interface " + "is normally controlled by the RTC alarm ioctl() interface. This interface " "does not exist, so the wake alarm tests will be aborted."); #else fwts_advice(fw, "non-x86 devices sometimes do not have an RTC wake alarm that " - "is normally controlled by the " WAKEALARM " interface. This " + "is normally controlled by the RTC alarm ioctl() interface. This " "interface does not exist, so the wake alarm tests will be aborted."); #endif return FWTS_ABORTED; @@ -64,6 +60,8 @@ static int wakealarm_test2(fwts_framework *fw) return FWTS_OK; } + (void)fwts_wakealarm_cancel(fw); + fwts_passed(fw, "RTC wakealarm was triggered successfully."); return FWTS_OK; @@ -122,7 +120,7 @@ static int wakealarm_test4(fwts_framework *fw) } static fwts_framework_minor_test wakealarm_tests[] = { - { wakealarm_test1, "Check existence of " WAKEALARM "." }, + { wakealarm_test1, "Check existence of RTC with alarm interface." }, { wakealarm_test2, "Trigger wakealarm for 1 seconds in the future." }, { wakealarm_test3, "Check if wakealarm is fired." }, { wakealarm_test4, "Multiple wakealarm firing tests." }, diff --git a/src/lib/include/fwts_wakealarm.h b/src/lib/include/fwts_wakealarm.h index df95e41..b4994fd 100644 --- a/src/lib/include/fwts_wakealarm.h +++ b/src/lib/include/fwts_wakealarm.h @@ -22,10 +22,9 @@ #include "fwts_framework.h" -#define WAKEALARM "/sys/class/rtc/rtc0/wakealarm" - -int fwts_wakealarm_get_irq_state(void); +int fwts_wakealarm_exits(fwts_framework *fw); int fwts_wakealarm_test_firing(fwts_framework *fw, const int sleep); int fwts_wakealarm_trigger(fwts_framework *fw, const int seconds); +int fwts_wakealarm_cancel(fwts_framework *fw); #endif diff --git a/src/lib/src/fwts_wakealarm.c b/src/lib/src/fwts_wakealarm.c index f22ce4c..a2573b3 100644 --- a/src/lib/src/fwts_wakealarm.c +++ b/src/lib/src/fwts_wakealarm.c @@ -18,38 +18,42 @@ */ #include <stdlib.h> #include <stdio.h> +#include <stdint.h> +#include <errno.h> #include <sys/types.h> #include <sys/stat.h> +#include <sys/ioctl.h> #include <unistd.h> #include <string.h> +#include <fcntl.h> +#include <linux/rtc.h> #include "fwts.h" -static char *fwts_wkalarm = "/sys/class/rtc/rtc0/wakealarm"; +static char *fwts_rtc = "/dev/rtc0"; /* - * fwts_wakealarm_get_irq_state() - * get wakealarm IRQ state. checks if alarm_IRQ exists and if - * it is set. + * fwts_wakealarm_exits() + * check that a RTC exists that supports minimal RTC alarm ioctl */ -int fwts_wakealarm_get_irq_state(void) +int fwts_wakealarm_exits(fwts_framework *fw) { - FILE *fp; - char field[32]; - char value[32]; + int fd; + int ret = FWTS_OK; + struct rtc_time rtc_tm; - if ((fp = fopen("/proc/driver/rtc", "r")) == NULL) + if ((fd = open(fwts_rtc, O_RDWR)) < 0) { + fwts_log_error(fw, "Cannot access Real Time Clock device %s.", fwts_rtc); return FWTS_ERROR; + } - while (fscanf(fp, "%s : %s\n", field, value) != EOF) { - if (!strcmp(field, "alarm_IRQ")) { - fclose(fp); - return strcmp(value, "no"); - } + if (ioctl(fd, RTC_ALM_READ, &rtc_tm) < 0) { + fwts_log_error(fw, "Cannot read Real Time Clock with ioctl RTC_RD_TIME %s.", fwts_rtc); + ret = FWTS_ERROR; } - fclose(fp); + (void)close(fd); - return FWTS_ERROR; + return ret; } /* @@ -58,29 +62,110 @@ int fwts_wakealarm_get_irq_state(void) */ int fwts_wakealarm_trigger(fwts_framework *fw, const int seconds) { - char buffer[32]; - int ret; - - snprintf(buffer, sizeof(buffer), "+%d", seconds); + int fd, ret = FWTS_OK; + struct rtc_time rtc_tm; - if (fwts_set("0", fwts_wkalarm)) { - fwts_log_error(fw, "Cannot write '0' to %s", fwts_wkalarm); + if ((fd = open(fwts_rtc, O_RDWR)) < 0) { + fwts_log_error(fw, "Cannot access Real Time Clock device %s.", fwts_rtc); return FWTS_ERROR; } - if (fwts_set(buffer, fwts_wkalarm)) { - fwts_log_error(fw, "Cannot write '%s' to %s", buffer, fwts_wkalarm); - return FWTS_ERROR; + + if (ioctl(fd, RTC_RD_TIME, &rtc_tm) < 0) { + fwts_log_error(fw, "Cannot read Real Time Clock with ioctl RTC_RD_TIME %s.", fwts_rtc); + ret = FWTS_ERROR; + goto out; } - if ((ret = fwts_wakealarm_get_irq_state()) == FWTS_ERROR) + + rtc_tm.tm_sec += seconds; + if (rtc_tm.tm_sec >= 60) { + rtc_tm.tm_min += rtc_tm.tm_sec / 60; + rtc_tm.tm_sec %= 60; + } + if (rtc_tm.tm_min >= 60) { + rtc_tm.tm_hour += rtc_tm.tm_min / 60; + rtc_tm.tm_min %= 60; + } + if (rtc_tm.tm_hour >= 24) { + rtc_tm.tm_hour %= 24; + } + errno = 0; + if (ioctl(fd, RTC_ALM_SET, &rtc_tm) < 0) { + if (errno == ENOTTY) { + fwts_log_error(fw, "Real Time Clock device %s does not support alarm interrupts.", fwts_rtc); + ret = FWTS_ERROR; + goto out; + } + } + if (ioctl(fd, RTC_AIE_ON, 0) < 0) { + fwts_log_error(fw, "Cannot enable alarm interrupts on Real Time Clock device %s.", fwts_rtc); + ret = FWTS_ERROR; + } +out: + (void)close(fd); + + return ret; +} + +int fwts_wakealarm_cancel(fwts_framework *fw) +{ + int fd, ret = FWTS_OK; + + if ((fd = open(fwts_rtc, O_RDWR)) < 0) { + fwts_log_error(fw, "Cannot access Real Time Clock device %s.", fwts_rtc); return FWTS_ERROR; + } + + if (ioctl(fd, RTC_AIE_OFF, 0) < 0) { + fwts_log_error(fw, "Cannot read Real Time Clock with ioctl RTC_RD_TIME %s.", fwts_rtc); + ret = FWTS_ERROR; + } + (void)close(fd); + + return ret; +} + +/* + * fwts_wakealarm_check_fired() + * check if wakealarm fires + */ +int fwts_wakealarm_check_fired(fwts_framework *fw, const int seconds) +{ + int fd, rc, ret = FWTS_OK; + fd_set rfds; + struct timeval tv; - if (!fwts_wakealarm_get_irq_state()) { - fwts_log_error(fw, "Wakealarm %s did not get set", fwts_wkalarm); + if ((fd = open(fwts_rtc, O_RDWR)) < 0) { + fwts_log_error(fw, "Cannot access Real Time Clock device %s.", fwts_rtc); return FWTS_ERROR; } - return FWTS_OK; + + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + /* Wait for 1 second longer than the alarm */ + tv.tv_sec = seconds + 1; + tv.tv_usec = 0; + + /* Wait for data to be available or timeout */ + rc = select(fd + 1, &rfds, NULL, NULL, &tv); + if (rc == -1) { + fwts_log_error(fw, "Select failed waitin for Real Time Clock device %s to fire.\n", fwts_rtc); + ret = FWTS_ERROR; + goto out; + } + + /* Timed out, no data available, so alarm did not fire */ + if (rc == 0) { + fwts_log_error(fw, "Wakealarm Real Time Clock device %s did not fire", fwts_rtc); + ret = FWTS_ERROR; + } +out: + (void)close(fd); + + return ret; } + /* * fwts_wakealarm_test_firing() * test RTC wakealarm trigger and firing from 'seconds' seconds time @@ -88,15 +173,15 @@ int fwts_wakealarm_trigger(fwts_framework *fw, const int seconds) */ int fwts_wakealarm_test_firing(fwts_framework *fw, const int seconds) { - int ret; + int ret = FWTS_OK; - if ((ret = fwts_wakealarm_trigger(fw, seconds)) != FWTS_OK) + if (fwts_wakealarm_trigger(fw, seconds + 2) != FWTS_OK) return FWTS_ERROR; - sleep(seconds+1); - if (fwts_wakealarm_get_irq_state() != FWTS_OK) { - fwts_log_error(fw, "Wakealarm %s did not fire", fwts_wkalarm); - return FWTS_ERROR; - } - return FWTS_OK; + if (fwts_wakealarm_check_fired(fw, seconds + 2) != FWTS_OK) + ret = FWTS_ERROR; + + fwts_wakealarm_cancel(fw); + + return ret; }