// SPDX-License-Identifier: GPL-2.0 /* TODO * créer char device avec un mineur dynamique * appeler le device eudyptula */ #include #include #include #include #include #define BUFFER_LENGTH 10 #define NUMBER_MINORS 1 static char *msg; static int major; static ssize_t my_read(struct file *, char __user *buffer, size_t length, loff_t *offset) { /* le nombre de bytes qu'on va lire */ int bytes = 0; /* le pointeur qui va parcourir notre message pour le mettre dans le buffer * du userspace */ const char *msg_tmp = msg; /* si on essaie de lire plus que le message */ if (!*(msg + *offset)) { *offset = 0; /* on reset l'offset */ return 0; /* on a rien lu */ } /* on commence à l'offset */ msg_tmp += *offset; while (*msg_tmp && bytes < length) { /* on va copier char par char le message dans le userspace */ put_user(*(msg_tmp), (buffer + bytes)); bytes++; msg_tmp++; } /* on déplace l'offset du nombre de bytes qu'on a lu */ *offset += bytes; return bytes; } static ssize_t my_write(struct file *, const char __user *buffer, size_t size, loff_t *) { int ret; /* là où on stocke l'entrée utilisateur */ char *tmp_buffer; /* on peut pas écrire dans un buffer sans place */ if (size == 0) return 0; /* on alloue BUFFER_LENGTH qui vaut exactement la taille de "congruent", le * mot qu'on souhaite détecter */ tmp_buffer = kzalloc(BUFFER_LENGTH, GFP_KERNEL); /* si on arrive pas à copier les données utilisateurs, on retourne une * erreur */ if (copy_from_user(tmp_buffer, buffer, BUFFER_LENGTH)) { kfree(tmp_buffer); return -EINVAL; } /* comme on copie des bytes et non une string, il faut mettre le byte de fin * de string manuellement, à la fin du buffer. */ *(tmp_buffer + BUFFER_LENGTH - 1) = '\0'; pr_info("Test %s-\n", tmp_buffer); if (!strcmp(tmp_buffer, "congruent")) /* on retourne la longueur du buffer écrit pour dire que tout est OK */ ret = BUFFER_LENGTH; else ret = -EINVAL; kfree(tmp_buffer); return ret; } static const struct file_operations fops = { .owner = THIS_MODULE, .read = my_read, .write = my_write, }; static struct cdev *my_cdev; static int __init my_init(void) { dev_t dev; int ret; msg = kmalloc(19, GFP_KERNEL); strcpy(msg, "coucou c'est rick\n"); /* on demande un numéro majeur dynamiquement avec uniquement un seul numéro * mineur */ ret = alloc_chrdev_region(&dev, 0, NUMBER_MINORS, "eudyptula"); if (ret) pr_err("Erreur lors de l'initialisation du device : %d\n", ret); major = MAJOR(dev); /* on récupère le numéro majeur alloué */ /* on initialise notre chardevice */ my_cdev = cdev_alloc(); my_cdev->ops = &fops; my_cdev->owner = THIS_MODULE; ret = cdev_add(my_cdev, dev, NUMBER_MINORS); if (ret) pr_err("Erreur lors de la création du device : %d\n", ret); pr_info("Initialisation terminée, majeur: %d\n", major); return 0; } static void __exit my_exit(void) { dev_t dev; pr_info("Suppression du device avec pour majeur: %d\n", major); kfree(msg); cdev_del(my_cdev); dev = MKDEV(major, 0); unregister_chrdev_region(dev, NUMBER_MINORS); } module_init(my_init); module_exit(my_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("rick "); MODULE_DESCRIPTION("Création d'un device accessible en lecture et écriture.");