xref: /illumos-gate/usr/src/test/os-tests/tests/gpio/gpio_lookup.c (revision fd71220ba0fafcc9cf5ea0785db206f3f31336e7)
1*fd71220bSRobert Mustacchi /*
2*fd71220bSRobert Mustacchi  * This file and its contents are supplied under the terms of the
3*fd71220bSRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4*fd71220bSRobert Mustacchi  * You may only use this file in accordance with the terms of version
5*fd71220bSRobert Mustacchi  * 1.0 of the CDDL.
6*fd71220bSRobert Mustacchi  *
7*fd71220bSRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8*fd71220bSRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9*fd71220bSRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10*fd71220bSRobert Mustacchi  */
11*fd71220bSRobert Mustacchi 
12*fd71220bSRobert Mustacchi /*
13*fd71220bSRobert Mustacchi  * Copyright 2023 Oxide Computer Company
14*fd71220bSRobert Mustacchi  */
15*fd71220bSRobert Mustacchi 
16*fd71220bSRobert Mustacchi /*
17*fd71220bSRobert Mustacchi  * This test verifies that we can look up names across the gpio_sim controllers
18*fd71220bSRobert Mustacchi  * and that all three return the same results for a given pin.
19*fd71220bSRobert Mustacchi  */
20*fd71220bSRobert Mustacchi 
21*fd71220bSRobert Mustacchi #include <err.h>
22*fd71220bSRobert Mustacchi #include <sys/stat.h>
23*fd71220bSRobert Mustacchi #include <sys/types.h>
24*fd71220bSRobert Mustacchi #include <fcntl.h>
25*fd71220bSRobert Mustacchi #include <stdlib.h>
26*fd71220bSRobert Mustacchi #include <sys/sysmacros.h>
27*fd71220bSRobert Mustacchi #include <stdbool.h>
28*fd71220bSRobert Mustacchi #include <string.h>
29*fd71220bSRobert Mustacchi #include <unistd.h>
30*fd71220bSRobert Mustacchi #include <errno.h>
31*fd71220bSRobert Mustacchi 
32*fd71220bSRobert Mustacchi #include <sys/gpio/kgpio.h>
33*fd71220bSRobert Mustacchi 
34*fd71220bSRobert Mustacchi static int gpio_lookup_ret = EXIT_SUCCESS;
35*fd71220bSRobert Mustacchi static const char *gpio_paths[] = {
36*fd71220bSRobert Mustacchi 	"/devices/pseudo/kgpio@0:gpio_sim0",
37*fd71220bSRobert Mustacchi 	"/devices/pseudo/kgpio@0:gpio_sim1",
38*fd71220bSRobert Mustacchi 	"/devices/pseudo/kgpio@0:gpio_sim2"
39*fd71220bSRobert Mustacchi };
40*fd71220bSRobert Mustacchi 
41*fd71220bSRobert Mustacchi static const char *gpio_names[] = {
42*fd71220bSRobert Mustacchi 	"3v3",
43*fd71220bSRobert Mustacchi 	"periodic-500ms",
44*fd71220bSRobert Mustacchi 	"open-drain"
45*fd71220bSRobert Mustacchi };
46*fd71220bSRobert Mustacchi 
47*fd71220bSRobert Mustacchi static void
gpio_lookup(int fd,const char * name,uint32_t * idp)48*fd71220bSRobert Mustacchi gpio_lookup(int fd, const char *name, uint32_t *idp)
49*fd71220bSRobert Mustacchi {
50*fd71220bSRobert Mustacchi 	kgpio_ioc_name2id_t kin;
51*fd71220bSRobert Mustacchi 
52*fd71220bSRobert Mustacchi 	(void) memset(&kin, 0, sizeof (kin));
53*fd71220bSRobert Mustacchi 	if (strlcpy(kin.kin_name, name, sizeof (kin.kin_name)) >=
54*fd71220bSRobert Mustacchi 	    sizeof (kin.kin_name)) {
55*fd71220bSRobert Mustacchi 		errx(EXIT_FAILURE, "would have exceeded kin_name with %s",
56*fd71220bSRobert Mustacchi 		    name);
57*fd71220bSRobert Mustacchi 	}
58*fd71220bSRobert Mustacchi 
59*fd71220bSRobert Mustacchi 	if (ioctl(fd, KGPIO_IOC_GPIO_NAME2ID, &kin) != 0) {
60*fd71220bSRobert Mustacchi 		warn("TEST FAILED: failed to translate %s", name);
61*fd71220bSRobert Mustacchi 		gpio_lookup_ret = EXIT_FAILURE;
62*fd71220bSRobert Mustacchi 	} else {
63*fd71220bSRobert Mustacchi 		*idp = kin.kin_id;
64*fd71220bSRobert Mustacchi 	}
65*fd71220bSRobert Mustacchi }
66*fd71220bSRobert Mustacchi 
67*fd71220bSRobert Mustacchi /*
68*fd71220bSRobert Mustacchi  * Generate a few different error cases that we know to expect:
69*fd71220bSRobert Mustacchi  *
70*fd71220bSRobert Mustacchi  *  o Invalid name due to no '\0'
71*fd71220bSRobert Mustacchi  *  o Invalid name of length 0
72*fd71220bSRobert Mustacchi  *  o An unkonwn name
73*fd71220bSRobert Mustacchi  */
74*fd71220bSRobert Mustacchi static void
gpio_lookup_errs(int fd)75*fd71220bSRobert Mustacchi gpio_lookup_errs(int fd)
76*fd71220bSRobert Mustacchi {
77*fd71220bSRobert Mustacchi 	kgpio_ioc_name2id_t kin;
78*fd71220bSRobert Mustacchi 
79*fd71220bSRobert Mustacchi 	(void) memset(&kin, 0, sizeof (kin));
80*fd71220bSRobert Mustacchi 	if (ioctl(fd, KGPIO_IOC_GPIO_NAME2ID, &kin) == 0) {
81*fd71220bSRobert Mustacchi 		warnx("TEST FAILED: zero length lookup passed, expected "
82*fd71220bSRobert Mustacchi 		    "EINVAL");
83*fd71220bSRobert Mustacchi 		gpio_lookup_ret = EXIT_FAILURE;
84*fd71220bSRobert Mustacchi 	} else if (errno != EINVAL) {
85*fd71220bSRobert Mustacchi 		warn("TEST FAILED: zero length lookup had wrong errno, "
86*fd71220bSRobert Mustacchi 		    "expected EINVAL, found");
87*fd71220bSRobert Mustacchi 		gpio_lookup_ret = EXIT_FAILURE;
88*fd71220bSRobert Mustacchi 	}
89*fd71220bSRobert Mustacchi 
90*fd71220bSRobert Mustacchi 	(void) memset(kin.kin_name, 'a', sizeof (kin.kin_name));
91*fd71220bSRobert Mustacchi 	if (ioctl(fd, KGPIO_IOC_GPIO_NAME2ID, &kin) == 0) {
92*fd71220bSRobert Mustacchi 		warnx("TEST FAILED: no '\\0' lookup passed, expected "
93*fd71220bSRobert Mustacchi 		    "EINVAL");
94*fd71220bSRobert Mustacchi 		gpio_lookup_ret = EXIT_FAILURE;
95*fd71220bSRobert Mustacchi 	} else if (errno != EINVAL) {
96*fd71220bSRobert Mustacchi 		warn("TEST FAILED: no '\\0' lookup had wrong errno, "
97*fd71220bSRobert Mustacchi 		    "expected EINVAL, found");
98*fd71220bSRobert Mustacchi 		gpio_lookup_ret = EXIT_FAILURE;
99*fd71220bSRobert Mustacchi 	}
100*fd71220bSRobert Mustacchi 
101*fd71220bSRobert Mustacchi 	(void) strlcpy(kin.kin_name, "three rings for elven kings",
102*fd71220bSRobert Mustacchi 	    sizeof (kin.kin_name));
103*fd71220bSRobert Mustacchi 	if (ioctl(fd, KGPIO_IOC_GPIO_NAME2ID, &kin) == 0) {
104*fd71220bSRobert Mustacchi 		warnx("TEST FAILED: found rings for elven kings, expected "
105*fd71220bSRobert Mustacchi 		    "ENOENT");
106*fd71220bSRobert Mustacchi 		gpio_lookup_ret = EXIT_FAILURE;
107*fd71220bSRobert Mustacchi 	} else if (errno != ENOENT) {
108*fd71220bSRobert Mustacchi 		warn("TEST FAILED: rings for elven kings had wrong errno, "
109*fd71220bSRobert Mustacchi 		    "expected ENOENT, found");
110*fd71220bSRobert Mustacchi 		gpio_lookup_ret = EXIT_FAILURE;
111*fd71220bSRobert Mustacchi 	}
112*fd71220bSRobert Mustacchi }
113*fd71220bSRobert Mustacchi 
114*fd71220bSRobert Mustacchi int
main(void)115*fd71220bSRobert Mustacchi main(void)
116*fd71220bSRobert Mustacchi {
117*fd71220bSRobert Mustacchi 	int fds[ARRAY_SIZE(gpio_paths)];
118*fd71220bSRobert Mustacchi 	uint32_t found_ids[ARRAY_SIZE(gpio_paths)];
119*fd71220bSRobert Mustacchi 
120*fd71220bSRobert Mustacchi 	for (size_t i = 0; i < ARRAY_SIZE(gpio_paths); i++) {
121*fd71220bSRobert Mustacchi 		fds[i] = open(gpio_paths[i], O_RDONLY);
122*fd71220bSRobert Mustacchi 		if (fds[i] < 0) {
123*fd71220bSRobert Mustacchi 			err(EXIT_FAILURE, "failed to open controller %s",
124*fd71220bSRobert Mustacchi 			    gpio_paths[i]);
125*fd71220bSRobert Mustacchi 		}
126*fd71220bSRobert Mustacchi 	}
127*fd71220bSRobert Mustacchi 
128*fd71220bSRobert Mustacchi 	/*
129*fd71220bSRobert Mustacchi 	 * We expect all of these to be successful.
130*fd71220bSRobert Mustacchi 	 */
131*fd71220bSRobert Mustacchi 	for (size_t name = 0; name < ARRAY_SIZE(gpio_names); name++) {
132*fd71220bSRobert Mustacchi 		uint32_t id0;
133*fd71220bSRobert Mustacchi 
134*fd71220bSRobert Mustacchi 		for (size_t ctrl = 0; ctrl < ARRAY_SIZE(gpio_paths); ctrl++) {
135*fd71220bSRobert Mustacchi 			gpio_lookup(fds[ctrl], gpio_names[name],
136*fd71220bSRobert Mustacchi 			    &found_ids[ctrl]);
137*fd71220bSRobert Mustacchi 		}
138*fd71220bSRobert Mustacchi 
139*fd71220bSRobert Mustacchi 		id0 = found_ids[0];
140*fd71220bSRobert Mustacchi 		for (size_t ctrl = 0; ctrl < ARRAY_SIZE(gpio_paths); ctrl++) {
141*fd71220bSRobert Mustacchi 			if (found_ids[ctrl] != id0) {
142*fd71220bSRobert Mustacchi 				warnx("ID Mismatch for %s: got %u on "
143*fd71220bSRobert Mustacchi 				    "%s and %u on %s", gpio_names[name],
144*fd71220bSRobert Mustacchi 				    id0, gpio_paths[0], found_ids[ctrl],
145*fd71220bSRobert Mustacchi 				    gpio_paths[ctrl]);
146*fd71220bSRobert Mustacchi 				gpio_lookup_ret = EXIT_FAILURE;
147*fd71220bSRobert Mustacchi 			}
148*fd71220bSRobert Mustacchi 		}
149*fd71220bSRobert Mustacchi 
150*fd71220bSRobert Mustacchi 	}
151*fd71220bSRobert Mustacchi 
152*fd71220bSRobert Mustacchi 	gpio_lookup_errs(fds[0]);
153*fd71220bSRobert Mustacchi 
154*fd71220bSRobert Mustacchi 	return (gpio_lookup_ret);
155*fd71220bSRobert Mustacchi }
156