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 2022 Oxide Computer Company
14*fd71220bSRobert Mustacchi */
15*fd71220bSRobert Mustacchi
16*fd71220bSRobert Mustacchi #include <err.h>
17*fd71220bSRobert Mustacchi #include <stdlib.h>
18*fd71220bSRobert Mustacchi #include <stdarg.h>
19*fd71220bSRobert Mustacchi #include <ofmt.h>
20*fd71220bSRobert Mustacchi #include <libdevinfo.h>
21*fd71220bSRobert Mustacchi #include <string.h>
22*fd71220bSRobert Mustacchi #include <sys/sysmacros.h>
23*fd71220bSRobert Mustacchi
24*fd71220bSRobert Mustacchi #include "gpioadm.h"
25*fd71220bSRobert Mustacchi
26*fd71220bSRobert Mustacchi static void
gpioadm_dpio_list_usage(FILE * f)27*fd71220bSRobert Mustacchi gpioadm_dpio_list_usage(FILE *f)
28*fd71220bSRobert Mustacchi {
29*fd71220bSRobert Mustacchi (void) fprintf(f, "\tgpioadm dpio list [-H] [-o field[,...] [-p]] "
30*fd71220bSRobert Mustacchi "[filter...]\n");
31*fd71220bSRobert Mustacchi }
32*fd71220bSRobert Mustacchi
33*fd71220bSRobert Mustacchi static void __PRINTFLIKE(1)
gpioadm_dpio_list_help(const char * fmt,...)34*fd71220bSRobert Mustacchi gpioadm_dpio_list_help(const char *fmt, ...)
35*fd71220bSRobert Mustacchi {
36*fd71220bSRobert Mustacchi if (fmt != NULL) {
37*fd71220bSRobert Mustacchi va_list ap;
38*fd71220bSRobert Mustacchi
39*fd71220bSRobert Mustacchi va_start(ap, fmt);
40*fd71220bSRobert Mustacchi vwarnx(fmt, ap);
41*fd71220bSRobert Mustacchi va_end(ap);
42*fd71220bSRobert Mustacchi }
43*fd71220bSRobert Mustacchi
44*fd71220bSRobert Mustacchi (void) fprintf(stderr, "Usage: gpioadm dpio list [-H] [-o "
45*fd71220bSRobert Mustacchi "field[,...] [-p]] [filter...]\n");
46*fd71220bSRobert Mustacchi (void) fprintf(stderr, "\nList information about DPIOs\n\n"
47*fd71220bSRobert Mustacchi "\t-H\t\tomit the column header\n"
48*fd71220bSRobert Mustacchi "\t-o field\toutput fields to print\n"
49*fd71220bSRobert Mustacchi "\t-p\t\tparsable output (requires -o)\n\n"
50*fd71220bSRobert Mustacchi "The following fields are supported:\n"
51*fd71220bSRobert Mustacchi "\tdpio\t\tthe name of the DPIO\n"
52*fd71220bSRobert Mustacchi "\tcontroller\tthe name of the underlying GPIO controller\n"
53*fd71220bSRobert Mustacchi "\tgpionum\t\tthe number of the underlying GPIO\n"
54*fd71220bSRobert Mustacchi "\tcaps\t\tDPIO capabilities\n"
55*fd71220bSRobert Mustacchi "\tflags\t\tDPIO flags that effect its behavior\n"
56*fd71220bSRobert Mustacchi "Filters restrict output to the named DPIOs. Each filter is "
57*fd71220bSRobert Mustacchi "treated\nlike an OR allowing one to limit output to specific "
58*fd71220bSRobert Mustacchi "controllers. It is\nan error if a DPIO isn't found.\n");
59*fd71220bSRobert Mustacchi }
60*fd71220bSRobert Mustacchi
61*fd71220bSRobert Mustacchi typedef enum gpioadm_dpio_list_otype {
62*fd71220bSRobert Mustacchi GPIOADM_DPIO_LIST_DPIO,
63*fd71220bSRobert Mustacchi GPIOADM_DPIO_LIST_CTRL,
64*fd71220bSRobert Mustacchi GPIOADM_DPIO_LIST_GPIONUM,
65*fd71220bSRobert Mustacchi GPIOADM_DPIO_LIST_CAPS,
66*fd71220bSRobert Mustacchi GPIOADM_DPIO_LIST_FLAGS
67*fd71220bSRobert Mustacchi } gpioadm_dpio_list_otype_t;
68*fd71220bSRobert Mustacchi
69*fd71220bSRobert Mustacchi static boolean_t
gpioadm_dpio_list_ofmt_caps(char * buf,uint_t buflen,xpio_dpio_info_t * info)70*fd71220bSRobert Mustacchi gpioadm_dpio_list_ofmt_caps(char *buf, uint_t buflen, xpio_dpio_info_t *info)
71*fd71220bSRobert Mustacchi {
72*fd71220bSRobert Mustacchi boolean_t first = B_TRUE;
73*fd71220bSRobert Mustacchi dpio_caps_t caps = xpio_dpio_info_caps(info);
74*fd71220bSRobert Mustacchi dpio_caps_t bits[3] = { DPIO_C_READ, DPIO_C_WRITE, DPIO_C_POLL };
75*fd71220bSRobert Mustacchi const char *strs[3] = { "read", "write", "poll" };
76*fd71220bSRobert Mustacchi uintptr_t off = 0;
77*fd71220bSRobert Mustacchi
78*fd71220bSRobert Mustacchi for (size_t i = 0; i < ARRAY_SIZE(bits); i++) {
79*fd71220bSRobert Mustacchi int len;
80*fd71220bSRobert Mustacchi
81*fd71220bSRobert Mustacchi if ((caps & bits[i]) == 0)
82*fd71220bSRobert Mustacchi continue;
83*fd71220bSRobert Mustacchi
84*fd71220bSRobert Mustacchi len = snprintf(buf + off, buflen - off, "%s%s",
85*fd71220bSRobert Mustacchi first ? "" : ",", strs[i]);
86*fd71220bSRobert Mustacchi if (len >= (buflen - off)) {
87*fd71220bSRobert Mustacchi return (B_FALSE);
88*fd71220bSRobert Mustacchi }
89*fd71220bSRobert Mustacchi off += len;
90*fd71220bSRobert Mustacchi first = B_FALSE;
91*fd71220bSRobert Mustacchi }
92*fd71220bSRobert Mustacchi
93*fd71220bSRobert Mustacchi return (B_TRUE);
94*fd71220bSRobert Mustacchi }
95*fd71220bSRobert Mustacchi
96*fd71220bSRobert Mustacchi static boolean_t
gpioadm_dpio_list_ofmt_cb(ofmt_arg_t * ofarg,char * buf,uint_t buflen)97*fd71220bSRobert Mustacchi gpioadm_dpio_list_ofmt_cb(ofmt_arg_t *ofarg, char *buf, uint_t buflen)
98*fd71220bSRobert Mustacchi {
99*fd71220bSRobert Mustacchi xpio_dpio_info_t *info = ofarg->ofmt_cbarg;
100*fd71220bSRobert Mustacchi dpio_flags_t flags;
101*fd71220bSRobert Mustacchi
102*fd71220bSRobert Mustacchi switch (ofarg->ofmt_id) {
103*fd71220bSRobert Mustacchi case GPIOADM_DPIO_LIST_DPIO:
104*fd71220bSRobert Mustacchi if (strlcpy(buf, xpio_dpio_info_name(info), buflen) >= buflen) {
105*fd71220bSRobert Mustacchi return (B_FALSE);
106*fd71220bSRobert Mustacchi }
107*fd71220bSRobert Mustacchi break;
108*fd71220bSRobert Mustacchi case GPIOADM_DPIO_LIST_CTRL:
109*fd71220bSRobert Mustacchi if (strlcpy(buf, xpio_dpio_info_ctrl(info), buflen) >= buflen) {
110*fd71220bSRobert Mustacchi return (B_FALSE);
111*fd71220bSRobert Mustacchi }
112*fd71220bSRobert Mustacchi break;
113*fd71220bSRobert Mustacchi case GPIOADM_DPIO_LIST_GPIONUM:
114*fd71220bSRobert Mustacchi if (snprintf(buf, buflen, "%u", xpio_dpio_info_gpionum(info)) >=
115*fd71220bSRobert Mustacchi buflen) {
116*fd71220bSRobert Mustacchi return (B_FALSE);
117*fd71220bSRobert Mustacchi }
118*fd71220bSRobert Mustacchi break;
119*fd71220bSRobert Mustacchi case GPIOADM_DPIO_LIST_CAPS:
120*fd71220bSRobert Mustacchi return (gpioadm_dpio_list_ofmt_caps(buf, buflen, info));
121*fd71220bSRobert Mustacchi case GPIOADM_DPIO_LIST_FLAGS:
122*fd71220bSRobert Mustacchi flags = xpio_dpio_info_flags(info);
123*fd71220bSRobert Mustacchi if (flags == 0) {
124*fd71220bSRobert Mustacchi if (strlcpy(buf, "-", buflen) >= buflen) {
125*fd71220bSRobert Mustacchi return (B_FALSE);
126*fd71220bSRobert Mustacchi }
127*fd71220bSRobert Mustacchi } else {
128*fd71220bSRobert Mustacchi if (strlcpy(buf, "K", buflen) >= buflen) {
129*fd71220bSRobert Mustacchi return (B_FALSE);
130*fd71220bSRobert Mustacchi }
131*fd71220bSRobert Mustacchi }
132*fd71220bSRobert Mustacchi break;
133*fd71220bSRobert Mustacchi default:
134*fd71220bSRobert Mustacchi return (B_FALSE);
135*fd71220bSRobert Mustacchi }
136*fd71220bSRobert Mustacchi
137*fd71220bSRobert Mustacchi return (B_TRUE);
138*fd71220bSRobert Mustacchi }
139*fd71220bSRobert Mustacchi
140*fd71220bSRobert Mustacchi static const char *gpioadm_dpio_list_fields = "dpio,caps,flags,controller,"
141*fd71220bSRobert Mustacchi "gpionum";
142*fd71220bSRobert Mustacchi static const ofmt_field_t gpioadm_dpio_list_ofmt[] = {
143*fd71220bSRobert Mustacchi { "DPIO", 16, GPIOADM_DPIO_LIST_DPIO, gpioadm_dpio_list_ofmt_cb },
144*fd71220bSRobert Mustacchi { "CAPS", 16, GPIOADM_DPIO_LIST_CAPS, gpioadm_dpio_list_ofmt_cb },
145*fd71220bSRobert Mustacchi { "FLAGS", 8, GPIOADM_DPIO_LIST_FLAGS, gpioadm_dpio_list_ofmt_cb },
146*fd71220bSRobert Mustacchi { "CONTROLLER", 16, GPIOADM_DPIO_LIST_CTRL, gpioadm_dpio_list_ofmt_cb },
147*fd71220bSRobert Mustacchi { "GPIONUM", 8, GPIOADM_DPIO_LIST_GPIONUM, gpioadm_dpio_list_ofmt_cb },
148*fd71220bSRobert Mustacchi { NULL, 0, 0, NULL }
149*fd71220bSRobert Mustacchi };
150*fd71220bSRobert Mustacchi
151*fd71220bSRobert Mustacchi typedef struct {
152*fd71220bSRobert Mustacchi ofmt_handle_t gdl_ofmt;
153*fd71220bSRobert Mustacchi uint32_t gdl_nprint;
154*fd71220bSRobert Mustacchi bool gdl_err;
155*fd71220bSRobert Mustacchi int gdl_nfilts;
156*fd71220bSRobert Mustacchi char **gdl_filts;
157*fd71220bSRobert Mustacchi bool *gdl_used;
158*fd71220bSRobert Mustacchi } gpioadm_dpio_list_t;
159*fd71220bSRobert Mustacchi
160*fd71220bSRobert Mustacchi static bool
gpioadm_dpio_list_cb(xpio_t * xpio,xpio_dpio_disc_t * disc,void * arg)161*fd71220bSRobert Mustacchi gpioadm_dpio_list_cb(xpio_t *xpio, xpio_dpio_disc_t *disc, void *arg)
162*fd71220bSRobert Mustacchi {
163*fd71220bSRobert Mustacchi gpioadm_dpio_list_t *gdl = arg;
164*fd71220bSRobert Mustacchi /* Strip out the kernel mandated 'dpio:' */
165*fd71220bSRobert Mustacchi const char *name = di_minor_name(disc->xdd_minor) + 5;
166*fd71220bSRobert Mustacchi xpio_dpio_info_t *info;
167*fd71220bSRobert Mustacchi
168*fd71220bSRobert Mustacchi if (gdl->gdl_nfilts > 0) {
169*fd71220bSRobert Mustacchi bool found = false;
170*fd71220bSRobert Mustacchi
171*fd71220bSRobert Mustacchi for (int i = 0; i < gdl->gdl_nfilts; i++) {
172*fd71220bSRobert Mustacchi if (strcmp(name, gdl->gdl_filts[i]) == 0) {
173*fd71220bSRobert Mustacchi found = true;
174*fd71220bSRobert Mustacchi gdl->gdl_used[i] = true;
175*fd71220bSRobert Mustacchi break;
176*fd71220bSRobert Mustacchi }
177*fd71220bSRobert Mustacchi }
178*fd71220bSRobert Mustacchi
179*fd71220bSRobert Mustacchi if (!found) {
180*fd71220bSRobert Mustacchi return (true);
181*fd71220bSRobert Mustacchi }
182*fd71220bSRobert Mustacchi }
183*fd71220bSRobert Mustacchi
184*fd71220bSRobert Mustacchi gdl->gdl_nprint++;
185*fd71220bSRobert Mustacchi
186*fd71220bSRobert Mustacchi if (!xpio_dpio_info(gpioadm.gpio_xpio, disc->xdd_minor, &info)) {
187*fd71220bSRobert Mustacchi gpioadm_warn("failed to get controller info for %s", name);
188*fd71220bSRobert Mustacchi gdl->gdl_err = true;
189*fd71220bSRobert Mustacchi return (true);
190*fd71220bSRobert Mustacchi }
191*fd71220bSRobert Mustacchi
192*fd71220bSRobert Mustacchi ofmt_print(gdl->gdl_ofmt, info);
193*fd71220bSRobert Mustacchi xpio_dpio_info_free(info);
194*fd71220bSRobert Mustacchi
195*fd71220bSRobert Mustacchi return (true);
196*fd71220bSRobert Mustacchi }
197*fd71220bSRobert Mustacchi
198*fd71220bSRobert Mustacchi static int
gpioadm_dpio_list(int argc,char * argv[])199*fd71220bSRobert Mustacchi gpioadm_dpio_list(int argc, char *argv[])
200*fd71220bSRobert Mustacchi {
201*fd71220bSRobert Mustacchi int c;
202*fd71220bSRobert Mustacchi uint_t flags = 0;
203*fd71220bSRobert Mustacchi boolean_t parse = B_FALSE;
204*fd71220bSRobert Mustacchi const char *fields = NULL;
205*fd71220bSRobert Mustacchi ofmt_status_t oferr;
206*fd71220bSRobert Mustacchi ofmt_handle_t ofmt;
207*fd71220bSRobert Mustacchi gpioadm_dpio_list_t gdl;
208*fd71220bSRobert Mustacchi
209*fd71220bSRobert Mustacchi (void) memset(&gdl, 0, sizeof (gdl));
210*fd71220bSRobert Mustacchi
211*fd71220bSRobert Mustacchi while ((c = getopt(argc, argv, ":Ho:p")) != -1) {
212*fd71220bSRobert Mustacchi switch (c) {
213*fd71220bSRobert Mustacchi case 'H':
214*fd71220bSRobert Mustacchi flags |= OFMT_NOHEADER;
215*fd71220bSRobert Mustacchi break;
216*fd71220bSRobert Mustacchi case 'o':
217*fd71220bSRobert Mustacchi fields = optarg;
218*fd71220bSRobert Mustacchi break;
219*fd71220bSRobert Mustacchi case 'p':
220*fd71220bSRobert Mustacchi parse = B_TRUE;
221*fd71220bSRobert Mustacchi flags |= OFMT_PARSABLE;
222*fd71220bSRobert Mustacchi break;
223*fd71220bSRobert Mustacchi case ':':
224*fd71220bSRobert Mustacchi gpioadm_dpio_list_help("option -%c requires an "
225*fd71220bSRobert Mustacchi "argument", optopt);
226*fd71220bSRobert Mustacchi exit(EXIT_USAGE);
227*fd71220bSRobert Mustacchi case '?':
228*fd71220bSRobert Mustacchi gpioadm_dpio_list_help("unknown option: -%c", optopt);
229*fd71220bSRobert Mustacchi exit(EXIT_USAGE);
230*fd71220bSRobert Mustacchi }
231*fd71220bSRobert Mustacchi }
232*fd71220bSRobert Mustacchi
233*fd71220bSRobert Mustacchi if (parse && fields == NULL) {
234*fd71220bSRobert Mustacchi errx(EXIT_USAGE, "-p requires fields specified with -o");
235*fd71220bSRobert Mustacchi }
236*fd71220bSRobert Mustacchi
237*fd71220bSRobert Mustacchi if (fields == NULL) {
238*fd71220bSRobert Mustacchi fields = gpioadm_dpio_list_fields;
239*fd71220bSRobert Mustacchi }
240*fd71220bSRobert Mustacchi
241*fd71220bSRobert Mustacchi argc -= optind;
242*fd71220bSRobert Mustacchi argv += optind;
243*fd71220bSRobert Mustacchi if (argc > 0) {
244*fd71220bSRobert Mustacchi gdl.gdl_nfilts = argc;
245*fd71220bSRobert Mustacchi gdl.gdl_filts = argv;
246*fd71220bSRobert Mustacchi gdl.gdl_used = calloc(argc, sizeof (bool));
247*fd71220bSRobert Mustacchi if (gdl.gdl_used == NULL) {
248*fd71220bSRobert Mustacchi err(EXIT_FAILURE, "failed to allocate filter tracking "
249*fd71220bSRobert Mustacchi "memory");
250*fd71220bSRobert Mustacchi }
251*fd71220bSRobert Mustacchi }
252*fd71220bSRobert Mustacchi oferr = ofmt_open(fields, gpioadm_dpio_list_ofmt, flags, 0, &ofmt);
253*fd71220bSRobert Mustacchi ofmt_check(oferr, parse, ofmt, gpioadm_ofmt_errx, warnx);
254*fd71220bSRobert Mustacchi
255*fd71220bSRobert Mustacchi gdl.gdl_nprint = 0;
256*fd71220bSRobert Mustacchi gdl.gdl_err = B_FALSE;
257*fd71220bSRobert Mustacchi gdl.gdl_ofmt = ofmt;
258*fd71220bSRobert Mustacchi xpio_dpio_discover(gpioadm.gpio_xpio, gpioadm_dpio_list_cb, &gdl);
259*fd71220bSRobert Mustacchi
260*fd71220bSRobert Mustacchi for (int i = 0; i < gdl.gdl_nfilts; i++) {
261*fd71220bSRobert Mustacchi if (!gdl.gdl_used[i]) {
262*fd71220bSRobert Mustacchi warnx("filter '%s' did not match any DPIOs",
263*fd71220bSRobert Mustacchi gdl.gdl_filts[i]);
264*fd71220bSRobert Mustacchi gdl.gdl_err = true;
265*fd71220bSRobert Mustacchi }
266*fd71220bSRobert Mustacchi }
267*fd71220bSRobert Mustacchi
268*fd71220bSRobert Mustacchi if (gdl.gdl_nprint == 0) {
269*fd71220bSRobert Mustacchi /*
270*fd71220bSRobert Mustacchi * We only bother to warn about no DPIOs being found when there
271*fd71220bSRobert Mustacchi * are no filters as otherwise the user would have gotten a
272*fd71220bSRobert Mustacchi * message about unmatched filters just above.
273*fd71220bSRobert Mustacchi */
274*fd71220bSRobert Mustacchi if (gdl.gdl_nfilts == 0) {
275*fd71220bSRobert Mustacchi warnx("no DPIOs found");
276*fd71220bSRobert Mustacchi }
277*fd71220bSRobert Mustacchi gdl.gdl_err = true;
278*fd71220bSRobert Mustacchi }
279*fd71220bSRobert Mustacchi
280*fd71220bSRobert Mustacchi return (gdl.gdl_err ? EXIT_FAILURE : EXIT_SUCCESS);
281*fd71220bSRobert Mustacchi }
282*fd71220bSRobert Mustacchi
283*fd71220bSRobert Mustacchi static void
gpioadm_dpio_define_usage(FILE * f)284*fd71220bSRobert Mustacchi gpioadm_dpio_define_usage(FILE *f)
285*fd71220bSRobert Mustacchi {
286*fd71220bSRobert Mustacchi (void) fprintf(f, "\tgpioadm dpio define [-r] [-w] [-K] "
287*fd71220bSRobert Mustacchi "controller/gpio name\n");
288*fd71220bSRobert Mustacchi }
289*fd71220bSRobert Mustacchi
290*fd71220bSRobert Mustacchi static void __PRINTFLIKE(1)
gpioadm_dpio_define_help(const char * fmt,...)291*fd71220bSRobert Mustacchi gpioadm_dpio_define_help(const char *fmt, ...)
292*fd71220bSRobert Mustacchi {
293*fd71220bSRobert Mustacchi if (fmt != NULL) {
294*fd71220bSRobert Mustacchi va_list ap;
295*fd71220bSRobert Mustacchi
296*fd71220bSRobert Mustacchi va_start(ap, fmt);
297*fd71220bSRobert Mustacchi vwarnx(fmt, ap);
298*fd71220bSRobert Mustacchi va_end(ap);
299*fd71220bSRobert Mustacchi }
300*fd71220bSRobert Mustacchi
301*fd71220bSRobert Mustacchi (void) fprintf(stderr, "Usage: gpioadm dpio define [-r] [-w] [-K] "
302*fd71220bSRobert Mustacchi "controller/gpio name\n");
303*fd71220bSRobert Mustacchi (void) fprintf(stderr, "\nCreate a new DPIO from the specified GPIO\n\n"
304*fd71220bSRobert Mustacchi "\t-r\t\tthe DPIO is allowed to read the GPIO input value\n"
305*fd71220bSRobert Mustacchi "\t-w\t\tthe DPIO is allowed to set the GPIO output value\n"
306*fd71220bSRobert Mustacchi "\t-K\t\tthe DPIO should only be accessible from the kernel\n");
307*fd71220bSRobert Mustacchi }
308*fd71220bSRobert Mustacchi
309*fd71220bSRobert Mustacchi static int
gpioadm_dpio_define(int argc,char * argv[])310*fd71220bSRobert Mustacchi gpioadm_dpio_define(int argc, char *argv[])
311*fd71220bSRobert Mustacchi {
312*fd71220bSRobert Mustacchi int c;
313*fd71220bSRobert Mustacchi xpio_ctrl_t *ctrl;
314*fd71220bSRobert Mustacchi xpio_gpio_info_t *gpio;
315*fd71220bSRobert Mustacchi xpio_dpio_features_t feats = 0;
316*fd71220bSRobert Mustacchi
317*fd71220bSRobert Mustacchi while ((c = getopt(argc, argv, ":rwK")) != -1) {
318*fd71220bSRobert Mustacchi switch (c) {
319*fd71220bSRobert Mustacchi case 'r':
320*fd71220bSRobert Mustacchi feats |= XPIO_DPIO_F_READ;
321*fd71220bSRobert Mustacchi break;
322*fd71220bSRobert Mustacchi case 'K':
323*fd71220bSRobert Mustacchi feats |= XPIO_DPIO_F_KERNEL;
324*fd71220bSRobert Mustacchi break;
325*fd71220bSRobert Mustacchi case 'w':
326*fd71220bSRobert Mustacchi feats |= XPIO_DPIO_F_WRITE;
327*fd71220bSRobert Mustacchi break;
328*fd71220bSRobert Mustacchi case ':':
329*fd71220bSRobert Mustacchi gpioadm_dpio_define_help("option -%c requires an "
330*fd71220bSRobert Mustacchi "argument", optopt);
331*fd71220bSRobert Mustacchi exit(EXIT_USAGE);
332*fd71220bSRobert Mustacchi case '?':
333*fd71220bSRobert Mustacchi gpioadm_dpio_define_help("unknown option: -%c",
334*fd71220bSRobert Mustacchi optopt);
335*fd71220bSRobert Mustacchi exit(EXIT_USAGE);
336*fd71220bSRobert Mustacchi }
337*fd71220bSRobert Mustacchi }
338*fd71220bSRobert Mustacchi
339*fd71220bSRobert Mustacchi argc -= optind;
340*fd71220bSRobert Mustacchi argv += optind;
341*fd71220bSRobert Mustacchi
342*fd71220bSRobert Mustacchi if (argc == 0) {
343*fd71220bSRobert Mustacchi errx(EXIT_FAILURE, "missing required gpio specifier and dpio "
344*fd71220bSRobert Mustacchi "name");
345*fd71220bSRobert Mustacchi } else if (argc == 1) {
346*fd71220bSRobert Mustacchi errx(EXIT_FAILURE, "missing required dpio name");
347*fd71220bSRobert Mustacchi } else if (argc > 2) {
348*fd71220bSRobert Mustacchi errx(EXIT_FAILURE, "encountered extraneous arguments beginning "
349*fd71220bSRobert Mustacchi "with '%s'", argv[2]);
350*fd71220bSRobert Mustacchi }
351*fd71220bSRobert Mustacchi
352*fd71220bSRobert Mustacchi gpioadm_ctrl_gpio_init(argv[0], &ctrl, &gpio);
353*fd71220bSRobert Mustacchi if (!xpio_dpio_create(ctrl, gpio, argv[1], feats)) {
354*fd71220bSRobert Mustacchi gpioadm_fatal("failed to create dpio %s from gpio %s", argv[1],
355*fd71220bSRobert Mustacchi argv[0]);
356*fd71220bSRobert Mustacchi }
357*fd71220bSRobert Mustacchi
358*fd71220bSRobert Mustacchi return (EXIT_SUCCESS);
359*fd71220bSRobert Mustacchi }
360*fd71220bSRobert Mustacchi
361*fd71220bSRobert Mustacchi static void
gpioadm_dpio_undefine_usage(FILE * f)362*fd71220bSRobert Mustacchi gpioadm_dpio_undefine_usage(FILE *f)
363*fd71220bSRobert Mustacchi {
364*fd71220bSRobert Mustacchi (void) fprintf(f, "\tgpioadm dpio undefine controller/gpio\n");
365*fd71220bSRobert Mustacchi }
366*fd71220bSRobert Mustacchi
367*fd71220bSRobert Mustacchi static void __PRINTFLIKE(1)
gpioadm_dpio_undefine_help(const char * fmt,...)368*fd71220bSRobert Mustacchi gpioadm_dpio_undefine_help(const char *fmt, ...)
369*fd71220bSRobert Mustacchi {
370*fd71220bSRobert Mustacchi if (fmt != NULL) {
371*fd71220bSRobert Mustacchi va_list ap;
372*fd71220bSRobert Mustacchi
373*fd71220bSRobert Mustacchi va_start(ap, fmt);
374*fd71220bSRobert Mustacchi vwarnx(fmt, ap);
375*fd71220bSRobert Mustacchi va_end(ap);
376*fd71220bSRobert Mustacchi }
377*fd71220bSRobert Mustacchi
378*fd71220bSRobert Mustacchi (void) fprintf(stderr, "Usage: gpioadm dpio undefine "
379*fd71220bSRobert Mustacchi "controller/gpio\n");
380*fd71220bSRobert Mustacchi (void) fprintf(stderr, "\nRemove a DPIO from the system backed by the "
381*fd71220bSRobert Mustacchi "specified controller and GPIO\n");
382*fd71220bSRobert Mustacchi }
383*fd71220bSRobert Mustacchi
384*fd71220bSRobert Mustacchi static int
gpioadm_dpio_undefine(int argc,char * argv[])385*fd71220bSRobert Mustacchi gpioadm_dpio_undefine(int argc, char *argv[])
386*fd71220bSRobert Mustacchi {
387*fd71220bSRobert Mustacchi int c;
388*fd71220bSRobert Mustacchi xpio_ctrl_t *ctrl;
389*fd71220bSRobert Mustacchi xpio_gpio_info_t *gpio;
390*fd71220bSRobert Mustacchi
391*fd71220bSRobert Mustacchi while ((c = getopt(argc, argv, ":")) != -1) {
392*fd71220bSRobert Mustacchi switch (c) {
393*fd71220bSRobert Mustacchi case ':':
394*fd71220bSRobert Mustacchi gpioadm_dpio_undefine_help("option -%c requires an "
395*fd71220bSRobert Mustacchi "argument", optopt);
396*fd71220bSRobert Mustacchi exit(EXIT_USAGE);
397*fd71220bSRobert Mustacchi case '?':
398*fd71220bSRobert Mustacchi gpioadm_dpio_undefine_help("unknown option: -%c",
399*fd71220bSRobert Mustacchi optopt);
400*fd71220bSRobert Mustacchi exit(EXIT_USAGE);
401*fd71220bSRobert Mustacchi }
402*fd71220bSRobert Mustacchi }
403*fd71220bSRobert Mustacchi
404*fd71220bSRobert Mustacchi argc -= optind;
405*fd71220bSRobert Mustacchi argv += optind;
406*fd71220bSRobert Mustacchi
407*fd71220bSRobert Mustacchi if (argc < 1) {
408*fd71220bSRobert Mustacchi errx(EXIT_FAILURE, "missing required gpio specifier");
409*fd71220bSRobert Mustacchi } else if (argc > 1) {
410*fd71220bSRobert Mustacchi errx(EXIT_FAILURE, "encountered extraneous arguments beginning "
411*fd71220bSRobert Mustacchi "with '%s'", argv[1]);
412*fd71220bSRobert Mustacchi }
413*fd71220bSRobert Mustacchi
414*fd71220bSRobert Mustacchi gpioadm_ctrl_gpio_init(argv[0], &ctrl, &gpio);
415*fd71220bSRobert Mustacchi if (!xpio_dpio_destroy(ctrl, gpio)) {
416*fd71220bSRobert Mustacchi gpioadm_fatal("failed to release gpio %s from being a DPIO",
417*fd71220bSRobert Mustacchi argv[0]);
418*fd71220bSRobert Mustacchi }
419*fd71220bSRobert Mustacchi
420*fd71220bSRobert Mustacchi return (EXIT_SUCCESS);
421*fd71220bSRobert Mustacchi }
422*fd71220bSRobert Mustacchi
423*fd71220bSRobert Mustacchi static const gpioadm_cmdtab_t gpioadm_cmds_dpio[] = {
424*fd71220bSRobert Mustacchi { "list", gpioadm_dpio_list, gpioadm_dpio_list_usage },
425*fd71220bSRobert Mustacchi { "define", gpioadm_dpio_define, gpioadm_dpio_define_usage },
426*fd71220bSRobert Mustacchi { "undefine", gpioadm_dpio_undefine, gpioadm_dpio_undefine_usage },
427*fd71220bSRobert Mustacchi { NULL, NULL, NULL }
428*fd71220bSRobert Mustacchi };
429*fd71220bSRobert Mustacchi
430*fd71220bSRobert Mustacchi int
gpioadm_dpio(int argc,char * argv[])431*fd71220bSRobert Mustacchi gpioadm_dpio(int argc, char *argv[])
432*fd71220bSRobert Mustacchi {
433*fd71220bSRobert Mustacchi return (gpioadm_walk_tab(gpioadm_cmds_dpio, argc, argv));
434*fd71220bSRobert Mustacchi }
435*fd71220bSRobert Mustacchi
436*fd71220bSRobert Mustacchi void
gpioadm_dpio_usage(FILE * f)437*fd71220bSRobert Mustacchi gpioadm_dpio_usage(FILE *f)
438*fd71220bSRobert Mustacchi {
439*fd71220bSRobert Mustacchi gpioadm_walk_usage(gpioadm_cmds_dpio, f);
440*fd71220bSRobert Mustacchi }
441