Linux Kernel Driver Program:
12_sysfs_kernel_driver
neelkanth_surekha#cat Read\ me
This directory contains three files.1.Driver
2.Make File
3.User Application
Driver is running on kernel space
Makefile is used to build the kernel linux device driver
neelkanth_surekha#cat driver.c
/** Sysfs is a virtual filesystem exported by the kernel, similar to /proc.
* The files in Sysfs contain information about devices and drivers. Some
* files in Sysfs are even writable, for configuration and control of devices
* attached to the system. Sysfs is always mounted on /sys.
*
* The directories in Sysfs contain the hierarchy of devices,
* as they are attached to the computer.
*
* "Sysfs" is the commonly used method to export system information
* from the kernel space to the user space for specific devices.
* The "sysfs" is tied to the device driver model of the kernel.
* The "procfs" is used to export the process specific information
* and the "debugfs" is used to used for exporting the debug information
* by the developer.
******************************************************************************************
* There are many ways to Communicate between the User space and Kernel Space, they are:
******************************************************************************************
* 1. IOCTL
* 2. Procfs
* 3. Sysfs <---------------------------------
* 4. Configfs
* 5. Debugfs
* 6. Sysctl
* 7. UDP Sockets
* 8. Netlink Sockets*
*/
#if 0
#############################################################################
Heart of the sysfs model is the Kobject.
Kobject is the glue that binds the sysfs and the kernel,
which is represented by struct kobject.
A struct kobject represents a kernel object, maybe a device or so,
such as the things that show up as directory in the sysfs filesystem.
#############################################################################
#endif
/***********************************************************************
* OUTPUT
***********************************************************************
neelkanth_surekha#pwd
/sys/kernel
neelkanth_surekha#cd dummy_sysfs/
neelkanth_surekha#ls
dummy_value
neelkanth_surekha#sudo cat dummy_value
[sudo] password for neelkanth_surekha:
0
neelkanth_surekha#sudo chmod 777 dummy_value
neelkanth_surekha#sudo echo 1 > dummy_value
neelkanth_surekha#cat dummy_value
1
************************************************************************/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.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/sysfs.h>
#include<linux/kobject.h>
volatile int dummy_value = 0;
dev_t dev = 0;
static struct class *dev_class;
static struct cdev dummy_cdev;
struct kobject *kobj_ref;
static int __init dummy_driver_init(void);
static void __exit dummy_driver_exit(void);
/*************** Driver Fuctions **********************/
static int dummy_open(struct inode *inode, struct file *file);
static int dummy_release(struct inode *inode, struct file *file);
static ssize_t dummy_read(struct file *filp,
char __user *buf, size_t len,loff_t * off);
static ssize_t dummy_write(struct file *filp,
const char *buf, size_t len, loff_t * off);
/*************** Sysfs Fuctions **********************/
static ssize_t sysfs_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf);
static ssize_t sysfs_store(struct kobject *kobj,
struct kobj_attribute *attr, char *buf, size_t count);
struct kobj_attribute dummy_attr = __ATTR(dummy_value, 0660, sysfs_show, sysfs_store);
static struct file_operations fops =
{
.owner = THIS_MODULE,
.read = dummy_read,
.write = dummy_write,
.open = dummy_open,
.release = dummy_release,
};
static ssize_t sysfs_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
printk(KERN_INFO "Sysfs - Read!!!\n");
return sprintf(buf, "%d", dummy_value);
}
static ssize_t sysfs_store(struct kobject *kobj,
struct kobj_attribute *attr, char *buf, size_t count)
{
printk(KERN_INFO "Sysfs - Write!!!\n");
sscanf(buf,"%d",&dummy_value);
return count;
}
static int dummy_open(struct inode *inode, struct file *file)
{
printk(KERN_INFO "Device File Opened...!!!\n");
return 0;
}
static int dummy_release(struct inode *inode, struct file *file)
{
printk(KERN_INFO "Device File Closed...!!!\n");
return 0;
}
static ssize_t dummy_read(struct file *filp,
char __user *buf, size_t len, loff_t *off)
{
printk(KERN_INFO "Read function\n");
return 0;
}
static ssize_t dummy_write(struct file *filp,
const char __user *buf, size_t len, loff_t *off)
{
printk(KERN_INFO "Write Function\n");
return 0;
}
static int __init dummy_driver_init(void)
{
/*Allocating Major number*/
if((alloc_chrdev_region(&dev, 0, 1, "dummy_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(&dummy_cdev, &fops);
dummy_cdev.owner = THIS_MODULE;
dummy_cdev.ops = &fops;
/*Adding character device to the system*/
if((cdev_add(&dummy_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, "dummy_class")) == NULL){
printk(KERN_INFO "Cannot create the struct class\n");
goto r_class;
}
/*Creating device*/
if((device_create(dev_class,NULL, dev, NULL, "dummy_device")) == NULL){
printk(KERN_INFO "Cannot create the Device 1\n");
goto r_device;
}
/*Creating a directory in /sys/kernel/ */
kobj_ref = kobject_create_and_add("dummy_sysfs", kernel_kobj);
/*Creating sysfs file for dummy_value*/
if(sysfs_create_file(kobj_ref, &dummy_attr.attr)){
printk(KERN_INFO"Cannot create sysfs file......\n");
goto r_sysfs;
}
printk(KERN_INFO "Device Driver Insert...Done!!!\n");
return 0;
r_sysfs:
kobject_put(kobj_ref);
sysfs_remove_file(kernel_kobj, &dummy_attr.attr);
r_device:
class_destroy(dev_class);
r_class:
unregister_chrdev_region(dev,1);
cdev_del(&dummy_cdev);
return -1;
}
void __exit dummy_driver_exit(void)
{
kobject_put(kobj_ref);
sysfs_remove_file(kernel_kobj, &dummy_attr.attr);
device_destroy(dev_class,dev);
class_destroy(dev_class);
cdev_del(&dummy_cdev);
unregister_chrdev_region(dev, 1);
printk(KERN_INFO "Device Driver Remove...Done!!!\n");
}
module_init(dummy_driver_init);
module_exit(dummy_driver_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Neelkanth Reddy <www.neelkanth.13@gmail.com>");
MODULE_DESCRIPTION("A simple device driver - SysFs");
MODULE_VERSION("1:1.0");
neelkanth_surekha#cat Makefile
obj-m += driver.oKDIR = /lib/modules/$(shell uname -r)/build
#e.g. : make -C /lib/modules/4.4.0-93-generic/build M=/home/neelkanth_surekha/Device_Driver/8_IOCTL_Driver_code modules
all:
make -C $(KDIR) M=$(shell pwd) modules
clean:
make -C $(KDIR) M=$(shell pwd) clean