1 sys 文件的创建
1.1 定义xxx_show 和xxx_store函数,这两个函数对应对SYS文件的读写,show对应read ,store对应write
函数的类型如下:
ssize_t xxx_show(struct device *d, struct device_attribute*attr, char *buf) //对应read
ssize_t xxx_store(struct device *d, struct device_attribute*attr,const char *buf,size_t count) //对应write
这两个函数名可以任意命名,只要类型对了就可以
1.2 用DEVICE_ATTR宏创建属性文件
示例代码如下:
static DEVICE_ATTR(xxxtest, S_IWUSR |S_IRUGO, xxx_show, xxx_store);
这是一个宏定义,将定义一个 dev_attr_xxxtest,类型为struct attribute的结构体。
其中xxxtest为要创建的sys文件名。
xxx_show, xxx_store不一定都要定义,例如如果只提供读的接口可以定义为
static DEVICE_ATTR(xxxtest, S_IWUSR |S_IRUGO, xxx_show, NULL);
1.3 调用sysfs_create_file创建sys文件
sysfs_create_file(&pdev->dev.kobj,&dev_attr_xxxtest);
1.4 注销sys文件
sysfs_remove_file(&pdev->dev.kobj,&dev_attr_xxxtest);
2 示例代码如下:
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/power_supply.h>
#include <linux/platform_device.h>
#include <linux/power/sabresd_battery.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
static ssize_t xxx_show(struct device *d, struct device_attribute*attr, char *buf)
{
return sprintf(buf,"this is test\n");
}
static ssize_t xxx_store(struct device *d, struct device_attribute*attr,const char *buf,size_t count)
{
if(*buf=='0')
{
printk("gpio low\n");
}
else
{
printk("gpio high\n");
}
return count;
}
//用DEVICE_ATTR宏创建属性文件,如果show()或是store()没有功能,就以NULL代替
static DEVICE_ATTR(xxxtest, S_IWUSR |S_IRUGO, gpio_show, gpio_store);
static int xxx_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
int ret;
ret = sysfs_create_file(&pdev->dev.kobj,&dev_attr_xxxtest);
return ret;
}
static int xxx_remove(struct platform_device *pdev)
{
sysfs_remove_file(&pdev->dev.kobj,&dev_attr_xxxtest);
return 0;
}
static const struct of_device_id xxx_dt_ids[] = {
{ .compatible = "test,test-xxx", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, xxx_dt_ids);
static struct platform_driver test_xxx_driver = {
.probe = xxx_probe,
.remove = xxx_remove,
.driver = {
.name = "xxx-int",
.owner = THIS_MODULE,
.of_match_table = xxx_dt_ids,
},
};
module_platform_driver(test_xxx_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Freescale Semiconductor, Inc.");
MODULE_DESCRIPTION("test Driver");
MODULE_ALIAS("test");
如果上面的驱动加载成功,我们可以在/ sys/bus/platform/drivers/目录下看到xxx-int找到xxxtest的sys文件。可以读写操作。
2 但是在很多时候,我们的驱动可能有很多参数需要配置,这时我们可以创建一组sys文件。
下面是例子
//用DEVICE_ATTR宏创建属性文件,如果show()或是store()没有功能,就以NULL代替
static DEVICE_ATTR(xxxtest, S_IWUSR |S_IRUGO, xxx_show, xxx_store);
static DEVICE_ATTR(xxxset, S_IWUSR |S_IRUGO, xxx_show, xxx_store);
//属性结构体数组最后一项必须以NULL结尾。
static struct attribute *xxx_attrs[] = {
&dev_attr_xxxtest.attr,
&dev_attr_xxxset.attr,
NULL
};
static const struct attribute_group xxx_attr_grp = {
.attrs = xxx_attrs,
} ;
static int xxx_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
int ret;
ret = sysfs_create_group(&pdev->dev.kobj,&dev_attr_xxxtest);
return ret;
}
static int xxx_remove(struct platform_device *pdev)
{
sysfs_remove_file(&pdev->dev.kobj,&dev_attr_xxxtest);
return 0;
}
替换上面的代码,重新编译,驱动加载成功后,就可以在可以在/sys/bus/platform/drivers/目录下看到xxx-int找到xxxtest和xxxset两个sys文件。可以读写操作。
3 通过上面的例子我们已经创建了sys文件,但是在/sys/bus/platform/drivers/xxx-int还有很多其他的文件,很不好找。而且这个文件的目录是和驱动的名字相关的
我们可以自己在指定的目录创建SYS文件。
我们可以通过struct kobject * kobject_create_and_add(const char *name, struct kobject *parent);创建是sys文件的目录
这个函数参数name是目录名,parent是父节点的指针
例如我们可以调用
kobj = kobject_create_and_add("test-xxx", &platform_bus.kobj);
ret = sysfs_create_file(kobj,&dev_attr_xxxtest);
则可以在/sys/devices/platform/test-xxx目录下看到xxxtest的SYS文件
如果要在/sys下创建则可以调用
kobj = kobject_create_and_add("test-xxx", NULL);
ret = sysfs_create_file(kobj,&dev_attr_xxxtest);
下面是示例代码
struct kobject *kobj = NULL;
static int xxx_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
int ret;
kobj = kobject_create_and_add("test-xxx", &platform_bus.kobj);// 在/sys/devices/platform/下创建
kobj = kobject_create_and_add("test-xxx", NULL);// 在/sys/ 下创建
ret = sysfs_create_group(kobj,&dev_attr_xxxtest);
return ret;
}
static int xxx_remove(struct platform_device *pdev)
{
sysfs_remove_file(&pdev->dev.kobj,&dev_attr_xxxtest);
kobject_del(kobj);
kobject_put(kobj);
return 0;
}
1.1 定义xxx_show 和xxx_store函数,这两个函数对应对SYS文件的读写,show对应read ,store对应write
函数的类型如下:
ssize_t xxx_show(struct device *d, struct device_attribute*attr, char *buf) //对应read
ssize_t xxx_store(struct device *d, struct device_attribute*attr,const char *buf,size_t count) //对应write
这两个函数名可以任意命名,只要类型对了就可以
1.2 用DEVICE_ATTR宏创建属性文件
示例代码如下:
static DEVICE_ATTR(xxxtest, S_IWUSR |S_IRUGO, xxx_show, xxx_store);
这是一个宏定义,将定义一个 dev_attr_xxxtest,类型为struct attribute的结构体。
其中xxxtest为要创建的sys文件名。
xxx_show, xxx_store不一定都要定义,例如如果只提供读的接口可以定义为
static DEVICE_ATTR(xxxtest, S_IWUSR |S_IRUGO, xxx_show, NULL);
1.3 调用sysfs_create_file创建sys文件
sysfs_create_file(&pdev->dev.kobj,&dev_attr_xxxtest);
1.4 注销sys文件
sysfs_remove_file(&pdev->dev.kobj,&dev_attr_xxxtest);
2 示例代码如下:
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/power_supply.h>
#include <linux/platform_device.h>
#include <linux/power/sabresd_battery.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
static ssize_t xxx_show(struct device *d, struct device_attribute*attr, char *buf)
{
return sprintf(buf,"this is test\n");
}
static ssize_t xxx_store(struct device *d, struct device_attribute*attr,const char *buf,size_t count)
{
if(*buf=='0')
{
printk("gpio low\n");
}
else
{
printk("gpio high\n");
}
return count;
}
//用DEVICE_ATTR宏创建属性文件,如果show()或是store()没有功能,就以NULL代替
static DEVICE_ATTR(xxxtest, S_IWUSR |S_IRUGO, gpio_show, gpio_store);
static int xxx_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
int ret;
ret = sysfs_create_file(&pdev->dev.kobj,&dev_attr_xxxtest);
return ret;
}
static int xxx_remove(struct platform_device *pdev)
{
sysfs_remove_file(&pdev->dev.kobj,&dev_attr_xxxtest);
return 0;
}
static const struct of_device_id xxx_dt_ids[] = {
{ .compatible = "test,test-xxx", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, xxx_dt_ids);
static struct platform_driver test_xxx_driver = {
.probe = xxx_probe,
.remove = xxx_remove,
.driver = {
.name = "xxx-int",
.owner = THIS_MODULE,
.of_match_table = xxx_dt_ids,
},
};
module_platform_driver(test_xxx_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Freescale Semiconductor, Inc.");
MODULE_DESCRIPTION("test Driver");
MODULE_ALIAS("test");
如果上面的驱动加载成功,我们可以在/ sys/bus/platform/drivers/目录下看到xxx-int找到xxxtest的sys文件。可以读写操作。
2 但是在很多时候,我们的驱动可能有很多参数需要配置,这时我们可以创建一组sys文件。
下面是例子
//用DEVICE_ATTR宏创建属性文件,如果show()或是store()没有功能,就以NULL代替
static DEVICE_ATTR(xxxtest, S_IWUSR |S_IRUGO, xxx_show, xxx_store);
static DEVICE_ATTR(xxxset, S_IWUSR |S_IRUGO, xxx_show, xxx_store);
//属性结构体数组最后一项必须以NULL结尾。
static struct attribute *xxx_attrs[] = {
&dev_attr_xxxtest.attr,
&dev_attr_xxxset.attr,
NULL
};
static const struct attribute_group xxx_attr_grp = {
.attrs = xxx_attrs,
} ;
static int xxx_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
int ret;
ret = sysfs_create_group(&pdev->dev.kobj,&dev_attr_xxxtest);
return ret;
}
static int xxx_remove(struct platform_device *pdev)
{
sysfs_remove_file(&pdev->dev.kobj,&dev_attr_xxxtest);
return 0;
}
替换上面的代码,重新编译,驱动加载成功后,就可以在可以在/sys/bus/platform/drivers/目录下看到xxx-int找到xxxtest和xxxset两个sys文件。可以读写操作。
3 通过上面的例子我们已经创建了sys文件,但是在/sys/bus/platform/drivers/xxx-int还有很多其他的文件,很不好找。而且这个文件的目录是和驱动的名字相关的
我们可以自己在指定的目录创建SYS文件。
我们可以通过struct kobject * kobject_create_and_add(const char *name, struct kobject *parent);创建是sys文件的目录
这个函数参数name是目录名,parent是父节点的指针
例如我们可以调用
kobj = kobject_create_and_add("test-xxx", &platform_bus.kobj);
ret = sysfs_create_file(kobj,&dev_attr_xxxtest);
则可以在/sys/devices/platform/test-xxx目录下看到xxxtest的SYS文件
如果要在/sys下创建则可以调用
kobj = kobject_create_and_add("test-xxx", NULL);
ret = sysfs_create_file(kobj,&dev_attr_xxxtest);
下面是示例代码
struct kobject *kobj = NULL;
static int xxx_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
int ret;
kobj = kobject_create_and_add("test-xxx", &platform_bus.kobj);// 在/sys/devices/platform/下创建
kobj = kobject_create_and_add("test-xxx", NULL);// 在/sys/ 下创建
ret = sysfs_create_group(kobj,&dev_attr_xxxtest);
return ret;
}
static int xxx_remove(struct platform_device *pdev)
{
sysfs_remove_file(&pdev->dev.kobj,&dev_attr_xxxtest);
kobject_del(kobj);
kobject_put(kobj);
return 0;
}