[LTP] [PATCH v3] kernel/input: fix failure on an old kernel
Xiao Yang
yangx.jy@cn.fujitsu.com
Mon Dec 4 08:45:24 CET 2017
Hi Cyril,
Ping. :-)
Thanks,
Xiao Yang
On 2017/11/13 14:45, Xiao Yang wrote:
> 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 */
More information about the ltp
mailing list