Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include<linux/module.h>
- #include<linux/kernel.h>
- #include<linux/fs.h>
- #include<linux/interrupt.h>
- #include<linux/cdev.h>
- #include<asm/uaccess.h>
- #include<asm/io.h>
- #include<linux/semaphore.h>
- #include<linux/spinlock.h>
- #include<linux/sched.h>
- #include<linux/device.h>
- #define DEVICE_NAME "klg_app"
- #define AUTHOR "morpheus15"
- #define LICENSE "GPL"
- #define CLASS_NAME "klg_class"
- #define FOR(i,x,n) for(i=x;i<n;i++)
- #define BUF_MAX_SIZE 10
- #define FIRST_MINOR_NUM 0
- #define MINOR_DEVICE_COUNT 1
- typedef struct
- {
- char data[BUF_MAX_SIZE];
- }klg_device_t;
- static klg_device_t klgdev;
- static int ret,major;
- static dev_t dev_num;
- static struct cdev *kcdev = NULL;
- static struct class *klg_class = NULL;
- static struct semaphore semm;
- static int klg_open(struct inode *klg_inode,struct file *filp)
- {
- filp->private_data = &klgdev;
- /*if(down_interruptible(&semm))
- {
- printk(KERN_INFO "could not open device %sn",DEVICE_NAME);
- return -ERESTARTSYS;
- }
- */
- printk(KERN_INFO "device %s called open()n",DEVICE_NAME);
- return 0;
- }
- static int klg_close(struct inode *klg_inode,struct file *filp)
- {
- //up(&semm);
- printk(KERN_INFO "device %s called close()n",DEVICE_NAME);
- return 0;
- }
- static ssize_t klg_read(struct file *filp,char __user *buf,size_t count,loff_t *pos)
- {
- printk(KERN_INFO "device %s called read()n",DEVICE_NAME);
- klg_device_t *klgp = filp->private_data;
- if (down_interruptible(&semm))
- {
- printk(KERN_INFO "device %s already in use. could not open for readingn",DEVICE_NAME);
- return -ERESTARTSYS;
- }
- int len = strlen(klgp->data);
- if (!len || (*pos) > len)
- {
- up(&semm);
- return 0;
- }
- if (*pos + count > len)
- {
- count = len - *pos;
- }
- ret = copy_to_user(buf,klgp->data,count);
- if (ret)
- {
- printk(KERN_INFO "copy_to_user() failed for device %s, exit with error %dn",DEVICE_NAME,ret);
- up(&semm);
- return -EFAULT;
- }
- (*pos) += count;
- up(&semm);
- return count;
- }
- static ssize_t klg_write(struct file *filp,char __user *buf,size_t count,loff_t *pos)
- {
- printk(KERN_INFO "device %s called write()n",DEVICE_NAME);
- klg_device_t *klgp = filp->private_data;
- if (down_interruptible(&semm))
- {
- printk(KERN_INFO "device %s already in use. Could not open for writingn",DEVICE_NAME);
- return -ERESTARTSYS;
- }
- memset(klgp->data,0,BUF_MAX_SIZE);
- if (count > BUF_MAX_SIZE)
- {
- count = BUF_MAX_SIZE;
- }
- ret = copy_from_user(klgp->data,buf,count);
- if (ret)
- {
- printk(KERN_INFO "copy_from_user() failed for device %s, exit with error %dn",DEVICE_NAME,ret);
- up(&semm);
- return -EFAULT;
- }
- up(&semm);
- return count;
- }
- static struct file_operations fops =
- {
- .owner = AUTHOR,
- .open = klg_open,
- .release = klg_close,
- .read = klg_read,
- .write = klg_write
- };
- static void initialize_constructs(void)
- {
- sema_init(&semm,1);
- }
- static int __init klg_init(void)
- {
- ret = alloc_chrdev_region(&dev_num,FIRST_MINOR_NUM,MINOR_DEVICE_COUNT,DEVICE_NAME);
- if (ret)
- {
- printk(KERN_INFO "could not alloc_chrdev_region for device %sn",DEVICE_NAME);
- return -1;
- }
- major = MAJOR(dev_num);
- printk(KERN_INFO "registered device %s with major number %dn",DEVICE_NAME,major);
- // add the device to /sys/class/CLASS_NAME
- klg_class = class_create(DEVICE_NAME,CLASS_NAME);
- if (!klg_class)
- {
- printk(KERN_INFO "could not add device %s to /sys/class/%sn",CLASS_NAME);
- unregister_chrdev_region(dev_num,MINOR_DEVICE_COUNT);
- return -2;
- }
- // create an entry in /dev for the device file
- if (!device_create(klg_class,NULL,dev_num,NULL,DEVICE_NAME))
- {
- printk(KERN_INFO "could not create entry /dev/%s for device %sn",DEVICE_NAME,DEVICE_NAME);
- class_destroy(klg_class);
- unregister_chrdev_region(dev_num,MINOR_DEVICE_COUNT);
- return -2;
- }
- // create the cdev struct for the character device
- kcdev = cdev_alloc();
- kcdev->owner = AUTHOR;
- kcdev->ops = &fops;
- ret = cdev_add(kcdev,dev_num,MINOR_DEVICE_COUNT);
- if (ret)
- {
- printk(KERN_INFO "could not allocate a char dev struct for device %sn",DEVICE_NAME);
- device_destroy(klg_class,dev_num);
- class_destroy(klg_class);
- unregister_chrdev_region(dev_num,MINOR_DEVICE_COUNT);
- return -1;
- }
- initialize_constructs();
- printk(KERN_INFO "successfully created a character device driver for device %sn",DEVICE_NAME);
- return 0;
- }
- static void __exit klg_exit(void)
- {
- // destroy in the reverse order
- cdev_del(kcdev);
- device_destroy(klg_class,dev_num);
- class_destroy(klg_class);
- unregister_chrdev_region(dev_num,MINOR_DEVICE_COUNT);
- printk(KERN_INFO "successfully unregistered character device %s and all its componentsn",DEVICE_NAME);
- }
- module_init(klg_init);
- module_exit(klg_exit);
- MODULE_AUTHOR(AUTHOR);
- MODULE_LICENSE(LICENSE);
- MODULE_DESCRIPTION("this is a sample application");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement