[PATCH] wakealarm: use ioctl() interface as this more of a generic interface
Colin King
colin.king at canonical.com
Mon Oct 28 17:36:15 UTC 2013
From: Colin Ian King <colin.king at 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 at 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;
}
--
1.8.3.2
More information about the fwts-devel
mailing list