#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");