189 lines
3.7 KiB
C
189 lines
3.7 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
#define DEBUG 1
|
|
|
|
#include <asm/page.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/kobject.h>
|
|
#include <linux/jiffies.h>
|
|
#include <linux/module.h>
|
|
#include <linux/rwsem.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/string.h>
|
|
#include <linux/sysfs.h>
|
|
|
|
#ifdef DEBUG
|
|
#include <linux/delay.h>
|
|
#endif
|
|
|
|
#define BUFFER_LENGTH 10
|
|
|
|
// représente un dossier sur sysfs
|
|
static struct kobject eudyptula;
|
|
|
|
// représente un fichier sur sysfs
|
|
static struct attribute id_file = {
|
|
.name = "id",
|
|
.mode = 0666
|
|
};
|
|
|
|
static struct attribute jiffies_file = {
|
|
.name = "jiffies",
|
|
.mode = 0444
|
|
};
|
|
|
|
static struct attribute foo_file = {
|
|
.name = "foo",
|
|
.mode = 0644
|
|
};
|
|
|
|
static char *id_msg;
|
|
static char *foo_msg;
|
|
static struct rw_semaphore foo_sem;
|
|
|
|
/*
|
|
* fonctions pour pouvoir lire et écrire dans les fichiers. elles sont ici
|
|
* découpées pour mieux se rendre compte. Il faut cependant les appeler depuis
|
|
* les fonctions se trouvant plus bas.
|
|
*/
|
|
|
|
static ssize_t id_read(char *buffer)
|
|
{
|
|
return sysfs_emit(buffer, id_msg);
|
|
}
|
|
|
|
static ssize_t id_write(const char *buffer, size_t size)
|
|
{
|
|
int ret = -EINVAL;
|
|
|
|
if (!strcmp(buffer, "congruent"))
|
|
ret = size;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static ssize_t jiffies_read(char *buffer)
|
|
{
|
|
return sprintf(buffer, "%lld\n", jiffies_64);
|
|
}
|
|
|
|
static ssize_t foo_read(char *buffer)
|
|
{
|
|
int ret = -EINVAL;
|
|
|
|
if (down_read_trylock(&foo_sem)) {
|
|
ret = sysfs_emit(buffer, foo_msg);
|
|
#ifdef DEBUG
|
|
msleep(5000);
|
|
#endif
|
|
up_read(&foo_sem);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static ssize_t foo_write(const char *buffer, size_t count)
|
|
{
|
|
int ret = -EINVAL;
|
|
|
|
if (down_write_trylock(&foo_sem)) {
|
|
ret = strscpy(foo_msg, buffer, count + 1);
|
|
#ifdef DEBUG
|
|
msleep(5000);
|
|
#endif
|
|
up_write(&foo_sem);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* fonctions utilisées pour lire et écrire dans les attributes. Elles sont
|
|
* mises dans une structure sysfs_ops et mis à l'initialisation du kobject via
|
|
* un ktype.
|
|
*/
|
|
|
|
ssize_t show(struct kobject *kobj, struct attribute *attr, char *buffer)
|
|
{
|
|
ssize_t ret = 0;
|
|
|
|
if (!strcmp(attr->name, "id"))
|
|
ret = id_read(buffer);
|
|
else if (!strcmp(attr->name, "jiffies"))
|
|
ret = jiffies_read(buffer);
|
|
else if (!strcmp(attr->name, "foo"))
|
|
ret = foo_read(buffer);
|
|
else
|
|
pr_info("keske tu essaies de lire ?!");
|
|
|
|
return ret;
|
|
}
|
|
|
|
ssize_t store(struct kobject *kobj, struct attribute *attr, const char *buffer,
|
|
size_t len)
|
|
{
|
|
ssize_t ret = 0;
|
|
|
|
if (!strcmp(attr->name, "id"))
|
|
ret = id_write(buffer, len);
|
|
else if (!strcmp(attr->name, "foo"))
|
|
ret = foo_write(buffer, len);
|
|
else
|
|
pr_info("keske tu essaies d'ecrire ?!");
|
|
|
|
return ret;
|
|
}
|
|
|
|
static const struct sysfs_ops my_ops = {
|
|
.show = &show,
|
|
.store = &store,
|
|
};
|
|
|
|
static const struct kobj_type my_type = {
|
|
.sysfs_ops = &my_ops,
|
|
};
|
|
|
|
static int __init my_init(void)
|
|
{
|
|
pr_info("Coucou le gens !!!!\n");
|
|
|
|
if (!memset(&eudyptula, 0, sizeof(struct kobject)))
|
|
return -ENOMEM;
|
|
|
|
if (kobject_init_and_add(&eudyptula, &my_type, NULL, "eudyptula")) {
|
|
kobject_put(&eudyptula);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
if (sysfs_create_file(&eudyptula, &id_file)
|
|
|| sysfs_create_file(&eudyptula, &jiffies_file)
|
|
|| sysfs_create_file(&eudyptula, &foo_file)) {
|
|
kobject_put(&eudyptula);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
init_rwsem(&foo_sem);
|
|
id_msg = kmalloc(12, GFP_KERNEL);
|
|
foo_msg = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
|
strscpy(id_msg, "pouetpouet\n", 12);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void __exit my_exit(void)
|
|
{
|
|
sysfs_remove_file(&eudyptula, &id_file);
|
|
sysfs_remove_file(&eudyptula, &jiffies_file);
|
|
sysfs_remove_file(&eudyptula, &foo_file);
|
|
kobject_put(&eudyptula);
|
|
kfree(id_msg);
|
|
kfree(foo_msg);
|
|
pr_info("Tschuss !!!\n");
|
|
}
|
|
|
|
module_init(my_init);
|
|
module_exit(my_exit);
|
|
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_AUTHOR("rick <rick@gnous.eu>");
|
|
MODULE_DESCRIPTION("Module pour tester le sysfs.");
|