[PATCH v3 3/6] tests: check decoding of GPIO ioctls

Kent Gibson warthog618 at gmail.com
Sat Jan 23 00:04:02 UTC 2021


* tests/.gitignore: Add ioctl_gpio, ioctl_gpio-success,
    ioctl_gpio-success-Xabbrev, ioctl_gpio-success-Xraw,
    ioctl_gpio-success-Xverbose, ioctl_gpio-success-v,
    ioctl_gpio-success-v-Xabbrev, ioctl_gpio-success-v-Xraw,
    ioctl_gpio-success-v-Xverbose, ioctl_gpio-Xabbrev,
    ioctl_gpio-Xraw, ioctl_gpio-Xverbose, ioctl_gpio-v,
    ioctl_gpio-v-Xabbrev, ioctl_gpio-v-Xraw, and ioctl_gpio-v-Xverbose.
* tests/Makefile.am (check_PROGRAMS): Add ioctl_gpio-success,
    ioctl_gpio-success-Xabbrev, ioctl_gpio-success-Xraw,
    ioctl_gpio-success-Xverbose, ioctl_gpio-success-v,
    ioctl_gpio-success-v-Xabbrev, ioctl_gpio-success-v-Xraw,
    and ioctl_gpio-success-v-Xverbose.
* tests/gen_tests.in (ioctl_gpio, ioctl_gpio-Xabbrev, ioctl_gpio-Xraw,
    ioctl_gpio-Xverbose, ioctl_gpio-v, ioctl_gpio-v-Xabbrev,
    ioctl_gpio-v-Xraw, ioctl_gpio-v-Xverbose, ioctl_gpio-success,
    ioctl_gpio-success-Xabbrev, ioctl_gpio-success-Xraw,
    ioctl_gpio-success-Xverbose, ioctl_gpio-success-v,
    ioctl_gpio-success-v-Xabbrev, ioctl_gpio-success-v-Xraw,
    ioctl_gpio-success-v-Xverbose): New tests.
* tests/ioctl_gpio.c: New file.
* tests/ioctl_gpio-Xabbrev.c: Likewise.
* tests/ioctl_gpio-Xraw.c: Likewise.
* tests/ioctl_gpio-Xverbose.c: Likewise.
* tests/ioctl_gpio-success.c: Likewise.
* tests/ioctl_gpio-success-Xabbrev.c: Likewise.
* tests/ioctl_gpio-success-Xraw.c: Likewise.
* tests/ioctl_gpio-success-Xverbose.c: Likewise.
* tests/ioctl_gpio-success-v.c: Likewise.
* tests/ioctl_gpio-success-v-Xabbrev.c: Likewise.
* tests/ioctl_gpio-success-v-Xraw.c: Likewise.
* tests/ioctl_gpio-success-v-Xverbose.c: Likewise.
* tests/ioctl_gpio-v.c: Likewise.
* tests/ioctl_gpio-v-Xabbrev.c: Likewise.
* tests/ioctl_gpio-v-Xraw.c: Likewise.
* tests/ioctl_gpio-v-Xverbose.c: Likewise.
* tests/pure_executables.list: Add ioctl_gpio, ioctl_gpio-Xabbrev,
    ioctl_gpio-Xraw, ioctl_gpio-Xverbose, ioctl_gpio-v,
    ioctl_gpio-v-Xabbrev, ioctl_gpio-v-Xraw, and ioctl_gpio-v-Xverbose.

