Kernel under linux
#include<linux/module.h> #include<linux/kernel.h> #include<linux/semaphore.h> #include<linux/uaccess.h> #include<linux/fs.h> #include<linux/cdev.h> //........................... Variable declaration.................................................. #define DEVICENAME "CHARACTER_DEVICE" #define BUFFER_SIZE 1024 static char device_buffer[BUFFER_SIZE]; struct cdev *mcdev; struct semaphore semaph; int MAJOR_NUMBER; int return_value; dev_t dev_number; //..........................Function ................................................... static int _driver_device_open(struct inode *inode, struct file *filp) { if(down_interruptible(&semaph) != 0) { printk(KERN_ALERT "Device is already in use, unable to open lock\n"); return -1; } printk(KERN_INFO "Device is now opened :)\n"); return 0; } static ssize_t _driver_device_read(struct file *fp, char *buff, size_t length, loff_t *ppos) { int bytes_read; int max_bytes; int bytes_to_read; max_bytes = BUFFER_SIZE - *ppos; if(max_bytes > length) bytes_to_read = length; else bytes_to_read = max_bytes; if(bytes_to_read == 0) printk(KERN_INFO "At end\n"); bytes_read = bytes_to_read - copy_to_user(buff, device_buffer + *ppos, bytes_to_read); printk(KERN_INFO "Read Device%d\n",bytes_read); *ppos += bytes_read; printk(KERN_INFO "Deviceis read\n"); return bytes_read; } static ssize_t _driver_device_write(struct file *fp, const char *buff, size_t len, loff_t *ppos) { int bytes_writen; int max_bytes; int bytes_to_write; max_bytes = BUFFER_SIZE - *ppos; if(max_bytes > len) bytes_to_write = len; else bytes_to_write = max_bytes; bytes_writen = bytes_to_write - copy_from_user(device_buffer + *ppos, buff, bytes_to_write); printk(KERN_INFO "Device has been written %d\n",bytes_writen); *ppos += bytes_writen; printk(KERN_INFO "Device has been written\n"); return bytes_writen; } static loff_t device_lseek(struct file *file, loff_t offset, int orig) { loff_t new_position = 0; switch(orig) { case 0 : new_position = offset; //set break; case 1 : new_position = file->f_pos + offset; //current break; case 2 : new_position = BUFFER_SIZE - offset; //end break; } if(new_position > BUFFER_SIZE) new_position = BUFFER_SIZE; if(new_position < 0) new_position = 0; file->f_pos = new_position; return new_position; } static int _driver_device_close(struct inode *inode, struct file *filp) { printk(KERN_INFO "Device Driver is going to be closed\n"); up(&semaph); return return_value; } //..................... Device functionality provided by the driver........................ struct file_operations fops = { .owner = THIS_MODULE, .open = _driver_device_open, .write = _driver_device_write, .read = _driver_device_read, .release = _driver_device_close, .llseek = device_lseek }; int chardevice_init(void) { printk(KERN_ALERT " initializing the device....\n"); return_value = alloc_chrdev_region(&dev_number,0,1,DEVICENAME); if(return_value < 0) { printk(KERN_ALERT " Failed :( \n"); return return_value; } else printk(KERN_INFO "Number allocated succesful\n"); MAJOR_NUMBER = MAJOR(dev_number); printk(KERN_INFO "Number allocated to device is %d\n",MAJOR_NUMBER); printk(KERN_INFO " to use mknod /dev/%s c %d 0\n",DEVICENAME, MAJOR_NUMBER); mcdev = cdev_alloc(); mcdev->ops = &fops; mcdev->owner = THIS_MODULE; return_value = cdev_add(mcdev,dev_number,1); if(return_value < 0) { printk(KERN_ALERT " Adding Device to kernel is failed\n"); return return_value;} else printk(KERN_INFO " Device addition to the kernel succesful\n"); sema_init(&semaph,1); return 0; } void chardevice_exit(void) { cdev_delelet(mcdev); printk(KERN_INFO " mcdev has been removed from kernel\n"); unregister_chrdev_region(dev_number,1); printk(KERN_ALERT "Character Device driver is now exiting\n"); } MODULE_AUTHOR("A"); MODULE_DESCRIPTION("A Simple CHARACTER DEVICE DRIVER"); module_init(chardevice_init); module_exit(chardevice_exit);