Linux虚拟文件系统sysfs之属性文件attribute整理(一)

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Linux虚拟文件系统sysfs之属性文件attribute整理(一)
sysfs接口函数到建立_DEVICE_ATTR
架构图:
最近在弄Sensor驱动,看过一个某厂家的成品驱动,里面实现的全都是sysfs接口,hal层利用sysfs生成的接口,对Sensor进行操作。

说道sysfs接口,就不得不提到函数宏 DEVICE_ATTR
原型是#define DEVICE_ATTR(_name, _mode, _show, _store) \ struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
函数宏DEVICE_ATTR内封装的是__ATTR(_name,_mode,_show,_stroe)方法,_show表示的是读方法,_stroe表示的是写方法。

当然_ATTR不是独生子女,他还有一系列的姊妹__ATTR_RO宏只有读方法,__ATTR_NULL等等
如对设备的使用 DEVICE_ATTR ,对总线使用 BUS_ATTR ,对驱动使用 DRIVER_ATTR ,对类别 (class) 使用 CLASS_ATTR, 这四个高级的宏来自于<include/linux/device.h>
DEVICE_ATTR 宏声明有四个参数,分别是名称、权限位、读函数、写函数。

其中读函数和写函数是读写功能函数的函数名。

如果你完成了DEVICE_ATTR函数宏的填充,下面就需要创建接口了
例如:
static DEVICE_ATTR(polling, S_IRUGO | S_IWUSR, show_polling, set_polling);
static struct attribute *dev_attrs[] = {
&dev_attr_polling.attr,
NULL,
};
当你想要实现的接口名字是polling的时候,需要实现结构体struct attribute *dev_attrs[]
其中成员变量的名字必须是&dev_attr_polling.attr
然后再封装
static struct attribute_group dev_attr_grp = {
.attrs = dev_attrs,
};
在利用sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp);创建接口
通过以上简单的三个步骤,就可以在adb shell 终端查看到接口了。

当我们将数据 echo 到接口中时,在上层实际上完成了一次 write 操作,对应到 kernel ,调用了驱动中的“store”。

同理,当我们cat 一个接口时则会调用“show”。

到这里,只是简单的建立了 android 层到 kernel 的桥梁,真正实现对硬件操作的,还是在 "show" 和 "store" 中完成的。

示例代码:
1.
2.#include <linux/ctype.h>
3.#include <linux/device.h>
4.#include <linux/err.h>
5.#include <linux/init.h>
6.#include <linux/kernel.h>
7.#include <linux/leds.h>
8.#include <linux/list.h>
9.#include <linux/module.h>
10.#include <linux/slab.h>
11.#include <linux/spinlock.h>
12.#include <linux/timer.h>
13.#include "leds.h"
14.#include <linux/init.h>
15.#include <linux/module.h>
16.#include <linux/mutex.h>
17.#include <linux/of.h>
18.#include <linux/of_gpio.h>
19.#include <linux/gpio/consumer.h>
20.
22.
23.static struct class *leds_class;
24.
25.static ssize_t brightness_show(struct device *dev,
26.struct device_attribute *attr, char *buf)
27.{
28.struct led_classdev *led_cdev = dev_get_drvdata(dev);
29.
30./* no lock needed for this */
31.led_update_brightness(led_cdev);
32.
33.return sprintf(buf, "%u\n", led_cdev->brightness);
34.}
35.
36.static ssize_t brightness_store(struct device *dev,
37.struct device_attribute *attr, const char *buf, size_t size)
38.{
39.struct led_classdev *led_cdev = dev_get_drvdata(dev);
40.unsigned long state;
41.ssize_t ret;
42.
43.mutex_lock(&led_cdev->led_access);
44.
45.if (led_sysfs_is_disabled(led_cdev)) {
46.ret = -EBUSY;
47.goto unlock;
49.
50.ret = kstrtoul(buf, 10, &state);
51.if (ret)
52.goto unlock;
53.
54.if (state == LED_OFF && !(led_cdev->flags & LED_KEEP_TRIGGER))
55.led_trigger_remove(led_cdev);
56.led_set_brightness(led_cdev, state);
57.led_cdev->usr_brightness_req = state;
58.
59.ret = size;
60.unlock:
61.mutex_unlock(&led_cdev->led_access);
62.return ret;
63.}
64.static DEVICE_ATTR_RW(brightness);
65.
66.static ssize_t max_brightness_show(struct device *dev,
67.struct device_attribute *attr, char *buf)
68.{
69.struct led_classdev *led_cdev = dev_get_drvdata(dev);
70.
71.return sprintf(buf, "%u\n", led_cdev->max_brightness);
72.}
73.
74.static ssize_t max_brightness_store(struct device *dev,
75.struct device_attribute *attr, const char *buf, size_t size)
76.{
77.struct led_classdev *led_cdev = dev_get_drvdata(dev);
78.unsigned long state;
79.ssize_t ret = -EINVAL;
80.
81.ret = kstrtoul(buf, 10, &state);
82.if (ret)
83.return ret;
84.
85.led_cdev->max_brightness = state;
86.led_set_brightness(led_cdev,
led_cdev->usr_brightness_req);
87.
88.return size;
89.}
90.static DEVICE_ATTR_RW(max_brightness);
91.
92.static ssize_t chenp_show(struct device *dev,
93.struct device_attribute *attr, char *buf)
94.{
95.
96.struct led_classdev *led_cdev = dev_get_drvdata(dev);
97.
98./* no lock needed for this */
99.led_update_brightness(led_cdev);
100.
101.return sprintf(buf, "%u\n", led_cdev->brightness);
102.
103.}
104.
105.static ssize_t chenp_store(struct device *dev,
106.struct device_attribute *attr, const char *buf, size_t size)
107.{
108.
109.
110.struct led_classdev *led_cdev = dev_get_drvdata(dev);
111.unsigned long state;
112.ssize_t ret;
113.struct lp8860_led *led = container_of(led_cdev, struct lp8860_led, led_dev);
114.
115.led->brightness = 12;
116.//if (led->enable_gpio)
117.
118.
119.mutex_lock(&led_cdev->led_access);
120.
121.if (led_sysfs_is_disabled(led_cdev)) {
122.ret = -EBUSY;
123.goto unlock;
124.}
125.
126.ret = kstrtoul(buf, 10, &state);
127.printk("chenp %s(line%d) state=%lu \n",__FILE__,__LINE__,state);
128.if (state)
129.gpiod_direction_output(led->enable_gpio, 1);
130.else
131.gpiod_directiosn_output(led->enable_gpio, 0);
132.if (ret)
133.goto unlock;
134.
135.if (state == LED_OFF && !(led_cdev->flags & LED_KEEP_TRIGGER))
136.led_trigger_remove(led_cdev);
137.//led_set_brightness(led_cdev, state);
138.led_cdev->usr_brightness_req = state;
139.
140.ret = size;
141.unlock:
142.mutex_unlock(&led_cdev->led_access);
143.return ret;
144.
145.}
146.static DEVICE_ATTR_RW(chenp);
147.
148.
149.#ifdef CONFIG_LEDS_TRIGGERS
150.static DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store);
151.static struct attribute *led_trigger_attrs[] = {
152.&dev_attr_trigger.attr,
153.NULL,
154.};
155.static const struct attribute_group led_trigger_group = {
156..attrs = led_trigger_attrs,
157.};
158.#endif
159.
160.static struct attribute *led_class_attrs[] = {
161.&dev_attr_brightness.attr,
162.&dev_attr_max_brightness.attr,
163.&dev_attr_chenp.attr,
164.NULL,
165.};
166.
167.static const struct attribute_group led_group = { 168..attrs = led_class_attrs,
169.};
170.
171.static const struct attribute_group *led_groups[] = {
172.&led_group,
173.#ifdef CONFIG_LEDS_TRIGGERS
174.&led_trigger_group,
175.#endif
176.NULL,
177.};。

相关文档
最新文档