A simple RTC driver that reads the time from the CMOS (Real Time Clock) registers.
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/rtc.h>
MODULE_LICENSE("GPL");
static dev_t rtc_dev;
static struct cdev rtc_cdev;
static int rtc_open(struct inode *inode, struct file *file)
{
return 0;
}
static ssize_t rtc_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
{
struct rtc_time tm;
rtc_time_to_tm(get_seconds(), &tm);
if (copy_to_user(buf, &tm, sizeof(struct rtc_time)))
{
pr_err("Failed to copy data to user\n");
return -EFAULT;
}
return sizeof(struct rtc_time);
}
static const struct file_operations rtc_fops = {
.owner = THIS_MODULE,
.open = rtc_open,
.read = rtc_read,
};
static int __init rtc_init(void)
{
if (alloc_chrdev_region(&rtc_dev, 0, 1, "rtc-cmos") < 0)
{
pr_err("Failed to allocate character device region\n");
return -1;
}
cdev_init(&rtc_cdev, &rtc_fops);
rtc_cdev.owner = THIS_MODULE;
if (cdev_add(&rtc_cdev, rtc_dev, 1) < 0)
{
pr_err("Failed to add character device\n");
unregister_chrdev_region(rtc_dev, 1);
return -1;
}
pr_info("RTC CMOS Driver loaded\n");
return 0;
}
static void __exit rtc_exit(void)
{
cdev_del(&rtc_cdev);
unregister_chrdev_region(rtc_dev, 1);
pr_info("RTC CMOS Driver unloaded\n");
}
module_init(rtc_init);
module_exit(rtc_exit);
This example initializes a simple character device using the cdev
structure. The rtc_read
function reads the current system time using the get_seconds
function and converts it to an rtc_time
structure, which is then copied to the user.