Signed-off-by: Kent Gibson <warthog618 at gmail.com>
---
 tests/.gitignore                      |  16 ++
 tests/Makefile.am                     |   8 +
 tests/gen_tests.in                    |  16 ++
 tests/ioctl_gpio-Xabbrev.c            |   2 +
 tests/ioctl_gpio-Xraw.c               |   2 +
 tests/ioctl_gpio-Xverbose.c           |   2 +
 tests/ioctl_gpio-success-Xabbrev.c    |   2 +
 tests/ioctl_gpio-success-Xraw.c       |   2 +
 tests/ioctl_gpio-success-Xverbose.c   |   2 +
 tests/ioctl_gpio-success-v-Xabbrev.c  |   2 +
 tests/ioctl_gpio-success-v-Xraw.c     |   2 +
 tests/ioctl_gpio-success-v-Xverbose.c |   2 +
 tests/ioctl_gpio-success-v.c          |   2 +
 tests/ioctl_gpio-success.c            |   2 +
 tests/ioctl_gpio-v-Xabbrev.c          |   2 +
 tests/ioctl_gpio-v-Xraw.c             |   2 +
 tests/ioctl_gpio-v-Xverbose.c         |   2 +
 tests/ioctl_gpio-v.c                  |   2 +
 tests/ioctl_gpio.c                    | 395 ++++++++++++++++++++++++++
 tests/pure_executables.list           |   8 +
 20 files changed, 473 insertions(+)
 create mode 100644 tests/ioctl_gpio-Xabbrev.c
 create mode 100644 tests/ioctl_gpio-Xraw.c
 create mode 100644 tests/ioctl_gpio-Xverbose.c
 create mode 100644 tests/ioctl_gpio-success-Xabbrev.c
 create mode 100644 tests/ioctl_gpio-success-Xraw.c
 create mode 100644 tests/ioctl_gpio-success-Xverbose.c
 create mode 100644 tests/ioctl_gpio-success-v-Xabbrev.c
 create mode 100644 tests/ioctl_gpio-success-v-Xraw.c
 create mode 100644 tests/ioctl_gpio-success-v-Xverbose.c
 create mode 100644 tests/ioctl_gpio-success-v.c
 create mode 100644 tests/ioctl_gpio-success.c
 create mode 100644 tests/ioctl_gpio-v-Xabbrev.c
 create mode 100644 tests/ioctl_gpio-v-Xraw.c
 create mode 100644 tests/ioctl_gpio-v-Xverbose.c
 create mode 100644 tests/ioctl_gpio-v.c
 create mode 100644 tests/ioctl_gpio.c

diff --git a/tests/.gitignore b/tests/.gitignore
index b1bfeb8f..b5b0bbe5 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -256,6 +256,22 @@ ioctl_fs_x-success
 ioctl_fs_x-success-Xabbrev
 ioctl_fs_x-success-Xraw
 ioctl_fs_x-success-Xverbose
+ioctl_gpio
+ioctl_gpio-success
+ioctl_gpio-success-Xabbrev
+ioctl_gpio-success-Xraw
+ioctl_gpio-success-Xverbose
+ioctl_gpio-success-v
+ioctl_gpio-success-v-Xabbrev
+ioctl_gpio-success-v-Xraw
+ioctl_gpio-success-v-Xverbose
+ioctl_gpio-Xabbrev
+ioctl_gpio-Xraw
+ioctl_gpio-Xverbose
+ioctl_gpio-v
+ioctl_gpio-v-Xabbrev
+ioctl_gpio-v-Xraw
+ioctl_gpio-v-Xverbose
 ioctl_hdio
 ioctl_hdio-success
 ioctl_hdio-success-Xabbrev
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 13338a5e..8e9550e3 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -154,6 +154,14 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \
 	ioctl_fs_x-success-Xabbrev \
 	ioctl_fs_x-success-Xraw \
 	ioctl_fs_x-success-Xverbose \
+	ioctl_gpio-success \
+	ioctl_gpio-success-Xabbrev \
+	ioctl_gpio-success-Xraw \
+	ioctl_gpio-success-Xverbose \
+	ioctl_gpio-success-v \
+	ioctl_gpio-success-v-Xabbrev \
+	ioctl_gpio-success-v-Xraw \
+	ioctl_gpio-success-v-Xverbose \
 	ioctl_hdio-success \
 	ioctl_hdio-success-Xabbrev \
 	ioctl_hdio-success-Xraw \
diff --git a/tests/gen_tests.in b/tests/gen_tests.in
index 0fc24977..82142b2a 100644
--- a/tests/gen_tests.in
+++ b/tests/gen_tests.in
@@ -228,6 +228,22 @@ ioctl_fs_x-success	+ioctl-success.sh -a18
 ioctl_fs_x-success-Xabbrev	+ioctl-success.sh -a18 -Xabbrev
 ioctl_fs_x-success-Xraw	+ioctl-success.sh -a21 -Xraw
 ioctl_fs_x-success-Xverbose	+ioctl-success.sh -a35 -Xverbose
