/* * intrpt.c - Handling GPIO with interrupts * * Based upon the RPi example by Stefan Wendler (devnull@kaltpost.de) * from: * https://github.com/wendlers/rpi-kmod-samples * * Press one button to turn on a LED and another to turn it off. */ #include #include #include /* for ARRAY_SIZE() */ #include #include static int button_irqs[] = { -1, -1 }; /* Define GPIOs for LEDs. * TODO: Change the numbers for the GPIO on your board. */ static struct gpio leds[] = { { 4, GPIOF_OUT_INIT_LOW, "LED 1" } }; /* Define GPIOs for BUTTONS * TODO: Change the numbers for the GPIO on your board. */ static struct gpio buttons[] = { { 17, GPIOF_IN, "LED 1 ON BUTTON" }, { 18, GPIOF_IN, "LED 1 OFF BUTTON" } }; /* interrupt function triggered when a button is pressed. */ static irqreturn_t button_isr(int irq, void *data) { /* first button */ if (irq == button_irqs[0] && !gpio_get_value(leds[0].gpio)) gpio_set_value(leds[0].gpio, 1); /* second button */ else if (irq == button_irqs[1] && gpio_get_value(leds[0].gpio)) gpio_set_value(leds[0].gpio, 0); return IRQ_HANDLED; } static int __init intrpt_init(void) { int ret = 0; pr_info("%s\n", __func__); /* register LED gpios */ ret = gpio_request_array(leds, ARRAY_SIZE(leds)); if (ret) { pr_err("Unable to request GPIOs for LEDs: %d\n", ret); return ret; } /* register BUTTON gpios */ ret = gpio_request_array(buttons, ARRAY_SIZE(buttons)); if (ret) { pr_err("Unable to request GPIOs for BUTTONs: %d\n", ret); goto fail1; } pr_info("Current button1 value: %d\n", gpio_get_value(buttons[0].gpio)); ret = gpio_to_irq(buttons[0].gpio); if (ret < 0) { pr_err("Unable to request IRQ: %d\n", ret); goto fail2; } button_irqs[0] = ret; pr_info("Successfully requested BUTTON1 IRQ # %d\n", button_irqs[0]); ret = request_irq(button_irqs[0], button_isr, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "gpiomod#button1", NULL); if (ret) { pr_err("Unable to request IRQ: %d\n", ret); goto fail2; } ret = gpio_to_irq(buttons[1].gpio); if (ret < 0) { pr_err("Unable to request IRQ: %d\n", ret); goto fail2; } button_irqs[1] = ret; pr_info("Successfully requested BUTTON2 IRQ # %d\n", button_irqs[1]); ret = request_irq(button_irqs[1], button_isr, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "gpiomod#button2", NULL); if (ret) { pr_err("Unable to request IRQ: %d\n", ret); goto fail3; } return 0; /* cleanup what has been setup so far */ fail3: free_irq(button_irqs[0], NULL); fail2: gpio_free_array(buttons, ARRAY_SIZE(leds)); fail1: gpio_free_array(leds, ARRAY_SIZE(leds)); return ret; } static void __exit intrpt_exit(void) { int i; pr_info("%s\n", __func__); /* free irqs */ free_irq(button_irqs[0], NULL); free_irq(button_irqs[1], NULL); /* turn all LEDs off */ for (i = 0; i < ARRAY_SIZE(leds); i++) gpio_set_value(leds[i].gpio, 0); /* unregister */ gpio_free_array(leds, ARRAY_SIZE(leds)); gpio_free_array(buttons, ARRAY_SIZE(buttons)); } module_init(intrpt_init); module_exit(intrpt_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Handle some GPIO interrupts");