126947304SEvan Yan /*
226947304SEvan Yan * CDDL HEADER START
326947304SEvan Yan *
426947304SEvan Yan * The contents of this file are subject to the terms of the
526947304SEvan Yan * Common Development and Distribution License (the "License").
626947304SEvan Yan * You may not use this file except in compliance with the License.
726947304SEvan Yan *
826947304SEvan Yan * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
926947304SEvan Yan * or http://www.opensolaris.org/os/licensing.
1026947304SEvan Yan * See the License for the specific language governing permissions
1126947304SEvan Yan * and limitations under the License.
1226947304SEvan Yan *
1326947304SEvan Yan * When distributing Covered Code, include this CDDL HEADER in each
1426947304SEvan Yan * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1526947304SEvan Yan * If applicable, add the following below this CDDL HEADER, with the
1626947304SEvan Yan * fields enclosed by brackets "[]" replaced with your own identifying
1726947304SEvan Yan * information: Portions Copyright [yyyy] [name of copyright owner]
1826947304SEvan Yan *
1926947304SEvan Yan * CDDL HEADER END
2026947304SEvan Yan */
2126947304SEvan Yan /*
2226947304SEvan Yan * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
2326947304SEvan Yan * Use is subject to license terms.
2426947304SEvan Yan */
2526947304SEvan Yan
2626947304SEvan Yan #include <stdio.h>
2726947304SEvan Yan #include <stdlib.h>
2826947304SEvan Yan #include <string.h>
2926947304SEvan Yan #include <locale.h>
3026947304SEvan Yan #include <libintl.h>
3126947304SEvan Yan #include <alloca.h>
3226947304SEvan Yan #include <getopt.h>
3326947304SEvan Yan #include <libhotplug.h>
3426947304SEvan Yan #include <sys/types.h>
3526947304SEvan Yan #include <sys/sunddi.h>
3626947304SEvan Yan #include <sys/ddi_hp.h>
3726947304SEvan Yan
3826947304SEvan Yan #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */
3926947304SEvan Yan #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
4026947304SEvan Yan #endif
4126947304SEvan Yan
4226947304SEvan Yan /*
4326947304SEvan Yan * Function prototypes.
4426947304SEvan Yan */
4526947304SEvan Yan static int cmd_list(int, char **, const char *);
4626947304SEvan Yan static int cmd_online(int, char **, const char *);
4726947304SEvan Yan static int cmd_offline(int, char **, const char *);
4826947304SEvan Yan static int cmd_enable(int, char **, const char *);
4926947304SEvan Yan static int cmd_disable(int, char **, const char *);
5026947304SEvan Yan static int cmd_poweron(int, char **, const char *);
5126947304SEvan Yan static int cmd_poweroff(int, char **, const char *);
5226947304SEvan Yan static int cmd_getpriv(int, char **, const char *);
5326947304SEvan Yan static int cmd_setpriv(int, char **, const char *);
5426947304SEvan Yan static int cmd_changestate(int, char **, const char *);
5526947304SEvan Yan static void parse_common(int, char **, const char *);
5626947304SEvan Yan static void parse_flags(int, char **, int *, const char *);
5726947304SEvan Yan static void parse_target(int, char **, char **, char **, const char *);
5826947304SEvan Yan static void parse_options(int, char **, char **, const char *);
5926947304SEvan Yan static void bad_option(int, int, const char *);
6026947304SEvan Yan static void usage(const char *);
6126947304SEvan Yan static int list_cb(hp_node_t, void *);
6226947304SEvan Yan static int list_long_cb(hp_node_t, void *);
6326947304SEvan Yan static int error_cb(hp_node_t, void *);
6426947304SEvan Yan static void print_options(const char *);
6526947304SEvan Yan static void print_error(int);
6626947304SEvan Yan static int state_atoi(char *);
6726947304SEvan Yan static char *state_itoa(int);
6826947304SEvan Yan static short valid_target(int);
6926947304SEvan Yan
7026947304SEvan Yan /*
7126947304SEvan Yan * Define a conversion table for hotplug states.
7226947304SEvan Yan */
7326947304SEvan Yan typedef struct {
7426947304SEvan Yan int state;
7526947304SEvan Yan char *state_str;
7626947304SEvan Yan short valid_target;
7726947304SEvan Yan } hpstate_t;
7826947304SEvan Yan
7926947304SEvan Yan static hpstate_t hpstates[] = {
8026947304SEvan Yan { DDI_HP_CN_STATE_EMPTY, "EMPTY", 0 },
8126947304SEvan Yan { DDI_HP_CN_STATE_PRESENT, "PRESENT", 1 },
8226947304SEvan Yan { DDI_HP_CN_STATE_POWERED, "POWERED", 1 },
8326947304SEvan Yan { DDI_HP_CN_STATE_ENABLED, "ENABLED", 1 },
8426947304SEvan Yan { DDI_HP_CN_STATE_PORT_EMPTY, "PORT-EMPTY", 0 },
8526947304SEvan Yan { DDI_HP_CN_STATE_PORT_PRESENT, "PORT-PRESENT", 1 },
8626947304SEvan Yan { DDI_HP_CN_STATE_OFFLINE, "OFFLINE", 1 },
8726947304SEvan Yan { DDI_HP_CN_STATE_ATTACHED, "ATTACHED", 0 },
8826947304SEvan Yan { DDI_HP_CN_STATE_MAINTENANCE, "MAINTENANCE", 0 },
8926947304SEvan Yan { DDI_HP_CN_STATE_ONLINE, "ONLINE", 1 },
9026947304SEvan Yan { 0, 0, 0 }
9126947304SEvan Yan };
9226947304SEvan Yan
9326947304SEvan Yan /*
9426947304SEvan Yan * Define tables of supported subcommands.
9526947304SEvan Yan */
9626947304SEvan Yan typedef struct {
9726947304SEvan Yan char *usage_str;
9826947304SEvan Yan char *cmd_str;
9926947304SEvan Yan int (*func)(int argc, char *argv[], const char *usage_str);
10026947304SEvan Yan } subcmd_t;
10126947304SEvan Yan
10226947304SEvan Yan static subcmd_t subcmds[] = {
10326947304SEvan Yan { "list [-l] [-v] [<path> [<connection>]]", "list", cmd_list },
10426947304SEvan Yan { "online <path> <port>", "online", cmd_online },
10526947304SEvan Yan { "offline [-f] [-q] <path> <port>", "offline", cmd_offline },
10626947304SEvan Yan { "enable <path> <connector>", "enable", cmd_enable },
10726947304SEvan Yan { "disable [-f] [-q] <path> <connector>", "disable", cmd_disable },
10826947304SEvan Yan { "poweron <path> <connector>", "poweron", cmd_poweron },
10926947304SEvan Yan { "poweroff [-f] [-q] <path> <connector>", "poweroff", cmd_poweroff },
11026947304SEvan Yan { "get -o <options> <path> <connector>", "get", cmd_getpriv },
11126947304SEvan Yan { "set -o <options> <path> <connector>", "set", cmd_setpriv }
11226947304SEvan Yan };
11326947304SEvan Yan
11426947304SEvan Yan static subcmd_t hidden_subcmds[] = {
11526947304SEvan Yan { "changestate [-f] [-q] -s <state> <path> <connection>",
11626947304SEvan Yan "changestate", cmd_changestate }
11726947304SEvan Yan };
11826947304SEvan Yan
11926947304SEvan Yan /*
12026947304SEvan Yan * Define tables of command line options.
12126947304SEvan Yan */
12226947304SEvan Yan static const struct option common_opts[] = {
12326947304SEvan Yan { "help", no_argument, 0, '?' },
12426947304SEvan Yan { "version", no_argument, 0, 'V' },
12526947304SEvan Yan { 0, 0, 0, 0 }
12626947304SEvan Yan };
12726947304SEvan Yan
12826947304SEvan Yan static const struct option list_opts[] = {
12926947304SEvan Yan { "list-path", no_argument, 0, 'l' },
13026947304SEvan Yan { "verbose", no_argument, 0, 'v' },
13126947304SEvan Yan { 0, 0, 0, 0 }
13226947304SEvan Yan };
13326947304SEvan Yan
13426947304SEvan Yan static const struct option flag_opts[] = {
13526947304SEvan Yan { "force", no_argument, 0, 'f' },
13626947304SEvan Yan { "query", no_argument, 0, 'q' },
13726947304SEvan Yan { 0, 0, 0, 0 }
13826947304SEvan Yan };
13926947304SEvan Yan
14026947304SEvan Yan static const struct option private_opts[] = {
14126947304SEvan Yan { "options", required_argument, 0, 'o' },
14226947304SEvan Yan { 0, 0, 0, 0 }
14326947304SEvan Yan };
14426947304SEvan Yan
14526947304SEvan Yan static const struct option changestate_opts[] = {
14626947304SEvan Yan { "force", no_argument, 0, 'f' },
14726947304SEvan Yan { "query", no_argument, 0, 'q' },
14826947304SEvan Yan { "state", required_argument, 0, 's' },
14926947304SEvan Yan { 0, 0, 0, 0 }
15026947304SEvan Yan };
15126947304SEvan Yan
15226947304SEvan Yan /*
15326947304SEvan Yan * Define exit codes.
15426947304SEvan Yan */
15526947304SEvan Yan #define EXIT_OK 0
15626947304SEvan Yan #define EXIT_EINVAL 1 /* invalid arguments */
15726947304SEvan Yan #define EXIT_ENOENT 2 /* path or connection doesn't exist */
15826947304SEvan Yan #define EXIT_FAILED 3 /* operation failed */
15926947304SEvan Yan #define EXIT_UNAVAIL 4 /* service not available */
16026947304SEvan Yan
16126947304SEvan Yan /*
16226947304SEvan Yan * Global variables.
16326947304SEvan Yan */
16426947304SEvan Yan static char *prog;
16526947304SEvan Yan static char version[] = "1.0";
16626947304SEvan Yan extern int errno;
16726947304SEvan Yan
16826947304SEvan Yan /*
16926947304SEvan Yan * main()
17026947304SEvan Yan *
17126947304SEvan Yan * The main routine determines which subcommand is used,
17226947304SEvan Yan * and dispatches control to the corresponding function.
17326947304SEvan Yan */
17426947304SEvan Yan int
main(int argc,char * argv[])17526947304SEvan Yan main(int argc, char *argv[])
17626947304SEvan Yan {
17726947304SEvan Yan int i, rv;
17826947304SEvan Yan
17926947304SEvan Yan (void) setlocale(LC_ALL, "");
18026947304SEvan Yan (void) textdomain(TEXT_DOMAIN);
18126947304SEvan Yan
18226947304SEvan Yan if ((prog = strrchr(argv[0], '/')) == NULL)
18326947304SEvan Yan prog = argv[0];
18426947304SEvan Yan else
18526947304SEvan Yan prog++;
18626947304SEvan Yan
18726947304SEvan Yan if (argc < 2) {
18826947304SEvan Yan usage(NULL);
18926947304SEvan Yan return (EXIT_EINVAL);
19026947304SEvan Yan }
19126947304SEvan Yan
19226947304SEvan Yan parse_common(argc, argv, NULL);
19326947304SEvan Yan
19426947304SEvan Yan /* Check the list of defined subcommands. */
19526947304SEvan Yan for (i = 0; i < (sizeof (subcmds) / sizeof (subcmd_t)); i++) {
19626947304SEvan Yan if (strcmp(argv[1], subcmds[i].cmd_str) == 0) {
19726947304SEvan Yan rv = subcmds[i].func(argc - 1, &argv[1],
19826947304SEvan Yan subcmds[i].usage_str);
19926947304SEvan Yan goto finished;
20026947304SEvan Yan }
20126947304SEvan Yan }
20226947304SEvan Yan
20326947304SEvan Yan /* Check the list of hidden subcommands. */
20426947304SEvan Yan for (i = 0; i < (sizeof (hidden_subcmds) / sizeof (subcmd_t)); i++) {
20526947304SEvan Yan if (strcmp(argv[1], hidden_subcmds[i].cmd_str) == 0) {
20626947304SEvan Yan rv = hidden_subcmds[i].func(argc - 1, &argv[1],
20726947304SEvan Yan hidden_subcmds[i].usage_str);
20826947304SEvan Yan goto finished;
20926947304SEvan Yan }
21026947304SEvan Yan }
21126947304SEvan Yan
21226947304SEvan Yan /* No matching subcommand found. */
21326947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: %s: unknown subcommand '%s'\n"),
21426947304SEvan Yan prog, argv[1]);
21526947304SEvan Yan usage(NULL);
21626947304SEvan Yan exit(EXIT_EINVAL);
21726947304SEvan Yan
21826947304SEvan Yan finished:
21926947304SEvan Yan /* Determine exit code */
22026947304SEvan Yan switch (rv) {
22126947304SEvan Yan case 0:
22226947304SEvan Yan break;
22326947304SEvan Yan case EINVAL:
22426947304SEvan Yan return (EXIT_EINVAL);
22526947304SEvan Yan case ENXIO:
22626947304SEvan Yan case ENOENT:
22726947304SEvan Yan return (EXIT_ENOENT);
22826947304SEvan Yan case EBADF:
22926947304SEvan Yan return (EXIT_UNAVAIL);
23026947304SEvan Yan default:
23126947304SEvan Yan return (EXIT_FAILED);
23226947304SEvan Yan }
23326947304SEvan Yan
23426947304SEvan Yan return (EXIT_OK);
23526947304SEvan Yan }
23626947304SEvan Yan
23726947304SEvan Yan /*
23826947304SEvan Yan * cmd_list()
23926947304SEvan Yan *
24026947304SEvan Yan * Subcommand to list hotplug information.
24126947304SEvan Yan */
24226947304SEvan Yan static int
cmd_list(int argc,char * argv[],const char * usage_str)24326947304SEvan Yan cmd_list(int argc, char *argv[], const char *usage_str)
24426947304SEvan Yan {
24526947304SEvan Yan hp_node_t root;
24626947304SEvan Yan char *path = NULL;
24726947304SEvan Yan char *connection = NULL;
24826947304SEvan Yan boolean_t long_flag = B_FALSE;
24926947304SEvan Yan int flags = 0;
25026947304SEvan Yan int opt;
25126947304SEvan Yan
25226947304SEvan Yan /* Parse command line options */
25326947304SEvan Yan parse_common(argc, argv, usage_str);
25426947304SEvan Yan while ((opt = getopt_clip(argc, argv, "lv", list_opts, NULL)) != -1) {
25526947304SEvan Yan switch (opt) {
25626947304SEvan Yan case 'l':
25726947304SEvan Yan long_flag = B_TRUE;
25826947304SEvan Yan break;
25926947304SEvan Yan case 'v':
26026947304SEvan Yan flags |= HPINFOUSAGE;
26126947304SEvan Yan break;
26226947304SEvan Yan default:
26326947304SEvan Yan bad_option(opt, optopt, usage_str);
26426947304SEvan Yan break;
26526947304SEvan Yan }
26626947304SEvan Yan }
26726947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str);
26826947304SEvan Yan
26926947304SEvan Yan /* Default path is "/" */
27026947304SEvan Yan if (path == NULL)
27126947304SEvan Yan path = "/";
27226947304SEvan Yan
27326947304SEvan Yan /* Get hotplug information snapshot */
27426947304SEvan Yan if ((root = hp_init(path, connection, flags)) == NULL) {
27526947304SEvan Yan print_error(errno);
27626947304SEvan Yan return (errno);
27726947304SEvan Yan }
27826947304SEvan Yan
27926947304SEvan Yan /* Display hotplug information */
28026947304SEvan Yan (void) hp_traverse(root, NULL, long_flag ? list_long_cb : list_cb);
28126947304SEvan Yan
28226947304SEvan Yan /* Discard hotplug information snapshot */
28326947304SEvan Yan hp_fini(root);
28426947304SEvan Yan
28526947304SEvan Yan return (0);
28626947304SEvan Yan }
28726947304SEvan Yan
28826947304SEvan Yan /*
28926947304SEvan Yan * cmd_online()
29026947304SEvan Yan *
29126947304SEvan Yan * Subcommand to online a hotplug port.
29226947304SEvan Yan */
29326947304SEvan Yan static int
cmd_online(int argc,char * argv[],const char * usage_str)29426947304SEvan Yan cmd_online(int argc, char *argv[], const char *usage_str)
29526947304SEvan Yan {
29626947304SEvan Yan hp_node_t root;
29726947304SEvan Yan hp_node_t results = NULL;
29826947304SEvan Yan char *path = NULL;
29926947304SEvan Yan char *connection = NULL;
30026947304SEvan Yan int rv;
30126947304SEvan Yan
30226947304SEvan Yan /* Parse command line options */
30326947304SEvan Yan parse_common(argc, argv, usage_str);
30426947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str);
30526947304SEvan Yan
30626947304SEvan Yan /* Path and connection are required */
30726947304SEvan Yan if ((path == NULL) || (connection == NULL)) {
30826947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
30926947304SEvan Yan usage(usage_str);
31026947304SEvan Yan return (EINVAL);
31126947304SEvan Yan }
31226947304SEvan Yan
31326947304SEvan Yan /* Get hotplug information snapshot */
31426947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) {
31526947304SEvan Yan print_error(errno);
31626947304SEvan Yan return (errno);
31726947304SEvan Yan }
31826947304SEvan Yan
31926947304SEvan Yan /* Verify target is a port */
32026947304SEvan Yan if (hp_type(root) != HP_NODE_PORT) {
32126947304SEvan Yan (void) fprintf(stderr,
32226947304SEvan Yan gettext("ERROR: invalid target (must be a port).\n"));
32326947304SEvan Yan hp_fini(root);
32426947304SEvan Yan return (EINVAL);
32526947304SEvan Yan }
32626947304SEvan Yan
32726947304SEvan Yan /* Do state change */
32826947304SEvan Yan rv = hp_set_state(root, 0, DDI_HP_CN_STATE_ONLINE, &results);
32926947304SEvan Yan
33026947304SEvan Yan /* Display results */
33126947304SEvan Yan if (rv == EIO) {
33226947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: failed to attach device "
33326947304SEvan Yan "drivers or other internal errors.\n"));
33426947304SEvan Yan } else if (rv != 0) {
33526947304SEvan Yan print_error(rv);
33626947304SEvan Yan }
33726947304SEvan Yan if (results != NULL) {
33826947304SEvan Yan (void) hp_traverse(results, NULL, error_cb);
33926947304SEvan Yan hp_fini(results);
34026947304SEvan Yan }
34126947304SEvan Yan
34226947304SEvan Yan /* Discard hotplug information snapshot */
34326947304SEvan Yan hp_fini(root);
34426947304SEvan Yan
34526947304SEvan Yan return (rv);
34626947304SEvan Yan }
34726947304SEvan Yan
34826947304SEvan Yan /*
34926947304SEvan Yan * cmd_offline()
35026947304SEvan Yan *
35126947304SEvan Yan * Subcommand to offline a hotplug port.
35226947304SEvan Yan */
35326947304SEvan Yan static int
cmd_offline(int argc,char * argv[],const char * usage_str)35426947304SEvan Yan cmd_offline(int argc, char *argv[], const char *usage_str)
35526947304SEvan Yan {
35626947304SEvan Yan hp_node_t root;
35726947304SEvan Yan hp_node_t results = NULL;
35826947304SEvan Yan char *path = NULL;
35926947304SEvan Yan char *connection = NULL;
36026947304SEvan Yan int flags = 0;
36126947304SEvan Yan int rv;
36226947304SEvan Yan
36326947304SEvan Yan /* Parse command line options */
36426947304SEvan Yan parse_common(argc, argv, usage_str);
36526947304SEvan Yan parse_flags(argc, argv, &flags, usage_str);
36626947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str);
36726947304SEvan Yan
36826947304SEvan Yan /* Path and connection are required */
36926947304SEvan Yan if ((path == NULL) || (connection == NULL)) {
37026947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
37126947304SEvan Yan usage(usage_str);
37226947304SEvan Yan return (EINVAL);
37326947304SEvan Yan }
37426947304SEvan Yan
37526947304SEvan Yan /* Get hotplug information snapshot */
37626947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) {
37726947304SEvan Yan print_error(errno);
37826947304SEvan Yan return (errno);
37926947304SEvan Yan }
38026947304SEvan Yan
38126947304SEvan Yan /* Verify target is a port */
38226947304SEvan Yan if (hp_type(root) != HP_NODE_PORT) {
38326947304SEvan Yan (void) fprintf(stderr,
38426947304SEvan Yan gettext("ERROR: invalid target (must be a port).\n"));
38526947304SEvan Yan hp_fini(root);
38626947304SEvan Yan return (EINVAL);
38726947304SEvan Yan }
38826947304SEvan Yan
38926947304SEvan Yan /* Do state change */
39026947304SEvan Yan rv = hp_set_state(root, flags, DDI_HP_CN_STATE_OFFLINE, &results);
39126947304SEvan Yan
39226947304SEvan Yan /* Display results */
39326947304SEvan Yan print_error(rv);
39426947304SEvan Yan if (results != NULL) {
39526947304SEvan Yan (void) hp_traverse(results, NULL, error_cb);
39626947304SEvan Yan hp_fini(results);
39726947304SEvan Yan }
39826947304SEvan Yan
39926947304SEvan Yan /* Discard hotplug information snapshot */
40026947304SEvan Yan hp_fini(root);
40126947304SEvan Yan
40226947304SEvan Yan return (rv);
40326947304SEvan Yan }
40426947304SEvan Yan
40526947304SEvan Yan /*
40626947304SEvan Yan * cmd_enable()
40726947304SEvan Yan *
40826947304SEvan Yan * Subcommand to enable a hotplug connector.
40926947304SEvan Yan */
41026947304SEvan Yan static int
cmd_enable(int argc,char * argv[],const char * usage_str)41126947304SEvan Yan cmd_enable(int argc, char *argv[], const char *usage_str)
41226947304SEvan Yan {
41326947304SEvan Yan hp_node_t root;
41426947304SEvan Yan hp_node_t results = NULL;
41526947304SEvan Yan char *path = NULL;
41626947304SEvan Yan char *connection = NULL;
41726947304SEvan Yan int rv;
41826947304SEvan Yan
41926947304SEvan Yan /* Parse command line options */
42026947304SEvan Yan parse_common(argc, argv, usage_str);
42126947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str);
42226947304SEvan Yan
42326947304SEvan Yan /* Path and connection are required */
42426947304SEvan Yan if ((path == NULL) || (connection == NULL)) {
42526947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
42626947304SEvan Yan usage(usage_str);
42726947304SEvan Yan return (EINVAL);
42826947304SEvan Yan }
42926947304SEvan Yan
43026947304SEvan Yan /* Get hotplug information snapshot */
43126947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) {
43226947304SEvan Yan print_error(errno);
43326947304SEvan Yan return (errno);
43426947304SEvan Yan }
43526947304SEvan Yan
43626947304SEvan Yan /* Verify target is a connector */
43726947304SEvan Yan if (hp_type(root) != HP_NODE_CONNECTOR) {
43826947304SEvan Yan (void) fprintf(stderr,
43926947304SEvan Yan gettext("ERROR: invalid target (must be a connector).\n"));
44026947304SEvan Yan hp_fini(root);
44126947304SEvan Yan return (EINVAL);
44226947304SEvan Yan }
44326947304SEvan Yan
44426947304SEvan Yan /* Do state change */
44526947304SEvan Yan rv = hp_set_state(root, 0, DDI_HP_CN_STATE_ENABLED, &results);
44626947304SEvan Yan
44726947304SEvan Yan /* Display results */
44826947304SEvan Yan print_error(rv);
44926947304SEvan Yan if (results != NULL) {
45026947304SEvan Yan (void) hp_traverse(results, NULL, error_cb);
45126947304SEvan Yan hp_fini(results);
45226947304SEvan Yan }
45326947304SEvan Yan
45426947304SEvan Yan /* Discard hotplug information snapshot */
45526947304SEvan Yan hp_fini(root);
45626947304SEvan Yan
45726947304SEvan Yan return (rv);
45826947304SEvan Yan }
45926947304SEvan Yan
46026947304SEvan Yan /*
46126947304SEvan Yan * cmd_disable()
46226947304SEvan Yan *
46326947304SEvan Yan * Subcommand to disable a hotplug connector.
46426947304SEvan Yan */
46526947304SEvan Yan static int
cmd_disable(int argc,char * argv[],const char * usage_str)46626947304SEvan Yan cmd_disable(int argc, char *argv[], const char *usage_str)
46726947304SEvan Yan {
46826947304SEvan Yan hp_node_t root;
46926947304SEvan Yan hp_node_t results = NULL;
47026947304SEvan Yan char *path = NULL;
47126947304SEvan Yan char *connection = NULL;
47226947304SEvan Yan int flags = 0;
47326947304SEvan Yan int rv;
47426947304SEvan Yan
47526947304SEvan Yan /* Parse command line options */
47626947304SEvan Yan parse_common(argc, argv, usage_str);
47726947304SEvan Yan parse_flags(argc, argv, &flags, usage_str);
47826947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str);
47926947304SEvan Yan
48026947304SEvan Yan /* Path and connection are required */
48126947304SEvan Yan if ((path == NULL) || (connection == NULL)) {
48226947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
48326947304SEvan Yan usage(usage_str);
48426947304SEvan Yan return (EINVAL);
48526947304SEvan Yan }
48626947304SEvan Yan
48726947304SEvan Yan /* Get hotplug information snapshot */
48826947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) {
48926947304SEvan Yan print_error(errno);
49026947304SEvan Yan return (errno);
49126947304SEvan Yan }
49226947304SEvan Yan
49326947304SEvan Yan /* Verify target is a connector */
49426947304SEvan Yan if (hp_type(root) != HP_NODE_CONNECTOR) {
49526947304SEvan Yan (void) fprintf(stderr,
49626947304SEvan Yan gettext("ERROR: invalid target (must be a connector).\n"));
49726947304SEvan Yan hp_fini(root);
49826947304SEvan Yan return (EINVAL);
49926947304SEvan Yan }
50026947304SEvan Yan
50126947304SEvan Yan /*
50226947304SEvan Yan * Do nothing unless the connector is in the ENABLED state.
50326947304SEvan Yan * Otherwise this subcommand becomes an alias for 'poweron.'
50426947304SEvan Yan */
50526947304SEvan Yan if (hp_state(root) != DDI_HP_CN_STATE_ENABLED) {
50626947304SEvan Yan hp_fini(root);
50726947304SEvan Yan return (0);
50826947304SEvan Yan }
50926947304SEvan Yan
51026947304SEvan Yan /* Do state change */
51126947304SEvan Yan rv = hp_set_state(root, flags, DDI_HP_CN_STATE_POWERED, &results);
51226947304SEvan Yan
51326947304SEvan Yan /* Display results */
51426947304SEvan Yan print_error(rv);
51526947304SEvan Yan if (results != NULL) {
51626947304SEvan Yan (void) hp_traverse(results, NULL, error_cb);
51726947304SEvan Yan hp_fini(results);
51826947304SEvan Yan }
51926947304SEvan Yan
52026947304SEvan Yan /* Discard hotplug information snapshot */
52126947304SEvan Yan hp_fini(root);
52226947304SEvan Yan
52326947304SEvan Yan return (rv);
52426947304SEvan Yan }
52526947304SEvan Yan
52626947304SEvan Yan /*
52726947304SEvan Yan * cmd_poweron()
52826947304SEvan Yan *
52926947304SEvan Yan * Subcommand to power on a hotplug connector.
53026947304SEvan Yan */
53126947304SEvan Yan static int
cmd_poweron(int argc,char * argv[],const char * usage_str)53226947304SEvan Yan cmd_poweron(int argc, char *argv[], const char *usage_str)
53326947304SEvan Yan {
53426947304SEvan Yan hp_node_t root;
53526947304SEvan Yan hp_node_t results = NULL;
53626947304SEvan Yan char *path = NULL;
53726947304SEvan Yan char *connection = NULL;
53826947304SEvan Yan int rv;
53926947304SEvan Yan
54026947304SEvan Yan /* Parse command line options */
54126947304SEvan Yan parse_common(argc, argv, usage_str);
54226947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str);
54326947304SEvan Yan
54426947304SEvan Yan /* Path and connection are required */
54526947304SEvan Yan if ((path == NULL) || (connection == NULL)) {
54626947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
54726947304SEvan Yan usage(usage_str);
54826947304SEvan Yan return (EINVAL);
54926947304SEvan Yan }
55026947304SEvan Yan
55126947304SEvan Yan /* Get hotplug information snapshot */
55226947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) {
55326947304SEvan Yan print_error(errno);
55426947304SEvan Yan return (errno);
55526947304SEvan Yan }
55626947304SEvan Yan
55726947304SEvan Yan /* Verify target is a connector */
55826947304SEvan Yan if (hp_type(root) != HP_NODE_CONNECTOR) {
55926947304SEvan Yan (void) fprintf(stderr,
56026947304SEvan Yan gettext("ERROR: invalid target (must be a connector).\n"));
56126947304SEvan Yan hp_fini(root);
56226947304SEvan Yan return (EINVAL);
56326947304SEvan Yan }
56426947304SEvan Yan
56526947304SEvan Yan /*
56626947304SEvan Yan * Do nothing if the connector is already powered.
56726947304SEvan Yan * Otherwise this subcommand becomes an alias for 'disable.'
56826947304SEvan Yan */
56926947304SEvan Yan if (hp_state(root) >= DDI_HP_CN_STATE_POWERED) {
57026947304SEvan Yan hp_fini(root);
57126947304SEvan Yan return (0);
57226947304SEvan Yan }
57326947304SEvan Yan
57426947304SEvan Yan /* Do state change */
57526947304SEvan Yan rv = hp_set_state(root, 0, DDI_HP_CN_STATE_POWERED, &results);
57626947304SEvan Yan
57726947304SEvan Yan /* Display results */
57826947304SEvan Yan print_error(rv);
57926947304SEvan Yan if (results != NULL) {
58026947304SEvan Yan (void) hp_traverse(results, NULL, error_cb);
58126947304SEvan Yan hp_fini(results);
58226947304SEvan Yan }
58326947304SEvan Yan
58426947304SEvan Yan /* Discard hotplug information snapshot */
58526947304SEvan Yan hp_fini(root);
58626947304SEvan Yan
58726947304SEvan Yan return (rv);
58826947304SEvan Yan }
58926947304SEvan Yan
59026947304SEvan Yan /*
59126947304SEvan Yan * cmd_poweroff()
59226947304SEvan Yan *
59326947304SEvan Yan * Subcommand to power off a hotplug connector.
59426947304SEvan Yan */
59526947304SEvan Yan static int
cmd_poweroff(int argc,char * argv[],const char * usage_str)59626947304SEvan Yan cmd_poweroff(int argc, char *argv[], const char *usage_str)
59726947304SEvan Yan {
59826947304SEvan Yan hp_node_t root;
59926947304SEvan Yan hp_node_t results = NULL;
60026947304SEvan Yan char *path = NULL;
60126947304SEvan Yan char *connection = NULL;
60226947304SEvan Yan int flags = 0;
60326947304SEvan Yan int rv;
60426947304SEvan Yan
60526947304SEvan Yan /* Parse command line options */
60626947304SEvan Yan parse_common(argc, argv, usage_str);
60726947304SEvan Yan parse_flags(argc, argv, &flags, usage_str);
60826947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str);
60926947304SEvan Yan
61026947304SEvan Yan /* Path and connection are required */
61126947304SEvan Yan if ((path == NULL) || (connection == NULL)) {
61226947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
61326947304SEvan Yan usage(usage_str);
61426947304SEvan Yan return (EINVAL);
61526947304SEvan Yan }
61626947304SEvan Yan
61726947304SEvan Yan /* Get hotplug information snapshot */
61826947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) {
61926947304SEvan Yan print_error(errno);
62026947304SEvan Yan return (errno);
62126947304SEvan Yan }
62226947304SEvan Yan
62326947304SEvan Yan /* Verify target is a connector */
62426947304SEvan Yan if (hp_type(root) != HP_NODE_CONNECTOR) {
62526947304SEvan Yan (void) fprintf(stderr,
62626947304SEvan Yan gettext("ERROR: invalid target (must be a connector).\n"));
62726947304SEvan Yan hp_fini(root);
62826947304SEvan Yan return (EINVAL);
62926947304SEvan Yan }
63026947304SEvan Yan
63126947304SEvan Yan /* Do state change */
63226947304SEvan Yan rv = hp_set_state(root, flags, DDI_HP_CN_STATE_PRESENT, &results);
63326947304SEvan Yan
63426947304SEvan Yan /* Display results */
63526947304SEvan Yan print_error(rv);
63626947304SEvan Yan if (results != NULL) {
63726947304SEvan Yan (void) hp_traverse(results, NULL, error_cb);
63826947304SEvan Yan hp_fini(results);
63926947304SEvan Yan }
64026947304SEvan Yan
64126947304SEvan Yan /* Discard hotplug information snapshot */
64226947304SEvan Yan hp_fini(root);
64326947304SEvan Yan
64426947304SEvan Yan return (rv);
64526947304SEvan Yan }
64626947304SEvan Yan
64726947304SEvan Yan /*
64826947304SEvan Yan * cmd_getpriv()
64926947304SEvan Yan *
65026947304SEvan Yan * Subcommand to get and display bus private options.
65126947304SEvan Yan */
65226947304SEvan Yan static int
cmd_getpriv(int argc,char * argv[],const char * usage_str)65326947304SEvan Yan cmd_getpriv(int argc, char *argv[], const char *usage_str)
65426947304SEvan Yan {
65526947304SEvan Yan hp_node_t root;
65626947304SEvan Yan char *path = NULL;
65726947304SEvan Yan char *connection = NULL;
65826947304SEvan Yan char *options = NULL;
65926947304SEvan Yan char *results = NULL;
66026947304SEvan Yan int rv;
66126947304SEvan Yan
66226947304SEvan Yan /* Parse command line options */
66326947304SEvan Yan parse_common(argc, argv, usage_str);
66426947304SEvan Yan parse_options(argc, argv, &options, usage_str);
66526947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str);
66626947304SEvan Yan
66726947304SEvan Yan /* Options, path, and connection are all required */
66826947304SEvan Yan if ((options == NULL) || (path == NULL) || (connection == NULL)) {
66926947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
67026947304SEvan Yan usage(usage_str);
67126947304SEvan Yan return (EINVAL);
67226947304SEvan Yan }
67326947304SEvan Yan
67426947304SEvan Yan /* Get hotplug information snapshot */
67526947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) {
67626947304SEvan Yan print_error(errno);
67726947304SEvan Yan return (errno);
67826947304SEvan Yan }
67926947304SEvan Yan
68026947304SEvan Yan /* Verify target is a connector */
68126947304SEvan Yan if (hp_type(root) != HP_NODE_CONNECTOR) {
68226947304SEvan Yan (void) fprintf(stderr,
68326947304SEvan Yan gettext("ERROR: invalid target (must be a connector).\n"));
68426947304SEvan Yan hp_fini(root);
68526947304SEvan Yan return (EINVAL);
68626947304SEvan Yan }
68726947304SEvan Yan
68826947304SEvan Yan /* Do the operation */
68926947304SEvan Yan rv = hp_get_private(root, options, &results);
69026947304SEvan Yan
69126947304SEvan Yan /* Display results */
69226947304SEvan Yan if (rv == ENOTSUP) {
69326947304SEvan Yan (void) fprintf(stderr,
69426947304SEvan Yan gettext("ERROR: unsupported property name or value.\n"));
69526947304SEvan Yan (void) fprintf(stderr,
69626947304SEvan Yan gettext("(Properties may depend upon connector state.)\n"));
69726947304SEvan Yan } else if (rv != 0) {
69826947304SEvan Yan print_error(rv);
69926947304SEvan Yan }
70026947304SEvan Yan if (results != NULL) {
70126947304SEvan Yan print_options(results);
70226947304SEvan Yan free(results);
70326947304SEvan Yan }
70426947304SEvan Yan
70526947304SEvan Yan /* Discard hotplug information snapshot */
70626947304SEvan Yan hp_fini(root);
70726947304SEvan Yan
70826947304SEvan Yan return (rv);
70926947304SEvan Yan }
71026947304SEvan Yan
71126947304SEvan Yan /*
71226947304SEvan Yan * cmd_setpriv()
71326947304SEvan Yan *
71426947304SEvan Yan * Subcommand to set bus private options.
71526947304SEvan Yan */
71626947304SEvan Yan static int
cmd_setpriv(int argc,char * argv[],const char * usage_str)71726947304SEvan Yan cmd_setpriv(int argc, char *argv[], const char *usage_str)
71826947304SEvan Yan {
71926947304SEvan Yan hp_node_t root;
72026947304SEvan Yan char *path = NULL;
72126947304SEvan Yan char *connection = NULL;
72226947304SEvan Yan char *options = NULL;
72326947304SEvan Yan char *results = NULL;
72426947304SEvan Yan int rv;
72526947304SEvan Yan
72626947304SEvan Yan /* Parse command line options */
72726947304SEvan Yan parse_common(argc, argv, usage_str);
72826947304SEvan Yan parse_options(argc, argv, &options, usage_str);
72926947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str);
73026947304SEvan Yan
73126947304SEvan Yan /* Options, path, and connection are all required */
73226947304SEvan Yan if ((options == NULL) || (path == NULL) || (connection == NULL)) {
73326947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
73426947304SEvan Yan usage(usage_str);
73526947304SEvan Yan return (EINVAL);
73626947304SEvan Yan }
73726947304SEvan Yan
73826947304SEvan Yan /* Get hotplug information snapshot */
73926947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) {
74026947304SEvan Yan print_error(errno);
74126947304SEvan Yan return (errno);
74226947304SEvan Yan }
74326947304SEvan Yan
74426947304SEvan Yan /* Verify target is a connector */
74526947304SEvan Yan if (hp_type(root) != HP_NODE_CONNECTOR) {
74626947304SEvan Yan (void) fprintf(stderr,
74726947304SEvan Yan gettext("ERROR: invalid target (must be a connector).\n"));
74826947304SEvan Yan hp_fini(root);
74926947304SEvan Yan return (EINVAL);
75026947304SEvan Yan }
75126947304SEvan Yan
75226947304SEvan Yan /* Do the operation */
75326947304SEvan Yan rv = hp_set_private(root, options, &results);
75426947304SEvan Yan
75526947304SEvan Yan /* Display results */
75626947304SEvan Yan if (rv == ENOTSUP) {
75726947304SEvan Yan (void) fprintf(stderr,
75826947304SEvan Yan gettext("ERROR: unsupported property name or value.\n"));
75926947304SEvan Yan (void) fprintf(stderr,
76026947304SEvan Yan gettext("(Properties may depend upon connector state.)\n"));
76126947304SEvan Yan } else if (rv != 0) {
76226947304SEvan Yan print_error(rv);
76326947304SEvan Yan }
76426947304SEvan Yan if (results != NULL) {
76526947304SEvan Yan print_options(results);
76626947304SEvan Yan free(results);
76726947304SEvan Yan }
76826947304SEvan Yan
76926947304SEvan Yan /* Discard hotplug information snapshot */
77026947304SEvan Yan hp_fini(root);
77126947304SEvan Yan
77226947304SEvan Yan return (rv);
77326947304SEvan Yan }
77426947304SEvan Yan
77526947304SEvan Yan /*
77626947304SEvan Yan * cmd_changestate()
77726947304SEvan Yan *
77826947304SEvan Yan * Subcommand to initiate a state change operation. This is
77926947304SEvan Yan * a hidden subcommand to directly set a connector or port to
78026947304SEvan Yan * a specific target state.
78126947304SEvan Yan */
78226947304SEvan Yan static int
cmd_changestate(int argc,char * argv[],const char * usage_str)78326947304SEvan Yan cmd_changestate(int argc, char *argv[], const char *usage_str)
78426947304SEvan Yan {
78526947304SEvan Yan hp_node_t root;
78626947304SEvan Yan hp_node_t results = NULL;
78726947304SEvan Yan char *path = NULL;
78826947304SEvan Yan char *connection = NULL;
78926947304SEvan Yan int state = -1;
79026947304SEvan Yan int flags = 0;
79126947304SEvan Yan int opt, rv;
79226947304SEvan Yan
79326947304SEvan Yan /* Parse command line options */
79426947304SEvan Yan parse_common(argc, argv, usage_str);
79526947304SEvan Yan while ((opt = getopt_clip(argc, argv, "fqs:", changestate_opts,
79626947304SEvan Yan NULL)) != -1) {
79726947304SEvan Yan switch (opt) {
79826947304SEvan Yan case 'f':
79926947304SEvan Yan flags |= HPFORCE;
80026947304SEvan Yan break;
80126947304SEvan Yan case 'q':
80226947304SEvan Yan flags |= HPQUERY;
80326947304SEvan Yan break;
80426947304SEvan Yan case 's':
80526947304SEvan Yan if ((state = state_atoi(optarg)) == -1) {
80626947304SEvan Yan (void) printf("ERROR: invalid target state\n");
80726947304SEvan Yan return (EINVAL);
80826947304SEvan Yan }
80926947304SEvan Yan break;
81026947304SEvan Yan default:
81126947304SEvan Yan bad_option(opt, optopt, usage_str);
81226947304SEvan Yan break;
81326947304SEvan Yan }
81426947304SEvan Yan }
81526947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str);
81626947304SEvan Yan
81726947304SEvan Yan /* State, path, and connection are all required */
81826947304SEvan Yan if ((state == -1) || (path == NULL) || (connection == NULL)) {
81926947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
82026947304SEvan Yan usage(usage_str);
82126947304SEvan Yan return (EINVAL);
82226947304SEvan Yan }
82326947304SEvan Yan
82426947304SEvan Yan /* Check that target state is valid */
82526947304SEvan Yan if (valid_target(state) == 0) {
82626947304SEvan Yan (void) fprintf(stderr,
82726947304SEvan Yan gettext("ERROR: invalid target state\n"));
82826947304SEvan Yan return (EINVAL);
82926947304SEvan Yan }
83026947304SEvan Yan
83126947304SEvan Yan /* Get hotplug information snapshot */
83226947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) {
83326947304SEvan Yan print_error(errno);
83426947304SEvan Yan return (errno);
83526947304SEvan Yan }
83626947304SEvan Yan
83726947304SEvan Yan /* Initiate state change operation on root of snapshot */
83826947304SEvan Yan rv = hp_set_state(root, flags, state, &results);
83926947304SEvan Yan
84026947304SEvan Yan /* Display results */
84126947304SEvan Yan print_error(rv);
84226947304SEvan Yan if (results) {
84326947304SEvan Yan (void) hp_traverse(results, NULL, error_cb);
84426947304SEvan Yan hp_fini(results);
84526947304SEvan Yan }
84626947304SEvan Yan
84726947304SEvan Yan /* Discard hotplug information snapshot */
84826947304SEvan Yan hp_fini(root);
84926947304SEvan Yan
85026947304SEvan Yan return (rv);
85126947304SEvan Yan }
85226947304SEvan Yan
85326947304SEvan Yan /*
85426947304SEvan Yan * parse_common()
85526947304SEvan Yan *
85626947304SEvan Yan * Parse command line options that are common to the
85726947304SEvan Yan * entire program, and to each of its subcommands.
85826947304SEvan Yan */
85926947304SEvan Yan static void
parse_common(int argc,char * argv[],const char * usage_str)86026947304SEvan Yan parse_common(int argc, char *argv[], const char *usage_str)
86126947304SEvan Yan {
86226947304SEvan Yan int opt;
86326947304SEvan Yan extern int opterr;
86426947304SEvan Yan extern int optind;
86526947304SEvan Yan
86626947304SEvan Yan /* Turn off error reporting */
86726947304SEvan Yan opterr = 0;
86826947304SEvan Yan
86926947304SEvan Yan while ((opt = getopt_clip(argc, argv, "?V", common_opts, NULL)) != -1) {
87026947304SEvan Yan switch (opt) {
87126947304SEvan Yan case '?':
87226947304SEvan Yan if (optopt == '?') {
87326947304SEvan Yan usage(usage_str);
87426947304SEvan Yan exit(0);
87526947304SEvan Yan }
87626947304SEvan Yan break;
87726947304SEvan Yan case 'V':
87826947304SEvan Yan (void) printf(gettext("%s: Version %s\n"),
87926947304SEvan Yan prog, version);
88026947304SEvan Yan exit(0);
88126947304SEvan Yan default:
88226947304SEvan Yan break;
88326947304SEvan Yan }
88426947304SEvan Yan }
88526947304SEvan Yan
88626947304SEvan Yan /* Reset option index */
88726947304SEvan Yan optind = 1;
88826947304SEvan Yan }
88926947304SEvan Yan
89026947304SEvan Yan /*
89126947304SEvan Yan * parse_flags()
89226947304SEvan Yan *
89326947304SEvan Yan * Parse command line flags common to all downward state
89426947304SEvan Yan * change operations (offline, disable, poweoff).
89526947304SEvan Yan */
89626947304SEvan Yan static void
parse_flags(int argc,char * argv[],int * flagsp,const char * usage_str)89726947304SEvan Yan parse_flags(int argc, char *argv[], int *flagsp, const char *usage_str)
89826947304SEvan Yan {
89926947304SEvan Yan int opt;
90026947304SEvan Yan int flags = 0;
90126947304SEvan Yan
90226947304SEvan Yan while ((opt = getopt_clip(argc, argv, "fq", flag_opts, NULL)) != -1) {
90326947304SEvan Yan switch (opt) {
90426947304SEvan Yan case 'f':
90526947304SEvan Yan flags |= HPFORCE;
90626947304SEvan Yan break;
90726947304SEvan Yan case 'q':
90826947304SEvan Yan flags |= HPQUERY;
90926947304SEvan Yan break;
91026947304SEvan Yan default:
91126947304SEvan Yan bad_option(opt, optopt, usage_str);
91226947304SEvan Yan break;
91326947304SEvan Yan }
91426947304SEvan Yan }
91526947304SEvan Yan
91626947304SEvan Yan *flagsp = flags;
91726947304SEvan Yan }
91826947304SEvan Yan
91926947304SEvan Yan /*
92026947304SEvan Yan * parse_options()
92126947304SEvan Yan *
92226947304SEvan Yan * Parse command line options common to the bus private set and
92326947304SEvan Yan * get subcommands.
92426947304SEvan Yan */
92526947304SEvan Yan static void
parse_options(int argc,char * argv[],char ** optionsp,const char * usage_str)92626947304SEvan Yan parse_options(int argc, char *argv[], char **optionsp, const char *usage_str)
92726947304SEvan Yan {
92826947304SEvan Yan int opt;
92926947304SEvan Yan
93026947304SEvan Yan while ((opt = getopt_clip(argc, argv, "o:", private_opts,
93126947304SEvan Yan NULL)) != -1) {
93226947304SEvan Yan switch (opt) {
93326947304SEvan Yan case 'o':
93426947304SEvan Yan *optionsp = optarg;
93526947304SEvan Yan break;
93626947304SEvan Yan default:
93726947304SEvan Yan bad_option(opt, optopt, usage_str);
93826947304SEvan Yan break;
93926947304SEvan Yan }
94026947304SEvan Yan }
94126947304SEvan Yan }
94226947304SEvan Yan
94326947304SEvan Yan /*
94426947304SEvan Yan * parse_target()
94526947304SEvan Yan *
94626947304SEvan Yan * Parse the target path and connection name from the command line.
94726947304SEvan Yan */
94826947304SEvan Yan static void
parse_target(int argc,char * argv[],char ** pathp,char ** connectionp,const char * usage_str)94926947304SEvan Yan parse_target(int argc, char *argv[], char **pathp, char **connectionp,
95026947304SEvan Yan const char *usage_str)
95126947304SEvan Yan {
95226947304SEvan Yan extern int optind;
95326947304SEvan Yan
95426947304SEvan Yan if (optind < argc)
95526947304SEvan Yan *pathp = argv[optind++];
95626947304SEvan Yan
95726947304SEvan Yan if (optind < argc)
95826947304SEvan Yan *connectionp = argv[optind++];
95926947304SEvan Yan
96026947304SEvan Yan if (optind < argc) {
96126947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too many arguments.\n"));
96226947304SEvan Yan usage(usage_str);
96326947304SEvan Yan exit(EINVAL);
96426947304SEvan Yan }
96526947304SEvan Yan }
96626947304SEvan Yan
96726947304SEvan Yan /*
96826947304SEvan Yan * bad_option()
96926947304SEvan Yan *
97026947304SEvan Yan * Routine to handle bad command line options.
97126947304SEvan Yan */
97226947304SEvan Yan static void
bad_option(int opt,int optopt,const char * usage_str)97326947304SEvan Yan bad_option(int opt, int optopt, const char *usage_str)
97426947304SEvan Yan {
97526947304SEvan Yan switch (opt) {
97626947304SEvan Yan case ':':
97726947304SEvan Yan (void) fprintf(stderr,
97826947304SEvan Yan gettext("ERROR: option '%c' requires an argument.\n"),
97926947304SEvan Yan optopt);
98026947304SEvan Yan break;
98126947304SEvan Yan default:
98226947304SEvan Yan if (optopt == '?') {
98326947304SEvan Yan usage(usage_str);
98426947304SEvan Yan exit(EXIT_OK);
98526947304SEvan Yan }
98626947304SEvan Yan (void) fprintf(stderr,
98726947304SEvan Yan gettext("ERROR: unrecognized option '%c'.\n"), optopt);
98826947304SEvan Yan break;
98926947304SEvan Yan }
99026947304SEvan Yan
99126947304SEvan Yan usage(usage_str);
99226947304SEvan Yan
99326947304SEvan Yan exit(EXIT_EINVAL);
99426947304SEvan Yan }
99526947304SEvan Yan
99626947304SEvan Yan /*
99726947304SEvan Yan * usage()
99826947304SEvan Yan *
99926947304SEvan Yan * Display general usage of the command. Including
100026947304SEvan Yan * the usage synopsis of each defined subcommand.
100126947304SEvan Yan */
100226947304SEvan Yan static void
usage(const char * usage_str)100326947304SEvan Yan usage(const char *usage_str)
100426947304SEvan Yan {
100526947304SEvan Yan int i;
100626947304SEvan Yan
100726947304SEvan Yan if (usage_str != NULL) {
100826947304SEvan Yan (void) fprintf(stderr, gettext("Usage: %s %s\n\n"),
100926947304SEvan Yan prog, usage_str);
101026947304SEvan Yan return;
101126947304SEvan Yan }
101226947304SEvan Yan
101326947304SEvan Yan (void) fprintf(stderr, gettext("Usage: %s <subcommand> [<args>]\n\n"),
101426947304SEvan Yan prog);
101526947304SEvan Yan
101626947304SEvan Yan (void) fprintf(stderr, gettext("Subcommands:\n\n"));
101726947304SEvan Yan
101826947304SEvan Yan for (i = 0; i < (sizeof (subcmds) / sizeof (subcmd_t)); i++)
101926947304SEvan Yan (void) fprintf(stderr, " %s\n\n", subcmds[i].usage_str);
102026947304SEvan Yan }
102126947304SEvan Yan
102226947304SEvan Yan /*
102326947304SEvan Yan * list_cb()
102426947304SEvan Yan *
102526947304SEvan Yan * Callback function for hp_traverse(), to display nodes
102626947304SEvan Yan * of a hotplug information snapshot. (Short version.)
102726947304SEvan Yan */
102826947304SEvan Yan /*ARGSUSED*/
102926947304SEvan Yan static int
list_cb(hp_node_t node,void * arg)103026947304SEvan Yan list_cb(hp_node_t node, void *arg)
103126947304SEvan Yan {
103226947304SEvan Yan hp_node_t parent;
103326947304SEvan Yan
103426947304SEvan Yan /* Indent */
103526947304SEvan Yan for (parent = hp_parent(node); parent; parent = hp_parent(parent))
103626947304SEvan Yan if (hp_type(parent) == HP_NODE_DEVICE)
103726947304SEvan Yan (void) printf(" ");
103826947304SEvan Yan
103926947304SEvan Yan switch (hp_type(node)) {
104026947304SEvan Yan case HP_NODE_DEVICE:
104126947304SEvan Yan (void) printf("%s\n", hp_name(node));
104226947304SEvan Yan break;
104326947304SEvan Yan
104426947304SEvan Yan case HP_NODE_CONNECTOR:
104526947304SEvan Yan (void) printf("[%s]", hp_name(node));
104626947304SEvan Yan (void) printf(" (%s)", state_itoa(hp_state(node)));
104726947304SEvan Yan (void) printf("\n");
104826947304SEvan Yan break;
104926947304SEvan Yan
105026947304SEvan Yan case HP_NODE_PORT:
105126947304SEvan Yan (void) printf("<%s>", hp_name(node));
105226947304SEvan Yan (void) printf(" (%s)", state_itoa(hp_state(node)));
105326947304SEvan Yan (void) printf("\n");
105426947304SEvan Yan break;
105526947304SEvan Yan
105626947304SEvan Yan case HP_NODE_USAGE:
105726947304SEvan Yan (void) printf("{ %s }\n", hp_usage(node));
105826947304SEvan Yan break;
105926947304SEvan Yan }
106026947304SEvan Yan
106126947304SEvan Yan return (HP_WALK_CONTINUE);
106226947304SEvan Yan }
106326947304SEvan Yan
106426947304SEvan Yan /*
106526947304SEvan Yan * list_long_cb()
106626947304SEvan Yan *
106726947304SEvan Yan * Callback function for hp_traverse(), to display nodes
106826947304SEvan Yan * of a hotplug information snapshot. (Long version.)
106926947304SEvan Yan */
107026947304SEvan Yan /*ARGSUSED*/
107126947304SEvan Yan static int
list_long_cb(hp_node_t node,void * arg)107226947304SEvan Yan list_long_cb(hp_node_t node, void *arg)
107326947304SEvan Yan {
107426947304SEvan Yan char path[MAXPATHLEN];
107526947304SEvan Yan char connection[MAXPATHLEN];
107626947304SEvan Yan
107726947304SEvan Yan if (hp_type(node) != HP_NODE_USAGE) {
107826947304SEvan Yan if (hp_path(node, path, connection) != 0)
107926947304SEvan Yan return (HP_WALK_CONTINUE);
108026947304SEvan Yan (void) printf("%s", path);
108126947304SEvan Yan }
108226947304SEvan Yan
108326947304SEvan Yan switch (hp_type(node)) {
108426947304SEvan Yan case HP_NODE_CONNECTOR:
108526947304SEvan Yan (void) printf(" [%s]", connection);
108626947304SEvan Yan (void) printf(" (%s)", state_itoa(hp_state(node)));
108726947304SEvan Yan break;
108826947304SEvan Yan
108926947304SEvan Yan case HP_NODE_PORT:
109026947304SEvan Yan (void) printf(" <%s>", connection);
109126947304SEvan Yan (void) printf(" (%s)", state_itoa(hp_state(node)));
109226947304SEvan Yan break;
109326947304SEvan Yan
109426947304SEvan Yan case HP_NODE_USAGE:
109526947304SEvan Yan (void) printf(" { %s }", hp_usage(node));
109626947304SEvan Yan break;
109726947304SEvan Yan }
109826947304SEvan Yan
109926947304SEvan Yan (void) printf("\n");
110026947304SEvan Yan
110126947304SEvan Yan return (HP_WALK_CONTINUE);
110226947304SEvan Yan }
110326947304SEvan Yan
110426947304SEvan Yan /*
110526947304SEvan Yan * error_cb()
110626947304SEvan Yan *
110726947304SEvan Yan * Callback function for hp_traverse(), to display
110826947304SEvan Yan * error results from a state change operation.
110926947304SEvan Yan */
111026947304SEvan Yan /*ARGSUSED*/
111126947304SEvan Yan static int
error_cb(hp_node_t node,void * arg)111226947304SEvan Yan error_cb(hp_node_t node, void *arg)
111326947304SEvan Yan {
111426947304SEvan Yan hp_node_t child;
111526947304SEvan Yan char *usage_str;
111626947304SEvan Yan static char path[MAXPATHLEN];
111726947304SEvan Yan static char connection[MAXPATHLEN];
111826947304SEvan Yan
111926947304SEvan Yan if (((child = hp_child(node)) != NULL) &&
112026947304SEvan Yan (hp_type(child) == HP_NODE_USAGE)) {
112126947304SEvan Yan if (hp_path(node, path, connection) == 0)
112226947304SEvan Yan (void) printf("%s:\n", path);
112326947304SEvan Yan return (HP_WALK_CONTINUE);
112426947304SEvan Yan }
112526947304SEvan Yan
112626947304SEvan Yan if ((hp_type(node) == HP_NODE_USAGE) &&
112726947304SEvan Yan ((usage_str = hp_usage(node)) != NULL))
112826947304SEvan Yan (void) printf(" { %s }\n", usage_str);
112926947304SEvan Yan
113026947304SEvan Yan return (HP_WALK_CONTINUE);
113126947304SEvan Yan }
113226947304SEvan Yan
113326947304SEvan Yan /*
113426947304SEvan Yan * print_options()
113526947304SEvan Yan *
113626947304SEvan Yan * Parse and display bus private options. The options are
113726947304SEvan Yan * formatted as a string which conforms to the getsubopt(3C)
113826947304SEvan Yan * format. This routine only splits the string elements as
113926947304SEvan Yan * separated by commas, and displays each portion on its own
114026947304SEvan Yan * separate line of output.
114126947304SEvan Yan */
114226947304SEvan Yan static void
print_options(const char * options)114326947304SEvan Yan print_options(const char *options)
114426947304SEvan Yan {
114526947304SEvan Yan char *buf, *curr, *next;
114626947304SEvan Yan size_t len;
114726947304SEvan Yan
114826947304SEvan Yan /* Do nothing if options string is empty */
114926947304SEvan Yan if ((len = strlen(options)) == 0)
115026947304SEvan Yan return;
115126947304SEvan Yan
115226947304SEvan Yan /* To avoid modifying the input string, make a copy on the stack */
115326947304SEvan Yan if ((buf = (char *)alloca(len + 1)) == NULL) {
115426947304SEvan Yan (void) printf("%s\n", options);
115526947304SEvan Yan return;
115626947304SEvan Yan }
115726947304SEvan Yan (void) strlcpy(buf, options, len + 1);
115826947304SEvan Yan
115926947304SEvan Yan /* Iterate through each comma-separated name/value pair */
116026947304SEvan Yan curr = buf;
116126947304SEvan Yan do {
116226947304SEvan Yan if ((next = strchr(curr, ',')) != NULL) {
116326947304SEvan Yan *next = '\0';
116426947304SEvan Yan next++;
116526947304SEvan Yan }
116626947304SEvan Yan (void) printf("%s\n", curr);
116726947304SEvan Yan } while ((curr = next) != NULL);
116826947304SEvan Yan }
116926947304SEvan Yan
117026947304SEvan Yan /*
117126947304SEvan Yan * print_error()
117226947304SEvan Yan *
117326947304SEvan Yan * Common routine to print error numbers in an appropriate way.
117426947304SEvan Yan * Prints nothing if error code is 0.
117526947304SEvan Yan */
117626947304SEvan Yan static void
print_error(int error)117726947304SEvan Yan print_error(int error)
117826947304SEvan Yan {
117926947304SEvan Yan switch (error) {
118026947304SEvan Yan case 0:
118126947304SEvan Yan /* No error */
118226947304SEvan Yan return;
118326947304SEvan Yan case EACCES:
118426947304SEvan Yan (void) fprintf(stderr,
118526947304SEvan Yan gettext("ERROR: operation not authorized.\n"));
118626947304SEvan Yan break;
118726947304SEvan Yan case EBADF:
118826947304SEvan Yan (void) fprintf(stderr,
118926947304SEvan Yan gettext("ERROR: hotplug service is not available.\n"));
119026947304SEvan Yan break;
119126947304SEvan Yan case EBUSY:
119226947304SEvan Yan (void) fprintf(stderr,
119326947304SEvan Yan gettext("ERROR: devices or resources are busy.\n"));
119426947304SEvan Yan break;
119526947304SEvan Yan case EEXIST:
119626947304SEvan Yan (void) fprintf(stderr,
119726947304SEvan Yan gettext("ERROR: resource already exists.\n"));
119826947304SEvan Yan break;
119926947304SEvan Yan case EFAULT:
120026947304SEvan Yan (void) fprintf(stderr,
120126947304SEvan Yan gettext("ERROR: internal failure in hotplug service.\n"));
120226947304SEvan Yan break;
120326947304SEvan Yan case EINVAL:
120426947304SEvan Yan (void) fprintf(stderr,
120526947304SEvan Yan gettext("ERROR: invalid arguments.\n"));
120626947304SEvan Yan break;
120726947304SEvan Yan case ENOENT:
120826947304SEvan Yan (void) fprintf(stderr,
120926947304SEvan Yan gettext("ERROR: there are no connections to display.\n"));
121026947304SEvan Yan (void) fprintf(stderr,
1211*bbf21555SRichard Lowe gettext("(See hotplug(8) for more information.)\n"));
121226947304SEvan Yan break;
121326947304SEvan Yan case ENXIO:
121426947304SEvan Yan (void) fprintf(stderr,
121526947304SEvan Yan gettext("ERROR: no such path or connection.\n"));
121626947304SEvan Yan break;
121726947304SEvan Yan case ENOMEM:
121826947304SEvan Yan (void) fprintf(stderr,
121926947304SEvan Yan gettext("ERROR: not enough memory.\n"));
122026947304SEvan Yan break;
122126947304SEvan Yan case ENOTSUP:
122226947304SEvan Yan (void) fprintf(stderr,
122326947304SEvan Yan gettext("ERROR: operation not supported.\n"));
122426947304SEvan Yan break;
122526947304SEvan Yan case EIO:
122626947304SEvan Yan (void) fprintf(stderr,
122726947304SEvan Yan gettext("ERROR: hardware or driver specific failure.\n"));
122826947304SEvan Yan break;
122926947304SEvan Yan default:
123026947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: operation failed: %s\n"),
123126947304SEvan Yan strerror(error));
123226947304SEvan Yan break;
123326947304SEvan Yan }
123426947304SEvan Yan }
123526947304SEvan Yan
123626947304SEvan Yan /*
123726947304SEvan Yan * state_atoi()
123826947304SEvan Yan *
123926947304SEvan Yan * Convert a hotplug state from a string to an integer.
124026947304SEvan Yan */
124126947304SEvan Yan static int
state_atoi(char * state)124226947304SEvan Yan state_atoi(char *state)
124326947304SEvan Yan {
124426947304SEvan Yan int i;
124526947304SEvan Yan
124626947304SEvan Yan for (i = 0; hpstates[i].state_str != NULL; i++)
124726947304SEvan Yan if (strcasecmp(state, hpstates[i].state_str) == 0)
124826947304SEvan Yan return (hpstates[i].state);
124926947304SEvan Yan
125026947304SEvan Yan return (-1);
125126947304SEvan Yan }
125226947304SEvan Yan
125326947304SEvan Yan /*
125426947304SEvan Yan * state_itoa()
125526947304SEvan Yan *
125626947304SEvan Yan * Convert a hotplug state from an integer to a string.
125726947304SEvan Yan */
125826947304SEvan Yan static char *
state_itoa(int state)125926947304SEvan Yan state_itoa(int state)
126026947304SEvan Yan {
126126947304SEvan Yan static char unknown[] = "UNKNOWN";
126226947304SEvan Yan int i;
126326947304SEvan Yan
126426947304SEvan Yan for (i = 0; hpstates[i].state_str != NULL; i++)
126526947304SEvan Yan if (state == hpstates[i].state)
126626947304SEvan Yan return (hpstates[i].state_str);
126726947304SEvan Yan
126826947304SEvan Yan return (unknown);
126926947304SEvan Yan }
127026947304SEvan Yan
127126947304SEvan Yan /*
127226947304SEvan Yan * valid_target()
127326947304SEvan Yan *
127426947304SEvan Yan * Check if a state is a valid target for a changestate command.
127526947304SEvan Yan */
127626947304SEvan Yan static short
valid_target(int state)127726947304SEvan Yan valid_target(int state)
127826947304SEvan Yan {
127926947304SEvan Yan int i;
128026947304SEvan Yan
128126947304SEvan Yan for (i = 0; hpstates[i].state_str != NULL; i++)
128226947304SEvan Yan if (state == hpstates[i].state)
128326947304SEvan Yan return (hpstates[i].valid_target);
128426947304SEvan Yan
128526947304SEvan Yan return (0);
128626947304SEvan Yan }
1287