-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patholed_sysfs.c
158 lines (138 loc) · 5.64 KB
/
oled_sysfs.c
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/**
* @file oled_sysfs.c
* @brief Init/deinit callbacks implementation to expose user-control through
* sysfs filesystem.
* @author Luyao Han (luyaohan1001@gmail.com)
* @date 12-21-2022
*/
#include "oled_sysfs.h"
#include "graphics.h"
#include <linux/kobject.h>
/* Function signatures. */
static ssize_t kobj_attr_display_text_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buffer);
static ssize_t kobj_attr_display_text_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buffer, size_t count);
/**
* @brief The pointer storing a oled kernel object to be created later.
* @note The kobject, once created, will show up as a directory under
* /sys/kernel/.
*/
struct kobject *oled_kobj;
/**
* @brief Link the symbol to its spawn in graphics.c
*/
extern oled_graphics_params_t oled_graphics_params;
/**
* @brief "display_text" attribute, storing the current text the oled
* displaying.
* @note "display_text" will show up as a file under /sys/kernel/oled_sysfs.
*/
static struct kobj_attribute kobj_attr_display_text = {
.attr = {.name = "display_text", .mode = 0666},
.show = kobj_attr_display_text_show,
.store = kobj_attr_display_text_store};
/**
* @brief Callback function prototype for when the user read display_text, i.e.
* cat /sys/kernel/oled_sysfs/display_text. The prototype implements the
* following function pointer in struct kobj_attribute in linux/kobject.h:
* ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,
* char *buf);
* @param kobj Kobject to which tied sysfs file is read (show).
* @param attr Attr.com/ibute to which the tied sysfs file is read (show).
* @param buffer Text display to the screen when the file is read.
* @return Error status.
*/
static ssize_t kobj_attr_display_text_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buffer) {
ssize_t status_code = 0;
/* TODO: Implement book-keeping of attribute values in datalink and use
* sprintf to print to buffer. */
// status_code = sprintf(buffer, "display_text kobj_attribute:\n%s/%s\n",
// kobj->name, attr->attr.name);
pr_info("/sys/kernel/%s/%s is successfully read through function "
"kobj_attr_display_text_show. \n",
kobj->name, attr->attr.name);
return status_code;
}
/**
* @brief Callback function prototype for when the user write to the
* display_text, i.e. echo "hello, world" > /sys/kernel/oled_sysfs/display_text.
* The prototype implements the following function pointer in struct
* kobj_attribute in linux/object.h.
* @param kobj Kobject to which tied sysfs file is written (store).
* @param attr Attribute to which the tied sysfs file is written (store).
* @param buffer Text display to the screen when the file is written.
* @return Number of characters written.
* @note Returning status code is wrong, and could cause the system looping in
* store function.
*/
static ssize_t kobj_attr_display_text_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buffer, size_t count) {
/* Print to kernel log. */
pr_info("'%s' has been written to /sys/kernel/%s/%s through "
"kobj_attr_display_text_store. \n",
buffer, kobj->name, attr->attr.name);
/* Store the buffer (text written to the file) to graphics data structure. */
/* The display_text will be deployed to oled screen through
* oled_display_text_thread in driver.c. */
/* TODO: Add multithread protection. */
sprintf(oled_graphics_params.display_text, "%s", buffer);
return count;
}
/**
* @brief Creates kobject and its attributes under sysfs.
* @param None.
* @return status_code.
*/
int oled_sysfs_init(void) {
int status_code = 0;
const char dir_name[] = "oled_sysfs";
struct kobject *parent = kernel_kobj;
/* Register kobject for sysfs, to expose control from user space. */
pr_info("Now creating sysfs directory path for oled device.\n");
/* Creating an kobject dynamically with register it with sysfs. */
/* The directory /sys/kernel/oled_sysfs will be created. */
oled_kobj = kobject_create_and_add(dir_name, parent);
/* Check create status. */
if (NULL == oled_kobj) {
pr_err("Error creating kobject for oled_sysfs, exiting...\n");
status_code = -1;
goto RETURN;
}
/* Create file under oled_sysfs directory. */;
status_code = sysfs_create_file(oled_kobj, &kobj_attr_display_text.attr);
if (status_code != 0) {
pr_err("Error creating sysfs attribute file display_text, exiting...\n");
/* Dynamically frees oled_kobj allocated by kobject_create_and_add. */
kobject_put(oled_kobj);
status_code = -1;
goto RETURN;
}
RETURN:
if (0 == status_code) {
pr_info("oled_sysfs kobject has been successfully created.\n");
pr_info(" -->$ cd /sys/kernel/oled_sysfs to start playing with it.\n");
}
return status_code;
}
/**
* @brief Cleans up the constructs created in oled_sysfs_init.
* Deletes the kernel object allocated and the sysfs folder created for
* oled_kobj.
* @param None.
* @return None.
*/
void oled_sysfs_deinit(void) {
/* Print to kernel logs. */
pr_info("Deleting oled_sysfs kobject. \n");
/* Remove display_text file from sysfs. */
sysfs_remove_file(oled_kobj, &kobj_attr_display_text.attr);
/* Removes kobject from sysfs, which also deletes the oled_sysfs directory in
* /sys/kernel/. */
kobject_put(oled_kobj);
}