commit ec5f3d9134e43752d3d15136f9eca92f4b73abfe Author: Nick Mello Date: Sat Feb 7 00:21:31 2026 -0600 initial commit diff --git a/Kconfig b/Kconfig new file mode 100644 index 0000000..655c166 --- /dev/null +++ b/Kconfig @@ -0,0 +1,4 @@ +config GPIO_KEYBOARD_DRIVER + tristate "gpio-keyboard-driver" + help + TODO write this diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2672b4a --- /dev/null +++ b/Makefile @@ -0,0 +1,13 @@ +# Makefile for building my_driver kernel module + +KERNEL_DIR ?= $(PWD) +KERNEL_BUILD ?= $(KERNEL_DIR)/build + +obj-m += gpio-keyboard-driver.o + +# The default target +all: + $(MAKE) -C $(KERNEL_BUILD) M=$(PWD) modules + +clean: + $(MAKE) -C $(KERNEL_BUILD) M=$(PWD) clean diff --git a/gpio-keyboard-driver.c b/gpio-keyboard-driver.c new file mode 100644 index 0000000..1525327 --- /dev/null +++ b/gpio-keyboard-driver.c @@ -0,0 +1,117 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct input_dev *input_device; +static int gpio_button = -1; +static int irq_number; + +// Interrupt handler when GPIO is asserted +static irqreturn_t gpio_isr(int irq, void *dev_id) +{ + // Simulate keypress for the letter 'a' + input_report_key(input_device, KEY_A, 1); // KEY_A is the keycode for 'a' + input_sync(input_device); // Sync the event + input_report_key(input_device, KEY_A, 0); // KEY_A release + input_sync(input_device); // Sync again + + return IRQ_HANDLED; +} + +static int __init gpio_key_init(void) +{ + int ret; + + // Parse the device tree to get the GPIO pin + struct device_node *node = of_find_node_by_path("/gpio_keys/button"); + if (!node) { + pr_err("Device tree node not found\n"); + return -ENODEV; + } + + gpio_button = of_get_named_gpio(node, "gpio", 0); + if (gpio_button < 0) { + pr_err("Failed to get GPIO from device tree\n"); + return gpio_button; + } + + // Request the GPIO + ret = gpio_request(gpio_button, "gpio_key"); + if (ret) { + pr_err("Failed to request GPIO\n"); + return ret; + } + + // Set the GPIO as input + ret = gpio_direction_input(gpio_button); + if (ret) { + pr_err("Failed to set GPIO as input\n"); + gpio_free(gpio_button); + return ret; + } + + // Get the interrupt number associated with this GPIO + irq_number = gpio_to_irq(gpio_button); + if (irq_number < 0) { + pr_err("Failed to get IRQ number for GPIO\n"); + gpio_free(gpio_button); + return irq_number; + } + + // Request IRQ + ret = request_irq(irq_number, gpio_isr, IRQF_TRIGGER_FALLING, "gpio_key_isr", NULL); + if (ret) { + pr_err("Failed to request IRQ\n"); + gpio_free(gpio_button); + return ret; + } + + // Register input device (keyboard emulator) + input_device = input_allocate_device(); + if (!input_device) { + pr_err("Failed to allocate input device\n"); + free_irq(irq_number, NULL); + gpio_free(gpio_button); + return -ENOMEM; + } + + input_device->name = "GPIO Keyboard"; + input_device->id.bustype = BUS_USB; + input_device->evbit[0] = BIT(EV_KEY); + input_device->keybit[BIT_WORD(KEY_A)] = BIT(KEY_A); + + ret = input_register_device(input_device); + if (ret) { + pr_err("Failed to register input device\n"); + input_free_device(input_device); + free_irq(irq_number, NULL); + gpio_free(gpio_button); + return ret; + } + + pr_info("GPIO keyboard driver loaded\n"); + return 0; +} + +static void __exit gpio_key_exit(void) +{ + // Free resources + input_unregister_device(input_device); + free_irq(irq_number, NULL); + gpio_free(gpio_button); + + pr_info("GPIO keyboard driver unloaded\n"); +} + +module_init(gpio_key_init); +module_exit(gpio_key_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Nicholas Mello"); +MODULE_DESCRIPTION("GPIO Keyboard Driver");