[LTP] [PATCH v3] kernel/input: fix failure on an old kernel
Xiao Yang
yangx.jy@cn.fujitsu.com
Mon Nov 13 07:45:04 CET 2017
1) On some old kernels(e.g. v2.6.32), we always triggered the following
error when running input04 and input05:
--------------------------------------------------------------------
TINFO : Found uinput dev at /dev/uinput
TINFO : Unexpected ev type=0 code=0 value=0
TFAIL : Data received /dev/inputX
---------------------------------------------------------------------
After investigation, the single EV_SYN event can be processed on an
old kernel. However, the EV_SYN event handling has been modfied by
the following patch:
'4369c64c79a2("Input: Send events one packet at a time")'
The patch is designed to reduce the time taken for processing a lot of
events. As a side effect, the single EV_SYN event handling depends on
one or more other events(e.g. EV_REL), so it should be processed
together with others, since this action is atomic.
Only when the number of queued events(include EV_SYN) is greater than
one can these events be processed.
Please see the kenrel code in drivers/input/input.c, as below:
--------------------------------------------------------------------
static void input_handle_event(struct input_dev *dev,
...
if (disposition & INPUT_FLUSH) {
// num_vals: number of values queued in the current frame
if (dev->num_vals >= 2)
input_pass_values(dev, dev->vals, dev->num_vals);
dev->num_vals = 0;
...
--------------------------------------------------------------------
For example, steps to send an empty move and EV_SYN:
-----------------------------------------------------
send_event(fd, EV_REL, REL_X, 0);
send_event(fd, EV_SYN, 0, 0);
-----------------------------------------------------
On an old kernel(before v3.7.0), the EV_SYN/SYN_REPORT event can be
processed independently, so it is passed into /dev/input/eventX.
On a new kernel(since v3.7.0), the EV_SYN/SYN_REPORT event depends on
EV_REL/REL_X which is an empty move, so it is ignored.
We feel this failure is due to the different mechanism of processing
EV_SYN instead of a kernel bug, so we ignore stray sync events on older
kernels.
2) We move the check_event_code and check_sync_event() helpers to the
library so that we can use them.
3) Fix compiler warning, as below:
------------------------------------------------------------------------
input06.c:213: warning: ‘ret’ may be used uninitialized in this function
------------------------------------------------------------------------
Signed-off-by: Xiao Yang <yangx.jy@cn.fujitsu.com>
---
testcases/kernel/input/input02.c | 2 +-
testcases/kernel/input/input04.c | 2 +-
testcases/kernel/input/input05.c | 2 +-
testcases/kernel/input/input06.c | 18 ++++--------------
testcases/kernel/input/input_helper.c | 34 +++++++++++++++++++++++++++++-----
testcases/kernel/input/input_helper.h | 4 +++-
6 files changed, 39 insertions(+), 23 deletions(-)
diff --git a/testcases/kernel/input/input02.c b/testcases/kernel/input/input02.c
index df3b257..6964ed7 100644
--- a/testcases/kernel/input/input02.c
+++ b/testcases/kernel/input/input02.c
@@ -61,7 +61,7 @@ int main(int ac, char **av)
case -1:
tst_brkm(TBROK | TERRNO, cleanup, "fork() failed");
default:
- if (no_events_queued(fd2))
+ if (no_events_queued(fd2, 0))
tst_resm(TPASS, "No data received in eventX");
else
tst_resm(TFAIL, "Data received in eventX");
diff --git a/testcases/kernel/input/input04.c b/testcases/kernel/input/input04.c
index 4b16ca7..e57b76b 100644
--- a/testcases/kernel/input/input04.c
+++ b/testcases/kernel/input/input04.c
@@ -57,7 +57,7 @@ int main(int ac, char **av)
case -1:
tst_brkm(TBROK | TERRNO, cleanup, "fork() failed");
default:
- if (no_events_queued(fd2))
+ if (no_events_queued(fd2, 1))
tst_resm(TPASS,
"No data received in /dev/inputX");
else
diff --git a/testcases/kernel/input/input05.c b/testcases/kernel/input/input05.c
index 5ca01d8..46b4fe8 100644
--- a/testcases/kernel/input/input05.c
+++ b/testcases/kernel/input/input05.c
@@ -63,7 +63,7 @@ int main(int ac, char **av)
case -1:
tst_brkm(TBROK | TERRNO, cleanup, "fork() failed");
default:
- if (no_events_queued(fd2))
+ if (no_events_queued(fd2, 1))
tst_resm(TPASS, "No data received in eventX");
else
tst_resm(TFAIL, "Data received in eventX");
diff --git a/testcases/kernel/input/input06.c b/testcases/kernel/input/input06.c
index 4c5f1a8..14141b7 100644
--- a/testcases/kernel/input/input06.c
+++ b/testcases/kernel/input/input06.c
@@ -115,11 +115,6 @@ static int check_event(struct input_event *iev, int event, int code, int value)
return iev->type == event && iev->code == code && iev->value == value;
}
-static int check_event_code(struct input_event *iev, int event, int code)
-{
- return iev->type == event && iev->code == code;
-}
-
static void read_events(void)
{
int rd = read(fd2, events, sizeof(events));
@@ -151,11 +146,6 @@ static struct input_event *next_event(void)
return &events[ev_iter++];
}
-static int check_sync_event(void)
-{
- return check_event_code(next_event(), EV_SYN, SYN_REPORT);
-}
-
static int parse_autorepeat_config(struct input_event *iev)
{
if (!check_event_code(iev, EV_REP, REP_DELAY)) {
@@ -177,13 +167,13 @@ static int parse_key(struct input_event *iev)
{
int autorep_count = 0;
- if (!check_event(iev, EV_KEY, KEY_X, 1) || !check_sync_event()) {
+ if (!check_event(iev, EV_KEY, KEY_X, 1) || !check_sync_event(next_event())) {
tst_resm(TFAIL, "Didn't get expected key press for KEY_X");
return 0;
}
iev = next_event();
- while (check_event(iev, EV_KEY, KEY_X, 2) && check_sync_event()) {
+ while (check_event(iev, EV_KEY, KEY_X, 2) && check_sync_event(next_event())) {
autorep_count++;
iev = next_event();
}
@@ -195,7 +185,7 @@ static int parse_key(struct input_event *iev)
return 0;
}
- if (!check_event(iev, EV_KEY, KEY_X, 0) || !check_sync_event()) {
+ if (!check_event(iev, EV_KEY, KEY_X, 0) || !check_sync_event(next_event())) {
tst_resm(TFAIL,
"Didn't get expected key release for KEY_X");
return 0;
@@ -210,7 +200,7 @@ static int parse_key(struct input_event *iev)
static int check_events(void)
{
struct input_event *iev;
- int ret;
+ int ret = 0;
int rep_config_done = 0;
int rep_keys_done = 0;
diff --git a/testcases/kernel/input/input_helper.c b/testcases/kernel/input/input_helper.c
index 08fa81c..13a6cd8 100644
--- a/testcases/kernel/input/input_helper.c
+++ b/testcases/kernel/input/input_helper.c
@@ -229,21 +229,45 @@ void destroy_device(int fd)
unload_uinput();
}
-int no_events_queued(int fd)
+int check_event_code(struct input_event *iev, int event, int code)
+{
+ return iev->type == event && iev->code == code;
+}
+
+int check_sync_event(struct input_event *iev)
+{
+ return check_event_code(iev, EV_SYN, SYN_REPORT);
+}
+
+/*
+ * the value of stray_sync_event:
+ * 0: EV_SYN/SYN_REPORT events should not be received in /dev/input/eventX
+ * 1: EV_SYN/SYN_REPORT events may be received in /dev/input/eventX
+ * On an old kernel(before v3.7.0), EV_SYN/SYN_REPORT events are always
+ * received even though we send empty moves.
+ */
+int no_events_queued(int fd, int stray_sync_event)
{
struct pollfd fds = {.fd = fd, .events = POLLIN};
- int ret, res;
+ int ret, res, sync_event_ignored;
struct input_event ev;
+ if (tst_kvercmp(3, 7, 0) < 0 && stray_sync_event)
+ sync_event_ignored = 1;
+
ret = poll(&fds, 1, 30);
if (ret > 0) {
res = read(fd, &ev, sizeof(ev));
if (res == sizeof(ev)) {
- tst_resm(TINFO,
- "Unexpected ev type=%i code=%i value=%i",
- ev.type, ev.code, ev.value);
+ if (sync_event_ignored && check_sync_event(&ev)) {
+ ret = 0;
+ } else {
+ tst_resm(TINFO,
+ "Unexpected ev type=%i code=%i value=%i",
+ ev.type, ev.code, ev.value);
+ }
}
}
diff --git a/testcases/kernel/input/input_helper.h b/testcases/kernel/input/input_helper.h
index 9b85dc9..7f61be1 100644
--- a/testcases/kernel/input/input_helper.h
+++ b/testcases/kernel/input/input_helper.h
@@ -29,6 +29,8 @@ int open_uinput(void);
void create_device(int fd);
void setup_mouse_events(int fd);
void destroy_device(int fd);
-int no_events_queued(int fd);
+int check_event_code(struct input_event *iev, int event, int code);
+int check_sync_event(struct input_event *iev);
+int no_events_queued(int fd, int stray_sync_event);
#endif /* INPUT_HELPER_H */
--
1.8.3.1
More information about the ltp
mailing list