====== Implémentation d'un périphérique caractère ====== ===ModuleDMX.c=== #include #include #include // Permet d'ouvrir et de fermer un fichier et de lire et d'écrire #include #include // Utilisé pour la synchronisation #include // Permet l'accès des données entre l'espace du Noyau et celui de l'utilisateur // Création d'une structure pour notre périphérique struct fake_device { char data[100]; struct semaphore sem; } virtual_device; // Pour enregistrer le périphérique plus tard nous avons besoin d'un objet cdev et d'autres variables struct cdev *mcdev; // m est préfixe veut dire que c'est le notre cdev = character device int major_number; int ret; //Variable de retour de fonctions, car la pile du noyau est très petite. //Si nous déclarions des variables tout au long du programme cela engorgerait la pile rapidement dev_t dev_num; // Enregistrera le nombre Majeur que le noyau nous donnera // Le nom apparaît dans /proc/devices #define DEVICE_NAME "DMX" // Méthode appelée lors de l'ouverture du périphérique // inode représente le fichier sur le disque // file est une représentation abstraite du fichier int device_open(struct inode *inode, struct file *filp) { // Permet à un seul processus d'ouvrir ce périphérique par l'utilisation d'un semaphore if (down_interruptible(&virtual_device.sem) != 0) { printk(KERN_ALERT "DMX : Impossible de bloquer le peripherique pendant l'ouverture\n"); return -1; } printk(KERN_INFO "DMX : Le peripherique est ouvert\n"); return 0; } // Méthode appelée quand un utiliasteur veut lire des informations provenant du périphérique ssize_t device_read(struct file* filp, char* bufStoreData, size_t bufCount, loff_t* curOffset) { // Prend les données l'espace utilisateur (processus) vers l'espace du Noyau (périphérique) // printk(KERN_ALERT "DMX : Ecriture de donnees\n"); ret = copy_to_user(bufStoreData, virtual_device.data, bufCount); return ret; } // Méthode appelée quand un utiliasteur veut lire des informations provenant du périphérique ssize_t device_write(struct file* filp, const char* bufStoreData, size_t bufCount, loff_t* curOffset) { // Prend les données de l'espace Noyau (périphérique) vers l'espace utlisateur (processus) // int i; printk(KERN_ALERT "DMX : Lecture de donnees\n"); ret = copy_from_user(virtual_device.data, bufStoreData, bufCount); for (i = 0; i < 100; i++) { virtual_device.data[i]++; } return ret; } int device_release(struct inode *inode, struct file *filp) { // Réalise l'inverse de d'ouverture en utilisant up pour le semaphore et permet ainsi // aux autres processus de pouvoir utiliser le périphérique à présent up(&virtual_device.sem); printk(KERN_ALERT "DMX : Le peripherique est ferme\n"); return 0; } struct file_operations fops = { .owner = THIS_MODULE, .read = device_read, .write = device_write, .open = device_open, .release = device_release }; static int driver_entry(void) { // L'enregistrement de notre périphérique dans le système se fait en deux temps : // 1 : Utilisation dynamique pour assigner notre périphérique ret = alloc_chrdev_region(&dev_num, 0, 1, DEVICE_NAME); if (ret < 0) { printk(KERN_ALERT "DMX : impossible d'obtenir un nombre majeur\n"); return ret; } major_number = MAJOR(dev_num); // Extrait le nombre Majeur printk(KERN_INFO "DMX : Le nombre majeur est %d\n", major_number); printk(KERN_INFO "Utiliser \"mknod /dev/%s c %d 0\" pour le fichier de peripherique\n", DEVICE_NAME, major_number); // 2 : mcdev = cdev_alloc(); // Initialisation de notre périphérique mcdev->ops = &fops; // Pointeur sur struct file_operations mcdev->owner = THIS_MODULE; // Après l'avoir initalisé, il faut l'ajouter au noyau // ret = cdev_add(mcdev, dev_num, 1); if (ret < 0) { printk(KERN_ALERT "DMX : Impossible de charger le peripherique dans le noyau\n"); return ret; } // Initialisation du semaphore sema_init(&virtual_device.sem, 1); return 0; } static void driver_exit(void) { cdev_del(mcdev); unregister_chrdev_region(dev_num, 1); printk(KERN_ALERT "DMX : Le module est decharge\n"); } module_init(driver_entry); module_exit(driver_exit); ===Makefile=== obj-m += ModuleDMX.o all: clean compile compile: make ARCH=arm CROSS_COMPILE=${CCPREFIX} -C /home/{nomUtilisateur}/rpi/linux-rpi-3.10.y M=$(PWD) modules clean: make -C /home/{nomUtilisateur}/rpi/linux-rpi-3.10.y M=$(PWD) clean {{tag>raspberry_pi sylvain}}