05、输入子系统实验
一、设备树
c
&{/} {
input_button: input_button {
status = "okay";
compatible = "input_button";
button-gpios = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>; //引脚可以根据具体板卡修改,这里以GPIO0_B0
pinctrl-names = "default";
pinctrl-0 = <&input_button_pin>;
interrupt-parent = <&gpio0>;
interrupts = <RK_PB0 IRQ_TYPE_EDGE_BOTH>;
};
};
&{/pinctrl} {
pinctrl_button {
input_button_pin: input_button_pin {
rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
};
};
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
二、驱动
c
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/of.h> /*设备树*/
#include <linux/platform_device.h> /*平台设备*/
#include <linux/gpio/consumer.h> /*GPIO 接口描述符*/
#include <linux/input.h>
#include <linux/interrupt.h>
struct button_data {
struct gpio_desc *button_input_gpiod; //GPIO
struct input_dev *button_input_dev; //按键输入子系统结构体
struct platform_device *pdev; //平台设备结构体
int irq; //中断irq
};
/*按键中断处理函数*/
static irqreturn_t button_input_irq_hander(int irq, void *dev_id)
{
struct button_data *priv = dev_id;
int button_satus;
/*读取按键引脚的电平,根据读取得到的结果输入按键状态*/
button_satus = (gpiod_get_value(priv->button_input_gpiod) & 1);
if(button_satus)
{
input_report_key(priv->button_input_dev, BTN_0, 1);
input_sync(priv->button_input_dev);
}
else
{
input_report_key(priv->button_input_dev, BTN_0, 0);
input_sync(priv->button_input_dev);
}
return IRQ_HANDLED;
}
static int btn_open(struct input_dev *i_dev)
{
pr_info("input device opened()\n");
return 0;
}
static void btn_close(struct input_dev *i_dev)
{
pr_info("input device closed()\n");
}
static int button_probe(struct platform_device *pdev)
{
struct button_data *priv;
struct gpio_desc *gpiod;
struct input_dev *i_dev;
int ret;
pr_info("button_probe\n");
priv = devm_kzalloc(&pdev->dev,sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
i_dev = input_allocate_device();
if (!i_dev)
return -ENOMEM;
i_dev->open = btn_open;
i_dev->close = btn_close;
i_dev->name = "key input";
i_dev->dev.parent = &pdev->dev;
priv->button_input_dev = i_dev;
priv->pdev = pdev;
set_bit(EV_KEY, i_dev->evbit); /*设置要使用的输入事件类型*/
set_bit(BTN_0, i_dev->keybit); /* 按钮 0*/
gpiod = gpiod_get(&pdev->dev, "button", GPIOD_IN); /*获取gpio,并设置为输入*/
if (IS_ERR(gpiod))
return -ENODEV;
priv->irq = gpiod_to_irq(gpiod);
priv->button_input_gpiod = gpiod;
ret = input_register_device(priv->button_input_dev);
if (ret) {
pr_err("Failed to register inputdevice\n");
goto err_input;
}
platform_set_drvdata(pdev, priv);
ret = request_any_context_irq(priv->irq, button_input_irq_hander,IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "input-button", priv);
if (ret < 0) {
dev_err(&pdev->dev,"请求gpio中断失败\n");
goto err_btn;
}
return 0;
err_btn:
gpiod_put(priv->button_input_gpiod);
err_input:
input_free_device(priv->button_input_dev);
return ret;
}
static int button_remove(struct platform_device *pdev)
{
struct button_data *priv;
priv = platform_get_drvdata(pdev);
input_unregister_device(priv->button_input_dev);
input_free_device(priv->button_input_dev);
free_irq(priv->irq, priv);
gpiod_put(priv->button_input_gpiod);
return 0;
}
static const struct of_device_id button_dt_ids[] =
{
{ .compatible = "input_button", },
{ /*标记结束*/ }
};
static struct platform_driver button_input = {
.probe = button_probe,
.remove = button_remove,
.driver = {
.name = "button-input",
.of_match_table = of_match_ptr(button_dt_ids),
.owner = THIS_MODULE,
},
};
module_platform_driver(button_input);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("llh<zgwinli555@163.com>");
MODULE_DESCRIPTION("Embedfire,Input key device");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
三、应用
c
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <linux/input.h>
struct input_event button_input_event;
int button_status = 0; //保存按键状态;
int main(int argc, char *argv[])
{
int error = -20;
int button_status = 0;
/*打开文件*/
int fd = open("/dev/input/event4", O_RDONLY);
if (fd < 0)
{
printf("open file : /dev/input/event4 error!\n");
return -1;
}
printf("wait button down... \n");
do
{
/*读取按键状态*/
error = read(fd, &button_input_event, sizeof(button_input_event));
if (error < 0)
{
printf("read file error! \n");
}
if((button_input_event.type == 1) && (button_input_event.code == 0x100))
{
if(button_input_event.value == 0)
{
printf("button up\n");
}
else if(button_input_event.value == 1)
{
printf("button down\n");
}
}
} while (1);
printf("button Down !\n");
/*关闭文件*/
error = close(fd);
if (error < 0)
{
printf("close file error! \n");
}
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57