Advertisement
Guest User

Untitled

a guest
May 26th, 2019
120
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.72 KB | None | 0 0
  1. /*
  2.  * Character device drivers lab
  3.  *
  4.  * All tasks
  5.  */
  6.  
  7. #include <linux/module.h>
  8. #include <linux/init.h>
  9. #include <linux/kernel.h>
  10. #include <linux/fs.h>
  11. #include <linux/cdev.h>
  12. #include <linux/uaccess.h>
  13. #include <linux/sched.h>
  14. #include <linux/wait.h>
  15.  
  16. #include "../include/so2_cdev.h"
  17.  
  18. MODULE_DESCRIPTION("SO2 character device");
  19. MODULE_AUTHOR("SO2");
  20. MODULE_LICENSE("GPL");
  21.  
  22. #define LOG_LEVEL   KERN_DEBUG
  23.  
  24. #define MY_MAJOR        42
  25. #define MY_MINOR        0
  26. #define NUM_MINORS      1
  27. #define MODULE_NAME     "so2_cdev"
  28. #define MESSAGE         "hello\n"
  29. #define IOCTL_MESSAGE       "Hello ioctl"
  30.  
  31. #ifndef BUFSIZ
  32. #define BUFSIZ      4096
  33. #endif
  34.  
  35.  
  36. struct so2_device_data {
  37.     /* TODO 2: add cdev member */
  38.     struct cdev c_dev;
  39.     /* TODO 4: add buffer with BUFSIZ elements */
  40.     char buffer[BUFSIZ];
  41.     /* TODO 7: extra members for home */
  42.     /* TODO 3: add atomic_t access variable to keep track if file is opened */
  43.     atomic_t access;
  44. };
  45.  
  46. struct so2_device_data devs[NUM_MINORS];
  47.  
  48. static int so2_cdev_open(struct inode *inode, struct file *file)
  49. {
  50.     struct so2_device_data *data;
  51.  
  52.     pr_info("open\n");
  53.  
  54.     /* TODO 3: inode->i_cdev contains our cdev struct, use container_of to obtain a pointer to so2_device_data */
  55.     data = container_of(inode->i_cdev, struct so2_device_data, c_dev);
  56.  
  57.     file->private_data = data;
  58.  
  59.     /* TODO 3: return immediately if access is != 0, use atomic_cmpxchg */
  60.     if (atomic_cmpxchg(&(data->access), 0, 1)) {
  61.         pr_info("it works\n");
  62.         return -EBUSY;
  63.     }
  64.  
  65.     set_current_state(TASK_INTERRUPTIBLE);
  66.     schedule_timeout(10);
  67.  
  68.     return 0;
  69. }
  70.  
  71. static int
  72. so2_cdev_release(struct inode *inode, struct file *file)
  73. {
  74. #ifndef EXTRA
  75.     struct so2_device_data *data =
  76.         (struct so2_device_data *) file->private_data;
  77.  
  78.     pr_info("release\n");
  79.  
  80.     /* TODO 3: reset access variable to 0, use atomic_set */
  81.     atomic_set(&(data->access), 0);
  82. #endif
  83.     return 0;
  84. }
  85.  
  86. static ssize_t
  87. so2_cdev_read(struct file *file,
  88.         char __user *user_buffer,
  89.         size_t size, loff_t *offset)
  90. {
  91.     struct so2_device_data *data =
  92.         (struct so2_device_data *) file->private_data;
  93.     ssize_t to_read = size;
  94.  
  95.     printk(LOG_LEVEL "Offset: %lld\n", *offset);
  96.  
  97. #ifdef EXTRA
  98.     /* TODO 7: extra tasks for home */
  99. #endif
  100.  
  101.     /* TODO 4: Copy data->buffer to user_buffer, use copy_to_user */
  102.     if (copy_to_user(user_buffer, data->buffer, size))
  103.         return -EFAULT;
  104.  
  105.     *offset += size;
  106.     to_read = size - *offset;
  107.  
  108.     return to_read;
  109. }
  110.  
  111. static ssize_t
  112. so2_cdev_write(struct file *file,
  113.         const char __user *user_buffer,
  114.         size_t size, loff_t *offset)
  115. {
  116.     struct so2_device_data *data =
  117.         (struct so2_device_data *) file->private_data;
  118.  
  119.     /* TODO 5: copy user_buffer to data->buffer, use copy_from_user */
  120.     if (copy_from_user(data->buffer, user_buffer, size))
  121.         return -EFAULT;
  122.  
  123.     *offset += size;
  124.     /* TODO 7: extra tasks for home */
  125.  
  126.     pr_info("write\n");
  127.  
  128.     return size;
  129. }
  130.  
  131. static long
  132. so2_cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  133. {
  134.     struct so2_device_data *data =
  135.         (struct so2_device_data *) file->private_data;
  136.     int ret = 0;
  137.     int remains;
  138.  
  139.     switch (cmd) {
  140.     /* TODO 6: if cmd = MY_IOCTL_PRINT, display IOCTL_MESSAGE */
  141.     /* TODO 7: extra tasks, for home */
  142.     default:
  143.         ret = -EINVAL;
  144.     }
  145.  
  146.     return ret;
  147. }
  148.  
  149. static const struct file_operations so2_fops = {
  150.     .owner = THIS_MODULE,
  151. /* TODO 2: add open, release, read, write functions */
  152.     .unlocked_ioctl = so2_cdev_ioctl,
  153.     .open = so2_cdev_open,
  154.     .release = so2_cdev_release,
  155.     .read = so2_cdev_read,
  156.     .write = so2_cdev_write
  157. };
  158.  
  159. static int so2_cdev_init(void)
  160. {
  161.     int err;
  162.     int i;
  163.  
  164.     pr_info("cdev init:");
  165.  
  166.         /* TODO 1: register char device region for MY_MAJOR and NUM_MINORS starting at MY_MINOR */
  167.     if (register_chrdev_region(MKDEV(MY_MAJOR, MY_MINOR), NUM_MINORS, MODULE_NAME) < 0)
  168.         pr_err("register failed!");
  169.     else pr_info("register success\n");
  170.  
  171.     for (i = 0; i < NUM_MINORS; i++) {
  172. #ifdef EXTRA
  173.         /* TODO 7: extra tasks, for home */
  174. #else
  175.         /*TODO 4: initialize buffer with MESSAGE string */
  176.         strcpy(devs[i].buffer, MESSAGE);
  177. #endif
  178.         /* TODO 7: extra tasks for home */
  179.         /* TODO 3: set access variable to 0, use atomic_set */
  180.         atomic_set(&(devs[i].access), 0);
  181.         /* TODO 2: init and add cdev to kernel core */
  182.         cdev_init(&devs[i].c_dev, &so2_fops);
  183.         cdev_add(&devs[i].c_dev, MKDEV(MY_MAJOR, MY_MINOR), 1);
  184.     }
  185.  
  186.     return 0;
  187. }
  188.  
  189. static void so2_cdev_exit(void)
  190. {
  191.     int i;
  192.  
  193.     pr_info("cdev exit:");
  194.  
  195.     for (i = 0; i < NUM_MINORS; i++) {
  196.         /* TODO 2: delete cdev from kernel core */
  197.         cdev_del(&devs[i].c_dev);
  198.     }
  199.  
  200.     /* TODO 1: unregister char device region, for MY_MAJOR and NUM_MINORS starting at MY_MINOR */
  201.     unregister_chrdev_region(MKDEV(MY_MAJOR, MY_MINOR), NUM_MINORS);
  202.     pr_info("unregister\n");
  203. }
  204.  
  205. module_init(so2_cdev_init);
  206. module_exit(so2_cdev_exit);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement