diff --git a/examples/vinput.c b/examples/vinput.c index 75e2a76..b692d3f 100644 --- a/examples/vinput.c +++ b/examples/vinput.c @@ -1,3 +1,7 @@ +/* + * vinput.c + */ + #include #include #include diff --git a/examples/vinput.h b/examples/vinput.h index 394b061..c77c138 100644 --- a/examples/vinput.h +++ b/examples/vinput.h @@ -1,3 +1,7 @@ +/* + * vinput.h + */ + #ifndef VINPUT_H #define VINPUT_H diff --git a/examples/vkbd.c b/examples/vkbd.c index 7b1a6a0..d1cb833 100644 --- a/examples/vkbd.c +++ b/examples/vkbd.c @@ -1,3 +1,7 @@ +/* + * vkbd.c + */ + #include #include #include diff --git a/lkmpg.tex b/lkmpg.tex index df9c060..7af09ca 100644 --- a/lkmpg.tex +++ b/lkmpg.tex @@ -1257,6 +1257,40 @@ You can find sysfs directories and files under the \verb|/sys| directory on your ls -l /sys \end{codebash} +Attributes can be exported for kobjects in the form of regular files in the filesystem. +Sysfs forwards file I/O operations to methods defined for the attributes, providing a means to read and write kernel attributes. + +An attribute definition in simply: + +\begin{code} +struct attribute { + char *name; + struct module *owner; + umode_t mode; +}; + +int sysfs_create_file(struct kobject * kobj, const struct attribute * attr); +void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr); +\end{code} + +For example, the driver model defines \cpp|struct device_attribute| like: + +\begin{code} +struct device_attribute { + struct attribute attr; + ssize_t (*show)(struct device *dev, struct device_attribute *attr, + char *buf); + ssize_t (*store)(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count); +}; + +int device_create_file(struct device *, const struct device_attribute *); +void device_remove_file(struct device *, const struct device_attribute *); +\end{code} + +To read or write attributes, \cpp|show()| or \cpp|store()| method must be specified when declaring the attribute. +For the common cases \src{include/linux/sysfs.h} provides convenience macros (\cpp|__ATTR|, \cpp|__ATTR_RO|, \cpp|__ATTR_WO|, etc.) to make defining attributes easier as well as making code more concise and readable. + An example of a hello world module which includes the creation of a variable accessible via sysfs is given below. \samplec{examples/hello-sysfs.c} @@ -1293,6 +1327,12 @@ Finally, remove the test module: sudo rmmod hello_sysfs \end{codebash} +In the above case, we use a simple kobject to create a directory under sysfs, and communicate with its attributes. +Since Linux v2.6.0, the \cpp|kobject| structure made its appearance. +It was initially meant as a simple way of unifying kernel code which manages reference counted objects. +After a bit of mission creep, it is now the glue that holds much of the device model and its sysfs interface together. +For more information about kobject and sysfs, see \src{Documentation/driver-api/driver-model/driver.rst} and \url{https://lwn.net/Articles/51437/}. + \section{Talking To Device Files} \label{sec:device_files} Device files are supposed to represent physical devices. @@ -1897,6 +1937,23 @@ The buffer will then be copied to user. vinput devices are created and destroyed using sysfs. And, event injection is done through a \verb|/dev| node. The device name will be used by the userland to export a new virtual input device. + +The \cpp|class_attribute| structure is similar to other attribute types we talked about in section \ref{sec:sysfs}: + +\begin{code} +struct class_attribute { + struct attribute attr; + ssize_t (*show)(struct class *class, struct class_attribute *attr, + char *buf); + ssize_t (*store)(struct class *class, struct class_attribute *attr, + const char *buf, size_t count); +}; +\end{code} + +In \verb|vinput.c|, the macro \cpp|CLASS_ATTR_WO(export/unexport)| defined in \src{include/linux/device.h} (in this case, \verb|device.h| is included in \src{include/linux/input.h}) will generate the \cpp|class_attribute| structures which are named \verb|class_attr_export/unexport|. +Then, put them into \cpp|vinput_class_attrs| array and the macro \cpp|ATTRIBUTE_GROUPS(vinput_class)| will generate the \cpp|struct attribute_group vinput_class_group| that should be assigned in \cpp|vinput_class|. +Finally, call \cpp|class_register(&vinput_class)| to create attributes in sysfs. + To create a \verb|vinputX| sysfs entry and \verb|/dev| node. \begin{codebash} @@ -1933,7 +1990,6 @@ echo "-34" | sudo tee /dev/vinput0 \samplec{examples/vkbd.c} -% TODO: Add description of attribute % TODO: Add vts.c and vmouse.c example \section{Standardizing the interfaces: The Device Model}