Demo
26 Nov 2024
Read time: 4 minute(s)
本次 Demo 是通过 ioctl 接口来访问设备节点
/dev/rtc0:
#include "base.h"
#include <sys/time.h>
#include <linux/rtc.h>
/* Global macro and variables */
#define ALARM_MAX_DELAY (60 * 60)
#define ALARM_MIN_DELAY 1
static const char sopts[] = "d:u";
static const struct option lopts[] = {
{"delay", required_argument, NULL, 'd'},
{"usage", no_argument, NULL, 'u'},
{0, 0, 0, 0}
};
/* Functions */
void usage(char *program)
{
printf("Usage: %s will start a timer of given seconds, and wait it\n",
program);
printf("\t -d, --delay\trange: [%d, %d]\n", ALARM_MIN_DELAY,
ALARM_MAX_DELAY);
printf("\t -u, --usage \n");
printf("\n");
printf("Example: %s -d 12\n\n", program);
}
/* Open a device file to be needed. */
int device_open(char *_fname, int _flag)
{
s32 fd = -1;
fd = open(_fname, _flag);
if (fd < 0) {
ERR("Failed to open %s errno: %d[%s]\n",
_fname, errno, strerror(errno));
exit(0);
}
return fd;
}
int main(int argc, char **argv)
{
int c, ret;
int delay = 0;
int rtc_fd = -1;
time_t tmp = 0;
struct rtc_time start = {0};
struct rtc_time end = {0};
struct rtc_wkalrm alrm_set = {0};
struct rtc_wkalrm alrm_get = {0};
DBG("Compile time: %s\n", __TIME__);
while ((c = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
switch (c) {
case 'd':
delay = str2int(optarg);
continue;
case 'u':
usage(argv[0]);
return 0;
default:
break;
}
}
if ((delay < ALARM_MIN_DELAY) || (delay > ALARM_MAX_DELAY)) {
ERR("Invalid delay: %d\n", delay);
return -1;
}
rtc_fd = open("/dev/rtc0", O_RDWR);
if (rtc_fd < 0) {
ERR("Failed to open RTC device!\n");
return -1;
}
DBG("ioctl(%#x)\n", RTC_RD_TIME);
ret = ioctl(rtc_fd, RTC_RD_TIME, &start);
if (ret < 0) {
ERR("Failed to read RTC time!\n");
goto err;
}
DBG("Current time: %04d-%02d-%02d %02d:%02d:%02d\n",
start.tm_year, start.tm_mon, start.tm_mday,
start.tm_hour, start.tm_min, start.tm_sec);
alrm_set.enabled = 1;
tmp = mktime((struct tm *)&start) + delay;
memcpy(&alrm_set.time, gmtime(&tmp), sizeof(struct rtc_time));
DBG("ioctl(%#x)\n", RTC_WKALM_SET);
ret = ioctl(rtc_fd, RTC_WKALM_SET, &alrm_set);
if (ret < 0) {
ERR("Failed to set alarm! [%d]: %s\n", errno, strerror(errno));
goto err;
}
DBG("Set a alarm to: %04d-%02d-%02d %02d:%02d:%02d\n",
alrm_set.time.tm_year, alrm_set.time.tm_mon,
alrm_set.time.tm_mday, alrm_set.time.tm_hour,
alrm_set.time.tm_min, alrm_set.time.tm_sec);
do {
memset(&alrm_get, 0, sizeof(struct rtc_wkalrm));
DBG("ioctl(%#x)\n", RTC_WKALM_RD);
ret = ioctl(rtc_fd, RTC_WKALM_RD, &alrm_get);
if (ret < 0) {
ERR("Failed to read alarm!\n");
goto err;
}
if (alrm_get.pending)
break;
printf("Waiting ...\n");
usleep(200000); // 200ms
} while (1);
DBG("ioctl(%#x)\n", RTC_RD_TIME);
ret = ioctl(rtc_fd, RTC_RD_TIME, &end);
if (ret < 0) {
ERR("Failed to read RTC time!\n");
goto err;
}
DBG("Current time: %04d-%02d-%02d %02d:%02d:%02d\n",
end.tm_year, end.tm_mon, end.tm_mday,
end.tm_hour, end.tm_min, end.tm_sec);
tmp = mktime((struct tm *)&end) - mktime((struct tm *)&start);
DBG("Start a timer of %d, actualy is %ld ...\n", delay, tmp);
if (ret != delay) {
ERR("The timer is not accurate!\n");
ret = -1;
}
else {
DBG("The timer is good!\n");
ret = 0;
}
err:
if (rtc_fd > 0)
close(rtc_fd);
return ret;
}