Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/moduleparam.h>
- #include <linux/kdev_t.h>
- #include <linux/fs.h>
- #include <linux/cdev.h>
- #include <linux/device.h>
- #include<linux/slab.h> //kmalloc()
- #include<linux/uaccess.h> //copy_to/from_user()
- #include <linux/proc_fs.h>
- #include <linux/string.h>
- #include <linux/spinlock.h>
- //uno spinlock per scrivere sul fileA
- static spinlock_t spinlock_fileA;
- #define mem_size 2048
- dev_t dev = 0;
- //uint8_t *kernel_buffer;
- static int device_file_major_number = 0;
- static const char device_name[] = "Simple-driver";
- static short size_of_message; ///< Used to remember the size of the string stored
- static int __init my_init_driver(void);
- static void __exit my_exit_driver(void);
- static int my_open(struct inode *inode, struct file *file);
- static int my_release(struct inode *inode, struct file *file);
- static ssize_t my_read(struct file *filp, char __user *buf, size_t len,loff_t * off);
- static ssize_t my_write(struct file *filp, const char *buf, size_t len, loff_t * off);
- static loff_t my_llseek(struct file *filp, loff_t off, int whence);
- static char* getFilenameAFromFilenameB(char* filenameB);
- //loff_t pos = 0;
- struct my_device_data {
- struct cdev cdev;
- /* my data starts here */
- char* kernel_buffer;
- loff_t offset;
- ssize_t size;
- //spinlock per scrivere sullo stesso kernel buffer in concorrenza
- spinlock_t spinlock_kbuffer;
- int flag;
- //...
- };
- //MOUDLE PARAM
- static char* dirA = "/home/valerio/Documents/dirA/";// directory di A
- module_param(dirA,charp,0660);
- static char* dirB = "/home/valerio/Documents/dirB/";// directory di B
- module_param(dirB,charp,0660);
- static struct file_operations fops =
- {
- .owner = THIS_MODULE,
- .read = my_read,
- .write = my_write,
- .open = my_open,
- .release = my_release,
- .llseek = my_llseek,
- };
- struct file *file_open(const char *path, int flags, int rights)
- {
- struct file *filp = NULL;
- mm_segment_t oldfs;
- int err = 0;
- oldfs = get_fs();
- set_fs(get_ds());
- filp = filp_open(path, flags, rights);
- set_fs(oldfs);
- if (IS_ERR(filp)) {
- err = PTR_ERR(filp);
- return NULL;
- }
- return filp;
- }
- void file_close(struct file *file)
- {
- filp_close(file, NULL);
- }
- static int my_open(struct inode *inode, struct file *file)
- {
- char* dentry_inode;
- struct file* fileA;
- ssize_t size_fileA;
- loff_t my_offset=0;
- //controllare i flag
- struct my_device_data *my_data;
- /* struct my_device_data *my_data;
- my_data = container_of(inode->i_cdev, struct my_device_data, cdev);
- //Creating Physical memory
- if((my_data->myKernelBuffer = kmalloc(mem_size , GFP_KERNEL)) == 0){
- printk(KERN_INFO "Cannot allocate memory in kernel\n");
- return -1;
- }
- file->private_data = my_data;
- */
- //logica del check se esiste un file in dirA
- if ((dentry_inode=getFilenameAFromFilenameB(file->f_path.dentry->d_iname))==NULL)
- {
- printk("errore nella open dalla directoryA\n");
- return -1;
- }
- printk("provo a fare il lock di spinlock fileA\n");
- spin_lock(&spinlock_fileA);
- printk("finito di fare lock di spinlock fileA\n");
- fileA=file_open(dentry_inode,O_RDWR,0);
- if (fileA ==NULL) {
- //non abbimao trovato il file in dirA
- printk (KERN_INFO "non posso aprire il file A\n");
- return -1;
- }
- size_fileA=fileA->f_path.dentry->d_inode->i_size;
- printk("info: size file A %d\n",size_fileA);
- /* if (size_fileA>mem_size){
- printk("fileA troppo grande");
- return -1;
- } */
- if ((my_data=kzalloc(sizeof(struct my_device_data),GFP_KERNEL))==NULL){
- printk("fallita la kmalloc\n");
- return -1;
- }
- if ((my_data->kernel_buffer=kzalloc(mem_size,GFP_KERNEL))==NULL){
- printk("fallita la kzalloc\n");
- return -1;
- }
- kernel_read(fileA,my_data->kernel_buffer,size_fileA,&my_offset);
- my_data->offset=0;
- my_data->size=mem_size;
- spin_lock_init(&(my_data->spinlock_kbuffer));
- my_data->flag=(file->f_flags & O_ACCMODE);
- file->private_data=my_data;
- file_close(fileA);
- /* if (size_fileA!=my_offset){
- printk("non è stato letto tutto il file\n");
- spin_unlock(&spinlock_fileA);
- return -1;
- } */
- spin_unlock(&spinlock_fileA);
- //abbiamo trovato il file in dirA
- printk(KERN_INFO "Device File Opened...!!!\n");
- return 0;
- }
- static char* getFilenameAFromFilenameB(char* filenameB){
- char* dentry_inode = kzalloc(strlen(dirA)+strlen(filenameB)+1 , GFP_KERNEL);
- if(dentry_inode==NULL){
- printk(KERN_INFO "Cannot allocate memory in kernel\n");
- return NULL;
- }
- strcpy(dentry_inode,dirA);
- strcpy(dentry_inode+strlen(dirA),filenameB);
- return dentry_inode;
- }
- static int my_release(struct inode *inode, struct file *file)
- {
- //questo devo modificarlo con llseek
- //pos=0;
- struct my_device_data *my_data;
- my_data = (struct my_device_data *) file->private_data;
- if (my_data->flag == O_RDONLY)
- return 0;
- ssize_t len=my_data->size;
- //metto l'offset a zero perchè faccio il fire di tutto il kernel buffer sul file
- loff_t off=0;
- char* dentry_inode;
- struct file* fileA;
- if ((dentry_inode=getFilenameAFromFilenameB(file->f_path.dentry->d_iname))==NULL)
- {
- printk("errore nella open dalla directoryA");
- return -1;
- }
- spin_lock(&spinlock_fileA);
- fileA=file_open(dentry_inode,O_RDWR,0);
- if (fileA ==NULL) {
- //non abbimao trovato il file in dirA
- printk (KERN_INFO "non posso aprire il file A\n");
- return -EPIPE;
- }
- printk("faccio la release del kernel buffer: %s",my_data->kernel_buffer);
- kernel_write(fileA, my_data->kernel_buffer, mem_size, &off);
- file_close(fileA);
- spin_unlock(&spinlock_fileA);
- printk(KERN_INFO "Device File Closed...!!!\n");
- return 0;
- }
- static ssize_t my_read(struct file *filp, char __user *buf, size_t size, loff_t *off)
- {
- //controllare se con la read devo spostare anche l'offset
- struct my_device_data *my_data;
- int error_count;
- ssize_t len;
- my_data = (struct my_device_data *) filp->private_data;
- if (my_data->flag==O_WRONLY){
- printk("il file era wronly, non puoi leggere\n");
- return -EFAULT;
- }
- len = min(my_data->size - *off, size);
- spin_lock(&(my_data->spinlock_kbuffer));
- if ((error_count=copy_to_user(buf, my_data->kernel_buffer + *off, len))!=0){
- printk(KERN_INFO "EBBChar: Failed to send %d characters to the user\n", error_count);
- return -EFAULT;
- }
- *off=*off+len;
- spin_unlock(&(my_data->spinlock_kbuffer));
- return len;
- }
- static ssize_t my_read2(struct file *filp, char __user *buf, size_t size, loff_t *off)
- {
- //struct my_device_data *my_data;
- //my_data = (struct my_device_data *) filp->private_data;
- //char* kernel_buffer=my_data->myKernelBuffer;
- //loff_t pos=my_data->offset;
- int i;
- //void* data; //Needs to be a kernel pointer, not userspace pointer
- int block_count; //Set me to something
- int block_size; //Set me to something
- int error_count;
- //mm_segment_t old_fs;
- //old_fs = get_fs(); //Save the current FS segment
- //set_fs(get_ds());
- char* filenameA;
- if ((filenameA=getFilenameAFromFilenameB(filp->f_path.dentry->d_iname))==NULL){
- printk("problema nel trovare il fileA\n");
- return -1;
- }
- struct file* fileA=file_open(filenameA, O_RDWR, 0);
- if (fileA ==NULL) {
- //non abbimao trovato il file in dirA
- printk (KERN_INFO "non posso aprire il file A\n");
- return -1;
- }
- if(fileA){
- //fileA->f_pos=0;
- //block_size=fileA->f_path.dentry->d_inode->i_size;
- //printk("la size del file A è %d",block_size);
- /*for(i=0; i < block_count ; i++){
- kernel_buffer=<somewhere>+block_count*i //Wherever your data is
- if(kernel_buffer==NULL){
- continue;
- }
- vfs_write(fileA, kernel_buffer, block_size, &pos);
- pos = pos+block_size;
- }*/
- //printk("pos: %d",pos);
- //printk("pos: %d",pos);
- //controllare se pos=size
- //vfs_read(fileA,kernel_buffer,block_size,&pos);
- //set_fs(old_fs); //Reset to save FS
- //struct my_device_data *my_data = (struct my_device_data *) filp->private_data;
- ssize_t len = min(fileA->f_path.dentry->d_inode->i_size - *off, size);
- loff_t my_offset=*off;
- //da cambiare l'offset, controllare che sono stati scritti tutti i byte
- //kernel_read(fileA,my_data->myKernelBuffer,len,&my_offset);
- fileA->f_pos=0;
- file_close(fileA);
- if (len <= 0)
- return 0;
- //printk("il counter +: %d",fileA->private_data);
- /* read data from my_data->buffer to user buffer */
- /*
- if ((error_count=copy_to_user(buf, my_data->myKernelBuffer + *off, len))!=0){
- printk(KERN_INFO "EBBChar: Failed to send %d characters to the user\n", error_count);
- return -EFAULT;
- }
- *off += len;
- printk(KERN_INFO "EBBChar: Sent %d characters to the user\n", len);
- return len; */
- }
- /*
- int temp = counter;
- if(*off >= len) return 0;
- temp = len - *off;
- if(len>temp)
- {
- len=temp;
- }
- copy_to_user(buf,kernel_buffer+(*off), len);
- //*offp += count;
- return len;
- */
- }
- /*void read_file(){
- // Create variables
- struct file *f;
- char buf[128];
- mm_segment_t current_fs;
- int i;
- // Init the buffer with 0
- for(i=0;i<128;i++)
- buf[i] = 0;
- // To see in /var/log/messages that the module is operating
- printk(KERN_INFO "My module is loaded\n");
- // I am using Fedora and for the test I have chosen following file
- // Obviously it is much smaller than the 128 bytes, but hell with it =)
- f = filp_open("/etc/fedora-release", O_RDONLY, 0);
- if(f == NULL)
- printk(KERN_ALERT "filp_open error!!.\n");
- else{
- // Get current segment descriptor
- current_fs = get_fs();
- // Set segment descriptor associated to kernel space
- set_fs(get_ds());
- // Read the file
- f->f_op->read(f, buf, 128, &f->f_pos);
- // Restore segment descriptor
- set_fs( current_fs);
- // See what we read from file
- printk(KERN_INFO "buf:%s\n",buf);
- }
- }*/
- /*void write(){
- char* dump_filename; //Set to the file you are targeting
- struct file *file;
- int i;
- void* data; //Needs to be a kernel pointer, not userspace pointer
- int block_count; //Set me to something
- int block_size; //Set me to something
- loff_t pos = 0;
- mm_segment_t old_fs;
- old_fs = get_fs(); //Save the current FS segment
- set_fs(get_ds());
- file = filp_open(dump_filename, O_WRONLY|O_CREAT, 0644);
- if(file){
- for(i=0; i < block_count ; i++){
- data=<somewhere>+block_count*i //Wherever your data is
- if(data==NULL){
- continue;
- }
- vfs_write(file, data, block_size, &pos);
- pos = pos+block_size;
- }
- filp_close(file,NULL);
- }
- set_fs(old_fs); //Reset to save FS
- kfree(dump_filename);
- }*/
- static ssize_t my_write(struct file *filp, const char __user *buf, size_t size, loff_t *off)
- {
- //chiedere come si comporta l'offset con l' lseek
- struct my_device_data *my_data;
- int error_count;
- ssize_t len;
- my_data = (struct my_device_data *) filp->private_data;
- if(my_data->flag==O_RDONLY){
- printk("il file è rdonly\n");
- return -EFAULT;
- }
- len = min(my_data->size - *off, size);
- if (len <= 0){
- printk("write: sto scrivendo qualcosa di lunghezza pari a 0");
- return 0;
- }
- spin_lock(&(my_data->spinlock_kbuffer));
- if ((error_count=copy_from_user(my_data->kernel_buffer + *off,buf,len))!=0){
- printk(KERN_INFO "EBBChar: Failed to send %d characters to the kernel\n", error_count);
- return -EFAULT;
- }
- my_data->size=len;
- spin_unlock(&(my_data->spinlock_kbuffer));
- return len;
- }
- loff_t my_llseek(struct file *filp, loff_t off, int whence){
- printk("hello world\n");
- struct my_device_data *my_data = (struct my_device_data *) filp->private_data;
- loff_t newpos;
- switch(whence) {
- case 0: /* SEEK_SET */
- newpos = off;
- break;
- case 1: /* SEEK_CUR */
- newpos = filp->f_pos + off;
- break;
- case 2: /* SEEK_END */
- newpos = my_data->size + off;
- break;
- default: /* can't happen */
- return -EINVAL;
- }
- if (newpos<0) return -EINVAL;
- filp->f_pos = newpos;
- my_data->offset=newpos;
- return newpos;
- }
- static ssize_t my_write2(struct file *filp, const char __user *buf, size_t size, loff_t *off)
- {
- printk("info write: size %d offset %d",size,*off);
- int counter;
- printk("inizio la write\n");
- //printk("buffer user: %s, size= %d\n",buf,len);
- //printk("buffer kernel: %s\n",kernel_buffer);
- //copy_from_user(kernel_buffer, buf+(*off), len);
- char* filenameA;
- if ((filenameA=getFilenameAFromFilenameB(filp->f_path.dentry->d_iname))==NULL){
- printk("problema nel trovare il fileA\n");
- return -1;
- }
- struct file* fileA=file_open(filenameA, O_RDWR, 0);
- if (fileA ==NULL) {
- //non abbimao trovato il file in dirA
- printk (KERN_INFO "non posso aprire il file A\n");
- return -1;
- }
- printk("write: size file %d",fileA->f_path.dentry->d_inode->i_size);
- fileA->f_pos=0;
- struct my_device_data *my_data = (struct my_device_data *) filp->private_data;
- ssize_t len = min(fileA->f_path.dentry->d_inode->i_size - *off, size);
- if (len <= 0){
- printk("write: sto scrivendo qualcosa di lunghezza pari a 0");
- return 0;
- }
- /* read data from user buffer to my_data->buffer */
- if ((counter=copy_from_user(my_data->kernel_buffer + *off, buf, len))!=0){
- printk("non ho scritto %d bytes",counter);
- return -EFAULT;
- }
- loff_t my_offset=*off;
- kernel_write(fileA, my_data->kernel_buffer, len, &my_offset);
- printk("write: ho scritto %d byte\n",len);
- *off += len;
- fileA->f_pos=0;
- file_close(fileA);
- return len;
- }
- static int register_device(void)
- {
- spin_lock_init(&spinlock_fileA);
- int result = 0;
- printk(KERN_INFO "Simple-driver: register_device() is called.\n" );
- result = register_chrdev( 0, device_name, &fops );
- if( result < 0 )
- {
- printk( KERN_INFO "Simple-driver: can\'t register character device with errorcode = %i\n", result );
- return result;
- }
- device_file_major_number = result;
- printk("Simple-driver: registered character device with major number = %i and minor numbers from 0 to 255\n", device_file_major_number );
- return 0;
- }
- void unregister_device(void)
- {
- printk( KERN_NOTICE "Simple-driver: unregister_device() is called\n" );
- if(device_file_major_number != 0)
- {
- unregister_chrdev(device_file_major_number, device_name);
- }
- }
- static int __init my_init_driver(void)
- {
- return register_device();
- /*
- //Allocating Major number
- if((alloc_chrdev_region(&dev, 0, 1, "my_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
- cdev_init(&etx_cdev,&fops);
- //Adding character device to the system
- if((cdev_add(&etx_cdev,dev,1)) < 0){
- printk(KERN_INFO "Cannot add the device to the system\n");
- goto r_class;
- }
- //Creating struct class
- if((dev_class = class_create(THIS_MODULE,"my_class")) == NULL){
- printk(KERN_INFO "Cannot create the struct class\n");
- goto r_class;
- }
- //Creating device
- if((device_create(dev_class,NULL,dev,NULL,"etx_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 my_exit_driver(void)
- {
- unregister_device();
- /*
- device_destroy(dev_class,dev);
- class_destroy(dev_class);
- cdev_del(&etx_cdev);
- unregister_chrdev_region(dev, 1);
- printk(KERN_INFO "Device Driver Remove...Done!!!\n");
- */
- }
- module_init(my_init_driver);
- module_exit(my_exit_driver);
- MODULE_LICENSE("GPL");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement