1
0
Files
MSE-CSEL/solutions/03_drivers/sample05.1/skeleton.c

102 lines
2.9 KiB
C

/* skeleton.c */
#include <linux/init.h> /* needed for macros */
#include <linux/kernel.h> /* needed for debugging */
#include <linux/module.h> /* needed by all modules */
#include <linux/cdev.h> /* needed for char device driver */
#include <linux/fs.h> /* needed for device drivers */
#include <linux/uaccess.h> /* needed to copy data to/from user */
#include <linux/device.h> /* needed for sysfs handling */
#include <linux/miscdevice.h>
#include <linux/of.h>
#include <linux/platform_device.h> /* needed for sysfs handling */
#define BUFFER_SZ 10000
static struct mydata {
struct device* device;
struct skeleton_attr {
char buffer[BUFFER_SZ];
struct device_attribute dev_attr;
} attr;
} mydevices[5];
#define ATTR_INSTANCE(a) \
{ \
a.attr.buffer[0] = 0; \
a.attr.dev_attr.attr.name = "val"; \
a.attr.dev_attr.attr.mode = 0664; \
a.attr.dev_attr.show = sysfs_show_attr; \
a.attr.dev_attr.store = sysfs_store_attr; \
}
// --- sysfs file opers ------------------------------------------------------
ssize_t sysfs_show_attr(struct device* dev,
struct device_attribute* attr,
char* buf)
{
struct mydata* mydata = container_of(attr, struct mydata, attr.dev_attr);
strcpy(buf, mydata->attr.buffer);
return strlen(buf);
}
ssize_t sysfs_store_attr(struct device* dev,
struct device_attribute* attr,
const char* buf,
size_t count)
{
struct mydata* mydata = container_of(attr, struct mydata, attr.dev_attr);
int len = sizeof(mydata->attr.buffer) - 1;
if (len > count) len = count;
strncpy(mydata->attr.buffer, buf, len);
mydata->attr.buffer[len] = 0;
return len;
}
static struct class* sysfs_class;
static int __init skeleton_init(void)
{
int status = 0;
int i =0;
sysfs_class = class_create(THIS_MODULE, "myclass");
for (i=0; i<ARRAY_SIZE(mydevices); i++) {
struct mydata* mydev = &mydevices[i];
mydev->device = device_create(sysfs_class, NULL, i, NULL, "mydevice.%d", i);
ATTR_INSTANCE((*mydev));
status = device_create_file(mydev->device, &(mydev->attr.dev_attr));
}
pr_info("Linux module skeleton loaded\n");
return status;
}
static void __exit skeleton_exit(void)
{
int i = 0;
for (i=0; i<ARRAY_SIZE(mydevices); i++) {
struct mydata* mydev = &mydevices[i];
device_remove_file(mydev->device, &(mydev->attr.dev_attr));
device_destroy(sysfs_class, i);
}
class_destroy(sysfs_class);
pr_info("Linux module skeleton unloaded\n");
}
module_init(skeleton_init);
module_exit(skeleton_exit);
MODULE_AUTHOR("Daniel Gachet <daniel.gachet@hefr.ch>");
MODULE_DESCRIPTION("Module skeleton");
MODULE_LICENSE("GPL");