+ioctl_gpio	+ioctl.test
+ioctl_gpio-Xabbrev	+ioctl.test -Xabbrev
+ioctl_gpio-Xraw	+ioctl.test -Xraw
+ioctl_gpio-Xverbose	+ioctl.test -Xverbose
+ioctl_gpio-v	+ioctl.test -v
+ioctl_gpio-v-Xabbrev	+ioctl.test -v -Xabbrev
+ioctl_gpio-v-Xraw	+ioctl.test -v -Xraw
+ioctl_gpio-v-Xverbose	+ioctl.test -v -Xverbose
+ioctl_gpio-success	+ioctl-success.sh -a30
+ioctl_gpio-success-Xabbrev	+ioctl-success.sh -a30 -Xabbrev
+ioctl_gpio-success-Xraw	+ioctl-success.sh -a20 -Xraw
+ioctl_gpio-success-Xverbose	+ioctl-success.sh -a30 -Xverbose
+ioctl_gpio-success-v	+ioctl-success.sh -a30 -v
+ioctl_gpio-success-v-Xabbrev	+ioctl-success.sh -a30 -v -Xabbrev
+ioctl_gpio-success-v-Xraw	+ioctl-success.sh -a20 -v -Xraw
+ioctl_gpio-success-v-Xverbose	+ioctl-success.sh -a30 -v -Xverbose
 ioctl_hdio	+ioctl.test -a27
 ioctl_hdio-Xabbrev	+ioctl.test -a27 -Xabbrev
 ioctl_hdio-Xraw	+ioctl.test -a20 -Xraw
