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 <string.h>
17*fd71220bSRobert Mustacchi #include <err.h>
18*fd71220bSRobert Mustacchi #include <stdlib.h>
19*fd71220bSRobert Mustacchi #include <stdarg.h>
20*fd71220bSRobert Mustacchi #include <ofmt.h>
21*fd71220bSRobert Mustacchi #include <libdevinfo.h>
22*fd71220bSRobert Mustacchi #include <strings.h>
23*fd71220bSRobert Mustacchi #include <sys/debug.h>
24*fd71220bSRobert Mustacchi
25*fd71220bSRobert Mustacchi #include "gpioadm.h"
26*fd71220bSRobert Mustacchi
27*fd71220bSRobert Mustacchi static void
gpioadm_gpio_attr_get_usage(FILE * f)28*fd71220bSRobert Mustacchi gpioadm_gpio_attr_get_usage(FILE *f)
29*fd71220bSRobert Mustacchi {
30*fd71220bSRobert Mustacchi (void) fprintf(f, "\tgpioadm gpio attr get [-H] [-o field[,...] [-p]] "
31*fd71220bSRobert Mustacchi "controller/gpio [filter...]\n");
32*fd71220bSRobert Mustacchi }
33*fd71220bSRobert Mustacchi
34*fd71220bSRobert Mustacchi static void __PRINTFLIKE(1)
gpioadm_gpio_attr_get_help(const char * fmt,...)35*fd71220bSRobert Mustacchi gpioadm_gpio_attr_get_help(const char *fmt, ...)
36*fd71220bSRobert Mustacchi {
37*fd71220bSRobert Mustacchi if (fmt != NULL) {
38*fd71220bSRobert Mustacchi va_list ap;
39*fd71220bSRobert Mustacchi
40*fd71220bSRobert Mustacchi va_start(ap, fmt);
41*fd71220bSRobert Mustacchi vwarnx(fmt, ap);
42*fd71220bSRobert Mustacchi va_end(ap);
43*fd71220bSRobert Mustacchi }
44*fd71220bSRobert Mustacchi
45*fd71220bSRobert Mustacchi (void) fprintf(stderr, "Usage: gpioadm gpio attr get [-H] "
46*fd71220bSRobert Mustacchi "[-o field[,...] [-p]] controller/gpio\n\t\t\t [filter...]\n");
47*fd71220bSRobert Mustacchi (void) fprintf(stderr, "\nList attributes of a specific GPIO\n\n"
48*fd71220bSRobert Mustacchi "\t-H\t\tomit the column header\n"
49*fd71220bSRobert Mustacchi "\t-o field\toutput fields to print\n"
50*fd71220bSRobert Mustacchi "\t-p\t\tparsable output (requires -o)\n\n"
51*fd71220bSRobert Mustacchi "The following fields are supported:\n"
52*fd71220bSRobert Mustacchi "\tattr\t\tthe name of the attribute\n"
53*fd71220bSRobert Mustacchi "\tvalue\t\tthe human-readable value of the attribute\n"
54*fd71220bSRobert Mustacchi "\traw\t\tan untranslated value of the attribute (e.g. "
55*fd71220bSRobert Mustacchi "underlying\n\t\t\tenum)\n"
56*fd71220bSRobert Mustacchi "\tperm\t\tthe permissions of the attribute\n"
57*fd71220bSRobert Mustacchi "\tpossible\tthe possible values the attribute may take\n\n"
58*fd71220bSRobert Mustacchi "Supported filters are the names of attributes. An attribute "
59*fd71220bSRobert Mustacchi "will be printed\nas long as it matches a single filter (they "
60*fd71220bSRobert Mustacchi "function as an OR). If any\nfilter does not match, then a non-"
61*fd71220bSRobert Mustacchi "zero exit status is returned.\n");
62*fd71220bSRobert Mustacchi }
63*fd71220bSRobert Mustacchi
64*fd71220bSRobert Mustacchi typedef enum gpioadm_gpio_attr_get_otype {
65*fd71220bSRobert Mustacchi GPIOADM_GPIO_ATTR_GET_ATTR,
66*fd71220bSRobert Mustacchi GPIOADM_GPIO_ATTR_GET_VALUE,
67*fd71220bSRobert Mustacchi GPIOADM_GPIO_ATTR_GET_RAW,
68*fd71220bSRobert Mustacchi GPIOADM_GPIO_ATTR_GET_PERM,
69*fd71220bSRobert Mustacchi GPIOADM_GPIO_ATTR_GET_POSSIBLE,
70*fd71220bSRobert Mustacchi } gpioadm_gpio_attr_get_otype_t;
71*fd71220bSRobert Mustacchi
72*fd71220bSRobert Mustacchi typedef struct gpioadm_gpio_attr_get_ofmt {
73*fd71220bSRobert Mustacchi xpio_gpio_info_t *ggag_info;
74*fd71220bSRobert Mustacchi xpio_gpio_attr_t *ggag_attr;
75*fd71220bSRobert Mustacchi } gpioadm_gpio_attr_get_ofmt_t;
76*fd71220bSRobert Mustacchi
77*fd71220bSRobert Mustacchi static boolean_t
gpioadm_gpio_attr_get_ofmt_cb(ofmt_arg_t * ofarg,char * buf,uint_t buflen)78*fd71220bSRobert Mustacchi gpioadm_gpio_attr_get_ofmt_cb(ofmt_arg_t *ofarg, char *buf, uint_t buflen)
79*fd71220bSRobert Mustacchi {
80*fd71220bSRobert Mustacchi const char *str;
81*fd71220bSRobert Mustacchi uint32_t u32;
82*fd71220bSRobert Mustacchi uint32_t *u32_arr;
83*fd71220bSRobert Mustacchi const char **str_arr;
84*fd71220bSRobert Mustacchi uint_t count;
85*fd71220bSRobert Mustacchi uintptr_t off = 0;
86*fd71220bSRobert Mustacchi
87*fd71220bSRobert Mustacchi gpioadm_gpio_attr_get_ofmt_t *ggag = ofarg->ofmt_cbarg;
88*fd71220bSRobert Mustacchi xpio_gpio_info_t *info = ggag->ggag_info;
89*fd71220bSRobert Mustacchi xpio_gpio_attr_t *attr = ggag->ggag_attr;
90*fd71220bSRobert Mustacchi
91*fd71220bSRobert Mustacchi switch (ofarg->ofmt_id) {
92*fd71220bSRobert Mustacchi case GPIOADM_GPIO_ATTR_GET_ATTR:
93*fd71220bSRobert Mustacchi if (strlcpy(buf, xpio_gpio_attr_name(info, attr), buflen) >=
94*fd71220bSRobert Mustacchi buflen) {
95*fd71220bSRobert Mustacchi return (B_FALSE);
96*fd71220bSRobert Mustacchi }
97*fd71220bSRobert Mustacchi break;
98*fd71220bSRobert Mustacchi case GPIOADM_GPIO_ATTR_GET_VALUE:
99*fd71220bSRobert Mustacchi switch (xpio_gpio_attr_type(info, attr)) {
100*fd71220bSRobert Mustacchi case XPIO_ATTR_TYPE_STRING:
101*fd71220bSRobert Mustacchi if (!xpio_gpio_attr_value_string(attr, &str)) {
102*fd71220bSRobert Mustacchi return (B_FALSE);
103*fd71220bSRobert Mustacchi }
104*fd71220bSRobert Mustacchi
105*fd71220bSRobert Mustacchi if (strlcpy(buf, str, buflen) >= buflen) {
106*fd71220bSRobert Mustacchi return (B_FALSE);
107*fd71220bSRobert Mustacchi }
108*fd71220bSRobert Mustacchi break;
109*fd71220bSRobert Mustacchi case XPIO_ATTR_TYPE_UINT32:
110*fd71220bSRobert Mustacchi if (!xpio_gpio_attr_xlate_to_str(info, attr, buf,
111*fd71220bSRobert Mustacchi buflen)) {
112*fd71220bSRobert Mustacchi return (B_FALSE);
113*fd71220bSRobert Mustacchi }
114*fd71220bSRobert Mustacchi break;
115*fd71220bSRobert Mustacchi }
116*fd71220bSRobert Mustacchi break;
117*fd71220bSRobert Mustacchi case GPIOADM_GPIO_ATTR_GET_RAW:
118*fd71220bSRobert Mustacchi switch (xpio_gpio_attr_type(info, attr)) {
119*fd71220bSRobert Mustacchi case XPIO_ATTR_TYPE_STRING:
120*fd71220bSRobert Mustacchi if (!xpio_gpio_attr_value_string(attr, &str)) {
121*fd71220bSRobert Mustacchi return (B_FALSE);
122*fd71220bSRobert Mustacchi }
123*fd71220bSRobert Mustacchi
124*fd71220bSRobert Mustacchi if (strlcpy(buf, str, buflen) >= buflen) {
125*fd71220bSRobert Mustacchi return (B_FALSE);
126*fd71220bSRobert Mustacchi }
127*fd71220bSRobert Mustacchi break;
128*fd71220bSRobert Mustacchi case XPIO_ATTR_TYPE_UINT32:
129*fd71220bSRobert Mustacchi if (!xpio_gpio_attr_value_uint32(attr, &u32)) {
130*fd71220bSRobert Mustacchi return (B_FALSE);
131*fd71220bSRobert Mustacchi }
132*fd71220bSRobert Mustacchi
133*fd71220bSRobert Mustacchi if (snprintf(buf, buflen, "0x%x", u32) >= buflen) {
134*fd71220bSRobert Mustacchi return (B_FALSE);
135*fd71220bSRobert Mustacchi }
136*fd71220bSRobert Mustacchi break;
137*fd71220bSRobert Mustacchi }
138*fd71220bSRobert Mustacchi break;
139*fd71220bSRobert Mustacchi case GPIOADM_GPIO_ATTR_GET_PERM:
140*fd71220bSRobert Mustacchi switch (xpio_gpio_attr_prot(info, attr)) {
141*fd71220bSRobert Mustacchi case XPIO_ATTR_PROT_RO:
142*fd71220bSRobert Mustacchi if (strlcpy(buf, "r-", buflen) >= buflen) {
143*fd71220bSRobert Mustacchi return (B_FALSE);
144*fd71220bSRobert Mustacchi }
145*fd71220bSRobert Mustacchi break;
146*fd71220bSRobert Mustacchi case XPIO_ATTR_PROT_RW:
147*fd71220bSRobert Mustacchi if (strlcpy(buf, "rw", buflen) >= buflen) {
148*fd71220bSRobert Mustacchi return (B_FALSE);
149*fd71220bSRobert Mustacchi }
150*fd71220bSRobert Mustacchi break;
151*fd71220bSRobert Mustacchi }
152*fd71220bSRobert Mustacchi break;
153*fd71220bSRobert Mustacchi case GPIOADM_GPIO_ATTR_GET_POSSIBLE:
154*fd71220bSRobert Mustacchi switch (xpio_gpio_attr_type(info, attr)) {
155*fd71220bSRobert Mustacchi case XPIO_ATTR_TYPE_STRING:
156*fd71220bSRobert Mustacchi xpio_gpio_attr_possible_string(info, attr, &str_arr,
157*fd71220bSRobert Mustacchi &count);
158*fd71220bSRobert Mustacchi for (uint_t i = 0; i < count; i++) {
159*fd71220bSRobert Mustacchi int len = snprintf(buf + off, buflen - off,
160*fd71220bSRobert Mustacchi "%s%s", i > 0 ? "," : "", str_arr[i]);
161*fd71220bSRobert Mustacchi if (len >= (buflen - off)) {
162*fd71220bSRobert Mustacchi return (B_FALSE);
163*fd71220bSRobert Mustacchi }
164*fd71220bSRobert Mustacchi off += len;
165*fd71220bSRobert Mustacchi }
166*fd71220bSRobert Mustacchi break;
167*fd71220bSRobert Mustacchi case XPIO_ATTR_TYPE_UINT32:
168*fd71220bSRobert Mustacchi xpio_gpio_attr_possible_uint32(info, attr, &u32_arr,
169*fd71220bSRobert Mustacchi &count);
170*fd71220bSRobert Mustacchi for (uint_t i = 0; i < count; i++) {
171*fd71220bSRobert Mustacchi char xlate[512];
172*fd71220bSRobert Mustacchi if (!xpio_gpio_attr_xlate_uint32_to_str(info,
173*fd71220bSRobert Mustacchi attr, u32_arr[i], xlate, sizeof (xlate))) {
174*fd71220bSRobert Mustacchi return (B_FALSE);
175*fd71220bSRobert Mustacchi }
176*fd71220bSRobert Mustacchi int len = snprintf(buf + off, buflen - off,
177*fd71220bSRobert Mustacchi "%s%s", i > 0 ? "," : "", xlate);
178*fd71220bSRobert Mustacchi if (len >= (buflen - off)) {
179*fd71220bSRobert Mustacchi return (B_FALSE);
180*fd71220bSRobert Mustacchi }
181*fd71220bSRobert Mustacchi off += len;
182*fd71220bSRobert Mustacchi }
183*fd71220bSRobert Mustacchi break;
184*fd71220bSRobert Mustacchi }
185*fd71220bSRobert Mustacchi break;
186*fd71220bSRobert Mustacchi default:
187*fd71220bSRobert Mustacchi abort();
188*fd71220bSRobert Mustacchi }
189*fd71220bSRobert Mustacchi
190*fd71220bSRobert Mustacchi return (B_TRUE);
191*fd71220bSRobert Mustacchi }
192*fd71220bSRobert Mustacchi
193*fd71220bSRobert Mustacchi static const char *gpioadm_gpio_attr_get_fields = "attr,perm,value,possible";
194*fd71220bSRobert Mustacchi static const ofmt_field_t gpioadm_gpio_attr_get_ofmt[] = {
195*fd71220bSRobert Mustacchi { "ATTR", 22, GPIOADM_GPIO_ATTR_GET_ATTR,
196*fd71220bSRobert Mustacchi gpioadm_gpio_attr_get_ofmt_cb },
197*fd71220bSRobert Mustacchi { "PERM", 6, GPIOADM_GPIO_ATTR_GET_PERM,
198*fd71220bSRobert Mustacchi gpioadm_gpio_attr_get_ofmt_cb },
199*fd71220bSRobert Mustacchi { "VALUE", 24, GPIOADM_GPIO_ATTR_GET_VALUE,
200*fd71220bSRobert Mustacchi gpioadm_gpio_attr_get_ofmt_cb },
201*fd71220bSRobert Mustacchi { "RAW", 16, GPIOADM_GPIO_ATTR_GET_RAW,
202*fd71220bSRobert Mustacchi gpioadm_gpio_attr_get_ofmt_cb },
203*fd71220bSRobert Mustacchi { "POSSIBLE", 24, GPIOADM_GPIO_ATTR_GET_POSSIBLE,
204*fd71220bSRobert Mustacchi gpioadm_gpio_attr_get_ofmt_cb },
205*fd71220bSRobert Mustacchi { NULL, 0, 0, NULL }
206*fd71220bSRobert Mustacchi };
207*fd71220bSRobert Mustacchi
208*fd71220bSRobert Mustacchi static int
gpioadm_gpio_attr_get(int argc,char * argv[])209*fd71220bSRobert Mustacchi gpioadm_gpio_attr_get(int argc, char *argv[])
210*fd71220bSRobert Mustacchi {
211*fd71220bSRobert Mustacchi int c, ret;
212*fd71220bSRobert Mustacchi uint_t flags = 0;
213*fd71220bSRobert Mustacchi boolean_t parse = B_FALSE;
214*fd71220bSRobert Mustacchi const char *fields = NULL, *target = NULL;
215*fd71220bSRobert Mustacchi ofmt_status_t oferr;
216*fd71220bSRobert Mustacchi ofmt_handle_t ofmt;
217*fd71220bSRobert Mustacchi xpio_ctrl_t *ctrl;
218*fd71220bSRobert Mustacchi xpio_gpio_info_t *gpio;
219*fd71220bSRobert Mustacchi bool *filts = NULL;
220*fd71220bSRobert Mustacchi
221*fd71220bSRobert Mustacchi while ((c = getopt(argc, argv, ":Ho:p")) != -1) {
222*fd71220bSRobert Mustacchi switch (c) {
223*fd71220bSRobert Mustacchi case 'H':
224*fd71220bSRobert Mustacchi flags |= OFMT_NOHEADER;
225*fd71220bSRobert Mustacchi break;
226*fd71220bSRobert Mustacchi case 'o':
227*fd71220bSRobert Mustacchi fields = optarg;
228*fd71220bSRobert Mustacchi break;
229*fd71220bSRobert Mustacchi case 'p':
230*fd71220bSRobert Mustacchi parse = B_TRUE;
231*fd71220bSRobert Mustacchi flags |= OFMT_PARSABLE;
232*fd71220bSRobert Mustacchi break;
233*fd71220bSRobert Mustacchi case ':':
234*fd71220bSRobert Mustacchi gpioadm_gpio_attr_get_help("option -%c requires an "
235*fd71220bSRobert Mustacchi "argument", optopt);
236*fd71220bSRobert Mustacchi exit(EXIT_USAGE);
237*fd71220bSRobert Mustacchi case '?':
238*fd71220bSRobert Mustacchi gpioadm_gpio_attr_get_help("unknown option: -%c",
239*fd71220bSRobert Mustacchi optopt);
240*fd71220bSRobert Mustacchi exit(EXIT_USAGE);
241*fd71220bSRobert Mustacchi }
242*fd71220bSRobert Mustacchi }
243*fd71220bSRobert Mustacchi
244*fd71220bSRobert Mustacchi if (parse && fields == NULL) {
245*fd71220bSRobert Mustacchi errx(EXIT_USAGE, "-p requires fields specified with -o");
246*fd71220bSRobert Mustacchi }
247*fd71220bSRobert Mustacchi
248*fd71220bSRobert Mustacchi if (!parse) {
249*fd71220bSRobert Mustacchi flags |= OFMT_WRAP;
250*fd71220bSRobert Mustacchi }
251*fd71220bSRobert Mustacchi
252*fd71220bSRobert Mustacchi if (fields == NULL) {
253*fd71220bSRobert Mustacchi fields = gpioadm_gpio_attr_get_fields;
254*fd71220bSRobert Mustacchi }
255*fd71220bSRobert Mustacchi
256*fd71220bSRobert Mustacchi argc -= optind;
257*fd71220bSRobert Mustacchi argv += optind;
258*fd71220bSRobert Mustacchi if (argc == 0) {
259*fd71220bSRobert Mustacchi errx(EXIT_FAILURE, "missing required controller and gpio");
260*fd71220bSRobert Mustacchi }
261*fd71220bSRobert Mustacchi target = argv[0];
262*fd71220bSRobert Mustacchi argc--;
263*fd71220bSRobert Mustacchi argv++;
264*fd71220bSRobert Mustacchi
265*fd71220bSRobert Mustacchi if (argc > 0) {
266*fd71220bSRobert Mustacchi filts = calloc(argc, sizeof (bool));
267*fd71220bSRobert Mustacchi if (filts == NULL) {
268*fd71220bSRobert Mustacchi err(EXIT_FAILURE, "failed to allocate memory for "
269*fd71220bSRobert Mustacchi "filter tracking");
270*fd71220bSRobert Mustacchi }
271*fd71220bSRobert Mustacchi }
272*fd71220bSRobert Mustacchi oferr = ofmt_open(fields, gpioadm_gpio_attr_get_ofmt, flags, 0,
273*fd71220bSRobert Mustacchi &ofmt);
274*fd71220bSRobert Mustacchi ofmt_check(oferr, parse, ofmt, gpioadm_ofmt_errx, warnx);
275*fd71220bSRobert Mustacchi
276*fd71220bSRobert Mustacchi gpioadm_ctrl_gpio_init(target, &ctrl, &gpio);
277*fd71220bSRobert Mustacchi
278*fd71220bSRobert Mustacchi for (xpio_gpio_attr_t *attr = xpio_gpio_attr_next(gpio, NULL);
279*fd71220bSRobert Mustacchi attr != NULL; attr = xpio_gpio_attr_next(gpio, attr)) {
280*fd71220bSRobert Mustacchi gpioadm_gpio_attr_get_ofmt_t ggag;
281*fd71220bSRobert Mustacchi
282*fd71220bSRobert Mustacchi if (argc > 0) {
283*fd71220bSRobert Mustacchi const char *aname = xpio_gpio_attr_name(gpio, attr);
284*fd71220bSRobert Mustacchi bool match = false;
285*fd71220bSRobert Mustacchi for (int i = 0; i < argc; i++) {
286*fd71220bSRobert Mustacchi if (strcmp(argv[i], aname) == 0) {
287*fd71220bSRobert Mustacchi match = true;
288*fd71220bSRobert Mustacchi filts[i] = true;
289*fd71220bSRobert Mustacchi }
290*fd71220bSRobert Mustacchi }
291*fd71220bSRobert Mustacchi
292*fd71220bSRobert Mustacchi if (!match) {
293*fd71220bSRobert Mustacchi continue;
294*fd71220bSRobert Mustacchi }
295*fd71220bSRobert Mustacchi }
296*fd71220bSRobert Mustacchi
297*fd71220bSRobert Mustacchi ggag.ggag_info = gpio;
298*fd71220bSRobert Mustacchi ggag.ggag_attr = attr;
299*fd71220bSRobert Mustacchi ofmt_print(ofmt, &ggag);
300*fd71220bSRobert Mustacchi }
301*fd71220bSRobert Mustacchi
302*fd71220bSRobert Mustacchi ret = EXIT_SUCCESS;
303*fd71220bSRobert Mustacchi for (int i = 0; i < argc; i++) {
304*fd71220bSRobert Mustacchi if (!filts[i]) {
305*fd71220bSRobert Mustacchi warnx("filter '%s' did not match any attributes",
306*fd71220bSRobert Mustacchi argv[i]);
307*fd71220bSRobert Mustacchi ret = EXIT_FAILURE;
308*fd71220bSRobert Mustacchi }
309*fd71220bSRobert Mustacchi }
310*fd71220bSRobert Mustacchi
311*fd71220bSRobert Mustacchi free(filts);
312*fd71220bSRobert Mustacchi return (ret);
313*fd71220bSRobert Mustacchi }
314*fd71220bSRobert Mustacchi
315*fd71220bSRobert Mustacchi static void
gpioadm_gpio_attr_set_usage(FILE * f)316*fd71220bSRobert Mustacchi gpioadm_gpio_attr_set_usage(FILE *f)
317*fd71220bSRobert Mustacchi {
318*fd71220bSRobert Mustacchi (void) fprintf(f, "\tgpioadm gpio attr set controller/gpio attr=value "
319*fd71220bSRobert Mustacchi "[attr=value...]\n");
320*fd71220bSRobert Mustacchi }
321*fd71220bSRobert Mustacchi
322*fd71220bSRobert Mustacchi static void __PRINTFLIKE(1)
gpioadm_gpio_attr_set_help(const char * fmt,...)323*fd71220bSRobert Mustacchi gpioadm_gpio_attr_set_help(const char *fmt, ...)
324*fd71220bSRobert Mustacchi {
325*fd71220bSRobert Mustacchi if (fmt != NULL) {
326*fd71220bSRobert Mustacchi va_list ap;
327*fd71220bSRobert Mustacchi
328*fd71220bSRobert Mustacchi va_start(ap, fmt);
329*fd71220bSRobert Mustacchi vwarnx(fmt, ap);
330*fd71220bSRobert Mustacchi va_end(ap);
331*fd71220bSRobert Mustacchi }
332*fd71220bSRobert Mustacchi
333*fd71220bSRobert Mustacchi (void) fprintf(stderr, "Usage: gpioadm gpio attr set controller/gpio "
334*fd71220bSRobert Mustacchi "attr=value [attr=value...]\n");
335*fd71220bSRobert Mustacchi (void) fprintf(stderr, "\nSets the attributes of a single GPIO. "
336*fd71220bSRobert Mustacchi "All specified attributes are\napplied at once.\n");
337*fd71220bSRobert Mustacchi }
338*fd71220bSRobert Mustacchi
339*fd71220bSRobert Mustacchi static int
gpioadm_gpio_attr_set(int argc,char * argv[])340*fd71220bSRobert Mustacchi gpioadm_gpio_attr_set(int argc, char *argv[])
341*fd71220bSRobert Mustacchi {
342*fd71220bSRobert Mustacchi int c;
343*fd71220bSRobert Mustacchi const char *target;
344*fd71220bSRobert Mustacchi xpio_ctrl_t *ctrl;
345*fd71220bSRobert Mustacchi xpio_gpio_info_t *gpio;
346*fd71220bSRobert Mustacchi xpio_gpio_update_t *update;
347*fd71220bSRobert Mustacchi
348*fd71220bSRobert Mustacchi while ((c = getopt(argc, argv, ":")) != -1) {
349*fd71220bSRobert Mustacchi switch (c) {
350*fd71220bSRobert Mustacchi case ':':
351*fd71220bSRobert Mustacchi gpioadm_gpio_attr_set_help("option -%c requires an "
352*fd71220bSRobert Mustacchi "argument", optopt);
353*fd71220bSRobert Mustacchi exit(EXIT_USAGE);
354*fd71220bSRobert Mustacchi case '?':
355*fd71220bSRobert Mustacchi gpioadm_gpio_attr_set_help("unknown option: -%c",
356*fd71220bSRobert Mustacchi optopt);
357*fd71220bSRobert Mustacchi exit(EXIT_USAGE);
358*fd71220bSRobert Mustacchi }
359*fd71220bSRobert Mustacchi }
360*fd71220bSRobert Mustacchi
361*fd71220bSRobert Mustacchi argc -= optind;
362*fd71220bSRobert Mustacchi argv += optind;
363*fd71220bSRobert Mustacchi
364*fd71220bSRobert Mustacchi if (argc == 0) {
365*fd71220bSRobert Mustacchi errx(EXIT_USAGE, "missing required controller/gpio target");
366*fd71220bSRobert Mustacchi }
367*fd71220bSRobert Mustacchi
368*fd71220bSRobert Mustacchi if (argc == 1) {
369*fd71220bSRobert Mustacchi errx(EXIT_USAGE, "missing required attribute settings");
370*fd71220bSRobert Mustacchi }
371*fd71220bSRobert Mustacchi
372*fd71220bSRobert Mustacchi target = argv[0];
373*fd71220bSRobert Mustacchi gpioadm_ctrl_gpio_init(target, &ctrl, &gpio);
374*fd71220bSRobert Mustacchi if (!xpio_gpio_update_init(gpioadm.gpio_xpio, gpio, &update)) {
375*fd71220bSRobert Mustacchi gpioadm_fatal("failed to initialize update");
376*fd71220bSRobert Mustacchi }
377*fd71220bSRobert Mustacchi
378*fd71220bSRobert Mustacchi for (int i = 1; i < argc; i++) {
379*fd71220bSRobert Mustacchi char *eq = strchr(argv[i], '=');
380*fd71220bSRobert Mustacchi const char *name, *value;
381*fd71220bSRobert Mustacchi xpio_gpio_attr_t *attr;
382*fd71220bSRobert Mustacchi
383*fd71220bSRobert Mustacchi if (eq == NULL) {
384*fd71220bSRobert Mustacchi errx(EXIT_FAILURE, "invalid attribute: missing equals "
385*fd71220bSRobert Mustacchi "sign for value: %s", argv[i]);
386*fd71220bSRobert Mustacchi }
387*fd71220bSRobert Mustacchi name = argv[i];
388*fd71220bSRobert Mustacchi value = eq + 1;
389*fd71220bSRobert Mustacchi *eq = '\0';
390*fd71220bSRobert Mustacchi
391*fd71220bSRobert Mustacchi attr = xpio_gpio_attr_find(gpio, name);
392*fd71220bSRobert Mustacchi if (attr == NULL) {
393*fd71220bSRobert Mustacchi errx(EXIT_FAILURE, "invalid attribute: no attribute "
394*fd71220bSRobert Mustacchi "named %s exists for GPIO %s", name, target);
395*fd71220bSRobert Mustacchi }
396*fd71220bSRobert Mustacchi
397*fd71220bSRobert Mustacchi if (!xpio_gpio_attr_from_str(update, attr, value)) {
398*fd71220bSRobert Mustacchi gpioadm_update_fatal(update, "failed to set attribute "
399*fd71220bSRobert Mustacchi "%s to %s on GPIO %s", name, value, target);
400*fd71220bSRobert Mustacchi }
401*fd71220bSRobert Mustacchi }
402*fd71220bSRobert Mustacchi
403*fd71220bSRobert Mustacchi if (!xpio_gpio_update(ctrl, update)) {
404*fd71220bSRobert Mustacchi if (xpio_err(gpioadm.gpio_xpio) != XPIO_ERR_BAD_UPDATE) {
405*fd71220bSRobert Mustacchi gpioadm_fatal("failed to update GPIO %s", target);
406*fd71220bSRobert Mustacchi }
407*fd71220bSRobert Mustacchi
408*fd71220bSRobert Mustacchi gpioadm_warn("failed to update GPIO %s", target);
409*fd71220bSRobert Mustacchi
410*fd71220bSRobert Mustacchi for (xpio_gpio_attr_err_t *err =
411*fd71220bSRobert Mustacchi xpio_gpio_attr_err_next(update, NULL); err != NULL;
412*fd71220bSRobert Mustacchi err = xpio_gpio_attr_err_next(update, err)) {
413*fd71220bSRobert Mustacchi xpio_update_err_t uerr = xpio_gpio_attr_err_err(err);
414*fd71220bSRobert Mustacchi
415*fd71220bSRobert Mustacchi (void) fprintf(stderr, "\tattribute %s -- %s (0x%x)\n",
416*fd71220bSRobert Mustacchi xpio_gpio_attr_err_name(err),
417*fd71220bSRobert Mustacchi xpio_update_err2str(update, uerr), uerr);
418*fd71220bSRobert Mustacchi }
419*fd71220bSRobert Mustacchi }
420*fd71220bSRobert Mustacchi
421*fd71220bSRobert Mustacchi return (EXIT_SUCCESS);
422*fd71220bSRobert Mustacchi }
423*fd71220bSRobert Mustacchi
424*fd71220bSRobert Mustacchi static const gpioadm_cmdtab_t gpioadm_cmds_gpio_attr[] = {
425*fd71220bSRobert Mustacchi { "get", gpioadm_gpio_attr_get, gpioadm_gpio_attr_get_usage },
426*fd71220bSRobert Mustacchi { "set", gpioadm_gpio_attr_set, gpioadm_gpio_attr_set_usage },
427*fd71220bSRobert Mustacchi { NULL, NULL, NULL }
428*fd71220bSRobert Mustacchi };
429*fd71220bSRobert Mustacchi
430*fd71220bSRobert Mustacchi static void
gpioadm_gpio_attr_usage(FILE * f)431*fd71220bSRobert Mustacchi gpioadm_gpio_attr_usage(FILE *f)
432*fd71220bSRobert Mustacchi {
433*fd71220bSRobert Mustacchi gpioadm_walk_usage(gpioadm_cmds_gpio_attr, f);
434*fd71220bSRobert Mustacchi }
435*fd71220bSRobert Mustacchi
436*fd71220bSRobert Mustacchi static int
gpioadm_gpio_attr(int argc,char * argv[])437*fd71220bSRobert Mustacchi gpioadm_gpio_attr(int argc, char *argv[])
438*fd71220bSRobert Mustacchi {
439*fd71220bSRobert Mustacchi return (gpioadm_walk_tab(gpioadm_cmds_gpio_attr, argc, argv));
440*fd71220bSRobert Mustacchi }
441*fd71220bSRobert Mustacchi
442*fd71220bSRobert Mustacchi static void
gpioadm_gpio_list_usage(FILE * f)443*fd71220bSRobert Mustacchi gpioadm_gpio_list_usage(FILE *f)
444*fd71220bSRobert Mustacchi {
445*fd71220bSRobert Mustacchi (void) fprintf(f, "\tgpioadm gpio list [-H] [-o field[,...] [-p]] "
446*fd71220bSRobert Mustacchi "[-1] [filter...]\n");
447*fd71220bSRobert Mustacchi }
448*fd71220bSRobert Mustacchi
449*fd71220bSRobert Mustacchi static void __PRINTFLIKE(1)
gpioadm_gpio_list_help(const char * fmt,...)450*fd71220bSRobert Mustacchi gpioadm_gpio_list_help(const char *fmt, ...)
451*fd71220bSRobert Mustacchi {
452*fd71220bSRobert Mustacchi if (fmt != NULL) {
453*fd71220bSRobert Mustacchi va_list ap;
454*fd71220bSRobert Mustacchi
455*fd71220bSRobert Mustacchi va_start(ap, fmt);
456*fd71220bSRobert Mustacchi vwarnx(fmt, ap);
457*fd71220bSRobert Mustacchi va_end(ap);
458*fd71220bSRobert Mustacchi }
459*fd71220bSRobert Mustacchi
460*fd71220bSRobert Mustacchi (void) fprintf(stderr, "Usage: gpioadm gpio list [-H] [-o "
461*fd71220bSRobert Mustacchi "field[,...] [-p]] [-1] [filter...]\n");
462*fd71220bSRobert Mustacchi (void) fprintf(stderr, "\nList GPIOs in the system.\n\n"
463*fd71220bSRobert Mustacchi "\t-H\t\tomit the column header\n"
464*fd71220bSRobert Mustacchi "\t-o field\toutput fields to print\n"
465*fd71220bSRobert Mustacchi "\t-p\t\tparsable output (requires -o)\n"
466*fd71220bSRobert Mustacchi "\t-1\t\terror if more than one GPIO is listed\n\n"
467*fd71220bSRobert Mustacchi "The following fields are supported:\n"
468*fd71220bSRobert Mustacchi "\tcontroller\tthe name of the controller\n"
469*fd71220bSRobert Mustacchi "\tgpio\t\tthe name of the gpio\n"
470*fd71220bSRobert Mustacchi "\tid\t\tthe GPIO's numeric id\n"
471*fd71220bSRobert Mustacchi "Filters can be used to constrain the GPIOs that are listed. If a "
472*fd71220bSRobert Mustacchi "filter is\npresent, it will be an error if it is unused. Filters "
473*fd71220bSRobert Mustacchi "can specify either an\nentire controller, a specific GPIO on a "
474*fd71220bSRobert Mustacchi "controller, or all GPIOs with a given\nname. The controller and "
475*fd71220bSRobert Mustacchi "GPIO are separated with a '/' character. For example:\n\n"
476*fd71220bSRobert Mustacchi "\tgpio_sim0\t\tThis would match all GPIOs on the controller\n"
477*fd71220bSRobert Mustacchi "\t\t\t\t'gpio_sim0'.\n"
478*fd71220bSRobert Mustacchi "\tzen_gpio0/EGPIO9_3\tThis would match the specific GPIO, "
479*fd71220bSRobert Mustacchi "EGPIO9_3,\n\t\t\t\ton the specified controller, zen_gpio0.\n"
480*fd71220bSRobert Mustacchi "\t*/gpio3\t\t\tThis would match all GPIOs named 'gpio3' on any\n"
481*fd71220bSRobert Mustacchi "\t\t\t\tcontroller.\n");
482*fd71220bSRobert Mustacchi }
483*fd71220bSRobert Mustacchi
484*fd71220bSRobert Mustacchi typedef enum gpioadm_gpio_list_otype {
485*fd71220bSRobert Mustacchi GPIOADM_GPIO_LIST_CTRL,
486*fd71220bSRobert Mustacchi GPIOADM_GPIO_LIST_NAME,
487*fd71220bSRobert Mustacchi GPIOADM_GPIO_LIST_ID
488*fd71220bSRobert Mustacchi } gpioadm_gpio_list_otype_t;
489*fd71220bSRobert Mustacchi
490*fd71220bSRobert Mustacchi typedef struct gpioadm_gpio_list_ofmt {
491*fd71220bSRobert Mustacchi const char *gglo_minor;
492*fd71220bSRobert Mustacchi const char *gglo_name;
493*fd71220bSRobert Mustacchi uint32_t gglo_id;
494*fd71220bSRobert Mustacchi uint32_t gglo_flags;
495*fd71220bSRobert Mustacchi } gpioadm_gpio_list_ofmt_t;
496*fd71220bSRobert Mustacchi
497*fd71220bSRobert Mustacchi static boolean_t
gpioadm_gpio_list_ofmt_cb(ofmt_arg_t * ofarg,char * buf,uint_t buflen)498*fd71220bSRobert Mustacchi gpioadm_gpio_list_ofmt_cb(ofmt_arg_t *ofarg, char *buf, uint_t buflen)
499*fd71220bSRobert Mustacchi {
500*fd71220bSRobert Mustacchi gpioadm_gpio_list_ofmt_t *gglo = ofarg->ofmt_cbarg;
501*fd71220bSRobert Mustacchi
502*fd71220bSRobert Mustacchi switch (ofarg->ofmt_id) {
503*fd71220bSRobert Mustacchi case GPIOADM_GPIO_LIST_CTRL:
504*fd71220bSRobert Mustacchi if (strlcpy(buf, gglo->gglo_minor, buflen) >= buflen) {
505*fd71220bSRobert Mustacchi return (B_FALSE);
506*fd71220bSRobert Mustacchi }
507*fd71220bSRobert Mustacchi break;
508*fd71220bSRobert Mustacchi case GPIOADM_GPIO_LIST_NAME:
509*fd71220bSRobert Mustacchi if (strlcpy(buf, gglo->gglo_name, buflen) >= buflen) {
510*fd71220bSRobert Mustacchi return (B_FALSE);
511*fd71220bSRobert Mustacchi }
512*fd71220bSRobert Mustacchi break;
513*fd71220bSRobert Mustacchi case GPIOADM_GPIO_LIST_ID:
514*fd71220bSRobert Mustacchi if (snprintf(buf, buflen, "%u", gglo->gglo_id) >= buflen) {
515*fd71220bSRobert Mustacchi return (B_FALSE);
516*fd71220bSRobert Mustacchi }
517*fd71220bSRobert Mustacchi break;
518*fd71220bSRobert Mustacchi default:
519*fd71220bSRobert Mustacchi abort();
520*fd71220bSRobert Mustacchi }
521*fd71220bSRobert Mustacchi return (B_TRUE);
522*fd71220bSRobert Mustacchi }
523*fd71220bSRobert Mustacchi
524*fd71220bSRobert Mustacchi static const char *gpioadm_gpio_list_fields = "controller,gpio,id";
525*fd71220bSRobert Mustacchi static const ofmt_field_t gpioadm_gpio_list_ofmt[] = {
526*fd71220bSRobert Mustacchi { "CONTROLLER", 16, GPIOADM_GPIO_LIST_CTRL,
527*fd71220bSRobert Mustacchi gpioadm_gpio_list_ofmt_cb },
528*fd71220bSRobert Mustacchi { "GPIO", 20, GPIOADM_GPIO_LIST_NAME,
529*fd71220bSRobert Mustacchi gpioadm_gpio_list_ofmt_cb },
530*fd71220bSRobert Mustacchi { "ID", 8, GPIOADM_GPIO_LIST_ID,
531*fd71220bSRobert Mustacchi gpioadm_gpio_list_ofmt_cb },
532*fd71220bSRobert Mustacchi { NULL, 0, 0, NULL }
533*fd71220bSRobert Mustacchi };
534*fd71220bSRobert Mustacchi
535*fd71220bSRobert Mustacchi typedef struct {
536*fd71220bSRobert Mustacchi bool ggl_err;
537*fd71220bSRobert Mustacchi bool ggl_one;
538*fd71220bSRobert Mustacchi uint_t ggl_nprint;
539*fd71220bSRobert Mustacchi ofmt_handle_t ggl_ofmt;
540*fd71220bSRobert Mustacchi int ggl_nfilts;
541*fd71220bSRobert Mustacchi char *const *ggl_filts;
542*fd71220bSRobert Mustacchi bool *ggl_used;
543*fd71220bSRobert Mustacchi } gpioadm_gpio_list_t;
544*fd71220bSRobert Mustacchi
545*fd71220bSRobert Mustacchi static bool
gpioadm_gpio_list_match(const char * ctrl,const char * gpio,gpioadm_gpio_list_t * ggl)546*fd71220bSRobert Mustacchi gpioadm_gpio_list_match(const char *ctrl, const char *gpio,
547*fd71220bSRobert Mustacchi gpioadm_gpio_list_t *ggl)
548*fd71220bSRobert Mustacchi {
549*fd71220bSRobert Mustacchi if (ggl->ggl_nfilts <= 0) {
550*fd71220bSRobert Mustacchi return (true);
551*fd71220bSRobert Mustacchi }
552*fd71220bSRobert Mustacchi
553*fd71220bSRobert Mustacchi for (int i = 0; i < ggl->ggl_nfilts; i++) {
554*fd71220bSRobert Mustacchi const char *filt = ggl->ggl_filts[i];
555*fd71220bSRobert Mustacchi const char *slash = strchr(filt, '/');
556*fd71220bSRobert Mustacchi bool all_ctrls;
557*fd71220bSRobert Mustacchi size_t ctrl_len;
558*fd71220bSRobert Mustacchi
559*fd71220bSRobert Mustacchi /*
560*fd71220bSRobert Mustacchi * This is just a controller filter.
561*fd71220bSRobert Mustacchi */
562*fd71220bSRobert Mustacchi if (slash == NULL) {
563*fd71220bSRobert Mustacchi if (strcmp(ctrl, filt) == 0) {
564*fd71220bSRobert Mustacchi ggl->ggl_used[i] = true;
565*fd71220bSRobert Mustacchi return (true);
566*fd71220bSRobert Mustacchi }
567*fd71220bSRobert Mustacchi }
568*fd71220bSRobert Mustacchi
569*fd71220bSRobert Mustacchi ctrl_len = (uintptr_t)slash - (uintptr_t)filt;
570*fd71220bSRobert Mustacchi if (ctrl_len == 0) {
571*fd71220bSRobert Mustacchi return (false);
572*fd71220bSRobert Mustacchi }
573*fd71220bSRobert Mustacchi
574*fd71220bSRobert Mustacchi all_ctrls = ctrl_len == 1 && filt[0] == '*';
575*fd71220bSRobert Mustacchi if (!all_ctrls && (strlen(ctrl) != ctrl_len ||
576*fd71220bSRobert Mustacchi strncmp(ctrl, filt, ctrl_len) != 0)) {
577*fd71220bSRobert Mustacchi continue;
578*fd71220bSRobert Mustacchi }
579*fd71220bSRobert Mustacchi
580*fd71220bSRobert Mustacchi if (strcmp(slash + 1, gpio) == 0) {
581*fd71220bSRobert Mustacchi ggl->ggl_used[i] = true;
582*fd71220bSRobert Mustacchi return (true);
583*fd71220bSRobert Mustacchi }
584*fd71220bSRobert Mustacchi }
585*fd71220bSRobert Mustacchi
586*fd71220bSRobert Mustacchi return (false);
587*fd71220bSRobert Mustacchi }
588*fd71220bSRobert Mustacchi
589*fd71220bSRobert Mustacchi static bool
gpioadm_gpio_list_cb(xpio_t * xpio,xpio_ctrl_disc_t * disc,void * arg)590*fd71220bSRobert Mustacchi gpioadm_gpio_list_cb(xpio_t *xpio, xpio_ctrl_disc_t *disc, void *arg)
591*fd71220bSRobert Mustacchi {
592*fd71220bSRobert Mustacchi xpio_ctrl_t *ctrl;
593*fd71220bSRobert Mustacchi xpio_ctrl_info_t *info;
594*fd71220bSRobert Mustacchi uint32_t ngpios;
595*fd71220bSRobert Mustacchi const char *mname = di_minor_name(disc->xcd_minor);
596*fd71220bSRobert Mustacchi gpioadm_gpio_list_t *ggl = arg;
597*fd71220bSRobert Mustacchi
598*fd71220bSRobert Mustacchi if (!xpio_ctrl_init(xpio, disc->xcd_minor, &ctrl)) {
599*fd71220bSRobert Mustacchi gpioadm_warn("failed to initialize controller %s", mname);
600*fd71220bSRobert Mustacchi ggl->ggl_err = true;
601*fd71220bSRobert Mustacchi return (true);
602*fd71220bSRobert Mustacchi }
603*fd71220bSRobert Mustacchi
604*fd71220bSRobert Mustacchi if (!xpio_ctrl_info(ctrl, &info)) {
605*fd71220bSRobert Mustacchi gpioadm_warn("failed to get controller info for %s", mname);
606*fd71220bSRobert Mustacchi xpio_ctrl_fini(ctrl);
607*fd71220bSRobert Mustacchi ggl->ggl_err = true;
608*fd71220bSRobert Mustacchi return (true);
609*fd71220bSRobert Mustacchi }
610*fd71220bSRobert Mustacchi
611*fd71220bSRobert Mustacchi ngpios = xpio_ctrl_info_ngpios(info);
612*fd71220bSRobert Mustacchi for (uint32_t i = 0; i < ngpios; i++) {
613*fd71220bSRobert Mustacchi gpioadm_gpio_list_ofmt_t list;
614*fd71220bSRobert Mustacchi xpio_gpio_info_t *gpio_info;
615*fd71220bSRobert Mustacchi xpio_gpio_attr_t *attr;
616*fd71220bSRobert Mustacchi
617*fd71220bSRobert Mustacchi if (!xpio_gpio_info(ctrl, i, &gpio_info)) {
618*fd71220bSRobert Mustacchi ggl->ggl_err = true;
619*fd71220bSRobert Mustacchi gpioadm_warn("failed to get gpio info for %s:%u",
620*fd71220bSRobert Mustacchi mname, i);
621*fd71220bSRobert Mustacchi continue;
622*fd71220bSRobert Mustacchi }
623*fd71220bSRobert Mustacchi
624*fd71220bSRobert Mustacchi attr = xpio_gpio_attr_find(gpio_info, KGPIO_ATTR_NAME);
625*fd71220bSRobert Mustacchi if (attr == NULL || !xpio_gpio_attr_value_string(attr,
626*fd71220bSRobert Mustacchi &list.gglo_name)) {
627*fd71220bSRobert Mustacchi warnx("GPIO %s/%u missing name attribute",
628*fd71220bSRobert Mustacchi mname, i);
629*fd71220bSRobert Mustacchi goto skip;
630*fd71220bSRobert Mustacchi }
631*fd71220bSRobert Mustacchi list.gglo_minor = mname;
632*fd71220bSRobert Mustacchi list.gglo_id = i;
633*fd71220bSRobert Mustacchi list.gglo_flags = 0;
634*fd71220bSRobert Mustacchi
635*fd71220bSRobert Mustacchi if (!gpioadm_gpio_list_match(mname, list.gglo_name, ggl)) {
636*fd71220bSRobert Mustacchi goto skip;
637*fd71220bSRobert Mustacchi }
638*fd71220bSRobert Mustacchi
639*fd71220bSRobert Mustacchi ggl->ggl_nprint++;
640*fd71220bSRobert Mustacchi ofmt_print(ggl->ggl_ofmt, &list);
641*fd71220bSRobert Mustacchi
642*fd71220bSRobert Mustacchi skip:
643*fd71220bSRobert Mustacchi xpio_gpio_info_free(gpio_info);
644*fd71220bSRobert Mustacchi }
645*fd71220bSRobert Mustacchi
646*fd71220bSRobert Mustacchi xpio_ctrl_fini(ctrl);
647*fd71220bSRobert Mustacchi return (true);
648*fd71220bSRobert Mustacchi }
649*fd71220bSRobert Mustacchi
650*fd71220bSRobert Mustacchi static int
gpioadm_gpio_list(int argc,char * argv[])651*fd71220bSRobert Mustacchi gpioadm_gpio_list(int argc, char *argv[])
652*fd71220bSRobert Mustacchi {
653*fd71220bSRobert Mustacchi int c;
654*fd71220bSRobert Mustacchi uint_t flags = 0;
655*fd71220bSRobert Mustacchi boolean_t parse = B_FALSE;
656*fd71220bSRobert Mustacchi const char *fields = NULL;
657*fd71220bSRobert Mustacchi ofmt_status_t oferr;
658*fd71220bSRobert Mustacchi ofmt_handle_t ofmt;
659*fd71220bSRobert Mustacchi gpioadm_gpio_list_t ggl;
660*fd71220bSRobert Mustacchi
661*fd71220bSRobert Mustacchi (void) memset(&ggl, 0, sizeof (ggl));
662*fd71220bSRobert Mustacchi while ((c = getopt(argc, argv, ":Ho:p1")) != -1) {
663*fd71220bSRobert Mustacchi switch (c) {
664*fd71220bSRobert Mustacchi case 'H':
665*fd71220bSRobert Mustacchi flags |= OFMT_NOHEADER;
666*fd71220bSRobert Mustacchi break;
667*fd71220bSRobert Mustacchi case 'o':
668*fd71220bSRobert Mustacchi fields = optarg;
669*fd71220bSRobert Mustacchi break;
670*fd71220bSRobert Mustacchi case 'p':
671*fd71220bSRobert Mustacchi parse = B_TRUE;
672*fd71220bSRobert Mustacchi flags |= OFMT_PARSABLE;
673*fd71220bSRobert Mustacchi break;
674*fd71220bSRobert Mustacchi case '1':
675*fd71220bSRobert Mustacchi ggl.ggl_one = true;
676*fd71220bSRobert Mustacchi break;
677*fd71220bSRobert Mustacchi case ':':
678*fd71220bSRobert Mustacchi gpioadm_gpio_list_help("option -%c requires an "
679*fd71220bSRobert Mustacchi "argument", optopt);
680*fd71220bSRobert Mustacchi exit(EXIT_USAGE);
681*fd71220bSRobert Mustacchi case '?':
682*fd71220bSRobert Mustacchi gpioadm_gpio_list_help("unknown option: -%c", optopt);
683*fd71220bSRobert Mustacchi exit(EXIT_USAGE);
684*fd71220bSRobert Mustacchi }
685*fd71220bSRobert Mustacchi }
686*fd71220bSRobert Mustacchi
687*fd71220bSRobert Mustacchi if (parse && fields == NULL) {
688*fd71220bSRobert Mustacchi errx(EXIT_USAGE, "-p requires fields specified with -o");
689*fd71220bSRobert Mustacchi }
690*fd71220bSRobert Mustacchi
691*fd71220bSRobert Mustacchi if (fields == NULL) {
692*fd71220bSRobert Mustacchi fields = gpioadm_gpio_list_fields;
693*fd71220bSRobert Mustacchi }
694*fd71220bSRobert Mustacchi
695*fd71220bSRobert Mustacchi argc -= optind;
696*fd71220bSRobert Mustacchi argv += optind;
697*fd71220bSRobert Mustacchi if (argc > 0) {
698*fd71220bSRobert Mustacchi ggl.ggl_nfilts = argc;
699*fd71220bSRobert Mustacchi ggl.ggl_filts = argv;
700*fd71220bSRobert Mustacchi ggl.ggl_used = calloc(argc, sizeof (bool));
701*fd71220bSRobert Mustacchi if (ggl.ggl_used == NULL) {
702*fd71220bSRobert Mustacchi err(EXIT_FAILURE, "failed to allocate memory for "
703*fd71220bSRobert Mustacchi "filter tracking");
704*fd71220bSRobert Mustacchi }
705*fd71220bSRobert Mustacchi }
706*fd71220bSRobert Mustacchi oferr = ofmt_open(fields, gpioadm_gpio_list_ofmt, flags, 0, &ofmt);
707*fd71220bSRobert Mustacchi ofmt_check(oferr, parse, ofmt, gpioadm_ofmt_errx, warnx);
708*fd71220bSRobert Mustacchi
709*fd71220bSRobert Mustacchi ggl.ggl_err = false;
710*fd71220bSRobert Mustacchi ggl.ggl_ofmt = ofmt;
711*fd71220bSRobert Mustacchi xpio_ctrl_discover(gpioadm.gpio_xpio, gpioadm_gpio_list_cb, &ggl);
712*fd71220bSRobert Mustacchi
713*fd71220bSRobert Mustacchi for (int i = 0; i < ggl.ggl_nfilts; i++) {
714*fd71220bSRobert Mustacchi if (!ggl.ggl_used[i]) {
715*fd71220bSRobert Mustacchi warnx("filter '%s' did not match any GPIOs",
716*fd71220bSRobert Mustacchi ggl.ggl_filts[i]);
717*fd71220bSRobert Mustacchi ggl.ggl_err = true;
718*fd71220bSRobert Mustacchi }
719*fd71220bSRobert Mustacchi }
720*fd71220bSRobert Mustacchi
721*fd71220bSRobert Mustacchi if (ggl.ggl_one && ggl.ggl_nprint > 1) {
722*fd71220bSRobert Mustacchi warnx("-1 specified, but %u GPIOs printed", ggl.ggl_nprint);
723*fd71220bSRobert Mustacchi ggl.ggl_err = true;
724*fd71220bSRobert Mustacchi }
725*fd71220bSRobert Mustacchi
726*fd71220bSRobert Mustacchi if (ggl.ggl_nprint == 0) {
727*fd71220bSRobert Mustacchi if (ggl.ggl_nfilts == 0) {
728*fd71220bSRobert Mustacchi warnx("no GPIOs found");
729*fd71220bSRobert Mustacchi }
730*fd71220bSRobert Mustacchi ggl.ggl_err = true;
731*fd71220bSRobert Mustacchi }
732*fd71220bSRobert Mustacchi
733*fd71220bSRobert Mustacchi return (ggl.ggl_err ? EXIT_FAILURE : EXIT_SUCCESS);
734*fd71220bSRobert Mustacchi }
735*fd71220bSRobert Mustacchi
736*fd71220bSRobert Mustacchi static const gpioadm_cmdtab_t gpioadm_cmds_gpio[] = {
737*fd71220bSRobert Mustacchi { "attr", gpioadm_gpio_attr, gpioadm_gpio_attr_usage },
738*fd71220bSRobert Mustacchi { "list", gpioadm_gpio_list, gpioadm_gpio_list_usage },
739*fd71220bSRobert Mustacchi { NULL, NULL, NULL }
740*fd71220bSRobert Mustacchi };
741*fd71220bSRobert Mustacchi
742*fd71220bSRobert Mustacchi int
gpioadm_gpio(int argc,char * argv[])743*fd71220bSRobert Mustacchi gpioadm_gpio(int argc, char *argv[])
744*fd71220bSRobert Mustacchi {
745*fd71220bSRobert Mustacchi return (gpioadm_walk_tab(gpioadm_cmds_gpio, argc, argv));
746*fd71220bSRobert Mustacchi }
747*fd71220bSRobert Mustacchi
748*fd71220bSRobert Mustacchi void
gpioadm_gpio_usage(FILE * f)749*fd71220bSRobert Mustacchi gpioadm_gpio_usage(FILE *f)
750*fd71220bSRobert Mustacchi {
751*fd71220bSRobert Mustacchi gpioadm_walk_usage(gpioadm_cmds_gpio, f);
752*fd71220bSRobert Mustacchi }
753