#include"linux/fs.h"
#include"linux/init.h"
#include"asm/uaccess.h"
#define MAX_SIZE_OF_DEV 10000
#define MAX_NO_OF_DEV 1
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ANKIT GUPTA");
MODULE_DESCRIPTION("Mapping Open Operation.");
void print_scull(void);
int scull_open(struct inode *inode,struct file *filp);
int scull_release(struct inode *inode,struct file *filp);
ssize_t scull_read(struct file *, char * , size_t, loff_t *);
ssize_t scull_write(struct file *, const char *, size_t, loff_t *);
struct scull_dev
{
unsigned int dev_size;
unsigned int data_size;
unsigned int dev_minor;
unsigned int read_count;
char *data;
struct scull_dev *next;
};
typedef struct scull_dev scull_dev;
struct file_operations fops=
{
open:scull_open,
release:scull_release,
read:scull_read,
write:scull_write
};
static unsigned int Major;
static unsigned int Minor;
scull_dev *sc;
int init_module(void)
{
int j=0;
printk("\n%s\n",__func__);
printk("HELLO, HI!!!\n");
Major= register_chrdev(0,"new_dev_Ankit",&fops);
printk("The character device registered is %d\n",Major);
sc=(scull_dev *)kmalloc(MAX_NO_OF_DEV * sizeof(scull_dev),GFP_KERNEL);
memset(sc,0,MAX_NO_OF_DEV *sizeof(scull_dev));
while(j
sc[j].dev_size= MAX_SIZE_OF_DEV ;
sc[j].data_size=0;
sc[j].dev_minor=0;
sc[j].read_count=0;
sc[j].data=NULL;
sc[j].next=NULL;
j++;
}
print_scull();
return 0;
}
void print_scull(void)
{
int j=0;
while(j
printk("dev_size = %d\n",sc[j].dev_size);
printk("data_size = %d\n",sc[j].data_size);
printk("data_minor = %d\n",sc[j].dev_minor);
printk("read_count = %d\n",sc[j].read_count);
printk("data = %p\n",sc[j].data);
printk("next = %p\n",sc[j].next);
j++;
}
}
void cleanup_module(void)
{
printk("\n%s\n",__func__);
printk("Gotta Go, BYE!!!\n");
unregister_chrdev(Major,"new_dev");
}
int scull_open(struct inode *inode,struct file *filp)
{
scull_dev *dev;
printk("\n%s\n",__func__);
Minor=MINOR(inode->i_rdev);
if(Minor>MAX_NO_OF_DEV)
{
printk("Error in MIONOR\n");
return -1;
}
dev=&sc[Minor];
if(dev==NULL)
{
cleanup_module();
return -1;
}
if((filp->f_flags & O_ACCMODE) == O_WRONLY)
{
printk("The device is truncated\n");
dev->data_size=0;
dev->read_count=0;
dev->data=NULL;
}
filp->private_data=dev;
printk("The opened device minor %d \n",Minor);
printk("In scull_open\n");
return 0;
}
int scull_release(struct inode *inode,struct file *filp)
{
printk("\n%s\n",__func__);
printk("In scull_release\n");
return 0;
}
ssize_t scull_read(struct file * filp, char * buff, size_t count, loff_t *fpos)
{
struct scull_dev *dev;
printk("\n%s\n",__func__);
printk("In scull_read\n");
dev = filp->private_data;
if(*fpos>dev->dev_size)
{
printk("The size has extended\n");
return -1;
}
if(*fpos+count > dev->dev_size)
{
printk("The size is more now performing partial read\n");
count=dev->dev_size - *fpos;
}
else
printk("Performing read\n");
if(copy_to_user(buff,dev->data+*fpos,count)==-1)
{
printk("Error in copy\n");
return -1;
}
*fpos=*fpos+count;
return count;
}
ssize_t scull_write(struct file * filp,const char * buff, size_t count,loff_t *fpos)
{
struct scull_dev *dev;
dev = filp->private_data;
printk("\n%s\n",__func__);
printk("In scull_write\n");
if(dev->data==NULL)
{
dev->data=(char *)kmalloc( MAX_SIZE_OF_DEV*sizeof(char),GFP_KERNEL);
if(!dev->data)
{
printk("ERROR\n");
return -1;
}
memset(dev->data,0,MAX_SIZE_OF_DEV);
}
if(*fpos>dev->dev_size)
{
printk("The size has extended\n");
return -1;
}
if(*fpos+count > dev->dev_size)
{
printk("The size is more now performing partial write\n");
count=dev->dev_size -*fpos;
}
if(copy_from_user(dev->data+*fpos,buff,count)==-1)
{
printk("Error in copy\n");
return -1;
}
printk("The data written : %s\n",dev->data);
printk("The count is : %d\n",count);
printk("The f_pos is : %d\n",*fpos);
dev->data_size=dev->data_size+count;
*fpos=dev->data_size;
return count;
}