Demo
本次 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; }