// SPDX-License-Identifier: GPL-2.0 #define DEBUG 1 #include #include #include #include #include #include #include #include #include #ifdef DEBUG #include #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 "); MODULE_DESCRIPTION("Module pour tester le sysfs.");