Monday, October 3, 2011

Simple Character Driver


#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>

#include <linux/kdev_t.h>
#include <linux/types.h>
#include <linux/fs.h>

#include <linux/device.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>

static dev_t first;
static struct cdev c_dev;
static struct class *cl;
static char c;

static int my_open(struct inode *i, struct file *f)
{
    printk(KERN_INFO "DRIVER: open()");
    return 0;
}

static int my_close(struct inode *i, struct file *f)
{
    printk(KERN_INFO "DRIVER: close()");
    return 0;
}

static ssize_t my_read(struct file *f,char __user *buf, size_t len, loff_t *off)
{
    printk(KERN_INFO "DRIVER: read()");
    if(copy_to_user(buf,&c,1) != 0)
        return -EFAULT;
    else
        return 1;
}

static ssize_t my_write(struct file *f, const char __user *buf, size_t len, loff_t *off)
{
    printk(KERN_INFO "DRIVER: write()");
    if(copy_from_user(&c, buf+len-1,1) != 0)
        return -EFAULT;
    else
        return len;
}

static struct file_operations my_fops =
{
    .owner    = THIS_MODULE,
    .open     = my_open,
    .release  = my_close,
    .read     = my_read,
    .write    = my_write
};

static int __init dd_init(void)
{
    printk(KERN_INFO "Namaskar: dd initialization");
   
    if(alloc_chrdev_region(&first, 0, 1, "VINZU") < 0)
    {
        return -1;
    } 

    if( (cl = class_create(THIS_MODULE,"chrdrv")) == NULL)
    {
        unregister_chrdev_region(first,1);
        return -1;
    }  

    if(device_create(cl,NULL,first,NULL,"mynull") == NULL)
    {
        class_destroy(cl);
        unregister_chrdev_region(first,1);
        return -1;
    }

    cdev_init(&c_dev,&my_fops);
    if(cdev_add(&c_dev,first,1) == -1)
    {
        device_destroy(cl,first);
        class_destroy(cl);
        unregister_chrdev_region(first,1);
        return -1;
    }

    printk(KERN_INFO "dd registerd successfully...");
    return 0;
}

static void __exit dd_exit(void)
{
    cdev_del(&c_dev);
    device_destroy(cl,first);
    class_destroy(cl);
    unregister_chrdev_region(first,1);
    printk(KERN_INFO "Alvida: dd unregisterd");
}

module_init(dd_init);
module_exit(dd_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("VINOD");
MODULE_DESCRIPTION("Simple character driver");



|COMMANDS FOR TESTING:



cat /proc/devices - VINZU
ls /sys/class - chardrv
ls -l /dev - mynull

echo -n "hello" > /dev/mynull
dmesg | tail -10
cat /dev/mynull
ctrl + c
dmesg | tail -10




No comments: