给驱动添加sysfs设备模型(基于中断的按键程序)
Posted 王东力
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了给驱动添加sysfs设备模型(基于中断的按键程序)相关的知识,希望对你有一定的参考价值。
linux kernel version:4.4.38
硬件平台:exynos4412-tiny4412
参考链接:https://www.cnblogs.com/ethandlwang/p/14759735.html
基于上一篇按键点灯程序,我给设备驱动添加了sysfs设备模型,demo级程序
添加了myled_status文件在用户空间获取灯的状态~
1 #include <linux/err.h>
2 #include <linux/gpio.h>
3 #include <linux/fs.h>
4 #include <linux/gpio/consumer.h>
5 #include <linux/kernel.h>
6 #include <linux/leds.h>
7 #include <linux/module.h>
8 #include <linux/of.h>
9 #include <linux/of_gpio.h>
10 #include <linux/of_irq.h>
11 #include <linux/platform_device.h>
12 #include <linux/property.h>
13 #include <linux/slab.h>
14 #include <linux/workqueue.h>
15 #include <linux/interrupt.h>
16 #include <linux/acpi.h>
17
18 static struct gpio_desc *gpiod;
19
20 static ssize_t myled_status_show(struct device *dev,
21 struct device_attribute *attr, char *buf)
22 {
23 int level = gpiod_get_value(gpiod);
24 printk(KERN_ALERT "%s %d level=%d\\n", __FUNCTION__, __LINE__, level);
25 return 0;
26
27 }
28
29 static ssize_t myled_status_store(struct device *dev,
30 struct device_attribute *attr,
31 const char *buf, size_t len)
32 {
33 printk(KERN_ALERT "%s %d buf=%s len=%d\\n", __FUNCTION__, __LINE__, buf, len);
34 int level = 1;
35
36 if(len >= 2){
37 if(buf[0] == \'0\'){
38 level = 0;
39 }
40 }
41 gpiod_set_value(gpiod, level);
42 return len;
43 }
44
45 static DEVICE_ATTR_RW(myled_status);
46
47 static struct attribute* myled_status_attrs[] = {
48 &dev_attr_myled_status.attr,
49 NULL
50 };
51
52 static const struct attribute_group myled_group = {
53 .attrs = myled_status_attrs,
54 };
55
56 static irqreturn_t my_irq(int irqno, void *dev_id)
57 {
58 int level = gpiod_get_value(gpiod);
59 printk(KERN_ALERT "%s %d irqno=%d level=%d\\n", __FUNCTION__, __LINE__, irqno, level);
60 gpiod_set_value(gpiod, !level);
61 return IRQ_HANDLED;
62 }
63
64 static int hello_probe(struct platform_device *pdev)
65 {
66 int error = 0;
67 struct fwnode_handle *fwhandle;
68 const char *str;
69 u32 val[3];
70 u32 interrupts_val[2];
71 unsigned int irq;
72 int ret;
73
74 struct device_node* np = pdev->dev.of_node;
75 if(np == NULL)
76 {
77 printk(KERN_ALERT "%s %d of_node is NULL\\n", __FUNCTION__, __LINE__);
78 return 0;
79 }
80
81
82 irq = platform_get_irq(pdev, 0);
83 printk(KERN_ALERT "%s %d irq = %d\\n", __FUNCTION__, __LINE__, irq);
84 ret = devm_request_irq(&pdev->dev, irq, my_irq, 0, dev_name(&pdev->dev), NULL);
85 printk(KERN_ALERT "%s %d ret = %d\\n", __FUNCTION__, __LINE__, ret);
86
87 gpiod = devm_gpiod_get_optional(&pdev->dev, "key1", GPIOD_OUT_LOW);
88 if(gpiod == NULL){
89 printk(KERN_ALERT "%s %d devm_gpiod_get_optional fail!!!\\n", __FUNCTION__, __LINE__);
90 }
91
92 ret = sysfs_create_group(&pdev->dev.kobj, &myled_group);
93 if(ret)
94 {
95 printk(KERN_ALERT "%s %d sysfs_create_group fail!!!\\n", __FUNCTION__, __LINE__);
96 return 1;
97 }
98
99 printk(KERN_ALERT "%s %d success===\\n", __FUNCTION__, __LINE__);
100 return error;
101 }
102
103 static int hello_remove(struct platform_device *pdev)
104 {
105 sysfs_remove_group(&pdev->dev.kobj,&myled_group);
106
107 printk(KERN_ALERT "%s %d success===\\n", __FUNCTION__, __LINE__);
108
109 return 0;
110
111 }
112
113 static void hello_shutdown(struct platform_device *pdev)
114 {
115 printk(KERN_ALERT "%s %d success===\\n", __FUNCTION__, __LINE__);
116
117 }
118
119 static struct of_device_id of_platform_hello_match[] = {
120 { .compatible = "interrupt-keys",},
121 { },
122 };
123 MODULE_DEVICE_TABLE(of, of_platform_hello_match);
124
125 static struct platform_driver platform_hello_driver = {
126 .probe = hello_probe,
127 .remove = hello_remove,
128 .shutdown = hello_shutdown,
129 .driver = {
130 .name = "my_keys",
131 //.owner = THIS_MODULE,
132 .of_match_table = of_platform_hello_match,
133 },
134 };
135
136 module_platform_driver(platform_hello_driver);
137
138 MODULE_AUTHOR("EthanDL");
139 MODULE_DESCRIPTION("platform hello");
140 MODULE_LICENSE("GPL");
92行:向sysfs添加myled_status文件,所在目录/sys/devices/platform/my_keys/,因为my_keys是platform device,所以my_keys就会在/sys/devices/platform/下,sysfs_create_group的第一个参数kobj对应的正好是my_keys,所以myled_status是在my_keys下
20&29行:myled_status_show和myled_status_store,对应myled_status的读写,实现查看和控制led的亮灭~
以上是关于给驱动添加sysfs设备模型(基于中断的按键程序)的主要内容,如果未能解决你的问题,请参考以下文章
[kernel]字符设备驱动平台设备驱动设备驱动模型sysfs几者之间的比较和关联
基于RT-Thread的CAN电机驱动板设计 使用PIN设备配置按键中断实现电机启停