Template Information

Trang

IOCTL program in Linux Device Driver

Thứ Bảy, 4 tháng 6, 2011 / 21:53

#include<linux/init.h>
#include<linux/module.h>
#include<linux/types.h>
#include<linux/kdev_t.h>
#include<linux/fs.h>
#include<linux/slab.h>
#include<linux/cdev.h>
#include<asm/uaccess.h>
#include<linux/ioctl.h>
#define SCULL_IOCSQUANTUM

_IOW(SCULL_IOC_MAGIC, 1, int)
#define

SCULL_IOC_MAGIC 'k'
#define SCULL_IOCRESET _IO

(SCULL_IOC_MAGIC, 0)
#define SCULL_IOC_MAXNR 14
#define SCULL_IOCGQUANTUM _IOR(SCULL_IOC_MAGIC, 5,

 int)
MODULE_LICENSE("Dual BSD/GPL");
int open1(struct

inode *inode, struct file *filp);
int close1(struct inode

*inode, struct file *filp);
int ioctl1(struct inode *inode,struct

file *filp,unsigned int cmd, unsigned long arg);
ssize_t

write1(struct file *filp,char __user *buf,size_t count,loff_t

*f_pos);
ssize_t read1(struct file *filp,char __user

*buf,size_t count,loff_t *f_pos);
int major=0;
int minor=0;
int

maxi=24;
struct file_operations scull_fops =
{
    .owner =

THIS_MODULE,
    .open =  open1,
    .read =  read1,
   

.write = write1,
    .ioctl = ioctl1,
    .release=close1,
};
struct

scull_dev
{
    void *data;
    long int maxium;
    unsigned int

long size;
    struct cdev cdev;    
};
struct scull_dev dev;

static void scull_setup_cdev(struct scull_dev *dev)
{
     int

err, devno = MKDEV(major, minor);
     cdev_init(&dev-

>cdev, &scull_fops);
     dev->cdev.owner = THIS_MODULE;


    dev->cdev.ops = &scull_fops;
     err = cdev_add

(&dev->cdev, devno, 1);
     if (err)
     printk(KERN_NOTICE

"Error %d adding scull", err);
}
static int hello(void)
{   
   
    int result,devno;
    if(major)
    {
   

devno=MKDEV(major,minor);
   

result=register_chrdev_region(major,1,"ravi");
    }
   

else
    {
    result=alloc_chrdev_region

(&devno,minor,1,"ravi");
    major=MAJOR(devno);
    }
   

if(result<0)
    return -1;
    dev.maxium=24;
   

scull_setup_cdev(&dev);
    return 0;
}


int open1(struct

inode *inode, struct file *filp)
{
    struct scull_dev

*ptr;
    ptr=container_of(inode->i_cdev,struct scull_dev,

cdev);
    filp->private_data=ptr;
    return 0;
}
int close1

(struct inode *inode, struct file *filp)
{
     return 0;
}
int

ioctl1(struct inode *inode,struct file *filp,unsigned int cmd,

unsigned long arg)
{
    int err = 0;
        int retval =

0;
    struct scull_dev *ptr;
    ptr=filp-

>private_data;
       if (_IOC_TYPE(cmd) !=

SCULL_IOC_MAGIC)
        return -1;
       if

(_IOC_NR(cmd) > SCULL_IOC_MAXNR)
       

return -1;
       if (_IOC_DIR(cmd) & _IOC_READ)
               

err = !access_ok(VERIFY_WRITE, (void __user *)arg,

_IOC_SIZE(cmd));
       else if (_IOC_DIR(cmd) &

_IOC_WRITE)
                err = !access_ok(VERIFY_READ,

(void __user *)arg, _IOC_SIZE(cmd));
       if (err)
       

return -1;
    switch(cmd)
     {
            case

SCULL_IOCSQUANTUM:
               retval =

__get_user(ptr->maxium, (int __user *)arg);
             

break;
            case SCULL_IOCGQUANTUM:
           

       retval = __put_user(ptr->maxium, (int __user

*)arg);
              break;
        }
                    

return retval;


}
ssize_t read1(struct file *filp,char __user

*buf,size_t count,loff_t *f_pos)
{
    int retval=-1;
   

struct scull_dev *ptr;
    ptr=filp->private_data;
   

if(*f_pos>=ptr->size)
    goto out;
    if((*f_pos+count)

>ptr->size)
    count=(ptr->size)-(*f_pos);
    if

(copy_to_user(buf,ptr->data,count))
    {
    retval=-1;
   

goto out;
    }
    *f_pos+=count;
    retval=count;
   

out:
    return retval;   
}

ssize_t write1(struct file

*filp,char __user *buf,size_t count,loff_t *f_pos)
{
   

int retval=-1;   
    struct scull_dev *ptr;
   

ptr=filp->private_data;
    ptr->data=kmalloc(ptr-

>maxium,GFP_KERNEL);
    ptr->size=0;
    memset

(ptr->data,0,ptr->maxium);
    if(*f_pos>=ptr->maxium)
   

goto out;
    if((*f_pos+count)>ptr->maxium)
    count=

(ptr->maxium)-(*f_pos);
    if(copy_from_user(ptr-

>data,buf,count))
    {
    retval=-1;
    goto out;
    }
   

*f_pos+=count;
    retval=count;
    if(ptr->size<*f_pos)
   

ptr->size=*f_pos;
    out:
    return retval;   
}

static

void exit1(void)

{
    //int result;
    //kfree(ptr);
   

cdev_del(&dev.cdev);
    unregister_chrdev

(major,"ravi");
}
module_init(hello);
module_exit(exit1);

0 nhận xét:

Đăng nhận xét