Home | History | Annotate | Download | only in input
      1 /*
      2  * Copyright (c) 2015 Cedric Hnyda <chnyda (at) suse.com>
      3  *
      4  * This program is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU General Public License as
      6  * published by the Free Software Foundation; either version 2 of
      7  * the License, or (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it would be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12  * GNU General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program; if not, write the Free Software Foundation,
     16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     17  */
     18 
     19  /*
     20   *  Create a virtual device (mouse), send events to /dev/uinput
     21   *  and check that the events are well received in /dev/input/eventX
     22   */
     23 
     24 #include <linux/input.h>
     25 
     26 #include "input_helper.h"
     27 #include "test.h"
     28 #include "safe_macros.h"
     29 #include "lapi/fcntl.h"
     30 
     31 #define NB_TEST 20
     32 
     33 static void setup(void);
     34 static void send_events(void);
     35 static int verify_data(struct input_event *iev, int nb);
     36 static int check_events(void);
     37 static void cleanup(void);
     38 
     39 static int fd;
     40 static int fd2;
     41 
     42 char *TCID = "input01";
     43 
     44 int main(int ac, char **av)
     45 {
     46 	int lc;
     47 	int pid;
     48 
     49 	tst_parse_opts(ac, av, NULL, NULL);
     50 
     51 	setup();
     52 
     53 	for (lc = 0; TEST_LOOPING(lc); ++lc) {
     54 		pid = tst_fork();
     55 
     56 		switch (pid) {
     57 		case 0:
     58 			send_events();
     59 			exit(0);
     60 		case -1:
     61 			tst_brkm(TBROK | TERRNO, cleanup, "fork() failed");
     62 		default:
     63 			if (check_events())
     64 				tst_resm(TFAIL, "Wrong data read from eventX");
     65 			else
     66 				tst_resm(TPASS, "Data received from eventX");
     67 		break;
     68 		}
     69 
     70 		SAFE_WAITPID(NULL, pid, NULL, 0);
     71 	}
     72 
     73 	cleanup();
     74 	tst_exit();
     75 }
     76 
     77 static void setup(void)
     78 {
     79 	tst_require_root();
     80 
     81 	fd = open_uinput();
     82 	setup_mouse_events(fd);
     83 	create_device(fd);
     84 
     85 	fd2 = open_device();
     86 }
     87 
     88 static void send_events(void)
     89 {
     90 	int nb;
     91 
     92 	for (nb = 0; nb < NB_TEST; ++nb) {
     93 		send_rel_move(fd, 10, 1);
     94 		usleep(1000);
     95 	}
     96 }
     97 
     98 static int check_events(void)
     99 {
    100 	int nb, rd;
    101 	unsigned int i;
    102 	struct input_event iev[64];
    103 
    104 	nb = 0;
    105 
    106 	while (nb < NB_TEST * 3) {
    107 		rd = read(fd2, iev, sizeof(iev));
    108 
    109 		if (rd < 0)
    110 			tst_brkm(TBROK | TERRNO, cleanup, "read()");
    111 
    112 		if (rd == 0 || rd % sizeof(struct input_event)) {
    113 			tst_resm(TINFO, "read() returned unexpected %i", rd);
    114 			return 1;
    115 		}
    116 
    117 		for (i = 0; i < rd / sizeof(struct input_event); i++) {
    118 			if (verify_data(&iev[i], nb++))
    119 				return 1;
    120 		}
    121 	}
    122 
    123 	return 0;
    124 }
    125 
    126 static int verify_data(struct input_event *iev, int nb)
    127 {
    128 	if (nb % 3 == 0) {
    129 		if (iev->type != EV_REL) {
    130 			tst_resm(TINFO,
    131 			         "%i: Unexpected event type %i expected %i",
    132 			         nb, iev->type, EV_REL);
    133 			return 1;
    134 		}
    135 
    136 		if (iev->code != REL_X)
    137 			return 1;
    138 
    139 		if (iev->value != 10)
    140 			return 1;
    141 
    142 		return 0;
    143 	}
    144 
    145 	if (nb % 3 == 1) {
    146 		if (iev->type != EV_REL) {
    147 			tst_resm(TINFO,
    148 			         "%i: Unexpected event type %i expected %i",
    149 			         nb, iev->type, EV_REL);
    150 			return 1;
    151 		}
    152 
    153 		if (iev->code != REL_Y)
    154 			return 1;
    155 
    156 		if (iev->value != 1)
    157 			return 1;
    158 
    159 		return 0;
    160 	}
    161 
    162 	if (nb % 3 == 2) {
    163 		if (iev->type != EV_SYN) {
    164 			tst_resm(TINFO,
    165 			         "%i: Unexpected event type %i expected %i",
    166 			         nb, iev->type, EV_SYN);
    167 			return 1;
    168 		}
    169 
    170 		if (iev->code != 0)
    171 			return 1;
    172 
    173 		if (iev->value != 0)
    174 			return 1;
    175 
    176 		return 0;
    177 	}
    178 	return 1;
    179 }
    180 
    181 static void cleanup(void)
    182 {
    183 	if (fd2 > 0 && close(fd2))
    184 		tst_resm(TWARN | TERRNO, "close(fd2)");
    185 
    186 	destroy_device(fd);
    187 }
    188