1*26947304SEvan Yan /*
2*26947304SEvan Yan * CDDL HEADER START
3*26947304SEvan Yan *
4*26947304SEvan Yan * The contents of this file are subject to the terms of the
5*26947304SEvan Yan * Common Development and Distribution License (the "License").
6*26947304SEvan Yan * You may not use this file except in compliance with the License.
7*26947304SEvan Yan *
8*26947304SEvan Yan * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*26947304SEvan Yan * or http://www.opensolaris.org/os/licensing.
10*26947304SEvan Yan * See the License for the specific language governing permissions
11*26947304SEvan Yan * and limitations under the License.
12*26947304SEvan Yan *
13*26947304SEvan Yan * When distributing Covered Code, include this CDDL HEADER in each
14*26947304SEvan Yan * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*26947304SEvan Yan * If applicable, add the following below this CDDL HEADER, with the
16*26947304SEvan Yan * fields enclosed by brackets "[]" replaced with your own identifying
17*26947304SEvan Yan * information: Portions Copyright [yyyy] [name of copyright owner]
18*26947304SEvan Yan *
19*26947304SEvan Yan * CDDL HEADER END
20*26947304SEvan Yan */
21*26947304SEvan Yan /*
22*26947304SEvan Yan * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23*26947304SEvan Yan * Use is subject to license terms.
24*26947304SEvan Yan */
25*26947304SEvan Yan
26*26947304SEvan Yan #include <stdio.h>
27*26947304SEvan Yan #include <stdlib.h>
28*26947304SEvan Yan #include <string.h>
29*26947304SEvan Yan #include <locale.h>
30*26947304SEvan Yan #include <libintl.h>
31*26947304SEvan Yan #include <alloca.h>
32*26947304SEvan Yan #include <getopt.h>
33*26947304SEvan Yan #include <libhotplug.h>
34*26947304SEvan Yan #include <sys/types.h>
35*26947304SEvan Yan #include <sys/sunddi.h>
36*26947304SEvan Yan #include <sys/ddi_hp.h>
37*26947304SEvan Yan
38*26947304SEvan Yan #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */
39*26947304SEvan Yan #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
40*26947304SEvan Yan #endif
41*26947304SEvan Yan
42*26947304SEvan Yan /*
43*26947304SEvan Yan * Function prototypes.
44*26947304SEvan Yan */
45*26947304SEvan Yan static int cmd_list(int, char **, const char *);
46*26947304SEvan Yan static int cmd_online(int, char **, const char *);
47*26947304SEvan Yan static int cmd_offline(int, char **, const char *);
48*26947304SEvan Yan static int cmd_enable(int, char **, const char *);
49*26947304SEvan Yan static int cmd_disable(int, char **, const char *);
50*26947304SEvan Yan static int cmd_poweron(int, char **, const char *);
51*26947304SEvan Yan static int cmd_poweroff(int, char **, const char *);
52*26947304SEvan Yan static int cmd_getpriv(int, char **, const char *);
53*26947304SEvan Yan static int cmd_setpriv(int, char **, const char *);
54*26947304SEvan Yan static int cmd_changestate(int, char **, const char *);
55*26947304SEvan Yan static void parse_common(int, char **, const char *);
56*26947304SEvan Yan static void parse_flags(int, char **, int *, const char *);
57*26947304SEvan Yan static void parse_target(int, char **, char **, char **, const char *);
58*26947304SEvan Yan static void parse_options(int, char **, char **, const char *);
59*26947304SEvan Yan static void bad_option(int, int, const char *);
60*26947304SEvan Yan static void usage(const char *);
61*26947304SEvan Yan static int list_cb(hp_node_t, void *);
62*26947304SEvan Yan static int list_long_cb(hp_node_t, void *);
63*26947304SEvan Yan static int error_cb(hp_node_t, void *);
64*26947304SEvan Yan static void print_options(const char *);
65*26947304SEvan Yan static void print_error(int);
66*26947304SEvan Yan static int state_atoi(char *);
67*26947304SEvan Yan static char *state_itoa(int);
68*26947304SEvan Yan static short valid_target(int);
69*26947304SEvan Yan
70*26947304SEvan Yan /*
71*26947304SEvan Yan * Define a conversion table for hotplug states.
72*26947304SEvan Yan */
73*26947304SEvan Yan typedef struct {
74*26947304SEvan Yan int state;
75*26947304SEvan Yan char *state_str;
76*26947304SEvan Yan short valid_target;
77*26947304SEvan Yan } hpstate_t;
78*26947304SEvan Yan
79*26947304SEvan Yan static hpstate_t hpstates[] = {
80*26947304SEvan Yan { DDI_HP_CN_STATE_EMPTY, "EMPTY", 0 },
81*26947304SEvan Yan { DDI_HP_CN_STATE_PRESENT, "PRESENT", 1 },
82*26947304SEvan Yan { DDI_HP_CN_STATE_POWERED, "POWERED", 1 },
83*26947304SEvan Yan { DDI_HP_CN_STATE_ENABLED, "ENABLED", 1 },
84*26947304SEvan Yan { DDI_HP_CN_STATE_PORT_EMPTY, "PORT-EMPTY", 0 },
85*26947304SEvan Yan { DDI_HP_CN_STATE_PORT_PRESENT, "PORT-PRESENT", 1 },
86*26947304SEvan Yan { DDI_HP_CN_STATE_OFFLINE, "OFFLINE", 1 },
87*26947304SEvan Yan { DDI_HP_CN_STATE_ATTACHED, "ATTACHED", 0 },
88*26947304SEvan Yan { DDI_HP_CN_STATE_MAINTENANCE, "MAINTENANCE", 0 },
89*26947304SEvan Yan { DDI_HP_CN_STATE_ONLINE, "ONLINE", 1 },
90*26947304SEvan Yan { 0, 0, 0 }
91*26947304SEvan Yan };
92*26947304SEvan Yan
93*26947304SEvan Yan /*
94*26947304SEvan Yan * Define tables of supported subcommands.
95*26947304SEvan Yan */
96*26947304SEvan Yan typedef struct {
97*26947304SEvan Yan char *usage_str;
98*26947304SEvan Yan char *cmd_str;
99*26947304SEvan Yan int (*func)(int argc, char *argv[], const char *usage_str);
100*26947304SEvan Yan } subcmd_t;
101*26947304SEvan Yan
102*26947304SEvan Yan static subcmd_t subcmds[] = {
103*26947304SEvan Yan { "list [-l] [-v] [<path> [<connection>]]", "list", cmd_list },
104*26947304SEvan Yan { "online <path> <port>", "online", cmd_online },
105*26947304SEvan Yan { "offline [-f] [-q] <path> <port>", "offline", cmd_offline },
106*26947304SEvan Yan { "enable <path> <connector>", "enable", cmd_enable },
107*26947304SEvan Yan { "disable [-f] [-q] <path> <connector>", "disable", cmd_disable },
108*26947304SEvan Yan { "poweron <path> <connector>", "poweron", cmd_poweron },
109*26947304SEvan Yan { "poweroff [-f] [-q] <path> <connector>", "poweroff", cmd_poweroff },
110*26947304SEvan Yan { "get -o <options> <path> <connector>", "get", cmd_getpriv },
111*26947304SEvan Yan { "set -o <options> <path> <connector>", "set", cmd_setpriv }
112*26947304SEvan Yan };
113*26947304SEvan Yan
114*26947304SEvan Yan static subcmd_t hidden_subcmds[] = {
115*26947304SEvan Yan { "changestate [-f] [-q] -s <state> <path> <connection>",
116*26947304SEvan Yan "changestate", cmd_changestate }
117*26947304SEvan Yan };
118*26947304SEvan Yan
119*26947304SEvan Yan /*
120*26947304SEvan Yan * Define tables of command line options.
121*26947304SEvan Yan */
122*26947304SEvan Yan static const struct option common_opts[] = {
123*26947304SEvan Yan { "help", no_argument, 0, '?' },
124*26947304SEvan Yan { "version", no_argument, 0, 'V' },
125*26947304SEvan Yan { 0, 0, 0, 0 }
126*26947304SEvan Yan };
127*26947304SEvan Yan
128*26947304SEvan Yan static const struct option list_opts[] = {
129*26947304SEvan Yan { "list-path", no_argument, 0, 'l' },
130*26947304SEvan Yan { "verbose", no_argument, 0, 'v' },
131*26947304SEvan Yan { 0, 0, 0, 0 }
132*26947304SEvan Yan };
133*26947304SEvan Yan
134*26947304SEvan Yan static const struct option flag_opts[] = {
135*26947304SEvan Yan { "force", no_argument, 0, 'f' },
136*26947304SEvan Yan { "query", no_argument, 0, 'q' },
137*26947304SEvan Yan { 0, 0, 0, 0 }
138*26947304SEvan Yan };
139*26947304SEvan Yan
140*26947304SEvan Yan static const struct option private_opts[] = {
141*26947304SEvan Yan { "options", required_argument, 0, 'o' },
142*26947304SEvan Yan { 0, 0, 0, 0 }
143*26947304SEvan Yan };
144*26947304SEvan Yan
145*26947304SEvan Yan static const struct option changestate_opts[] = {
146*26947304SEvan Yan { "force", no_argument, 0, 'f' },
147*26947304SEvan Yan { "query", no_argument, 0, 'q' },
148*26947304SEvan Yan { "state", required_argument, 0, 's' },
149*26947304SEvan Yan { 0, 0, 0, 0 }
150*26947304SEvan Yan };
151*26947304SEvan Yan
152*26947304SEvan Yan /*
153*26947304SEvan Yan * Define exit codes.
154*26947304SEvan Yan */
155*26947304SEvan Yan #define EXIT_OK 0
156*26947304SEvan Yan #define EXIT_EINVAL 1 /* invalid arguments */
157*26947304SEvan Yan #define EXIT_ENOENT 2 /* path or connection doesn't exist */
158*26947304SEvan Yan #define EXIT_FAILED 3 /* operation failed */
159*26947304SEvan Yan #define EXIT_UNAVAIL 4 /* service not available */
160*26947304SEvan Yan
161*26947304SEvan Yan /*
162*26947304SEvan Yan * Global variables.
163*26947304SEvan Yan */
164*26947304SEvan Yan static char *prog;
165*26947304SEvan Yan static char version[] = "1.0";
166*26947304SEvan Yan extern int errno;
167*26947304SEvan Yan
168*26947304SEvan Yan /*
169*26947304SEvan Yan * main()
170*26947304SEvan Yan *
171*26947304SEvan Yan * The main routine determines which subcommand is used,
172*26947304SEvan Yan * and dispatches control to the corresponding function.
173*26947304SEvan Yan */
174*26947304SEvan Yan int
main(int argc,char * argv[])175*26947304SEvan Yan main(int argc, char *argv[])
176*26947304SEvan Yan {
177*26947304SEvan Yan int i, rv;
178*26947304SEvan Yan
179*26947304SEvan Yan (void) setlocale(LC_ALL, "");
180*26947304SEvan Yan (void) textdomain(TEXT_DOMAIN);
181*26947304SEvan Yan
182*26947304SEvan Yan if ((prog = strrchr(argv[0], '/')) == NULL)
183*26947304SEvan Yan prog = argv[0];
184*26947304SEvan Yan else
185*26947304SEvan Yan prog++;
186*26947304SEvan Yan
187*26947304SEvan Yan if (argc < 2) {
188*26947304SEvan Yan usage(NULL);
189*26947304SEvan Yan return (EXIT_EINVAL);
190*26947304SEvan Yan }
191*26947304SEvan Yan
192*26947304SEvan Yan parse_common(argc, argv, NULL);
193*26947304SEvan Yan
194*26947304SEvan Yan /* Check the list of defined subcommands. */
195*26947304SEvan Yan for (i = 0; i < (sizeof (subcmds) / sizeof (subcmd_t)); i++) {
196*26947304SEvan Yan if (strcmp(argv[1], subcmds[i].cmd_str) == 0) {
197*26947304SEvan Yan rv = subcmds[i].func(argc - 1, &argv[1],
198*26947304SEvan Yan subcmds[i].usage_str);
199*26947304SEvan Yan goto finished;
200*26947304SEvan Yan }
201*26947304SEvan Yan }
202*26947304SEvan Yan
203*26947304SEvan Yan /* Check the list of hidden subcommands. */
204*26947304SEvan Yan for (i = 0; i < (sizeof (hidden_subcmds) / sizeof (subcmd_t)); i++) {
205*26947304SEvan Yan if (strcmp(argv[1], hidden_subcmds[i].cmd_str) == 0) {
206*26947304SEvan Yan rv = hidden_subcmds[i].func(argc - 1, &argv[1],
207*26947304SEvan Yan hidden_subcmds[i].usage_str);
208*26947304SEvan Yan goto finished;
209*26947304SEvan Yan }
210*26947304SEvan Yan }
211*26947304SEvan Yan
212*26947304SEvan Yan /* No matching subcommand found. */
213*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: %s: unknown subcommand '%s'\n"),
214*26947304SEvan Yan prog, argv[1]);
215*26947304SEvan Yan usage(NULL);
216*26947304SEvan Yan exit(EXIT_EINVAL);
217*26947304SEvan Yan
218*26947304SEvan Yan finished:
219*26947304SEvan Yan /* Determine exit code */
220*26947304SEvan Yan switch (rv) {
221*26947304SEvan Yan case 0:
222*26947304SEvan Yan break;
223*26947304SEvan Yan case EINVAL:
224*26947304SEvan Yan return (EXIT_EINVAL);
225*26947304SEvan Yan case ENXIO:
226*26947304SEvan Yan case ENOENT:
227*26947304SEvan Yan return (EXIT_ENOENT);
228*26947304SEvan Yan case EBADF:
229*26947304SEvan Yan return (EXIT_UNAVAIL);
230*26947304SEvan Yan default:
231*26947304SEvan Yan return (EXIT_FAILED);
232*26947304SEvan Yan }
233*26947304SEvan Yan
234*26947304SEvan Yan return (EXIT_OK);
235*26947304SEvan Yan }
236*26947304SEvan Yan
237*26947304SEvan Yan /*
238*26947304SEvan Yan * cmd_list()
239*26947304SEvan Yan *
240*26947304SEvan Yan * Subcommand to list hotplug information.
241*26947304SEvan Yan */
242*26947304SEvan Yan static int
cmd_list(int argc,char * argv[],const char * usage_str)243*26947304SEvan Yan cmd_list(int argc, char *argv[], const char *usage_str)
244*26947304SEvan Yan {
245*26947304SEvan Yan hp_node_t root;
246*26947304SEvan Yan char *path = NULL;
247*26947304SEvan Yan char *connection = NULL;
248*26947304SEvan Yan boolean_t long_flag = B_FALSE;
249*26947304SEvan Yan int flags = 0;
250*26947304SEvan Yan int opt;
251*26947304SEvan Yan
252*26947304SEvan Yan /* Parse command line options */
253*26947304SEvan Yan parse_common(argc, argv, usage_str);
254*26947304SEvan Yan while ((opt = getopt_clip(argc, argv, "lv", list_opts, NULL)) != -1) {
255*26947304SEvan Yan switch (opt) {
256*26947304SEvan Yan case 'l':
257*26947304SEvan Yan long_flag = B_TRUE;
258*26947304SEvan Yan break;
259*26947304SEvan Yan case 'v':
260*26947304SEvan Yan flags |= HPINFOUSAGE;
261*26947304SEvan Yan break;
262*26947304SEvan Yan default:
263*26947304SEvan Yan bad_option(opt, optopt, usage_str);
264*26947304SEvan Yan break;
265*26947304SEvan Yan }
266*26947304SEvan Yan }
267*26947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str);
268*26947304SEvan Yan
269*26947304SEvan Yan /* Default path is "/" */
270*26947304SEvan Yan if (path == NULL)
271*26947304SEvan Yan path = "/";
272*26947304SEvan Yan
273*26947304SEvan Yan /* Get hotplug information snapshot */
274*26947304SEvan Yan if ((root = hp_init(path, connection, flags)) == NULL) {
275*26947304SEvan Yan print_error(errno);
276*26947304SEvan Yan return (errno);
277*26947304SEvan Yan }
278*26947304SEvan Yan
279*26947304SEvan Yan /* Display hotplug information */
280*26947304SEvan Yan (void) hp_traverse(root, NULL, long_flag ? list_long_cb : list_cb);
281*26947304SEvan Yan
282*26947304SEvan Yan /* Discard hotplug information snapshot */
283*26947304SEvan Yan hp_fini(root);
284*26947304SEvan Yan
285*26947304SEvan Yan return (0);
286*26947304SEvan Yan }
287*26947304SEvan Yan
288*26947304SEvan Yan /*
289*26947304SEvan Yan * cmd_online()
290*26947304SEvan Yan *
291*26947304SEvan Yan * Subcommand to online a hotplug port.
292*26947304SEvan Yan */
293*26947304SEvan Yan static int
cmd_online(int argc,char * argv[],const char * usage_str)294*26947304SEvan Yan cmd_online(int argc, char *argv[], const char *usage_str)
295*26947304SEvan Yan {
296*26947304SEvan Yan hp_node_t root;
297*26947304SEvan Yan hp_node_t results = NULL;
298*26947304SEvan Yan char *path = NULL;
299*26947304SEvan Yan char *connection = NULL;
300*26947304SEvan Yan int rv;
301*26947304SEvan Yan
302*26947304SEvan Yan /* Parse command line options */
303*26947304SEvan Yan parse_common(argc, argv, usage_str);
304*26947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str);
305*26947304SEvan Yan
306*26947304SEvan Yan /* Path and connection are required */
307*26947304SEvan Yan if ((path == NULL) || (connection == NULL)) {
308*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
309*26947304SEvan Yan usage(usage_str);
310*26947304SEvan Yan return (EINVAL);
311*26947304SEvan Yan }
312*26947304SEvan Yan
313*26947304SEvan Yan /* Get hotplug information snapshot */
314*26947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) {
315*26947304SEvan Yan print_error(errno);
316*26947304SEvan Yan return (errno);
317*26947304SEvan Yan }
318*26947304SEvan Yan
319*26947304SEvan Yan /* Verify target is a port */
320*26947304SEvan Yan if (hp_type(root) != HP_NODE_PORT) {
321*26947304SEvan Yan (void) fprintf(stderr,
322*26947304SEvan Yan gettext("ERROR: invalid target (must be a port).\n"));
323*26947304SEvan Yan hp_fini(root);
324*26947304SEvan Yan return (EINVAL);
325*26947304SEvan Yan }
326*26947304SEvan Yan
327*26947304SEvan Yan /* Do state change */
328*26947304SEvan Yan rv = hp_set_state(root, 0, DDI_HP_CN_STATE_ONLINE, &results);
329*26947304SEvan Yan
330*26947304SEvan Yan /* Display results */
331*26947304SEvan Yan if (rv == EIO) {
332*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: failed to attach device "
333*26947304SEvan Yan "drivers or other internal errors.\n"));
334*26947304SEvan Yan } else if (rv != 0) {
335*26947304SEvan Yan print_error(rv);
336*26947304SEvan Yan }
337*26947304SEvan Yan if (results != NULL) {
338*26947304SEvan Yan (void) hp_traverse(results, NULL, error_cb);
339*26947304SEvan Yan hp_fini(results);
340*26947304SEvan Yan }
341*26947304SEvan Yan
342*26947304SEvan Yan /* Discard hotplug information snapshot */
343*26947304SEvan Yan hp_fini(root);
344*26947304SEvan Yan
345*26947304SEvan Yan return (rv);
346*26947304SEvan Yan }
347*26947304SEvan Yan
348*26947304SEvan Yan /*
349*26947304SEvan Yan * cmd_offline()
350*26947304SEvan Yan *
351*26947304SEvan Yan * Subcommand to offline a hotplug port.
352*26947304SEvan Yan */
353*26947304SEvan Yan static int
cmd_offline(int argc,char * argv[],const char * usage_str)354*26947304SEvan Yan cmd_offline(int argc, char *argv[], const char *usage_str)
355*26947304SEvan Yan {
356*26947304SEvan Yan hp_node_t root;
357*26947304SEvan Yan hp_node_t results = NULL;
358*26947304SEvan Yan char *path = NULL;
359*26947304SEvan Yan char *connection = NULL;
360*26947304SEvan Yan int flags = 0;
361*26947304SEvan Yan int rv;
362*26947304SEvan Yan
363*26947304SEvan Yan /* Parse command line options */
364*26947304SEvan Yan parse_common(argc, argv, usage_str);
365*26947304SEvan Yan parse_flags(argc, argv, &flags, usage_str);
366*26947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str);
367*26947304SEvan Yan
368*26947304SEvan Yan /* Path and connection are required */
369*26947304SEvan Yan if ((path == NULL) || (connection == NULL)) {
370*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
371*26947304SEvan Yan usage(usage_str);
372*26947304SEvan Yan return (EINVAL);
373*26947304SEvan Yan }
374*26947304SEvan Yan
375*26947304SEvan Yan /* Get hotplug information snapshot */
376*26947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) {
377*26947304SEvan Yan print_error(errno);
378*26947304SEvan Yan return (errno);
379*26947304SEvan Yan }
380*26947304SEvan Yan
381*26947304SEvan Yan /* Verify target is a port */
382*26947304SEvan Yan if (hp_type(root) != HP_NODE_PORT) {
383*26947304SEvan Yan (void) fprintf(stderr,
384*26947304SEvan Yan gettext("ERROR: invalid target (must be a port).\n"));
385*26947304SEvan Yan hp_fini(root);
386*26947304SEvan Yan return (EINVAL);
387*26947304SEvan Yan }
388*26947304SEvan Yan
389*26947304SEvan Yan /* Do state change */
390*26947304SEvan Yan rv = hp_set_state(root, flags, DDI_HP_CN_STATE_OFFLINE, &results);
391*26947304SEvan Yan
392*26947304SEvan Yan /* Display results */
393*26947304SEvan Yan print_error(rv);
394*26947304SEvan Yan if (results != NULL) {
395*26947304SEvan Yan (void) hp_traverse(results, NULL, error_cb);
396*26947304SEvan Yan hp_fini(results);
397*26947304SEvan Yan }
398*26947304SEvan Yan
399*26947304SEvan Yan /* Discard hotplug information snapshot */
400*26947304SEvan Yan hp_fini(root);
401*26947304SEvan Yan
402*26947304SEvan Yan return (rv);
403*26947304SEvan Yan }
404*26947304SEvan Yan
405*26947304SEvan Yan /*
406*26947304SEvan Yan * cmd_enable()
407*26947304SEvan Yan *
408*26947304SEvan Yan * Subcommand to enable a hotplug connector.
409*26947304SEvan Yan */
410*26947304SEvan Yan static int
cmd_enable(int argc,char * argv[],const char * usage_str)411*26947304SEvan Yan cmd_enable(int argc, char *argv[], const char *usage_str)
412*26947304SEvan Yan {
413*26947304SEvan Yan hp_node_t root;
414*26947304SEvan Yan hp_node_t results = NULL;
415*26947304SEvan Yan char *path = NULL;
416*26947304SEvan Yan char *connection = NULL;
417*26947304SEvan Yan int rv;
418*26947304SEvan Yan
419*26947304SEvan Yan /* Parse command line options */
420*26947304SEvan Yan parse_common(argc, argv, usage_str);
421*26947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str);
422*26947304SEvan Yan
423*26947304SEvan Yan /* Path and connection are required */
424*26947304SEvan Yan if ((path == NULL) || (connection == NULL)) {
425*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
426*26947304SEvan Yan usage(usage_str);
427*26947304SEvan Yan return (EINVAL);
428*26947304SEvan Yan }
429*26947304SEvan Yan
430*26947304SEvan Yan /* Get hotplug information snapshot */
431*26947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) {
432*26947304SEvan Yan print_error(errno);
433*26947304SEvan Yan return (errno);
434*26947304SEvan Yan }
435*26947304SEvan Yan
436*26947304SEvan Yan /* Verify target is a connector */
437*26947304SEvan Yan if (hp_type(root) != HP_NODE_CONNECTOR) {
438*26947304SEvan Yan (void) fprintf(stderr,
439*26947304SEvan Yan gettext("ERROR: invalid target (must be a connector).\n"));
440*26947304SEvan Yan hp_fini(root);
441*26947304SEvan Yan return (EINVAL);
442*26947304SEvan Yan }
443*26947304SEvan Yan
444*26947304SEvan Yan /* Do state change */
445*26947304SEvan Yan rv = hp_set_state(root, 0, DDI_HP_CN_STATE_ENABLED, &results);
446*26947304SEvan Yan
447*26947304SEvan Yan /* Display results */
448*26947304SEvan Yan print_error(rv);
449*26947304SEvan Yan if (results != NULL) {
450*26947304SEvan Yan (void) hp_traverse(results, NULL, error_cb);
451*26947304SEvan Yan hp_fini(results);
452*26947304SEvan Yan }
453*26947304SEvan Yan
454*26947304SEvan Yan /* Discard hotplug information snapshot */
455*26947304SEvan Yan hp_fini(root);
456*26947304SEvan Yan
457*26947304SEvan Yan return (rv);
458*26947304SEvan Yan }
459*26947304SEvan Yan
460*26947304SEvan Yan /*
461*26947304SEvan Yan * cmd_disable()
462*26947304SEvan Yan *
463*26947304SEvan Yan * Subcommand to disable a hotplug connector.
464*26947304SEvan Yan */
465*26947304SEvan Yan static int
cmd_disable(int argc,char * argv[],const char * usage_str)466*26947304SEvan Yan cmd_disable(int argc, char *argv[], const char *usage_str)
467*26947304SEvan Yan {
468*26947304SEvan Yan hp_node_t root;
469*26947304SEvan Yan hp_node_t results = NULL;
470*26947304SEvan Yan char *path = NULL;
471*26947304SEvan Yan char *connection = NULL;
472*26947304SEvan Yan int flags = 0;
473*26947304SEvan Yan int rv;
474*26947304SEvan Yan
475*26947304SEvan Yan /* Parse command line options */
476*26947304SEvan Yan parse_common(argc, argv, usage_str);
477*26947304SEvan Yan parse_flags(argc, argv, &flags, usage_str);
478*26947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str);
479*26947304SEvan Yan
480*26947304SEvan Yan /* Path and connection are required */
481*26947304SEvan Yan if ((path == NULL) || (connection == NULL)) {
482*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
483*26947304SEvan Yan usage(usage_str);
484*26947304SEvan Yan return (EINVAL);
485*26947304SEvan Yan }
486*26947304SEvan Yan
487*26947304SEvan Yan /* Get hotplug information snapshot */
488*26947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) {
489*26947304SEvan Yan print_error(errno);
490*26947304SEvan Yan return (errno);
491*26947304SEvan Yan }
492*26947304SEvan Yan
493*26947304SEvan Yan /* Verify target is a connector */
494*26947304SEvan Yan if (hp_type(root) != HP_NODE_CONNECTOR) {
495*26947304SEvan Yan (void) fprintf(stderr,
496*26947304SEvan Yan gettext("ERROR: invalid target (must be a connector).\n"));
497*26947304SEvan Yan hp_fini(root);
498*26947304SEvan Yan return (EINVAL);
499*26947304SEvan Yan }
500*26947304SEvan Yan
501*26947304SEvan Yan /*
502*26947304SEvan Yan * Do nothing unless the connector is in the ENABLED state.
503*26947304SEvan Yan * Otherwise this subcommand becomes an alias for 'poweron.'
504*26947304SEvan Yan */
505*26947304SEvan Yan if (hp_state(root) != DDI_HP_CN_STATE_ENABLED) {
506*26947304SEvan Yan hp_fini(root);
507*26947304SEvan Yan return (0);
508*26947304SEvan Yan }
509*26947304SEvan Yan
510*26947304SEvan Yan /* Do state change */
511*26947304SEvan Yan rv = hp_set_state(root, flags, DDI_HP_CN_STATE_POWERED, &results);
512*26947304SEvan Yan
513*26947304SEvan Yan /* Display results */
514*26947304SEvan Yan print_error(rv);
515*26947304SEvan Yan if (results != NULL) {
516*26947304SEvan Yan (void) hp_traverse(results, NULL, error_cb);
517*26947304SEvan Yan hp_fini(results);
518*26947304SEvan Yan }
519*26947304SEvan Yan
520*26947304SEvan Yan /* Discard hotplug information snapshot */
521*26947304SEvan Yan hp_fini(root);
522*26947304SEvan Yan
523*26947304SEvan Yan return (rv);
524*26947304SEvan Yan }
525*26947304SEvan Yan
526*26947304SEvan Yan /*
527*26947304SEvan Yan * cmd_poweron()
528*26947304SEvan Yan *
529*26947304SEvan Yan * Subcommand to power on a hotplug connector.
530*26947304SEvan Yan */
531*26947304SEvan Yan static int
cmd_poweron(int argc,char * argv[],const char * usage_str)532*26947304SEvan Yan cmd_poweron(int argc, char *argv[], const char *usage_str)
533*26947304SEvan Yan {
534*26947304SEvan Yan hp_node_t root;
535*26947304SEvan Yan hp_node_t results = NULL;
536*26947304SEvan Yan char *path = NULL;
537*26947304SEvan Yan char *connection = NULL;
538*26947304SEvan Yan int rv;
539*26947304SEvan Yan
540*26947304SEvan Yan /* Parse command line options */
541*26947304SEvan Yan parse_common(argc, argv, usage_str);
542*26947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str);
543*26947304SEvan Yan
544*26947304SEvan Yan /* Path and connection are required */
545*26947304SEvan Yan if ((path == NULL) || (connection == NULL)) {
546*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
547*26947304SEvan Yan usage(usage_str);
548*26947304SEvan Yan return (EINVAL);
549*26947304SEvan Yan }
550*26947304SEvan Yan
551*26947304SEvan Yan /* Get hotplug information snapshot */
552*26947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) {
553*26947304SEvan Yan print_error(errno);
554*26947304SEvan Yan return (errno);
555*26947304SEvan Yan }
556*26947304SEvan Yan
557*26947304SEvan Yan /* Verify target is a connector */
558*26947304SEvan Yan if (hp_type(root) != HP_NODE_CONNECTOR) {
559*26947304SEvan Yan (void) fprintf(stderr,
560*26947304SEvan Yan gettext("ERROR: invalid target (must be a connector).\n"));
561*26947304SEvan Yan hp_fini(root);
562*26947304SEvan Yan return (EINVAL);
563*26947304SEvan Yan }
564*26947304SEvan Yan
565*26947304SEvan Yan /*
566*26947304SEvan Yan * Do nothing if the connector is already powered.
567*26947304SEvan Yan * Otherwise this subcommand becomes an alias for 'disable.'
568*26947304SEvan Yan */
569*26947304SEvan Yan if (hp_state(root) >= DDI_HP_CN_STATE_POWERED) {
570*26947304SEvan Yan hp_fini(root);
571*26947304SEvan Yan return (0);
572*26947304SEvan Yan }
573*26947304SEvan Yan
574*26947304SEvan Yan /* Do state change */
575*26947304SEvan Yan rv = hp_set_state(root, 0, DDI_HP_CN_STATE_POWERED, &results);
576*26947304SEvan Yan
577*26947304SEvan Yan /* Display results */
578*26947304SEvan Yan print_error(rv);
579*26947304SEvan Yan if (results != NULL) {
580*26947304SEvan Yan (void) hp_traverse(results, NULL, error_cb);
581*26947304SEvan Yan hp_fini(results);
582*26947304SEvan Yan }
583*26947304SEvan Yan
584*26947304SEvan Yan /* Discard hotplug information snapshot */
585*26947304SEvan Yan hp_fini(root);
586*26947304SEvan Yan
587*26947304SEvan Yan return (rv);
588*26947304SEvan Yan }
589*26947304SEvan Yan
590*26947304SEvan Yan /*
591*26947304SEvan Yan * cmd_poweroff()
592*26947304SEvan Yan *
593*26947304SEvan Yan * Subcommand to power off a hotplug connector.
594*26947304SEvan Yan */
595*26947304SEvan Yan static int
cmd_poweroff(int argc,char * argv[],const char * usage_str)596*26947304SEvan Yan cmd_poweroff(int argc, char *argv[], const char *usage_str)
597*26947304SEvan Yan {
598*26947304SEvan Yan hp_node_t root;
599*26947304SEvan Yan hp_node_t results = NULL;
600*26947304SEvan Yan char *path = NULL;
601*26947304SEvan Yan char *connection = NULL;
602*26947304SEvan Yan int flags = 0;
603*26947304SEvan Yan int rv;
604*26947304SEvan Yan
605*26947304SEvan Yan /* Parse command line options */
606*26947304SEvan Yan parse_common(argc, argv, usage_str);
607*26947304SEvan Yan parse_flags(argc, argv, &flags, usage_str);
608*26947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str);
609*26947304SEvan Yan
610*26947304SEvan Yan /* Path and connection are required */
611*26947304SEvan Yan if ((path == NULL) || (connection == NULL)) {
612*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
613*26947304SEvan Yan usage(usage_str);
614*26947304SEvan Yan return (EINVAL);
615*26947304SEvan Yan }
616*26947304SEvan Yan
617*26947304SEvan Yan /* Get hotplug information snapshot */
618*26947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) {
619*26947304SEvan Yan print_error(errno);
620*26947304SEvan Yan return (errno);
621*26947304SEvan Yan }
622*26947304SEvan Yan
623*26947304SEvan Yan /* Verify target is a connector */
624*26947304SEvan Yan if (hp_type(root) != HP_NODE_CONNECTOR) {
625*26947304SEvan Yan (void) fprintf(stderr,
626*26947304SEvan Yan gettext("ERROR: invalid target (must be a connector).\n"));
627*26947304SEvan Yan hp_fini(root);
628*26947304SEvan Yan return (EINVAL);
629*26947304SEvan Yan }
630*26947304SEvan Yan
631*26947304SEvan Yan /* Do state change */
632*26947304SEvan Yan rv = hp_set_state(root, flags, DDI_HP_CN_STATE_PRESENT, &results);
633*26947304SEvan Yan
634*26947304SEvan Yan /* Display results */
635*26947304SEvan Yan print_error(rv);
636*26947304SEvan Yan if (results != NULL) {
637*26947304SEvan Yan (void) hp_traverse(results, NULL, error_cb);
638*26947304SEvan Yan hp_fini(results);
639*26947304SEvan Yan }
640*26947304SEvan Yan
641*26947304SEvan Yan /* Discard hotplug information snapshot */
642*26947304SEvan Yan hp_fini(root);
643*26947304SEvan Yan
644*26947304SEvan Yan return (rv);
645*26947304SEvan Yan }
646*26947304SEvan Yan
647*26947304SEvan Yan /*
648*26947304SEvan Yan * cmd_getpriv()
649*26947304SEvan Yan *
650*26947304SEvan Yan * Subcommand to get and display bus private options.
651*26947304SEvan Yan */
652*26947304SEvan Yan static int
cmd_getpriv(int argc,char * argv[],const char * usage_str)653*26947304SEvan Yan cmd_getpriv(int argc, char *argv[], const char *usage_str)
654*26947304SEvan Yan {
655*26947304SEvan Yan hp_node_t root;
656*26947304SEvan Yan char *path = NULL;
657*26947304SEvan Yan char *connection = NULL;
658*26947304SEvan Yan char *options = NULL;
659*26947304SEvan Yan char *results = NULL;
660*26947304SEvan Yan int rv;
661*26947304SEvan Yan
662*26947304SEvan Yan /* Parse command line options */
663*26947304SEvan Yan parse_common(argc, argv, usage_str);
664*26947304SEvan Yan parse_options(argc, argv, &options, usage_str);
665*26947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str);
666*26947304SEvan Yan
667*26947304SEvan Yan /* Options, path, and connection are all required */
668*26947304SEvan Yan if ((options == NULL) || (path == NULL) || (connection == NULL)) {
669*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
670*26947304SEvan Yan usage(usage_str);
671*26947304SEvan Yan return (EINVAL);
672*26947304SEvan Yan }
673*26947304SEvan Yan
674*26947304SEvan Yan /* Get hotplug information snapshot */
675*26947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) {
676*26947304SEvan Yan print_error(errno);
677*26947304SEvan Yan return (errno);
678*26947304SEvan Yan }
679*26947304SEvan Yan
680*26947304SEvan Yan /* Verify target is a connector */
681*26947304SEvan Yan if (hp_type(root) != HP_NODE_CONNECTOR) {
682*26947304SEvan Yan (void) fprintf(stderr,
683*26947304SEvan Yan gettext("ERROR: invalid target (must be a connector).\n"));
684*26947304SEvan Yan hp_fini(root);
685*26947304SEvan Yan return (EINVAL);
686*26947304SEvan Yan }
687*26947304SEvan Yan
688*26947304SEvan Yan /* Do the operation */
689*26947304SEvan Yan rv = hp_get_private(root, options, &results);
690*26947304SEvan Yan
691*26947304SEvan Yan /* Display results */
692*26947304SEvan Yan if (rv == ENOTSUP) {
693*26947304SEvan Yan (void) fprintf(stderr,
694*26947304SEvan Yan gettext("ERROR: unsupported property name or value.\n"));
695*26947304SEvan Yan (void) fprintf(stderr,
696*26947304SEvan Yan gettext("(Properties may depend upon connector state.)\n"));
697*26947304SEvan Yan } else if (rv != 0) {
698*26947304SEvan Yan print_error(rv);
699*26947304SEvan Yan }
700*26947304SEvan Yan if (results != NULL) {
701*26947304SEvan Yan print_options(results);
702*26947304SEvan Yan free(results);
703*26947304SEvan Yan }
704*26947304SEvan Yan
705*26947304SEvan Yan /* Discard hotplug information snapshot */
706*26947304SEvan Yan hp_fini(root);
707*26947304SEvan Yan
708*26947304SEvan Yan return (rv);
709*26947304SEvan Yan }
710*26947304SEvan Yan
711*26947304SEvan Yan /*
712*26947304SEvan Yan * cmd_setpriv()
713*26947304SEvan Yan *
714*26947304SEvan Yan * Subcommand to set bus private options.
715*26947304SEvan Yan */
716*26947304SEvan Yan static int
cmd_setpriv(int argc,char * argv[],const char * usage_str)717*26947304SEvan Yan cmd_setpriv(int argc, char *argv[], const char *usage_str)
718*26947304SEvan Yan {
719*26947304SEvan Yan hp_node_t root;
720*26947304SEvan Yan char *path = NULL;
721*26947304SEvan Yan char *connection = NULL;
722*26947304SEvan Yan char *options = NULL;
723*26947304SEvan Yan char *results = NULL;
724*26947304SEvan Yan int rv;
725*26947304SEvan Yan
726*26947304SEvan Yan /* Parse command line options */
727*26947304SEvan Yan parse_common(argc, argv, usage_str);
728*26947304SEvan Yan parse_options(argc, argv, &options, usage_str);
729*26947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str);
730*26947304SEvan Yan
731*26947304SEvan Yan /* Options, path, and connection are all required */
732*26947304SEvan Yan if ((options == NULL) || (path == NULL) || (connection == NULL)) {
733*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
734*26947304SEvan Yan usage(usage_str);
735*26947304SEvan Yan return (EINVAL);
736*26947304SEvan Yan }
737*26947304SEvan Yan
738*26947304SEvan Yan /* Get hotplug information snapshot */
739*26947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) {
740*26947304SEvan Yan print_error(errno);
741*26947304SEvan Yan return (errno);
742*26947304SEvan Yan }
743*26947304SEvan Yan
744*26947304SEvan Yan /* Verify target is a connector */
745*26947304SEvan Yan if (hp_type(root) != HP_NODE_CONNECTOR) {
746*26947304SEvan Yan (void) fprintf(stderr,
747*26947304SEvan Yan gettext("ERROR: invalid target (must be a connector).\n"));
748*26947304SEvan Yan hp_fini(root);
749*26947304SEvan Yan return (EINVAL);
750*26947304SEvan Yan }
751*26947304SEvan Yan
752*26947304SEvan Yan /* Do the operation */
753*26947304SEvan Yan rv = hp_set_private(root, options, &results);
754*26947304SEvan Yan
755*26947304SEvan Yan /* Display results */
756*26947304SEvan Yan if (rv == ENOTSUP) {
757*26947304SEvan Yan (void) fprintf(stderr,
758*26947304SEvan Yan gettext("ERROR: unsupported property name or value.\n"));
759*26947304SEvan Yan (void) fprintf(stderr,
760*26947304SEvan Yan gettext("(Properties may depend upon connector state.)\n"));
761*26947304SEvan Yan } else if (rv != 0) {
762*26947304SEvan Yan print_error(rv);
763*26947304SEvan Yan }
764*26947304SEvan Yan if (results != NULL) {
765*26947304SEvan Yan print_options(results);
766*26947304SEvan Yan free(results);
767*26947304SEvan Yan }
768*26947304SEvan Yan
769*26947304SEvan Yan /* Discard hotplug information snapshot */
770*26947304SEvan Yan hp_fini(root);
771*26947304SEvan Yan
772*26947304SEvan Yan return (rv);
773*26947304SEvan Yan }
774*26947304SEvan Yan
775*26947304SEvan Yan /*
776*26947304SEvan Yan * cmd_changestate()
777*26947304SEvan Yan *
778*26947304SEvan Yan * Subcommand to initiate a state change operation. This is
779*26947304SEvan Yan * a hidden subcommand to directly set a connector or port to
780*26947304SEvan Yan * a specific target state.
781*26947304SEvan Yan */
782*26947304SEvan Yan static int
cmd_changestate(int argc,char * argv[],const char * usage_str)783*26947304SEvan Yan cmd_changestate(int argc, char *argv[], const char *usage_str)
784*26947304SEvan Yan {
785*26947304SEvan Yan hp_node_t root;
786*26947304SEvan Yan hp_node_t results = NULL;
787*26947304SEvan Yan char *path = NULL;
788*26947304SEvan Yan char *connection = NULL;
789*26947304SEvan Yan int state = -1;
790*26947304SEvan Yan int flags = 0;
791*26947304SEvan Yan int opt, rv;
792*26947304SEvan Yan
793*26947304SEvan Yan /* Parse command line options */
794*26947304SEvan Yan parse_common(argc, argv, usage_str);
795*26947304SEvan Yan while ((opt = getopt_clip(argc, argv, "fqs:", changestate_opts,
796*26947304SEvan Yan NULL)) != -1) {
797*26947304SEvan Yan switch (opt) {
798*26947304SEvan Yan case 'f':
799*26947304SEvan Yan flags |= HPFORCE;
800*26947304SEvan Yan break;
801*26947304SEvan Yan case 'q':
802*26947304SEvan Yan flags |= HPQUERY;
803*26947304SEvan Yan break;
804*26947304SEvan Yan case 's':
805*26947304SEvan Yan if ((state = state_atoi(optarg)) == -1) {
806*26947304SEvan Yan (void) printf("ERROR: invalid target state\n");
807*26947304SEvan Yan return (EINVAL);
808*26947304SEvan Yan }
809*26947304SEvan Yan break;
810*26947304SEvan Yan default:
811*26947304SEvan Yan bad_option(opt, optopt, usage_str);
812*26947304SEvan Yan break;
813*26947304SEvan Yan }
814*26947304SEvan Yan }
815*26947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str);
816*26947304SEvan Yan
817*26947304SEvan Yan /* State, path, and connection are all required */
818*26947304SEvan Yan if ((state == -1) || (path == NULL) || (connection == NULL)) {
819*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
820*26947304SEvan Yan usage(usage_str);
821*26947304SEvan Yan return (EINVAL);
822*26947304SEvan Yan }
823*26947304SEvan Yan
824*26947304SEvan Yan /* Check that target state is valid */
825*26947304SEvan Yan if (valid_target(state) == 0) {
826*26947304SEvan Yan (void) fprintf(stderr,
827*26947304SEvan Yan gettext("ERROR: invalid target state\n"));
828*26947304SEvan Yan return (EINVAL);
829*26947304SEvan Yan }
830*26947304SEvan Yan
831*26947304SEvan Yan /* Get hotplug information snapshot */
832*26947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) {
833*26947304SEvan Yan print_error(errno);
834*26947304SEvan Yan return (errno);
835*26947304SEvan Yan }
836*26947304SEvan Yan
837*26947304SEvan Yan /* Initiate state change operation on root of snapshot */
838*26947304SEvan Yan rv = hp_set_state(root, flags, state, &results);
839*26947304SEvan Yan
840*26947304SEvan Yan /* Display results */
841*26947304SEvan Yan print_error(rv);
842*26947304SEvan Yan if (results) {
843*26947304SEvan Yan (void) hp_traverse(results, NULL, error_cb);
844*26947304SEvan Yan hp_fini(results);
845*26947304SEvan Yan }
846*26947304SEvan Yan
847*26947304SEvan Yan /* Discard hotplug information snapshot */
848*26947304SEvan Yan hp_fini(root);
849*26947304SEvan Yan
850*26947304SEvan Yan return (rv);
851*26947304SEvan Yan }
852*26947304SEvan Yan
853*26947304SEvan Yan /*
854*26947304SEvan Yan * parse_common()
855*26947304SEvan Yan *
856*26947304SEvan Yan * Parse command line options that are common to the
857*26947304SEvan Yan * entire program, and to each of its subcommands.
858*26947304SEvan Yan */
859*26947304SEvan Yan static void
parse_common(int argc,char * argv[],const char * usage_str)860*26947304SEvan Yan parse_common(int argc, char *argv[], const char *usage_str)
861*26947304SEvan Yan {
862*26947304SEvan Yan int opt;
863*26947304SEvan Yan extern int opterr;
864*26947304SEvan Yan extern int optind;
865*26947304SEvan Yan
866*26947304SEvan Yan /* Turn off error reporting */
867*26947304SEvan Yan opterr = 0;
868*26947304SEvan Yan
869*26947304SEvan Yan while ((opt = getopt_clip(argc, argv, "?V", common_opts, NULL)) != -1) {
870*26947304SEvan Yan switch (opt) {
871*26947304SEvan Yan case '?':
872*26947304SEvan Yan if (optopt == '?') {
873*26947304SEvan Yan usage(usage_str);
874*26947304SEvan Yan exit(0);
875*26947304SEvan Yan }
876*26947304SEvan Yan break;
877*26947304SEvan Yan case 'V':
878*26947304SEvan Yan (void) printf(gettext("%s: Version %s\n"),
879*26947304SEvan Yan prog, version);
880*26947304SEvan Yan exit(0);
881*26947304SEvan Yan default:
882*26947304SEvan Yan break;
883*26947304SEvan Yan }
884*26947304SEvan Yan }
885*26947304SEvan Yan
886*26947304SEvan Yan /* Reset option index */
887*26947304SEvan Yan optind = 1;
888*26947304SEvan Yan }
889*26947304SEvan Yan
890*26947304SEvan Yan /*
891*26947304SEvan Yan * parse_flags()
892*26947304SEvan Yan *
893*26947304SEvan Yan * Parse command line flags common to all downward state
894*26947304SEvan Yan * change operations (offline, disable, poweoff).
895*26947304SEvan Yan */
896*26947304SEvan Yan static void
parse_flags(int argc,char * argv[],int * flagsp,const char * usage_str)897*26947304SEvan Yan parse_flags(int argc, char *argv[], int *flagsp, const char *usage_str)
898*26947304SEvan Yan {
899*26947304SEvan Yan int opt;
900*26947304SEvan Yan int flags = 0;
901*26947304SEvan Yan
902*26947304SEvan Yan while ((opt = getopt_clip(argc, argv, "fq", flag_opts, NULL)) != -1) {
903*26947304SEvan Yan switch (opt) {
904*26947304SEvan Yan case 'f':
905*26947304SEvan Yan flags |= HPFORCE;
906*26947304SEvan Yan break;
907*26947304SEvan Yan case 'q':
908*26947304SEvan Yan flags |= HPQUERY;
909*26947304SEvan Yan break;
910*26947304SEvan Yan default:
911*26947304SEvan Yan bad_option(opt, optopt, usage_str);
912*26947304SEvan Yan break;
913*26947304SEvan Yan }
914*26947304SEvan Yan }
915*26947304SEvan Yan
916*26947304SEvan Yan *flagsp = flags;
917*26947304SEvan Yan }
918*26947304SEvan Yan
919*26947304SEvan Yan /*
920*26947304SEvan Yan * parse_options()
921*26947304SEvan Yan *
922*26947304SEvan Yan * Parse command line options common to the bus private set and
923*26947304SEvan Yan * get subcommands.
924*26947304SEvan Yan */
925*26947304SEvan Yan static void
parse_options(int argc,char * argv[],char ** optionsp,const char * usage_str)926*26947304SEvan Yan parse_options(int argc, char *argv[], char **optionsp, const char *usage_str)
927*26947304SEvan Yan {
928*26947304SEvan Yan int opt;
929*26947304SEvan Yan
930*26947304SEvan Yan while ((opt = getopt_clip(argc, argv, "o:", private_opts,
931*26947304SEvan Yan NULL)) != -1) {
932*26947304SEvan Yan switch (opt) {
933*26947304SEvan Yan case 'o':
934*26947304SEvan Yan *optionsp = optarg;
935*26947304SEvan Yan break;
936*26947304SEvan Yan default:
937*26947304SEvan Yan bad_option(opt, optopt, usage_str);
938*26947304SEvan Yan break;
939*26947304SEvan Yan }
940*26947304SEvan Yan }
941*26947304SEvan Yan }
942*26947304SEvan Yan
943*26947304SEvan Yan /*
944*26947304SEvan Yan * parse_target()
945*26947304SEvan Yan *
946*26947304SEvan Yan * Parse the target path and connection name from the command line.
947*26947304SEvan Yan */
948*26947304SEvan Yan static void
parse_target(int argc,char * argv[],char ** pathp,char ** connectionp,const char * usage_str)949*26947304SEvan Yan parse_target(int argc, char *argv[], char **pathp, char **connectionp,
950*26947304SEvan Yan const char *usage_str)
951*26947304SEvan Yan {
952*26947304SEvan Yan extern int optind;
953*26947304SEvan Yan
954*26947304SEvan Yan if (optind < argc)
955*26947304SEvan Yan *pathp = argv[optind++];
956*26947304SEvan Yan
957*26947304SEvan Yan if (optind < argc)
958*26947304SEvan Yan *connectionp = argv[optind++];
959*26947304SEvan Yan
960*26947304SEvan Yan if (optind < argc) {
961*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too many arguments.\n"));
962*26947304SEvan Yan usage(usage_str);
963*26947304SEvan Yan exit(EINVAL);
964*26947304SEvan Yan }
965*26947304SEvan Yan }
966*26947304SEvan Yan
967*26947304SEvan Yan /*
968*26947304SEvan Yan * bad_option()
969*26947304SEvan Yan *
970*26947304SEvan Yan * Routine to handle bad command line options.
971*26947304SEvan Yan */
972*26947304SEvan Yan static void
bad_option(int opt,int optopt,const char * usage_str)973*26947304SEvan Yan bad_option(int opt, int optopt, const char *usage_str)
974*26947304SEvan Yan {
975*26947304SEvan Yan switch (opt) {
976*26947304SEvan Yan case ':':
977*26947304SEvan Yan (void) fprintf(stderr,
978*26947304SEvan Yan gettext("ERROR: option '%c' requires an argument.\n"),
979*26947304SEvan Yan optopt);
980*26947304SEvan Yan break;
981*26947304SEvan Yan default:
982*26947304SEvan Yan if (optopt == '?') {
983*26947304SEvan Yan usage(usage_str);
984*26947304SEvan Yan exit(EXIT_OK);
985*26947304SEvan Yan }
986*26947304SEvan Yan (void) fprintf(stderr,
987*26947304SEvan Yan gettext("ERROR: unrecognized option '%c'.\n"), optopt);
988*26947304SEvan Yan break;
989*26947304SEvan Yan }
990*26947304SEvan Yan
991*26947304SEvan Yan usage(usage_str);
992*26947304SEvan Yan
993*26947304SEvan Yan exit(EXIT_EINVAL);
994*26947304SEvan Yan }
995*26947304SEvan Yan
996*26947304SEvan Yan /*
997*26947304SEvan Yan * usage()
998*26947304SEvan Yan *
999*26947304SEvan Yan * Display general usage of the command. Including
1000*26947304SEvan Yan * the usage synopsis of each defined subcommand.
1001*26947304SEvan Yan */
1002*26947304SEvan Yan static void
usage(const char * usage_str)1003*26947304SEvan Yan usage(const char *usage_str)
1004*26947304SEvan Yan {
1005*26947304SEvan Yan int i;
1006*26947304SEvan Yan
1007*26947304SEvan Yan if (usage_str != NULL) {
1008*26947304SEvan Yan (void) fprintf(stderr, gettext("Usage: %s %s\n\n"),
1009*26947304SEvan Yan prog, usage_str);
1010*26947304SEvan Yan return;
1011*26947304SEvan Yan }
1012*26947304SEvan Yan
1013*26947304SEvan Yan (void) fprintf(stderr, gettext("Usage: %s <subcommand> [<args>]\n\n"),
1014*26947304SEvan Yan prog);
1015*26947304SEvan Yan
1016*26947304SEvan Yan (void) fprintf(stderr, gettext("Subcommands:\n\n"));
1017*26947304SEvan Yan
1018*26947304SEvan Yan for (i = 0; i < (sizeof (subcmds) / sizeof (subcmd_t)); i++)
1019*26947304SEvan Yan (void) fprintf(stderr, " %s\n\n", subcmds[i].usage_str);
1020*26947304SEvan Yan }
1021*26947304SEvan Yan
1022*26947304SEvan Yan /*
1023*26947304SEvan Yan * list_cb()
1024*26947304SEvan Yan *
1025*26947304SEvan Yan * Callback function for hp_traverse(), to display nodes
1026*26947304SEvan Yan * of a hotplug information snapshot. (Short version.)
1027*26947304SEvan Yan */
1028*26947304SEvan Yan /*ARGSUSED*/
1029*26947304SEvan Yan static int
list_cb(hp_node_t node,void * arg)1030*26947304SEvan Yan list_cb(hp_node_t node, void *arg)
1031*26947304SEvan Yan {
1032*26947304SEvan Yan hp_node_t parent;
1033*26947304SEvan Yan
1034*26947304SEvan Yan /* Indent */
1035*26947304SEvan Yan for (parent = hp_parent(node); parent; parent = hp_parent(parent))
1036*26947304SEvan Yan if (hp_type(parent) == HP_NODE_DEVICE)
1037*26947304SEvan Yan (void) printf(" ");
1038*26947304SEvan Yan
1039*26947304SEvan Yan switch (hp_type(node)) {
1040*26947304SEvan Yan case HP_NODE_DEVICE:
1041*26947304SEvan Yan (void) printf("%s\n", hp_name(node));
1042*26947304SEvan Yan break;
1043*26947304SEvan Yan
1044*26947304SEvan Yan case HP_NODE_CONNECTOR:
1045*26947304SEvan Yan (void) printf("[%s]", hp_name(node));
1046*26947304SEvan Yan (void) printf(" (%s)", state_itoa(hp_state(node)));
1047*26947304SEvan Yan (void) printf("\n");
1048*26947304SEvan Yan break;
1049*26947304SEvan Yan
1050*26947304SEvan Yan case HP_NODE_PORT:
1051*26947304SEvan Yan (void) printf("<%s>", hp_name(node));
1052*26947304SEvan Yan (void) printf(" (%s)", state_itoa(hp_state(node)));
1053*26947304SEvan Yan (void) printf("\n");
1054*26947304SEvan Yan break;
1055*26947304SEvan Yan
1056*26947304SEvan Yan case HP_NODE_USAGE:
1057*26947304SEvan Yan (void) printf("{ %s }\n", hp_usage(node));
1058*26947304SEvan Yan break;
1059*26947304SEvan Yan }
1060*26947304SEvan Yan
1061*26947304SEvan Yan return (HP_WALK_CONTINUE);
1062*26947304SEvan Yan }
1063*26947304SEvan Yan
1064*26947304SEvan Yan /*
1065*26947304SEvan Yan * list_long_cb()
1066*26947304SEvan Yan *
1067*26947304SEvan Yan * Callback function for hp_traverse(), to display nodes
1068*26947304SEvan Yan * of a hotplug information snapshot. (Long version.)
1069*26947304SEvan Yan */
1070*26947304SEvan Yan /*ARGSUSED*/
1071*26947304SEvan Yan static int
list_long_cb(hp_node_t node,void * arg)1072*26947304SEvan Yan list_long_cb(hp_node_t node, void *arg)
1073*26947304SEvan Yan {
1074*26947304SEvan Yan char path[MAXPATHLEN];
1075*26947304SEvan Yan char connection[MAXPATHLEN];
1076*26947304SEvan Yan
1077*26947304SEvan Yan if (hp_type(node) != HP_NODE_USAGE) {
1078*26947304SEvan Yan if (hp_path(node, path, connection) != 0)
1079*26947304SEvan Yan return (HP_WALK_CONTINUE);
1080*26947304SEvan Yan (void) printf("%s", path);
1081*26947304SEvan Yan }
1082*26947304SEvan Yan
1083*26947304SEvan Yan switch (hp_type(node)) {
1084*26947304SEvan Yan case HP_NODE_CONNECTOR:
1085*26947304SEvan Yan (void) printf(" [%s]", connection);
1086*26947304SEvan Yan (void) printf(" (%s)", state_itoa(hp_state(node)));
1087*26947304SEvan Yan break;
1088*26947304SEvan Yan
1089*26947304SEvan Yan case HP_NODE_PORT:
1090*26947304SEvan Yan (void) printf(" <%s>", connection);
1091*26947304SEvan Yan (void) printf(" (%s)", state_itoa(hp_state(node)));
1092*26947304SEvan Yan break;
1093*26947304SEvan Yan
1094*26947304SEvan Yan case HP_NODE_USAGE:
1095*26947304SEvan Yan (void) printf(" { %s }", hp_usage(node));
1096*26947304SEvan Yan break;
1097*26947304SEvan Yan }
1098*26947304SEvan Yan
1099*26947304SEvan Yan (void) printf("\n");
1100*26947304SEvan Yan
1101*26947304SEvan Yan return (HP_WALK_CONTINUE);
1102*26947304SEvan Yan }
1103*26947304SEvan Yan
1104*26947304SEvan Yan /*
1105*26947304SEvan Yan * error_cb()
1106*26947304SEvan Yan *
1107*26947304SEvan Yan * Callback function for hp_traverse(), to display
1108*26947304SEvan Yan * error results from a state change operation.
1109*26947304SEvan Yan */
1110*26947304SEvan Yan /*ARGSUSED*/
1111*26947304SEvan Yan static int
error_cb(hp_node_t node,void * arg)1112*26947304SEvan Yan error_cb(hp_node_t node, void *arg)
1113*26947304SEvan Yan {
1114*26947304SEvan Yan hp_node_t child;
1115*26947304SEvan Yan char *usage_str;
1116*26947304SEvan Yan static char path[MAXPATHLEN];
1117*26947304SEvan Yan static char connection[MAXPATHLEN];
1118*26947304SEvan Yan
1119*26947304SEvan Yan if (((child = hp_child(node)) != NULL) &&
1120*26947304SEvan Yan (hp_type(child) == HP_NODE_USAGE)) {
1121*26947304SEvan Yan if (hp_path(node, path, connection) == 0)
1122*26947304SEvan Yan (void) printf("%s:\n", path);
1123*26947304SEvan Yan return (HP_WALK_CONTINUE);
1124*26947304SEvan Yan }
1125*26947304SEvan Yan
1126*26947304SEvan Yan if ((hp_type(node) == HP_NODE_USAGE) &&
1127*26947304SEvan Yan ((usage_str = hp_usage(node)) != NULL))
1128*26947304SEvan Yan (void) printf(" { %s }\n", usage_str);
1129*26947304SEvan Yan
1130*26947304SEvan Yan return (HP_WALK_CONTINUE);
1131*26947304SEvan Yan }
1132*26947304SEvan Yan
1133*26947304SEvan Yan /*
1134*26947304SEvan Yan * print_options()
1135*26947304SEvan Yan *
1136*26947304SEvan Yan * Parse and display bus private options. The options are
1137*26947304SEvan Yan * formatted as a string which conforms to the getsubopt(3C)
1138*26947304SEvan Yan * format. This routine only splits the string elements as
1139*26947304SEvan Yan * separated by commas, and displays each portion on its own
1140*26947304SEvan Yan * separate line of output.
1141*26947304SEvan Yan */
1142*26947304SEvan Yan static void
print_options(const char * options)1143*26947304SEvan Yan print_options(const char *options)
1144*26947304SEvan Yan {
1145*26947304SEvan Yan char *buf, *curr, *next;
1146*26947304SEvan Yan size_t len;
1147*26947304SEvan Yan
1148*26947304SEvan Yan /* Do nothing if options string is empty */
1149*26947304SEvan Yan if ((len = strlen(options)) == 0)
1150*26947304SEvan Yan return;
1151*26947304SEvan Yan
1152*26947304SEvan Yan /* To avoid modifying the input string, make a copy on the stack */
1153*26947304SEvan Yan if ((buf = (char *)alloca(len + 1)) == NULL) {
1154*26947304SEvan Yan (void) printf("%s\n", options);
1155*26947304SEvan Yan return;
1156*26947304SEvan Yan }
1157*26947304SEvan Yan (void) strlcpy(buf, options, len + 1);
1158*26947304SEvan Yan
1159*26947304SEvan Yan /* Iterate through each comma-separated name/value pair */
1160*26947304SEvan Yan curr = buf;
1161*26947304SEvan Yan do {
1162*26947304SEvan Yan if ((next = strchr(curr, ',')) != NULL) {
1163*26947304SEvan Yan *next = '\0';
1164*26947304SEvan Yan next++;
1165*26947304SEvan Yan }
1166*26947304SEvan Yan (void) printf("%s\n", curr);
1167*26947304SEvan Yan } while ((curr = next) != NULL);
1168*26947304SEvan Yan }
1169*26947304SEvan Yan
1170*26947304SEvan Yan /*
1171*26947304SEvan Yan * print_error()
1172*26947304SEvan Yan *
1173*26947304SEvan Yan * Common routine to print error numbers in an appropriate way.
1174*26947304SEvan Yan * Prints nothing if error code is 0.
1175*26947304SEvan Yan */
1176*26947304SEvan Yan static void
print_error(int error)1177*26947304SEvan Yan print_error(int error)
1178*26947304SEvan Yan {
1179*26947304SEvan Yan switch (error) {
1180*26947304SEvan Yan case 0:
1181*26947304SEvan Yan /* No error */
1182*26947304SEvan Yan return;
1183*26947304SEvan Yan case EACCES:
1184*26947304SEvan Yan (void) fprintf(stderr,
1185*26947304SEvan Yan gettext("ERROR: operation not authorized.\n"));
1186*26947304SEvan Yan break;
1187*26947304SEvan Yan case EBADF:
1188*26947304SEvan Yan (void) fprintf(stderr,
1189*26947304SEvan Yan gettext("ERROR: hotplug service is not available.\n"));
1190*26947304SEvan Yan break;
1191*26947304SEvan Yan case EBUSY:
1192*26947304SEvan Yan (void) fprintf(stderr,
1193*26947304SEvan Yan gettext("ERROR: devices or resources are busy.\n"));
1194*26947304SEvan Yan break;
1195*26947304SEvan Yan case EEXIST:
1196*26947304SEvan Yan (void) fprintf(stderr,
1197*26947304SEvan Yan gettext("ERROR: resource already exists.\n"));
1198*26947304SEvan Yan break;
1199*26947304SEvan Yan case EFAULT:
1200*26947304SEvan Yan (void) fprintf(stderr,
1201*26947304SEvan Yan gettext("ERROR: internal failure in hotplug service.\n"));
1202*26947304SEvan Yan break;
1203*26947304SEvan Yan case EINVAL:
1204*26947304SEvan Yan (void) fprintf(stderr,
1205*26947304SEvan Yan gettext("ERROR: invalid arguments.\n"));
1206*26947304SEvan Yan break;
1207*26947304SEvan Yan case ENOENT:
1208*26947304SEvan Yan (void) fprintf(stderr,
1209*26947304SEvan Yan gettext("ERROR: there are no connections to display.\n"));
1210*26947304SEvan Yan (void) fprintf(stderr,
1211*26947304SEvan Yan gettext("(See hotplug(1m) for more information.)\n"));
1212*26947304SEvan Yan break;
1213*26947304SEvan Yan case ENXIO:
1214*26947304SEvan Yan (void) fprintf(stderr,
1215*26947304SEvan Yan gettext("ERROR: no such path or connection.\n"));
1216*26947304SEvan Yan break;
1217*26947304SEvan Yan case ENOMEM:
1218*26947304SEvan Yan (void) fprintf(stderr,
1219*26947304SEvan Yan gettext("ERROR: not enough memory.\n"));
1220*26947304SEvan Yan break;
1221*26947304SEvan Yan case ENOTSUP:
1222*26947304SEvan Yan (void) fprintf(stderr,
1223*26947304SEvan Yan gettext("ERROR: operation not supported.\n"));
1224*26947304SEvan Yan break;
1225*26947304SEvan Yan case EIO:
1226*26947304SEvan Yan (void) fprintf(stderr,
1227*26947304SEvan Yan gettext("ERROR: hardware or driver specific failure.\n"));
1228*26947304SEvan Yan break;
1229*26947304SEvan Yan default:
1230*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: operation failed: %s\n"),
1231*26947304SEvan Yan strerror(error));
1232*26947304SEvan Yan break;
1233*26947304SEvan Yan }
1234*26947304SEvan Yan }
1235*26947304SEvan Yan
1236*26947304SEvan Yan /*
1237*26947304SEvan Yan * state_atoi()
1238*26947304SEvan Yan *
1239*26947304SEvan Yan * Convert a hotplug state from a string to an integer.
1240*26947304SEvan Yan */
1241*26947304SEvan Yan static int
state_atoi(char * state)1242*26947304SEvan Yan state_atoi(char *state)
1243*26947304SEvan Yan {
1244*26947304SEvan Yan int i;
1245*26947304SEvan Yan
1246*26947304SEvan Yan for (i = 0; hpstates[i].state_str != NULL; i++)
1247*26947304SEvan Yan if (strcasecmp(state, hpstates[i].state_str) == 0)
1248*26947304SEvan Yan return (hpstates[i].state);
1249*26947304SEvan Yan
1250*26947304SEvan Yan return (-1);
1251*26947304SEvan Yan }
1252*26947304SEvan Yan
1253*26947304SEvan Yan /*
1254*26947304SEvan Yan * state_itoa()
1255*26947304SEvan Yan *
1256*26947304SEvan Yan * Convert a hotplug state from an integer to a string.
1257*26947304SEvan Yan */
1258*26947304SEvan Yan static char *
state_itoa(int state)1259*26947304SEvan Yan state_itoa(int state)
1260*26947304SEvan Yan {
1261*26947304SEvan Yan static char unknown[] = "UNKNOWN";
1262*26947304SEvan Yan int i;
1263*26947304SEvan Yan
1264*26947304SEvan Yan for (i = 0; hpstates[i].state_str != NULL; i++)
1265*26947304SEvan Yan if (state == hpstates[i].state)
1266*26947304SEvan Yan return (hpstates[i].state_str);
1267*26947304SEvan Yan
1268*26947304SEvan Yan return (unknown);
1269*26947304SEvan Yan }
1270*26947304SEvan Yan
1271*26947304SEvan Yan /*
1272*26947304SEvan Yan * valid_target()
1273*26947304SEvan Yan *
1274*26947304SEvan Yan * Check if a state is a valid target for a changestate command.
1275*26947304SEvan Yan */
1276*26947304SEvan Yan static short
valid_target(int state)1277*26947304SEvan Yan valid_target(int state)
1278*26947304SEvan Yan {
1279*26947304SEvan Yan int i;
1280*26947304SEvan Yan
1281*26947304SEvan Yan for (i = 0; hpstates[i].state_str != NULL; i++)
1282*26947304SEvan Yan if (state == hpstates[i].state)
1283*26947304SEvan Yan return (hpstates[i].valid_target);
1284*26947304SEvan Yan
1285*26947304SEvan Yan return (0);
1286*26947304SEvan Yan }
1287