Patchwork [RESEND] wakealarm: use ioctl() interface as this more of a generic interface (LP: #1244184)

login
register
mail settings
Submitter Colin King
Date Oct. 28, 2013, 5:42 p.m.
Message ID <1382982135-2835-1-git-send-email-colin.king@canonical.com>
Download mbox | patch
Permalink /patch/286628/
State Accepted
Headers show

Comments

Colin King - Oct. 28, 2013, 5:42 p.m.
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(-)
Alex Hung - Oct. 31, 2013, 3:25 a.m.
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>
Alex Hung - Oct. 31, 2013, 3:36 a.m.
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>
Ivan Hu - Nov. 11, 2013, 9:41 a.m.
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>

Patch

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;
 }