Linux Kernel Driver Program: 6_File_opertions_device_driver

Linux Kernel Driver Program: 6_File_opertions_device_driver

neelkanth_surekha#cat hello_world_module.c 

/************************************************************************
 *
 * neelkanth_surekha#   sudo insmod hello_world_module.ko
 * neelkanth_surekha#   ls -lt /dev | grep dummy
 * crw-------  1 root root    242,   0 Jan 26 13:54 dummy_device_device
 *
 * neelkanth_surekha#   sudo rmmod hello_world_module.ko
 * neelkanth_surekha#   ls -lt /dev | grep dummy
 *
 ***************************************************************************/

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>

/* the dev_t for the char device to be added */
dev_t dev = 0;
/* pointer to the struct "class" that this device should be registered to */
static struct class *dev_class;
/* Character device structure */
static struct cdev dummy_device_cdev;

static int __init dummy_device_driver_init(void);
static void __exit dummy_device_driver_exit(void);
static int dummy_device_open(struct inode *inode, struct file *file);
static int dummy_device_release(struct inode *inode, struct file *file);
static ssize_t dummy_device_read(struct file *filp, char __user *buf, size_t len,loff_t * off);
static ssize_t dummy_device_write(struct file *filp, const char *buf, size_t len, loff_t * off);

static struct file_operations fops =
{
    .owner          = THIS_MODULE,
    .read           = dummy_device_read,
    .write          = dummy_device_write,
    .open           = dummy_device_open,
    .release        = dummy_device_release,
};

static int dummy_device_open(struct inode *inode, struct file *file)
{
    printk(KERN_INFO "Driver Open Function Called...!!!\n");
    return 0;
}

static int dummy_device_release(struct inode *inode, struct file *file)
{
    printk(KERN_INFO "Driver Release Function Called...!!!\n");
    return 0;
}

static ssize_t dummy_device_read(struct file *filp, char __user *buf, size_t len, loff_t *off)
{
    printk(KERN_INFO "Driver Read Function Called...!!!\n");
    return 0;
}
static ssize_t dummy_device_write(struct file *filp, const char __user *buf, size_t len, loff_t *off)
{
    printk(KERN_INFO "Driver Write Function Called...!!!\n");
    return len;
}

/*******************************************************************************************
 * How Applications will communicate with Hardware device
 * 
 * Step 1: Application
 * Step 2: Device File or device Node
 * Step 3: Major and Minor Number
 * Step 4: Device Driver
 * Step 5: Hardware 
 ******************************************************************************************/

static int __init dummy_device_driver_init(void)
{
    /* Allocating Major number */
    if((alloc_chrdev_region(&dev, 0, 1, "dummy_device_Dev")) <0){
        printk(KERN_INFO "Cannot allocate major number\n");
        return -1;
    }
    printk(KERN_INFO "Major = %d Minor = %d \n",MAJOR(dev), MINOR(dev));

    /*Creating cdev structure*/
    /* In linux kernel struct "inode" structure is used to represent files. Therefore, it is 
     * different from the file structure that represents an "open file descriptor". 
     * There can be numerous file structures representing multiple open descriptors on a 
     * single file, but they all point to a single "inode" structure.
     * The "inode" structure contains a great deal of information about the file. As a general 
     * rule, "cdev" structure is useful for writing driver code: 
     */
    cdev_init(&dummy_device_cdev, &fops);
    dummy_device_cdev.owner = THIS_MODULE;
    dummy_device_cdev.ops = &fops;

    /*Adding character device to the system*/
    if((cdev_add(&dummy_device_cdev, dev, 1)) < 0){
        printk(KERN_INFO "Cannot add the device to the system\n");
        goto r_class;
    }

    /*Creating struct class*/
    /* 
     * This will create the struct class for our device driver. 
     * It will create structure under/sys/class/.
     */            
    if((dev_class = class_create(THIS_MODULE, "dummy_device_class")) == NULL){
        printk(KERN_INFO "Cannot create the struct class\n");
        goto r_class;
    }

    /*Creating device*/
    /* 
     * This function can be used by char device classes. A struct device 
     * will be created in "sysfs", registered to the specified class. 
     */
    if((device_create(dev_class, NULL , dev, NULL, "dummy_device_device")) == NULL){
        printk(KERN_INFO "Cannot create the Device 1\n");
        goto r_device;
    }
    printk(KERN_INFO "Device Driver Insert...Done!!!\n");
    return 0;

r_device:
    class_destroy(dev_class);
r_class:
    unregister_chrdev_region(dev,1);
    return -1;
}

void __exit dummy_device_driver_exit(void)
{
    device_destroy(dev_class, dev);
    class_destroy(dev_class);
    cdev_del(&dummy_device_cdev);
    unregister_chrdev_region(dev, 1);
    printk(KERN_INFO "Device Driver Remove...Done!!!\n");
}

module_init(dummy_device_driver_init);
module_exit(dummy_device_driver_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Neelkanth Reddy <www.neelkanth.13@gmail.com>");
MODULE_DESCRIPTION("A simple device driver");
MODULE_VERSION("0:1.0");

neelkanth_surekha#cat Makefile 

obj-m += hello_world_module.o

KDIR = /lib/modules/$(shell uname -r)/build

all:
make -C $(KDIR)  M=$(shell pwd) modules

clean:
make -C $(KDIR)  M=$(shell pwd) clean