diff --git a/tests/ioctl_gpio-Xabbrev.c b/tests/ioctl_gpio-Xabbrev.c
new file mode 100644
index 00000000..e3905327
--- /dev/null
+++ b/tests/ioctl_gpio-Xabbrev.c
@@ -0,0 +1,2 @@
+#define XLAT_ABBREV 1
+#include "ioctl_gpio.c"
diff --git a/tests/ioctl_gpio-Xraw.c b/tests/ioctl_gpio-Xraw.c
new file mode 100644
index 00000000..9459d005
--- /dev/null
+++ b/tests/ioctl_gpio-Xraw.c
@@ -0,0 +1,2 @@
+#define XLAT_RAW 1
+#include "ioctl_gpio.c"
diff --git a/tests/ioctl_gpio-Xverbose.c b/tests/ioctl_gpio-Xverbose.c
new file mode 100644
index 00000000..95b1d0c9
--- /dev/null
+++ b/tests/ioctl_gpio-Xverbose.c
@@ -0,0 +1,2 @@
+#define XLAT_VERBOSE 1
+#include "ioctl_gpio.c"
diff --git a/tests/ioctl_gpio-success-Xabbrev.c b/tests/ioctl_gpio-success-Xabbrev.c
new file mode 100644
index 00000000..ff19e371
--- /dev/null
+++ b/tests/ioctl_gpio-success-Xabbrev.c
@@ -0,0 +1,2 @@
+#define XLAT_ABBREV 1
+#include "ioctl_gpio-success.c"
diff --git a/tests/ioctl_gpio-success-Xraw.c b/tests/ioctl_gpio-success-Xraw.c
new file mode 100644
index 00000000..e432c9ab
--- /dev/null
+++ b/tests/ioctl_gpio-success-Xraw.c
@@ -0,0 +1,2 @@
+#define XLAT_RAW 1
+#include "ioctl_gpio-success.c"
diff --git a/tests/ioctl_gpio-success-Xverbose.c b/tests/ioctl_gpio-success-Xverbose.c
new file mode 100644
index 00000000..faa3ca6f
--- /dev/null
+++ b/tests/ioctl_gpio-success-Xverbose.c
@@ -0,0 +1,2 @@
+#define XLAT_VERBOSE 1
+#include "ioctl_gpio-success.c"
diff --git a/tests/ioctl_gpio-success-v-Xabbrev.c b/tests/ioctl_gpio-success-v-Xabbrev.c
new file mode 100644
index 00000000..be96c8fb
--- /dev/null
+++ b/tests/ioctl_gpio-success-v-Xabbrev.c
@@ -0,0 +1,2 @@
+#define XLAT_ABBREV 1
+#include "ioctl_gpio-success-v.c"
diff --git a/tests/ioctl_gpio-success-v-Xraw.c b/tests/ioctl_gpio-success-v-Xraw.c
new file mode 100644
index 00000000..26c97be6
--- /dev/null
+++ b/tests/ioctl_gpio-success-v-Xraw.c
@@ -0,0 +1,2 @@
+#define XLAT_RAW 1
+#include "ioctl_gpio-success-v.c"
diff --git a/tests/ioctl_gpio-success-v-Xverbose.c b/tests/ioctl_gpio-success-v-Xverbose.c
new file mode 100644
index 00000000..7194f407
--- /dev/null
+++ b/tests/ioctl_gpio-success-v-Xverbose.c
@@ -0,0 +1,2 @@
+#define XLAT_VERBOSE 1
+#include "ioctl_gpio-success-v.c"
diff --git a/tests/ioctl_gpio-success-v.c b/tests/ioctl_gpio-success-v.c
new file mode 100644
index 00000000..4a9506a7
--- /dev/null
+++ b/tests/ioctl_gpio-success-v.c
@@ -0,0 +1,2 @@
+#define VERBOSE 1
+#include "ioctl_gpio-success.c"
diff --git a/tests/ioctl_gpio-success.c b/tests/ioctl_gpio-success.c
new file mode 100644
index 00000000..77640aca
--- /dev/null
+++ b/tests/ioctl_gpio-success.c
@@ -0,0 +1,2 @@
+#define INJECT_RETVAL 42
+#include "ioctl_gpio.c"
diff --git a/tests/ioctl_gpio-v-Xabbrev.c b/tests/ioctl_gpio-v-Xabbrev.c
new file mode 100644
index 00000000..81025c7b
--- /dev/null
+++ b/tests/ioctl_gpio-v-Xabbrev.c
@@ -0,0 +1,2 @@
+#define XLAT_ABBREV 1
+#include "ioctl_gpio-v.c"
diff --git a/tests/ioctl_gpio-v-Xraw.c b/tests/ioctl_gpio-v-Xraw.c
new file mode 100644
index 00000000..bb0dcfa1
--- /dev/null
+++ b/tests/ioctl_gpio-v-Xraw.c
@@ -0,0 +1,2 @@
+#define XLAT_RAW 1
+#include "ioctl_gpio-v.c"
diff --git a/tests/ioctl_gpio-v-Xverbose.c b/tests/ioctl_gpio-v-Xverbose.c
new file mode 100644
index 00000000..4f83c1e0
--- /dev/null
+++ b/tests/ioctl_gpio-v-Xverbose.c
@@ -0,0 +1,2 @@
+#define XLAT_VERBOSE 1
+#include "ioctl_gpio-v.c"
diff --git a/tests/ioctl_gpio-v.c b/tests/ioctl_gpio-v.c
new file mode 100644
index 00000000..74405bc7
--- /dev/null
+++ b/tests/ioctl_gpio-v.c
@@ -0,0 +1,2 @@
+#define VERBOSE 1
+#include "ioctl_gpio.c"
diff --git a/tests/ioctl_gpio.c b/tests/ioctl_gpio.c
new file mode 100644
index 00000000..6d526c1b
--- /dev/null
+++ b/tests/ioctl_gpio.c
@@ -0,0 +1,395 @@
+/*
+ * Check GPIO_* ioctl decoding.
+ *
+ * Copyright (c) 2021 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "tests.h"
+
+#if HAVE_LINUX_GPIO_H
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include "types/gpio.h"
+
+# define str_event_flags	XLAT_KNOWN(0x3, "GPIOEVENT_REQUEST_BOTH_EDGES")
+# define str_handle_flags	XLAT_KNOWN(0x14, \
+	"GPIOHANDLE_REQUEST_ACTIVE_LOW|GPIOHANDLE_REQUEST_OPEN_SOURCE")
+# define str_info_flags		XLAT_KNOWN(0xc, \
+	"GPIOLINE_FLAG_ACTIVE_LOW|GPIOLINE_FLAG_OPEN_DRAIN")
+
+#define UNK_GPIO_FLAG 0x8000
+
+# define str_handle_unk_flag	XLAT_UNKNOWN(UNK_GPIO_FLAG, "GPIOHANDLE_REQUEST_???")
+# define str_info_unk_flag	XLAT_UNKNOWN(UNK_GPIO_FLAG, "GPIOLINE_FLAG_???")
+
+#if VERBOSE
+# define str_line_seq		"[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]"
+# define str_default_seq	"[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, " \
+		"29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, " \
+		"63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, " \
+		"97, 99, 101, 103, 105, 107, 109, 111, 113, 115, 117, 119, 121, 123, " \
+		"125, 127]"
+#else
+# define str_line_seq		"[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, ...]"
+# define str_default_seq	"[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, " \
+		"29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, " \
+		"63, ...]"
+#endif
+
+static const char *errstr;
+
+static long
+do_ioctl(kernel_ulong_t cmd, kernel_ulong_t arg)
+{
+	long rc = ioctl(-1, cmd, arg);
+
+	errstr = sprintrc(rc);
+
+#ifdef INJECT_RETVAL
+	if (rc != INJECT_RETVAL)
+		error_msg_and_fail("Got a return value of %ld != %ld",
+				   rc, (long) INJECT_RETVAL);
+
+	static char inj_errstr[4096];
+
+	snprintf(inj_errstr, sizeof(inj_errstr), "%s (INJECTED)", errstr);
+	errstr = inj_errstr;
+#endif
+
+	return rc;
+}
+
+static inline long
+do_ioctl_ptr(kernel_ulong_t cmd, const void *arg)
+{
+	return do_ioctl(cmd, (uintptr_t) arg);
+}
+
+static void
+test_print_gpiochip_info(void)
+{
+	long rc;
+
+	do_ioctl(GPIO_GET_CHIPINFO_IOCTL, 0);
+	printf("ioctl(-1, %s, NULL) = %s\n",
+	       XLAT_STR(GPIO_GET_CHIPINFO_IOCTL), errstr);
+
+	TAIL_ALLOC_OBJECT_CONST_PTR(struct gpiochip_info, p_chipinfo);
+
+	p_chipinfo->lines = 0xca;
+	strcpy(p_chipinfo->name, "chip name");
+	strcpy(p_chipinfo->label, "chip label");
+
+	do_ioctl_ptr(GPIO_GET_CHIPINFO_IOCTL, (char *) p_chipinfo + 1);
+	printf("ioctl(-1, %s, %p) = %s\n",
+	       XLAT_STR(GPIO_GET_CHIPINFO_IOCTL), (char *) p_chipinfo + 1, errstr);
+
+	rc = do_ioctl_ptr(GPIO_GET_CHIPINFO_IOCTL, p_chipinfo);
+	printf("ioctl(-1, %s, ", XLAT_STR(GPIO_GET_CHIPINFO_IOCTL));
+	if (rc >= 0)
+		printf("{name=\"chip name\", label=\"chip label\", lines=202}");
+	else
+		printf("%p", p_chipinfo);
+	printf(") = %s\n", errstr);
+}
+
+static void
+test_print_gpioline_info(void)
+{
+	long rc;
+
+	do_ioctl(GPIO_GET_LINEINFO_IOCTL, 0);
+	printf("ioctl(-1, %s, NULL) = %s\n",
+	       XLAT_STR(GPIO_GET_LINEINFO_IOCTL), errstr);
+
+	TAIL_ALLOC_OBJECT_CONST_PTR(struct gpioline_info, p_lineinfo);
+
+	p_lineinfo->line_offset = 0x32;
+	p_lineinfo->flags = GPIOLINE_FLAG_ACTIVE_LOW|GPIOLINE_FLAG_OPEN_DRAIN;
+	strcpy(p_lineinfo->name, "line name");
+	strcpy(p_lineinfo->consumer, "line consumer");
+
+	do_ioctl_ptr(GPIO_GET_LINEINFO_IOCTL, (char *) p_lineinfo + 1);
+	printf("ioctl(-1, %s, %p) = %s\n",
+	       XLAT_STR(GPIO_GET_LINEINFO_IOCTL), (char *) p_lineinfo + 1, errstr);
+
+	/* GPIO_GET_LINEINFO_IOCTL */
+	rc = do_ioctl_ptr(GPIO_GET_LINEINFO_IOCTL, p_lineinfo);
+	printf("ioctl(-1, %s, {line_offset=50}",
+	       XLAT_STR(GPIO_GET_LINEINFO_IOCTL));
+	if (rc >= 0)
+		printf(" => {flags=" str_info_flags
+		       ", name=\"line name\", consumer=\"line consumer\"}");
+	printf(") = %s\n", errstr);
+
+	/* GPIO_GET_LINEINFO_WATCH_IOCTL */
+	rc = do_ioctl_ptr(GPIO_GET_LINEINFO_WATCH_IOCTL, p_lineinfo);
+	printf("ioctl(-1, %s, {line_offset=50}",
+	       XLAT_STR(GPIO_GET_LINEINFO_WATCH_IOCTL));
+	if (rc >= 0)
+		printf(" => {flags=" str_info_flags
+		       ", name=\"line name\", consumer=\"line consumer\"}");
+	printf(") = %s\n", errstr);
+
+	/* unknown flag */
+	p_lineinfo->flags = UNK_GPIO_FLAG;
+	rc = do_ioctl_ptr(GPIO_GET_LINEINFO_IOCTL, p_lineinfo);
+	printf("ioctl(-1, %s, {line_offset=50}",
+	       XLAT_STR(GPIO_GET_LINEINFO_IOCTL));
+	if (rc >= 0)
+		printf(" => {flags=" str_info_unk_flag
+		       ", name=\"line name\", consumer=\"line consumer\"}");
+	printf(") = %s\n", errstr);
+}
+
+static void
+test_print_gpioline_info_unwatch(void)
+{
+	do_ioctl_ptr(GPIO_GET_LINEINFO_UNWATCH_IOCTL, 0);
+	printf("ioctl(-1, %s, NULL) = %s\n",
+	       XLAT_STR(GPIO_GET_LINEINFO_UNWATCH_IOCTL), errstr);
+
+	TAIL_ALLOC_OBJECT_VAR_PTR(uint32_t, p_offset);
+
+	*p_offset = 0;
+	do_ioctl_ptr(GPIO_GET_LINEINFO_UNWATCH_IOCTL, p_offset);
+	printf("ioctl(-1, %s, {offset=0}) = %s\n",
+	       XLAT_STR(GPIO_GET_LINEINFO_UNWATCH_IOCTL), errstr);
+
+	*p_offset = 78;
+	do_ioctl_ptr(GPIO_GET_LINEINFO_UNWATCH_IOCTL, p_offset);
+	printf("ioctl(-1, %s, {offset=78}) = %s\n",
+	       XLAT_STR(GPIO_GET_LINEINFO_UNWATCH_IOCTL), errstr);
+}
+
+static void
+test_print_gpiohandle_request(void)
+{
+	long rc;
+
+	do_ioctl(GPIO_GET_LINEHANDLE_IOCTL, 0);
+	printf("ioctl(-1, %s, NULL) = %s\n",
+	       XLAT_STR(GPIO_GET_LINEHANDLE_IOCTL), errstr);
+
+	TAIL_ALLOC_OBJECT_CONST_PTR(struct gpiohandle_request, p_handle_request);
+
+	p_handle_request->lines = 4;
+	p_handle_request->lineoffsets[0] = 0x12;
+	p_handle_request->lineoffsets[1] = 0x23;
+	p_handle_request->lineoffsets[2] = 0x34;
+	p_handle_request->lineoffsets[3] = 0x45;
+	p_handle_request->default_values[0] = 0x0;
+	p_handle_request->default_values[1] = 0x1;
+	p_handle_request->default_values[2] = 0x2;
+	p_handle_request->default_values[3] = 0x6;
+	p_handle_request->flags = GPIOHANDLE_REQUEST_ACTIVE_LOW|GPIOHANDLE_REQUEST_OPEN_SOURCE;
+	strcpy(p_handle_request->consumer_label, "line consumer");
+	p_handle_request->fd = 0x64;
+
+	do_ioctl_ptr(GPIO_GET_LINEHANDLE_IOCTL, (char *) p_handle_request + 1);
+	printf("ioctl(-1, %s, %p) = %s\n",
+	       XLAT_STR(GPIO_GET_LINEHANDLE_IOCTL), (char *) p_handle_request + 1, errstr);
+
+	rc = do_ioctl_ptr(GPIO_GET_LINEHANDLE_IOCTL, p_handle_request);
+	printf("ioctl(-1, %s, {lines=4, lineoffsets=[18, 35, 52, 69], flags=" str_handle_flags
+	       ", default_values=[0, 1, 2, 6], consumer_label=\"line consumer\"}",
+	       XLAT_STR(GPIO_GET_LINEHANDLE_IOCTL));
+	if (rc >= 0)
+		printf(" => {fd=100}");
+	printf(") = %s\n", errstr);
+
+	/* lines > GPIOHANDLES_MAX */
+	p_handle_request->lines = GPIOHANDLES_MAX + 1;
+	for (int i = 0; i < GPIOHANDLES_MAX; i++) {
+		p_handle_request->lineoffsets[i] = i + 1;
+		p_handle_request->default_values[i] = 2*i + 1;
+	}
+	rc = do_ioctl_ptr(GPIO_GET_LINEHANDLE_IOCTL, p_handle_request);
+	printf("ioctl(-1, %s, {lines=65, lineoffsets=" str_line_seq
+	       ", flags=" str_handle_flags ", default_values=" str_default_seq
+	       ", consumer_label=\"line consumer\"}",
+	       XLAT_STR(GPIO_GET_LINEHANDLE_IOCTL));
+	if (rc >= 0)
+		printf(" => {fd=100}");
+	printf(") = %s\n", errstr);
+}
+
+static void
+test_print_gpioevent_request(void)
+{
+	long rc;
+
+	do_ioctl(GPIO_GET_LINEEVENT_IOCTL, 0);
+	printf("ioctl(-1, %s, NULL) = %s\n",
+	       XLAT_STR(GPIO_GET_LINEEVENT_IOCTL), errstr);
+
+	TAIL_ALLOC_OBJECT_CONST_PTR(struct gpioevent_request, p_event_request);
+
+	p_event_request->lineoffset = 4;
+	p_event_request->handleflags = GPIOHANDLE_REQUEST_ACTIVE_LOW|GPIOHANDLE_REQUEST_OPEN_SOURCE;
+	p_event_request->eventflags = GPIOEVENT_REQUEST_BOTH_EDGES;
+	strcpy(p_event_request->consumer_label, "line consumer");
+	p_event_request->fd = 0x65;
+
+	do_ioctl_ptr(GPIO_GET_LINEEVENT_IOCTL, (char *) p_event_request + 1);
+	printf("ioctl(-1, %s, %p) = %s\n",
+	       XLAT_STR(GPIO_GET_LINEEVENT_IOCTL), (char *) p_event_request + 1, errstr);
+
+	rc = do_ioctl_ptr(GPIO_GET_LINEEVENT_IOCTL, p_event_request);
+	printf("ioctl(-1, %s, {lineoffset=4, handleflags=" str_handle_flags
+	       ", eventflags=" str_event_flags ", consumer_label=\"line consumer\"}",
+	       XLAT_STR(GPIO_GET_LINEEVENT_IOCTL));
+	if (rc >= 0)
+		printf(" => {fd=101}");
+	printf(") = %s\n", errstr);
+}
+
+static void
+test_print_gpiohandle_get_values(void)
+{
+	long rc;
+
+	do_ioctl(GPIOHANDLE_GET_LINE_VALUES_IOCTL, 0);
+	printf("ioctl(-1, %s, NULL) = %s\n",
+	       XLAT_STR(GPIOHANDLE_GET_LINE_VALUES_IOCTL), errstr);
+
+	TAIL_ALLOC_OBJECT_CONST_PTR(struct gpiohandle_data, p_handle_data);
+
+	for (int i = 0; i < GPIOHANDLES_MAX; i++)
+		p_handle_data->values[i] = i + 1;
+
+	do_ioctl_ptr(GPIOHANDLE_GET_LINE_VALUES_IOCTL, (char *) p_handle_data + 1);
+	printf("ioctl(-1, %s, %p) = %s\n",
+	       XLAT_STR(GPIOHANDLE_GET_LINE_VALUES_IOCTL), (char *) p_handle_data + 1, errstr);
+
+	rc = do_ioctl_ptr(GPIOHANDLE_GET_LINE_VALUES_IOCTL, p_handle_data);
+	printf("ioctl(-1, %s, ", XLAT_STR(GPIOHANDLE_GET_LINE_VALUES_IOCTL));
+	if (rc >= 0)
+		printf("{values=" str_line_seq "}");
+	else
+		printf("%p", p_handle_data);
+	printf(") = %s\n", errstr);
+}
+
+static void
+test_print_gpiohandle_set_values(void)
+{
+	do_ioctl(GPIOHANDLE_SET_LINE_VALUES_IOCTL, 0);
+	printf("ioctl(-1, %s, NULL) = %s\n",
+	       XLAT_STR(GPIOHANDLE_SET_LINE_VALUES_IOCTL), errstr);
+
+	TAIL_ALLOC_OBJECT_CONST_PTR(struct gpiohandle_data, p_handle_data);
+
+	for (int i = 0; i < GPIOHANDLES_MAX; i++)
+		p_handle_data->values[i] = i + 1;
+
+	do_ioctl_ptr(GPIOHANDLE_SET_LINE_VALUES_IOCTL, (char *) p_handle_data + 1);
+	printf("ioctl(-1, %s, %p) = %s\n",
+	       XLAT_STR(GPIOHANDLE_SET_LINE_VALUES_IOCTL), (char *) p_handle_data + 1, errstr);
+
+	do_ioctl_ptr(GPIOHANDLE_SET_LINE_VALUES_IOCTL, p_handle_data);
+	printf("ioctl(-1, %s, {values=" str_line_seq "}) = %s\n",
+	       XLAT_STR(GPIOHANDLE_SET_LINE_VALUES_IOCTL),
+	       errstr);
+}
+
+static void
+test_print_gpiohandle_set_config(void)
+{
+	do_ioctl(GPIOHANDLE_SET_CONFIG_IOCTL, 0);
+	printf("ioctl(-1, %s, NULL) = %s\n",
+	       XLAT_STR(GPIOHANDLE_SET_CONFIG_IOCTL), errstr);
+
+	TAIL_ALLOC_OBJECT_CONST_PTR(struct_gpiohandle_config, p_handle_config);
+
+	p_handle_config->flags = GPIOHANDLE_REQUEST_ACTIVE_LOW|GPIOHANDLE_REQUEST_OPEN_SOURCE;
+	for (int i = 0; i < GPIOHANDLES_MAX; i++)
+		p_handle_config->default_values[i] = i + 1;
+
+	do_ioctl_ptr(GPIOHANDLE_SET_CONFIG_IOCTL, (char *) p_handle_config + 1);
+	printf("ioctl(-1, %s, %p) = %s\n",
+	       XLAT_STR(GPIOHANDLE_SET_CONFIG_IOCTL), (char *) p_handle_config + 1, errstr);
+
+	do_ioctl_ptr(GPIOHANDLE_SET_CONFIG_IOCTL, p_handle_config);
+	printf("ioctl(-1, %s, {flags=" str_handle_flags
+	       ", default_values=" str_line_seq "}) = %s\n",
+	       XLAT_STR(GPIOHANDLE_SET_CONFIG_IOCTL), errstr);
+
+	/* unknown flag */
+	p_handle_config->flags = UNK_GPIO_FLAG;
+	do_ioctl_ptr(GPIOHANDLE_SET_CONFIG_IOCTL, p_handle_config);
+	printf("ioctl(-1, %s, {flags=" str_handle_unk_flag
+	       ", default_values=" str_line_seq "}) = %s\n",
+	       XLAT_STR(GPIOHANDLE_SET_CONFIG_IOCTL), errstr);
+}
+
+int
+main(int argc, char *argv[])
+{
+	kernel_ulong_t unknown_gpio_cmd = (kernel_ulong_t) 0xbadc0dedfeedb45eULL;
+	kernel_ulong_t cmd_arg = (kernel_ulong_t) 0xdeadbeefbadc0dedULL;
+#ifdef INJECT_RETVAL
+	unsigned long num_skip;
+	bool locked = false;
+
+	if (argc < 2)
+		error_msg_and_fail("Usage: %s NUM_SKIP", argv[0]);
+
+	num_skip = strtoul(argv[1], NULL, 0);
+
+	for (size_t i = 0; i < num_skip; i++) {
+		long ret = ioctl(-1, GPIO_GET_CHIPINFO_IOCTL, 0);
+
+		printf("ioctl(-1, %s, NULL) = %s%s\n",
+		       XLAT_STR(GPIO_GET_CHIPINFO_IOCTL), sprintrc(ret),
+		       ret == INJECT_RETVAL ? " (INJECTED)" : "");
+
+		if (ret != INJECT_RETVAL)
+			continue;
+
+		locked = true;
+		break;
+	}
+
+	if (!locked)
+		error_msg_and_fail("Hasn't locked on ioctl(-1"
+				   ", GPIO_GET_CHIPINFO_IOCTL, NULL) returning %d",
+				   INJECT_RETVAL);
+#endif
+	/* unknown GPIO command */
+	do_ioctl(unknown_gpio_cmd, cmd_arg);
+	printf("ioctl(-1, " XLAT_FMT ", %#lx) = %s\n",
+		XLAT_SEL((unsigned int)unknown_gpio_cmd,
+		"_IOC(_IOC_READ|_IOC_WRITE, 0xb4, 0x5e, 0x3eed)"),
+		cmd_arg, errstr);
+
+	/* GPIO v1 ioctls */
+	test_print_gpiochip_info();
+	test_print_gpioline_info();
+	test_print_gpioline_info_unwatch();
+	test_print_gpiohandle_request();
+	test_print_gpioevent_request();
+	test_print_gpiohandle_get_values();
+	test_print_gpiohandle_set_values();
+	test_print_gpiohandle_set_config();
+
+	puts("+++ exited with 0 +++");
+	return 0;
+}
+
+#else
+
+SKIP_MAIN_UNDEFINED("HAVE_LINUX_GPIO_H")
+
+#endif
diff --git a/tests/pure_executables.list b/tests/pure_executables.list
index 0a23c47c..022873a7 100755
--- a/tests/pure_executables.list
+++ b/tests/pure_executables.list
@@ -181,6 +181,14 @@ ioctl_fs_x
 ioctl_fs_x-Xabbrev
 ioctl_fs_x-Xraw
 ioctl_fs_x-Xverbose
+ioctl_gpio
+ioctl_gpio-Xabbrev
+ioctl_gpio-Xraw
+ioctl_gpio-Xverbose
+ioctl_gpio-v
+ioctl_gpio-v-Xabbrev
+ioctl_gpio-v-Xraw
+ioctl_gpio-v-Xverbose
 ioctl_hdio
 ioctl_hdio-Xabbrev
 ioctl_hdio-Xraw
-- 
2.30.0



More information about the Strace-devel mailing list