Automatically creating device nodes without the need of user using mknod

In our previous post, we have created a null device which acts a block hole. We will add logic in our driver code to avoid user using mknod to create /dev/my_null, instead allow driver to automatically create it on loading the module.


Code:


#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kdev_t.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/cdev.h>
MODULE_LICENSE("GPL");
dev_t device_number;
bool dynamic = true;
struct class *my_class;
static struct cdev my_cdev;
static int mydevice_open(struct inode *inode, struct file *file)
{
pr_info("%s\n", __func__);
return 0;
}
static int mydevice_release(struct inode *inode, struct file *file)
{
pr_info("%s\n", __func__);
return 0;
}
ssize_t mydevice_read(struct file *file, char __user *user_buffer,
size_t count, loff_t *offset)
{
pr_info("%s\n", __func__);
return 0;
}
ssize_t mydevice_write(struct file *file, const char __user *user_buffer,
size_t count, loff_t *offset)
{
pr_info("%s\n", __func__);
return count;
}
struct file_operations fops = {
.owner = THIS_MODULE,
.open = mydevice_open,
.release = mydevice_release,
.read = mydevice_read,
.write = mydevice_write
};
static int mynull_device_init(void)
{
int retval;
pr_info("%s: In init\n", __func__);
if (dynamic) {
retval = alloc_chrdev_region(&device_number, 0, 1, "embedded");
}
else {
device_number = MKDEV(180, 0);
retval = register_chrdev_region(device_number, 1, "embedded");
}
if (!retval) {
pr_info("%s: Major Number:%d\t Minor Number:%d\n",
__func__, MAJOR(device_number), MINOR(device_number));
my_class = class_create(THIS_MODULE, "my_driver_class");
cdev_init(&my_cdev, &fops);
retval = cdev_add(&my_cdev, device_number, 1);
if (retval) {
pr_info("%s: Failed in adding cdev to subsystem "
"retval:%d\n", __func__, retval);
}
else {
device_create(my_class, NULL, device_number, NULL, "my_null");
}
}
else
pr_err("%s: Failed in allocating device number "
"Error:%d\n", __func__, retval);
return retval;
}
static void mynull_device_exit(void)
{
cdev_del(&my_cdev);
device_destroy(my_class, device_number);
class_destroy(my_class);
unregister_chrdev_region(device_number, 5);
pr_info("%s: In exit\n", __func__);
}
module_init(mynull_device_init);
module_exit(mynull_device_exit);
view raw null_device.c hosted with ❤ by GitHub


Output:


Notes:

Automatic creating/deleting of device nodes is handled by udev. For udev to work properly, device driver should expose major and minor number to sysfs, that is done by below API's

1. device_create — creates a device and registers it with sysfs. Verify it with (find /sys -name 'my_null')
2. class_create — create a struct class structure (ls -l /sys/class/my_driver_class)


Comments

Popular posts from this blog

bb.utils.contains yocto

Difference between RDEPENDS and DEPENDS in Yocto

PR, PN and PV Variable in Yocto