initial commit
This commit is contained in:
4
Kconfig
Normal file
4
Kconfig
Normal file
@@ -0,0 +1,4 @@
|
||||
config GPIO_KEYBOARD_DRIVER
|
||||
tristate "gpio-keyboard-driver"
|
||||
help
|
||||
TODO write this
|
||||
13
Makefile
Normal file
13
Makefile
Normal file
@@ -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
|
||||
128
gpio-keyboard-driver.c
Normal file
128
gpio-keyboard-driver.c
Normal file
@@ -0,0 +1,128 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
static struct input_dev *kbd_dev;
|
||||
static int gpio_num;
|
||||
static int irq_num;
|
||||
|
||||
static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
int state = gpio_get_value(gpio_num);
|
||||
|
||||
/* Active low button */
|
||||
if (state == 0) {
|
||||
input_report_key(kbd_dev, KEY_A, 1);
|
||||
input_sync(kbd_dev);
|
||||
} else {
|
||||
input_report_key(kbd_dev, KEY_A, 0);
|
||||
input_sync(kbd_dev);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int gpio_kbd_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
|
||||
if (!np)
|
||||
return -EINVAL;
|
||||
|
||||
/* Read GPIO from DT */
|
||||
gpio_num = of_get_named_gpio(np, "gpios", 0);
|
||||
if (gpio_num < 0) {
|
||||
dev_err(dev, "Failed to get GPIO from DT\n");
|
||||
return gpio_num;
|
||||
}
|
||||
|
||||
ret = gpio_request(gpio_num, "gpio_kbd_button");
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to request GPIO\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
gpio_direction_input(gpio_num);
|
||||
|
||||
/* Allocate input device */
|
||||
kbd_dev = input_allocate_device();
|
||||
if (!kbd_dev) {
|
||||
dev_err(dev, "Failed to allocate input device\n");
|
||||
gpio_free(gpio_num);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
kbd_dev->name = "GPIO Keyboard Device";
|
||||
kbd_dev->evbit[0] = BIT_MASK(EV_KEY);
|
||||
set_bit(KEY_A, kbd_dev->keybit);
|
||||
|
||||
ret = input_register_device(kbd_dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to register input device\n");
|
||||
input_free_device(kbd_dev);
|
||||
gpio_free(gpio_num);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get IRQ from DT */
|
||||
irq_num = of_irq_get(np, 0);
|
||||
if (irq_num < 0) {
|
||||
dev_err(dev, "Failed to get IRQ from DT\n");
|
||||
input_unregister_device(kbd_dev);
|
||||
gpio_free(gpio_num);
|
||||
return irq_num;
|
||||
}
|
||||
|
||||
ret = request_irq(irq_num,
|
||||
gpio_irq_handler,
|
||||
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
|
||||
"gpio_kbd_irq",
|
||||
NULL);
|
||||
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to request IRQ\n");
|
||||
input_unregister_device(kbd_dev);
|
||||
gpio_free(gpio_num);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_info(dev, "GPIO keyboard driver loaded\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gpio_kbd_remove(struct platform_device *pdev)
|
||||
{
|
||||
free_irq(irq_num, NULL);
|
||||
input_unregister_device(kbd_dev);
|
||||
gpio_free(gpio_num);
|
||||
}
|
||||
|
||||
static const struct of_device_id gpio_kbd_of_match[] = {
|
||||
{ .compatible = "arcade,gpio-keyboard" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, gpio_kbd_of_match);
|
||||
|
||||
static struct platform_driver gpio_kbd_driver = {
|
||||
.probe = gpio_kbd_probe,
|
||||
.remove = gpio_kbd_remove,
|
||||
.driver = {
|
||||
.name = "gpio-keyboard",
|
||||
.of_match_table = gpio_kbd_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(gpio_kbd_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Nicholas Mello");
|
||||
MODULE_DESCRIPTION("GPIO-based virtual keyboard driver using Device Tree");
|
||||
Reference in New Issue
Block a user