When developing a driver you have to do two basic steps before anything else: register for <major,minor>
range and then link the device file operations to the device driver functions.
Following is the working code for the init
and exit
modules of a basic char driver:
static int __init char_init(void)
{
int ret;
struct device *dev_ret;
printk(KERN_INFO "Char device registered");
if ((ret = alloc_chrdev_region(&first, 0, 3, "Abhinav")) < 0)
{
return ret;
}
if (IS_ERR(cl = class_create(THIS_MODULE, "char_dev")))
{
unregister_chrdev_region(first, 1);
return PTR_ERR(cl);
}
if (IS_ERR(dev_ret = device_create(cl, NULL, first, NULL, "mynull")))
{
class_destroy(cl);
unregister_chrdev_region(first, 1);
return PTR_ERR(dev_ret);
}
cdev_init(&c_dev, &file_ops);
if ((ret = cdev_add(&c_dev, first, 1)) < 0)
{
device_destroy(cl, first);
class_destroy(cl);
unregister_chrdev_region(first, 1);
return ret;
}
printk(KERN_INFO "<Major,Minor>: <%d, %d>\n", MAJOR(first), MINOR(first));
return 0;
}
static void __exit char_exit(void)
{
cdev_del(&c_dev);
device_destroy(cl, first);
class_destroy(cl);
unregister_chrdev_region(first, 3);
printk(KERN_INFO "Goodbye: Char device unregistered");
}
The probe
and disconnect
are left up to you.
In this code, the call to alloc_chrdev_region
is done to register for the major and minor numbers.
And the class_create
and device_create
API's are used for the creation of device file mynull
.
After executing, /dev/mynull
will be created.