Advertisement
Guest User

scullc

a guest
Sep 12th, 2019
126
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.81 KB | None | 0 0
  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/init.h>
  4. #include <linux/moduleparam.h>
  5. #include <linux/kdev_t.h>
  6. #include <linux/fs.h>
  7. #include <linux/cdev.h>
  8. #include <linux/slab.h>
  9. #include <linux/errno.h>
  10. #include <linux/uaccess.h>
  11. #include "scullc.h"
  12.  
  13. MODULE_LICENSE("Dual BSD/GPL");
  14. MODULE_DESCRIPTION("STARTING DEVICE DRIVERS");
  15.  
  16. static int major = SCULLC_MAJOR;
  17. static int minor = SCULLC_MINOR;
  18. static int count = SCULLC_COUNT;
  19. static int scullc_qset =    SCULLC_QSET;
  20. static int scullc_quantum = SCULLC_QUANTUM;
  21.  
  22. module_param(major,int,0);
  23. module_param(minor,int,0);
  24.  
  25. struct scull_qset {
  26.     void **data;
  27.     struct scull_qset *next;
  28. };
  29.  
  30. struct scull_dev {
  31.     struct scull_qset *data;
  32.     int quantum;
  33.     int qset;
  34.     unsigned long size;
  35.     unsigned int access_key;
  36.     struct semaphore sem;
  37.     struct cdev cdev;
  38. };
  39.  
  40. struct scull_dev *scullc_devices;
  41.  
  42. int scull_trim(struct scull_dev*);
  43.  
  44. int scull_open(struct inode *inode, struct file *filp)
  45. {
  46.     struct scull_dev *dev;
  47.  
  48.     dev = container_of(inode->i_cdev,struct scull_dev, cdev);
  49.     filp->private_data = dev;
  50.  
  51.     if ((filp->f_flags & O_ACCMODE) == O_WRONLY)
  52.         return 0;
  53.         //scull_trim(dev);
  54.     return 0;
  55. }
  56.  
  57. int scull_release(struct inode *inode, struct file *filp)
  58. {
  59.     return 0;
  60. }
  61.  
  62. struct scull_qset * scull_follow(struct scull_dev *dev, int n)
  63. {
  64.     struct scull_qset *dptr = dev->data;
  65.     while(n--) {
  66.         if (!dptr->next) {
  67.             dptr->next = kmalloc(sizeof(struct scull_qset),GFP_KERNEL);
  68.             memset(dptr->next,0,sizeof(struct scull_qset));
  69.         }
  70.         dptr = dptr->next;
  71.         continue;
  72.     }
  73.     return dptr;
  74. }
  75.  
  76. ssize_t scull_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
  77. {
  78.     struct scull_dev *dev = filp->private_data;
  79.     struct scull_qset *dptr;
  80.     int quantum = dev->quantum, qset = dev->qset;
  81.     int itemsize = quantum * qset;
  82.     int item, s_pos, q_pos, rest;
  83.     ssize_t retval = 0;
  84.  
  85.     if (down_interruptible(&dev->sem))
  86.         return -ERESTARTSYS;
  87.     if (*f_pos >= dev->size)
  88.         goto out;
  89.     if (*f_pos + count > dev->size)
  90.         count = dev->size - *f_pos;
  91.  
  92.     item = (long)*f_pos / itemsize;
  93.     rest = (long)*f_pos % itemsize;
  94.     s_pos = rest / quantum; q_pos = rest % quantum;
  95.  
  96.     dptr = scull_follow(dev,item);
  97.  
  98.     if (dptr == NULL || !dptr->data || !dptr->data[s_pos])
  99.         goto out;
  100.  
  101.     if (count > quantum - q_pos)
  102.         count = quantum - q_pos;
  103.  
  104.     if (copy_to_user(buf,dptr->data[s_pos] + q_pos,count)) {
  105.         retval = -EFAULT;
  106.         goto out;
  107.     }
  108.     *f_pos += count;
  109.     retval = count;
  110.  
  111.     out:
  112.       up(&dev->sem);
  113.       return retval;
  114. }
  115.  
  116. ssize_t scull_write(struct file *filp, const char __user *buf,
  117.         size_t count, loff_t *f_pos)
  118. {
  119.     struct scull_dev *dev = filp->private_data;
  120.     struct scull_qset *dptr;
  121.     int quantum = dev->quantum, qset = dev->qset;
  122.     int itemsize = quantum * qset;
  123.     int item, s_pos, q_pos, rest;
  124.     ssize_t retval = -ENOMEM;
  125.  
  126.     if (down_interruptible(&dev->sem))
  127.         return -ERESTARTSYS;
  128.  
  129.     item = (long)*f_pos / itemsize;
  130.     rest = (long)*f_pos % itemsize;
  131.     s_pos = rest / quantum; q_pos = rest % quantum;
  132.  
  133.     dptr = scull_follow(dev,item);
  134.  
  135.     if (dptr == NULL)
  136.         goto out;
  137.     if (!dptr->data) {
  138.         dptr->data = kmalloc(qset * sizeof(char *), GFP_KERNEL);
  139.         if (!dptr->data)
  140.             goto out;
  141.         memset(dptr->data,0,qset * sizeof(char*));
  142.     }
  143.     if (!dptr->data[s_pos]) {
  144.         dptr->data[s_pos] = kmalloc(quantum,GFP_KERNEL);
  145.         if (!dptr->data[s_pos])
  146.             goto out;
  147.     }
  148.     if (count > quantum - q_pos)
  149.         count = quantum - q_pos;
  150.  
  151.     if (copy_from_user(dptr->data[s_pos] + q_pos, buf, count)) {
  152.         retval = -EFAULT;
  153.         goto out;
  154.     }
  155.     *f_pos += count;
  156.     retval = count;
  157.  
  158.     if (dev->size < *f_pos)
  159.         dev->size = *f_pos;
  160.  
  161.     out:
  162.       up(&dev->sem);
  163.       return retval;
  164. }
  165.  
  166. struct file_operations scull_fops = {
  167.     .owner   = THIS_MODULE,
  168.     .open    = scull_open,
  169.     .release = scull_release,
  170. };
  171.  
  172. /*
  173. int scull_trim(struct scull_dev *dev)
  174. {
  175.     struct scull_qset *next, *dptr;
  176.     int qset = dev->qset;
  177.     int i;
  178.  
  179.     for (dptr = dev->data; dptr; dptr = next) {
  180.         if (dptr->data) {
  181.             for (i = 0; i < qset; i++)
  182.                 kfree(dptr->data[i]);
  183.             kfree(dptr->data);
  184.             dptr->data = NULL;
  185.         }
  186.         next = dptr->next;
  187.         kfree(dptr);
  188.     }
  189.     dev->size = 0;
  190.     dev->quantum = scullc_quantum;
  191.     dev->qset = scullc_qset;
  192.     dev->data = NULL;
  193.     return 0;
  194. }*/
  195.  
  196. static void scull_setup_cdev(struct scull_dev *dev, int index)
  197. {
  198.     int err, devno = MKDEV(major, minor + index);
  199.  
  200.     cdev_init(&dev->cdev,&scull_fops);
  201.     dev->cdev.owner = THIS_MODULE;
  202.     dev->cdev.ops = &scull_fops;
  203.     err = cdev_add(&dev->cdev,devno,1);
  204.     if (err)
  205.         printk(KERN_NOTICE "Error %d adding scull%d",err,index);
  206. }
  207.  
  208. static int initt(void)
  209. {
  210.     int result, i;
  211.     dev_t dev;
  212.  
  213.     if (major) {
  214.         dev = MKDEV(major,minor);
  215.         printk(KERN_WARNING "Manually registering device\n");
  216.         result = register_chrdev_region(dev,count,"scullc");
  217.     } else {
  218.         printk(KERN_WARNING "Automatically registering device\n");
  219.         alloc_chrdev_region(&dev,0,count,"scullc");
  220.         result = major = MAJOR(dev);
  221.     }
  222.  
  223.     if (result < 0) {
  224.         printk(KERN_CRIT "Failed obtaining major number\n");
  225.         return result;
  226.     }
  227.  
  228.     printk(KERN_WARNING "Major is %d\n",major);
  229.  
  230.     scullc_devices = kmalloc(sizeof(struct scull_dev)*count,GFP_KERNEL);
  231.  
  232.     printk(KERN_CRIT "Scullc_devices is %s",
  233.         (scullc_devices) ? "NONNULL" : "NULL");
  234.     printk(KERN_CRIT "scullc_devices @%p",scullc_devices);
  235.  
  236.     if (!scullc_devices)
  237.         goto fail;
  238.  
  239.     memset(scullc_devices,0,sizeof(struct scull_dev)*count);
  240.     for (i = 0; i < count; i++) {
  241.         scullc_devices[i].quantum = scullc_quantum;
  242.         scullc_devices[i].qset = scullc_qset;
  243.         scull_setup_cdev(scullc_devices + i, i);
  244.     }
  245.  
  246.     return 0;
  247.  
  248.     fail:
  249.         unregister_chrdev_region(dev,count);
  250.         return result;
  251. }
  252.  
  253. static void exitt(void) {
  254.     int i;
  255.  
  256.     printk(KERN_WARNING "ON EXIT\n");
  257.  
  258.     for (i = 0; i < count; i++) {
  259.         cdev_del(&scullc_devices[i].cdev);
  260.     }
  261.  
  262.     unregister_chrdev_region(major,count);
  263. }
  264.  
  265. module_init(initt);
  266. module_exit(exitt);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement