-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexample.c
More file actions
125 lines (106 loc) · 3.4 KB
/
example.c
File metadata and controls
125 lines (106 loc) · 3.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/uaccess.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Reuven Plevinsky");
static int major_number;
static struct class* sysfs_class = NULL;
static struct device* sysfs_device = NULL;
char* str = "without sysfs\n";
int str_len;
static unsigned int sysfs_int = 0;
static unsigned int sysfs_int_2 = 1;
int my_open(struct inode *_inode, struct file *_file)
{
str_len = strlen(str);
return 0;
}
ssize_t my_read(struct file *filp, char *buff, size_t length, loff_t *offp)
{
if (!str_len)
return 0;
if (copy_to_user(buff, str, str_len)) // Send the data to the user through 'copy_to_user'
return -EFAULT;
str_len = 0;
return strlen(str);
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.open = my_open,
.read = my_read
};
ssize_t display(struct device *dev, struct device_attribute *attr, char *buf) //sysfs show implementation
{
return scnprintf(buf, PAGE_SIZE, "%u\n", sysfs_int);
}
ssize_t display2(struct device *dev, struct device_attribute *attr, char *buf) //sysfs show implementation
{
return scnprintf(buf, PAGE_SIZE, "%u\n", sysfs_int_2);
}
ssize_t modify(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) //sysfs store implementation
{
int temp;
if (sscanf(buf, "%u", &temp) == 1)
sysfs_int = temp;
return count;
}
ssize_t modify2(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) //sysfs store implementation
{
int temp;
if (sscanf(buf, "%u", &temp) == 1)
sysfs_int_2 = temp;
return count;
}
static DEVICE_ATTR(sysfs_att, S_IWUSR | S_IRUGO , display, modify);
static DEVICE_ATTR(sysfs_att2, S_IWUSR | S_IRUGO , display2, modify2);
static int __init sysfs_example_init(void)
{
//create char device
major_number = register_chrdev(0, "Sysfs_Device", &fops);\
if (major_number < 0)
return -1;
//create sysfs class
sysfs_class = class_create(THIS_MODULE, "Sysfs_class");
if (IS_ERR(sysfs_class))
{
unregister_chrdev(major_number, "Sysfs_Device");
return -1;
}
//create sysfs device
sysfs_device = device_create(sysfs_class, NULL, MKDEV(major_number, 0), NULL, "sysfs_class" "_" "sysfs_Device");
if (IS_ERR(sysfs_device))
{
class_destroy(sysfs_class);
unregister_chrdev(major_number, "Sysfs_Device");
return -1;
}
//create sysfs file attributes
if (device_create_file(sysfs_device, (const struct device_attribute *)&dev_attr_sysfs_att.attr))
{
device_destroy(sysfs_class, MKDEV(major_number, 0));
class_destroy(sysfs_class);
unregister_chrdev(major_number, "Sysfs_Device");
return -1;
}
if (device_create_file(sysfs_device, (const struct device_attribute *)&dev_attr_sysfs_att2.attr))
{
device_remove_file(sysfs_device, (const struct device_attribute *)&dev_attr_sysfs_att.attr);
device_destroy(sysfs_class, MKDEV(major_number, 0));
class_destroy(sysfs_class);
unregister_chrdev(major_number, "Sysfs_Device");
return -1;
}
return 0;
}
static void __exit sysfs_example_exit(void)
{
device_remove_file(sysfs_device, (const struct device_attribute *)&dev_attr_sysfs_att2.attr);
device_remove_file(sysfs_device, (const struct device_attribute *)&dev_attr_sysfs_att.attr);
device_destroy(sysfs_class, MKDEV(major_number, 0));
class_destroy(sysfs_class);
unregister_chrdev(major_number, "Sysfs_Device");
}
module_init(sysfs_example_init);
module_exit(sysfs_example_exit);