Home | History | Annotate | Download | only in tests-m32
      1 #include "tests.h"
      2 
      3 #ifdef HAVE_LINUX_INPUT_H
      4 
      5 # include <inttypes.h>
      6 # include <stdio.h>
      7 # include <stdlib.h>
      8 # include <sys/ioctl.h>
      9 # include <linux/input.h>
     10 # include "print_fields.h"
     11 
     12 static const char *errstr;
     13 
     14 struct evdev_check {
     15 	unsigned long cmd;
     16 	const char *cmd_str;
     17 	void *arg_ptr;
     18 	void (*print_arg)(long rc, void *ptr, void *arg);
     19 };
     20 
     21 static long
     22 invoke_test_syscall(unsigned long cmd, void *p)
     23 {
     24 	long rc = ioctl(-1, cmd, p);
     25 	errstr = sprintrc(rc);
     26 	static char inj_errstr[4096];
     27 
     28 	snprintf(inj_errstr, sizeof(inj_errstr), "%s (INJECTED)", errstr);
     29 	errstr = inj_errstr;
     30 	return rc;
     31 }
     32 
     33 static void
     34 test_evdev(struct evdev_check *check, void *arg)
     35 {
     36 	long rc = invoke_test_syscall(check->cmd, check->arg_ptr);
     37 	printf("ioctl(-1, %s, ", check->cmd_str);
     38 	if (check->print_arg)
     39 		check->print_arg(rc, check->arg_ptr, arg);
     40 	else
     41 		printf("%p", check->arg_ptr);
     42 	printf(") = %s\n", errstr);
     43 }
     44 
     45 static void
     46 print_input_absinfo(long rc, void *ptr, void *arg)
     47 {
     48 	struct input_absinfo *absinfo = ptr;
     49 
     50 	if (rc < 0) {
     51 		printf("%p", absinfo);
     52 		return;
     53 	}
     54 	PRINT_FIELD_U("{", *absinfo, value);
     55 	PRINT_FIELD_U(", ", *absinfo, minimum);
     56 # if VERBOSE
     57 	PRINT_FIELD_U(", ", *absinfo, maximum);
     58 	PRINT_FIELD_U(", ", *absinfo, fuzz);
     59 	PRINT_FIELD_U(", ", *absinfo, flat);
     60 #  ifdef HAVE_STRUCT_INPUT_ABSINFO_RESOLUTION
     61 	PRINT_FIELD_U(", ", *absinfo, resolution);
     62 #  endif
     63 # else
     64 	printf(", ...");
     65 # endif
     66 	printf("}");
     67 }
     68 
     69 static void
     70 print_input_id(long rc, void *ptr, void *arg)
     71 {
     72 	struct input_id *id = ptr;
     73 
     74 	if (rc < 0) {
     75 		printf("%p", id);
     76 		return;
     77 	}
     78 	printf("{ID_BUS=%" PRIu16
     79 	       ", ID_VENDOR=%" PRIu16
     80 	       ", ID_PRODUCT=%" PRIu16
     81 	       ", ID_VERSION=%" PRIu16 "}",
     82 	       id->bustype, id->vendor, id->product, id->version);
     83 }
     84 
     85 # ifdef EVIOCGMTSLOTS
     86 static void
     87 print_mtslots(long rc, void *ptr, void *arg)
     88 {
     89 	int *buffer = ptr;
     90 	const char **str = arg;
     91 	int num = atoi(*(str + 1));
     92 
     93 	if (rc < 0) {
     94 		printf("%p", buffer);
     95 		return;
     96 	}
     97 
     98 	printf("{code=%s", *str);
     99 	printf(", values=[");
    100 	for (unsigned int i = 1; i <= (unsigned) num; i++)
    101 		printf("%s%s", i > 1 ? ", " : "", *(str + i + 1));
    102 	printf("]}");
    103 }
    104 # endif
    105 
    106 static void
    107 print_getbit(long rc, void *ptr, void *arg)
    108 {
    109 	const char **str = arg;
    110 	int num = atoi(*str);
    111 
    112 	if (rc < 0) {
    113 		printf("%p", ptr);
    114 		return;
    115 	}
    116 
    117 	printf("[");
    118 	printf("%s", *(str + 1));
    119 	for (unsigned int i = 2; i <= (unsigned) num; i++) {
    120 # if ! VERBOSE
    121 		if (i > 4) {
    122 			printf(", ...");
    123 			break;
    124 		}
    125 # endif
    126 		printf(", ");
    127 		printf("%s", *(str + i));
    128 	}
    129 	printf("]");
    130 }
    131 
    132 int
    133 main(int argc, char **argv)
    134 {
    135 	unsigned long num_skip;
    136 	long inject_retval;
    137 	bool locked = false;
    138 
    139 	if (argc == 1)
    140 		return 0;
    141 
    142 	if (argc < 3)
    143 		error_msg_and_fail("Usage: %s NUM_SKIP INJECT_RETVAL", argv[0]);
    144 
    145 	num_skip = strtoul(argv[1], NULL, 0);
    146 	inject_retval = strtol(argv[2], NULL, 0);
    147 
    148 	if (inject_retval < 0)
    149 		error_msg_and_fail("Expected non-negative INJECT_RETVAL, "
    150 				   "but got %ld", inject_retval);
    151 
    152 	for (unsigned int i = 0; i < num_skip; i++) {
    153 		long rc = ioctl(-1, EVIOCGID, NULL);
    154 		printf("ioctl(-1, EVIOCGID, NULL) = %s%s\n",
    155 		       sprintrc(rc),
    156 		       rc == inject_retval ? " (INJECTED)" : "");
    157 
    158 		if (rc != inject_retval)
    159 			continue;
    160 
    161 		locked = true;
    162 		break;
    163 	}
    164 
    165 	if (!locked)
    166 		error_msg_and_fail("Hasn't locked on ioctl(-1"
    167 				   ", EVIOCGID, NULL) returning %lu",
    168 				   inject_retval);
    169 
    170 	TAIL_ALLOC_OBJECT_CONST_PTR(struct input_id, id);
    171 	TAIL_ALLOC_OBJECT_CONST_PTR(struct input_absinfo, absinfo);
    172 	TAIL_ALLOC_OBJECT_CONST_PTR(int, bad_addr_slot);
    173 # ifdef EVIOCGMTSLOTS
    174 	int mtslots[] = { ABS_MT_SLOT, 1, 3 };
    175 	/* we use the second element to indicate the number of values */
    176 	/* mtslots_str[1] is "2" so the number of values is 2 */
    177 	const char *mtslots_str[] = { "ABS_MT_SLOT", "2", "1", "3" };
    178 
    179 	/* invalid flag */
    180 	int invalid_mtslot[] = { -1, 1 };
    181 	char invalid_str[4096];
    182 	snprintf(invalid_str, sizeof(invalid_str), "%#x /* ABS_MT_??? */", invalid_mtslot[0]);
    183 	const char *invalid_mtslot_str[] = { invalid_str, "1", "1" };
    184 # endif
    185 
    186 	/* set more than 4 bits */
    187 	unsigned long ev_more[] = { 1 << EV_ABS | 1 << EV_MSC | 1 << EV_LED | 1 << EV_SND | 1 << EV_PWR };
    188 	/* we use the first element to indicate the number of set bits */
    189 	/* ev_more_str[0] is "5" so the number of set bits is 5 */
    190 	const char *ev_more_str[] = { "5", "EV_ABS", "EV_MSC", "EV_LED", "EV_SND", "EV_PWR" };
    191 
    192 	/* set less than 4 bits */
    193 	unsigned long ev_less[] = { 1 << EV_ABS | 1 << EV_MSC | 1 << EV_LED };
    194 	const char *ev_less_str[] = { "3", "EV_ABS", "EV_MSC", "EV_LED" };
    195 
    196 	/* set zero bit */
    197 	unsigned long ev_zero[] = { 0x0 };
    198 	const char *ev_zero_str[] = { "0", " 0 " };
    199 
    200 	/* KEY_MAX is 0x2ff which is greater than retval * 8 */
    201 	unsigned long key[] = { 1 << KEY_1 | 1 << KEY_2, 0 };
    202 	const char *key_str[] = { "2", "KEY_1", "KEY_2" };
    203 
    204 	struct {
    205 		struct evdev_check check;
    206 		void *ptr;
    207 	} a[] = {
    208 		{ { ARG_STR(EVIOCGID), id, print_input_id }, NULL },
    209 		{ { ARG_STR(EVIOCGABS(ABS_X)), absinfo, print_input_absinfo }, NULL },
    210 		{ { ARG_STR(EVIOCGABS(ABS_Y)), absinfo, print_input_absinfo }, NULL },
    211 		{ { ARG_STR(EVIOCGABS(ABS_Y)), absinfo, print_input_absinfo }, NULL },
    212 		{ { ARG_STR(EVIOCGBIT(0, 0)), ev_more, print_getbit }, &ev_more_str },
    213 		{ { ARG_STR(EVIOCGBIT(0, 0)), ev_less, print_getbit }, &ev_less_str },
    214 		{ { ARG_STR(EVIOCGBIT(0, 0)), ev_zero, print_getbit }, &ev_zero_str },
    215 		{ { ARG_STR(EVIOCGBIT(EV_KEY, 0)), key, print_getbit }, &key_str},
    216 # ifdef EVIOCGMTSLOTS
    217 		{ { ARG_STR(EVIOCGMTSLOTS(12)), mtslots, print_mtslots }, &mtslots_str },
    218 		{ { ARG_STR(EVIOCGMTSLOTS(8)), invalid_mtslot, print_mtslots }, &invalid_mtslot_str }
    219 # endif
    220 	};
    221 	for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) {
    222 		test_evdev(&a[i].check, a[i].ptr);
    223 	}
    224 
    225 	puts("+++ exited with 0 +++");
    226 	return 0;
    227 }
    228 #else
    229 
    230 SKIP_MAIN_UNDEFINED("HAVE_LINUX_INPUT_H")
    231 
    232 #endif
    233