Monday, February 27, 2017

Creating Syfs Entry


The sysfs filesystem is an in-memory virtual filesystem that provides a view of the kobject hierarachy. It enables users to view the device topology.
The magic behind sysfs is simply tying kobjects to directory entries via the dentry member inside each kobject.

Adding and Removing kobjects from sysfs

int kobject_add(struct kobject *kobj, struct kobject *parent, const char *fmt) ..
struct kobject *kobject_create_and_add(const char *name, struct kobject *parent);
void kobject_del(struct kobject *kobj)
</linux/kobject.h>

Default Attributes
A default set of files is provided via ktype field in kobjects and ksets.
</linux/sysfs.h>
struct attribute
{
const char *name;
struct module *owner;
mode_t mode;
};

struct sysfs_ops{
ssize_t (*show) (struct kobject *kobj, struct attribute *attr, char *buffer);
ssize_t (*store) (struct kobject *kobj, struct attribute *attr, const char *buffer, size_t size);
}

Creating and Destroying New Attributes
int sysfs_create_file(struct kobject *kobj, const struct attribute *attr);
int sysfs_create_link(struct kobject *kobj, struct kobject *target, char *name);

void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr);
void sysfs_remove_link(struct kobject *kobj, char *name);

Example1:-

..
static ssize_t top_off_threshold_current_show(struct device *dev,struct device_attribute *attr, char *buf){

}
static ssize_t top_off_threshold_current_store(struct device *dev,struct device_attribute *attr, char *buf,size_t count){
}
..
static DEVICE_ATTR_RW(top_off_threshold_current);
..
probe()
{

..
 ret = device_create_file(&pdev->dev,&dev_attr_top_off_threshold_current);  
// NOTE:- device_create_file internally calls sysfs_create_file
     if (ret) {
             dev_err(&pdev->dev, "failed: create top off current sysfs entry\n");
               goto err;

    }
..
err: device_remove_file(&pdev->dev, &dev_attr_top_off_threshold_current);
}
remove()
{
device_remove_file(&pdev->dev, &dev_attr_top_off_threshold_current);
}

Example2:- 

static DEVICE_ATTR_RW(top_off_threshold_current);
..
..
static struct attribute *max77693_charger_attribute[] = {
&dev_attr_fast_charge_timer.attr,
&dev_attr_top_off_threshold_current.attr,
&dev_attr_top_off_timer.attr,
NULL,
};

static const struct attribute_group max77693_attr_group = {
.attrs = max77693_charger_attribute,

};

probe()
{
..
ret = sysfs_create_group(&pdev->dev.kobj, &max77693_attr_group);
if (ret != 0) {
dev_err(&pdev->dev, "Can't create sysfs entries\n");
return ret;

}
..
}
remove()
{
sysfs_remove_group(&pdev->dev.kobj, &max77693_attr_group);
}


Example3:- 

#include <linux/module.h>
#include <linux/printk.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/string.h>
static struct kobject *example_kobject;
static int foo;

static ssize_t foo_show(struct kobject *kobj, struct kobj_attribute *attr,
                      char *buf)
{
        return sprintf(buf, "%d\n", foo);
}

static ssize_t foo_store(struct kobject *kobj, struct kobj_attribute *attr,
                      char *buf, size_t count)
{
        sscanf(buf, "%du", &foo);
        return count;
}


static struct kobj_attribute foo_attribute =__ATTR(foo, 0660, foo_show,
                                                   foo_store);

static int __init mymodule_init (void)
{
        int error = 0;

        pr_debug("Module initialized successfully \n");

        example_kobject = kobject_create_and_add("kobject_example",
                                                 kernel_kobj);   //kernel_kobj is the parent
        if(!example_kobject)
                return -ENOMEM;

        error = sysfs_create_file(example_kobject, &foo_attribute.attr);
        if (error) {
                pr_debug("failed to create the foo file in /sys/kernel/kobject_example \n");
        }

        return error;
}

static void __exit mymodule_exit (void)
{
        pr_debug ("Module un initialized successfully \n");
        kobject_put(example_kobject);

}

No comments:

Post a Comment