button {
compatible = "gpio-button";
donw-disp,gpio = <&pio PH 2 1 1 1 0>;
linux,code = <194>;
};
2、驱动源码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <disp2/sunxi_display2.h>
#include <sys/time.h>
#define DRIVER_NAME "gpio_button_driver"
struct gpio_button_data {
int gpio;
int irq;
int keycode;
bool is_down;
struct input_dev *input;
};
static irqreturn_t gpio_button_irq(int irq, void *dev_id)
{
struct gpio_button_data *data = dev_id;
bool is_down = gpio_get_value(data->gpio) == 0;
if (is_down != data->is_down) {
data->is_down = is_down;
// 触发输入事件
input_event(data->input, EV_KEY, data->keycode, is_down ? 1 : 0);
input_sync(data->input);
}
return IRQ_HANDLED;
}
static int gpio_button_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
struct gpio_button_data *data;
int ret;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data) {
dev_err(dev, "Failed to allocate memory\n");
return -ENOMEM;
}
// data->gpio = of_get_gpio(node, 0);
data->gpio = of_get_named_gpio(node, "donw-disp,gpio", 0);
if (data->gpio < 0) {
dev_err(dev, "Failed to get gpio\n");
return data->gpio;
}
ret = gpio_request(data->gpio, "my-gpio-button");
if (ret) {
dev_err(dev, "Failed to request gpio\n");
return ret;
}
data->irq = gpio_to_irq(data->gpio);
ret = request_irq(data->irq, gpio_button_irq,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
"my-gpio-button", data);
if (ret) {
dev_err(dev, "Failed to request IRQ\n");
goto free_gpio;
}
// 获取按键对应的键值
if (of_property_read_u32(node, "linux,code", &data->keycode)) {
dev_err(dev, "Failed to get keycode\n");
ret = -EINVAL;
goto free_irq;
}
// 初始化 input_dev 结构体
data->input = input_allocate_device();
if (!data->input) {
dev_err(dev, "Failed to allocate input device\n");
ret = -ENOMEM;
goto free_irq;
}
data->input->name = dev_name(dev);
data->input->id.bustype = BUS_HOST;
data->input->id.vendor = 0x0000;
data->input->id.product = 0x0000;
data->input->id.version = 0x0000;
// 设置输入事件类型和代码
set_bit(EV_KEY, data->input->evbit);
set_bit(data->keycode, data->input->keybit);
// 注册输入设备
ret = input_register_device(data->input);
if (ret) {
dev_err(dev, "Failed to register input device\n");
goto free_input;
}
platform_set_drvdata(pdev, data);
return 0;
free_input:
input_free_device(data->input);
free_irq:
free_irq(data->irq, data);
free_gpio:
gpio_free(data->gpio);
return ret;
}
static int gpio_button_remove(struct platform_device *pdev)
{
struct gpio_button_data *data = platform_get_drvdata(pdev);
input_unregister_device(data->input);
free_irq(data->irq, data);
gpio_free(data->gpio);
return 0;
}
static const struct of_device_id gpio_button_of_match[] = {
{ .compatible = "gpio-button" },
{},
};
// MODULE_DEVICE_TABLE(of, gpio_button_of_match);
static struct platform_driver gpio_button_driver = {
.probe = gpio_button_probe,
.remove = gpio_button_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = of_match_ptr(gpio_button_of_match),
.owner = THIS_MODULE,
},
};
static int __init gpio_button_init(void)
{
return platform_driver_register(&gpio_button_driver);
}
static void __exit gpio_button_exit(void)
{
platform_driver_unregister(&gpio_button_driver);
}
module_init(gpio_button_init);
module_exit(gpio_button_exit);
MODULE_AUTHOR("yanjianbo");
MODULE_DESCRIPTION("SW GPIO USER driver");
MODULE_LICENSE("GPL");
3、应用源码
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <linux/input.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <disp2/sunxi_display2.h>
#define EVENT_DEV "/dev/input/event8"
int set_brightness(int fd, int value) {
unsigned long args[3];
int err, i;
for(i = 0; i < 2; i++)
{
args[0] = i;
if(ioctl(fd, DISP_GET_OUTPUT_TYPE,args) == DISP_OUTPUT_TYPE_LCD)
{
args[1] = value;
args[2] = 0;
err = ioctl(fd, DISP_LCD_SET_BRIGHTNESS, args);
return err;
}
}
return -1;
}
int main()
{
int fd;
struct input_event ev;
int flag_disp=0;
int fd_disp = open("/dev/disp", O_RDONLY);
if (fd_disp < 0) {
printf("open /dev/disp failed\n");
return -1;
}
// 打开输入设备文件
fd = open(EVENT_DEV, O_RDONLY);
if (fd == -1) {
perror("Failed to open event device");
return 1;
}
while (1) {
// 读取输入事件
if (read(fd, &ev, sizeof(struct input_event)) < 0) {
perror("Failed to read event");
break;
}
// 判断是否为按键事件且按键状态改变
if (ev.type == EV_KEY && ev.value == 1) {
printf("in\n");
}
close(fd);
}
这个示例是通过EVENT事件将信息传递给应用,如果不需要,去掉input子系统的相关内容就行。