From 372b4822122caae394d6e5060c669352b6193b91 Mon Sep 17 00:00:00 2001 From: Florian RICHER Date: Mon, 24 Feb 2025 20:42:34 +0100 Subject: [PATCH] Ajout d'un driver pour la gestion d'une led via un PIN GPIO --- 09_gpio_led_rpi3/Makefile | 7 ++ 09_gpio_led_rpi3/test_module.c | 141 +++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 09_gpio_led_rpi3/Makefile create mode 100644 09_gpio_led_rpi3/test_module.c diff --git a/09_gpio_led_rpi3/Makefile b/09_gpio_led_rpi3/Makefile new file mode 100644 index 0000000..b909b3c --- /dev/null +++ b/09_gpio_led_rpi3/Makefile @@ -0,0 +1,7 @@ +obj-m += test_module.o + +all: + make -C $(LINUX_MODULES_FOLDER)/build M=$(PWD) modules + +clean: + make -C $(LINUX_MODULES_FOLDER)/build M=$(PWD) clean diff --git a/09_gpio_led_rpi3/test_module.c b/09_gpio_led_rpi3/test_module.c new file mode 100644 index 0000000..1043699 --- /dev/null +++ b/09_gpio_led_rpi3/test_module.c @@ -0,0 +1,141 @@ +#include +#include +#include +#include + +// gpiochip0: GPIOs 512-565, parent: platform/3f200000.gpio, pinctrl-bcm2835 +// From /sys/kernel/debug/gpio +#define RPI3_BCM2835_GPIO_OFFSET 512 +#define BCM_TO_LINUX_GPIO(bcm) (RPI3_BCM2835_GPIO_OFFSET + (bcm)) + +static int gpio_pin = -1; +module_param(gpio_pin, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(gpio_pin, "BCM GPIO pin number (e.g., 17)"); + +struct gpio_led_rpi3 { + int linux_gpio; + int bcm_gpio; + struct gpio_desc *desc; + struct led_classdev *led; +}; + +static struct gpio_led_rpi3 pin; + +static void gpio_led_rpi3_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness) { + pr_info("gpio_led_rpi3: Luminosité défini sur la LED %s à %d\n", led_cdev->name, brightness); + + if (brightness < 0 || brightness > 1) { + pr_err("gpio_led_rpi3: Valeur incorrecte"); + return; + } + + // Applique la nouvelle valeur à la LED + gpiod_set_value(pin.desc, brightness); + pr_info("gpio_pin_rpi3: GPIO %d (BCM %d) défini à %d\n", pin.linux_gpio, pin.bcm_gpio, brightness); +} + +static enum led_brightness gpio_led_rpi3_brightness_get(struct led_classdev *led_cdev) { + pr_info("Luminosité lu sur la LED %s, valeur actuelle: %d\n", led_cdev->name, led_cdev->brightness); + return led_cdev->brightness; +} + +static int register_rpi3_gpio_pin(void) +{ + if (gpio_pin < 0) { + pr_err("gpio_led_rpi3: You must specify 'gpio_pin' (e.g., gpio_pin=17)\n"); + return -EINVAL; + } + + pin.bcm_gpio = gpio_pin; + pin.linux_gpio = BCM_TO_LINUX_GPIO(pin.bcm_gpio); + + // Récupération du descripteur GPIO à partir du numéro Globale Linux + pin.desc = gpio_to_desc(pin.linux_gpio); + if (!pin.desc) { + pr_err("gpio_led_rpi3: Le GPIO %d (BCM %d) non trouvé\n", pin.linux_gpio, pin.bcm_gpio); + return -ENODEV; + } + + // Réclame le PIN GPIO + if (gpiod_direction_output(pin.desc, 0)) { + pr_err("gpio_led_rpi3: Impossible de configurer le GPIO %d\n", pin.linux_gpio); + gpiod_put(pin.desc); + return -EINVAL; + } + + // Réinitialise la LED + gpiod_set_value(pin.desc, 0); + + return 0; +} + +static void unregister_rpi3_gpio_pin(void) +{ + // Turn LED off and release GPIO + gpiod_set_value(pin.desc, 0); + gpiod_put(pin.desc); + pr_info("gpio_led_rpi3: GPIO %d (BCM %d) libéré (LED OFF)\n", pin.linux_gpio, pin.bcm_gpio); +} + +static int register_rpi3_led(void) +{ + pin.led = kzalloc(sizeof(struct led_classdev), GFP_KERNEL); + if (!pin.led) { + pr_err("Échec de l'allocation de mémoire pour la LED virtuelle\n"); + return -ENOMEM; + } + + pin.led->name = kasprintf(GFP_KERNEL, "rpi3-led:white:gpio-%d", pin.bcm_gpio); + pin.led->color = LED_COLOR_ID_WHITE; + pin.led->brightness = 0; + pin.led->max_brightness = 1; + pin.led->brightness_set = gpio_led_rpi3_brightness_set; + pin.led->brightness_get = gpio_led_rpi3_brightness_get; + + int ret = led_classdev_register(NULL, pin.led); + if (ret < 0) { + kfree(pin.led->name); + kfree(pin.led); + pr_err("Impossible d'ajouter la LED virtuelle\n"); + return ret; + } + + return 0; +} + +static void unregister_rpi3_led(void) +{ + led_classdev_unregister(pin.led); + kfree(pin.led->name); + kfree(pin.led); +} + +static int __init gpio_led_rpi3_init(void) +{ + int ret = register_rpi3_gpio_pin(); + if (ret != 0) { + return ret; + } + + ret = register_rpi3_led(); + if (ret != 0) { + unregister_rpi3_gpio_pin(); + return ret; + } + + return 0; +} + +static void __exit gpio_led_rpi3_exit(void) +{ + unregister_rpi3_led(); + unregister_rpi3_gpio_pin(); +} + +module_init(gpio_led_rpi3_init); +module_exit(gpio_led_rpi3_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Florian RICHER "); +MODULE_DESCRIPTION("Un module noyau pour utiliser un PIN GPIO d'une RPI en tant que LED"); +MODULE_VERSION("1.0"); \ No newline at end of file