4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
29 #include <sys/param.h>
39 #include <sys/usb/usba/wusba_io.h>
40 #include <sys/usb/clients/wusb_ca/wusb_ca.h>
41 #include "crypto_util.h"
46 * The following exit values are returned:
47 * 0 Successful operation
48 * 1 Error: the operation failed.
51 #define WUSB_EXIT_SUCCESS 0
52 #define WUSB_EXIT_FAILURE 1
53 #define WUSB_EXIT_USAGE 2
57 #define ASSO_CABLE_NAME "wusb_ca"
59 #define WUSB_MAX_LEN 255
61 #define WUSB_HOSTID_LEN 2
62 #define WUSB_DEVID_LEN 6
64 /* wusba admin list options */
65 #define WUSB_FIELD_WIDTH 20
67 #define WUSB_LIST_HOST 0x01
68 #define WUSB_LIST_DEV 0x02
69 #define WUSB_LIST_HD (WUSB_LIST_HOST | WUSB_LIST_DEV)
70 #define WUSB_LIST_ID 0x04
71 #define WUSB_LIST_TYPE 0x08
72 #define WUSB_LIST_STATE 0x10
73 #define WUSB_LIST_ALL (WUSB_LIST_ID | WUSB_LIST_TYPE | WUSB_LIST_STATE)
75 /* cable device list */
76 typedef struct dev_list
{
77 char path
[MAXPATHLEN
];
78 struct dev_list
*next
;
81 static wusb_device_info_t
*dev_lists
= NULL
;
82 static uint32_t cnt
= 0;
84 /* log and debug helpers */
85 static void wusb_prt(const char *, ...);
86 static void wusb_usage(const char *, ...);
87 static void wusb_fail(const char *, ...);
88 static void wusb_opterr(int, int);
92 /* load host/dev list helpers */
93 static void wusb_load_list(wusb_device_info_t
**, uint32_t *cnt
);
94 static void wusb_free_list(wusb_device_info_t
*);
96 /* door call helpers */
97 static int wusb_door_req(int, door_arg_t
*, char *, int);
98 static void wusb_door_free(door_arg_t
*);
99 static uint16_t wusb_door_result(door_arg_t
*da
);
102 static void wusb_check_auth(const char *);
103 /* usr input funcs */
104 static void user_confirm(char *);
105 static void user_input(char *, char *, int);
107 /* string translation helpers */
108 static uint32_t str2id(char *);
112 static const struct option wusb_list_opts
[] = {
113 { "host", no_argument
, NULL
, 'h'},
114 { "device", no_argument
, NULL
, 'd'},
115 { "output", required_argument
, NULL
, 'o'},
118 static const char *WUSB_LIST_HEADER
[] = {
119 "ID", /* host-id or dev-id */
120 "STATE", /* host or device states */
121 "TYPE", /* host or deivce types */
125 static void do_list(int, char **);
126 static void do_list_args(int, char **, char *);
128 static void parse_subopts(char *, const char *);
129 static int parse_option(char *, const char *);
131 static void wusb_prt_titles(char);
132 static void wusb_prt_lists(char, wusb_device_info_t
*);
135 static int find_dev_id(uint8_t, uint16_t);
136 static void parse_dev_id(const char *, wusb_dev_ctrl_t
*);
137 static void parse_host_id(char *, uint8_t *);
140 static struct option wusb_asso_opts
[] = {
141 { "host", required_argument
, NULL
, 'h'},
142 { "cable", no_argument
, NULL
, 'c'},
143 { "numeric", required_argument
, NULL
, 'n'},
144 { "force", no_argument
, NULL
, 'f'},
145 { "onetime", no_argument
, NULL
, 'o'},
148 static void do_associate(int, char **);
149 static void do_asso_args(int, char **, wusb_asso_ctrl_t
*);
151 static int input_host_id(uint8_t *);
152 static void input_dev_id(wusb_dev_ctrl_t
*);
153 #ifdef NUMERIC_ENABLED
154 static int input_asso_type(uint8_t *);
156 static int select_cable_device(char *);
159 static struct option wusb_rmdev_opts
[] = {
160 { "host", required_argument
, NULL
, 'h'},
161 { "device", required_argument
, NULL
, 'd'},
162 { "force", no_argument
, NULL
, 'f'},
166 /* remove/enable/disable host */
167 static struct option wusb_host_opts
[] = {
168 { "host", required_argument
, NULL
, 'h'},
169 { "force", no_argument
, NULL
, 'f'},
173 static void do_host(int, char **, int);
174 static void do_host_args(int, char **, int, wusb_dev_ctrl_t
*);
175 static void do_remove_host(int, char **);
176 static void do_enable_host(int, char **);
177 static void do_disable_host(int, char **);
179 static void do_remove_dev(int, char **);
180 static void do_remove_dev_args(int, char **, wusb_dev_ctrl_t
*);
184 /* error message maps */
189 { WUSBADM_OK
, "success" },
190 { WUSBADM_AUTH_FAILURE
, "permisson denied" },
191 { WUSBADM_NO_HOST
, "host does not exist" },
192 { WUSBADM_NO_DEVICE
, "device does not exist" },
193 { WUSBADM_CCSTORE_ACC
, "fail to access CC store" },
194 { WUSBADM_NO_SUPPORT
, "command not supported" },
195 { WUSBADM_INVAL_HOSTID
, "invalid host id" },
196 { WUSBADM_INVAL_DEVID
, "invalid device id" },
197 { WUSBADM_HOST_NOT_ATTACH
, "host not attached" },
198 { WUSBADM_FAILURE
, "unknown error"}
202 wusb_strerror(int err
)
204 if (err
< 0 || err
> WUSBADM_FAILURE
) {
206 return (wusb_errors
[WUSBADM_FAILURE
].errmsg
);
209 return (wusb_errors
[err
].errmsg
);
214 * wusbadm cmd line tool is used for used to administrate the wireless usb
215 * host and wireless usb devices.
216 * list - List the device and host status
217 * associated - Setup assocaition between host and devices.
218 * remove-dev - Remove the assocation of device
219 * remove-host - Remove the host information and all the devices assocaiton to
221 * enable-host - Enable a host to be ready to accept wireless devices
222 * disable-host - Disable a host, host will not accpet connections
226 main(int argc
, char **argv
)
231 void (*func
)(int, char **);
234 { "list", do_list
, WUSB_AUTH_READ
},
235 { "associate", do_associate
, WUSB_AUTH_MODIFY
},
236 { "remove-dev", do_remove_dev
, WUSB_AUTH_MODIFY
},
237 { "remove-host", do_remove_host
, WUSB_AUTH_HOST
},
238 { "enable-host", do_enable_host
, WUSB_AUTH_HOST
},
239 { "disable-host", do_disable_host
, WUSB_AUTH_HOST
},
244 (void) setlocale(LC_ALL
, "");
247 #define TEXT_DOMAIN "SYS_TEST"
249 (void) textdomain(TEXT_DOMAIN
);
253 exit(WUSB_EXIT_USAGE
);
256 /* start wusb damemon */
257 if (strcmp(argv
[1], "--daemon") == 0) {
259 exit(WUSB_EXIT_SUCCESS
);
264 for (i
= 0; cmd_list
[i
].cmd
; i
++) {
265 if (strcmp(cmd_list
[i
].cmd
, argv
[1]) == 0) {
269 if (!cmd_list
[i
].cmd
) {
270 wusb_usage("unknown option %s", argv
[1]);
272 wusb_check_auth(cmd_list
[i
].auth
);
274 wusb_load_list(&dev_lists
, &cnt
);
276 cmd_list
[i
].func(argc
- 1, &argv
[1]);
278 wusb_free_list(dev_lists
);
279 return (WUSB_EXIT_SUCCESS
);
285 wusb_prt("\nUsage:\twusbadm sub-command args ...\n\n");
286 wusb_prt("\tlist [-h | -d] [-o field[,...]]\n");
287 wusb_prt("\tassociate [-h host-id] [[-c [-f]] | -n] [-o]\n");
288 wusb_prt("\tremove-dev [[-d dev-id] | [-h host-id]] [-f]\n");
289 wusb_prt("\tremove-host [-h host-id] [-f]\n");
290 wusb_prt("\tenable-host [-h host-id]\n");
291 wusb_prt("\tdisable-host [-h host-id] [-f]\n");
296 * list command routine.
297 * wusbadmin list [-h | -d] [-o field[,...]]
298 * 1. parse the options
299 * 2. load host/deivce info from daemon
300 * 3. print titles accoding to list options
301 * 4. print host/deivce list one by one
304 do_list(int argc
, char **argv
)
309 /* parse the list options */
310 do_list_args(argc
, argv
, &fields
);
313 /* print list title */
314 wusb_prt_titles(fields
);
316 /* print out the result */
317 for (i
= 0; i
< cnt
; i
++) {
318 wusb_prt_lists(fields
, &dev_lists
[i
]);
325 * associate command routine
326 * wusbadmin associate [-h host-id] [[-c [-f] | -n] [-o]
327 * 1. Parse the options and get user input
328 * 2. Send the asso infor the daemon
331 do_associate(int argc
, char **argv
)
334 wusb_asso_ctrl_t asso_ctrl
;
337 /* Get association options */
338 bzero(&asso_ctrl
, sizeof (wusb_asso_ctrl_t
));
339 do_asso_args(argc
, argv
, &asso_ctrl
);
342 (void) wusb_door_req(WUSB_DCMD_ASSOCIATE
, &da
,
343 (char *)&asso_ctrl
, sizeof (wusb_asso_ctrl_t
));
345 /* association result */
346 rval
= wusb_door_result(&da
);
350 if (rval
!= WUSBADM_OK
) {
351 wusb_fail("%s", wusb_strerror(rval
));
356 * remove-dev command routine
357 * remove-dev [[-d dev-id] | [-h host-id]] [-f]
358 * 1. parse options/user input
359 * 2. send message to daemon.
360 * dev-id != 0 means remove one dev
361 * dev-id == 0 means remove all dev with a host
364 do_remove_dev(int argc
, char **argv
)
366 wusb_dev_ctrl_t devctrl
;
369 uint16_t rval
= WUSBADM_OK
;
372 bzero(&devctrl
, sizeof (wusb_dev_ctrl_t
));
373 do_remove_dev_args(argc
, argv
, &devctrl
);
375 /* send command to daemon */
376 (void) wusb_door_req(WUSB_DCMD_REMOVE_DEV
, &da
,
377 (char *)&devctrl
, sizeof (wusb_dev_ctrl_t
));
380 rval
= wusb_door_result(&da
);
384 if (rval
!= WUSBADM_OK
) {
385 wusb_fail("%s", wusb_strerror(rval
));
392 * Send the LOAD_CC request to daemon. Daemon will allocate memory and put
393 * all CCs in that block of memory. We need to free the memory here.
394 * CCs are in data array format.
397 wusb_load_list(wusb_device_info_t
**cc_list
, uint32_t *cnt
)
403 uint16_t rval
= WUSBADM_OK
;
405 /* send command to daemon */
406 (void) wusb_door_req(WUSB_DCMD_LIST_DATA
, &da
, 0, 0);
408 rval
= wusb_door_result(&da
);
409 if (rval
!= WUSBADM_OK
) {
412 wusb_fail("%s", wusb_strerror(rval
));
415 /* number of the devinfo list */
416 (void) memcpy(&num
, da
.data_ptr
+sizeof (uint16_t), sizeof (uint32_t));
420 buflen
= (num
) * sizeof (wusb_device_info_t
);
421 if ((*cc_list
= malloc(buflen
)) == NULL
) {
424 wusb_fail("list: malloc buffer failed");
427 (void) memcpy(*cc_list
,
428 da
.data_ptr
+ sizeof (uint32_t) + sizeof (uint16_t),
433 /* unmap the buffer */
437 wusb_free_list(wusb_device_info_t
*cc_list
)
446 * This is a wrapper of door call for wusb adm tool.
448 * cmd - wusb admin command (WUSB_DCMD_*).
449 * da - door call arg.
451 * databuf - data send to daemon.
452 * size - data buf size.
455 wusb_door_req(int cmd
, door_arg_t
*da
, char *databuf
, int size
)
457 wusb_door_call_t dcall
;
460 bzero(&dcall
, sizeof (wusb_door_call_t
));
463 /* copy data buffer */
465 (void) memcpy(dcall
.buf
, databuf
, size
);
468 /* set rbuf to 0, unmap the data buf later */
469 bzero(da
, sizeof (door_arg_t
));
470 da
->data_ptr
= (char *)&dcall
;
471 da
->data_size
= sizeof (wusb_door_call_t
);
476 if ((fd
= open(DOOR_FILE
, O_RDONLY
)) < 0) {
478 wusb_fail("daemon not started");
482 if (door_call(fd
, da
) != 0) {
485 wusb_fail("daemon out of service:%s", strerror(errno
));
490 if (da
->data_size
== 0) {
492 wusb_fail("no data from daemon");
495 return (WUSBA_SUCCESS
);
499 * After each door call return, the first 2 bytes of the data
500 * returned is encoded as the door call result from daemon.
501 * This is a wrapper to get the door call result
504 wusb_door_result(door_arg_t
*da
) {
506 (void) memcpy(&rval
, da
->data_ptr
, sizeof (uint16_t));
512 * Unmap the buffer after door call.
513 * It is mandatory after any wusb_door_call since we set the rbuf to NULL
514 * in the wusb_door_call. So any buffer returned is from the client proces.
515 * See door_call(3C) for more infor
518 wusb_door_free(door_arg_t
*da
)
520 (void) munmap(da
->rbuf
, da
->rsize
);
524 * wusbadmin remove-host routine
525 * remove-host [-h host-id] [-f]
528 do_remove_host(int argc
, char **argv
)
530 do_host(argc
, argv
, WUSB_DCMD_REMOVE_HOST
);
534 * wusbadmin enable-host routine
535 * enable-host [-h host-id]
538 do_enable_host(int argc
, char **argv
)
540 do_host(argc
, argv
, WUSB_DCMD_ENABLE_HOST
);
544 * wusbadmin disable-host routine
545 * disable-host [-h host-id] [-f]
548 do_disable_host(int argc
, char **argv
)
550 do_host(argc
, argv
, WUSB_DCMD_DISABLE_HOST
);
554 * wusb do host routine. The wrapper for all host related
555 * subcommand (enable-host, disable-host, remove-host).
556 * 1. parser options/user input
557 * 2. send wusb command to daemon
560 do_host(int argc
, char **argv
, int cmd
)
562 wusb_dev_ctrl_t hostctrl
;
568 bzero(&hostctrl
, sizeof (wusb_dev_ctrl_t
));
569 do_host_args(argc
, argv
, cmd
, &hostctrl
);
571 /* door call to daemon */
572 (void) wusb_door_req(cmd
, &da
,
573 (char *)&hostctrl
, sizeof (wusb_dev_ctrl_t
));
575 rval
= wusb_door_result(&da
);
578 if (rval
!= WUSBADM_OK
) {
579 wusb_fail("%s", wusb_strerror(rval
));
584 * wusb list option parser
585 * wusbadmin list [-h | -d] [-o field[,...]]
588 do_list_args(int argc
, char **argv
, char *option
)
593 while ((c
= getopt_long(argc
, argv
, ":hdo:",
594 wusb_list_opts
, NULL
)) != -1) {
597 if (fields
& WUSB_LIST_HOST
) {
598 wusb_usage("too many -h specified");
600 if (fields
& WUSB_LIST_DEV
) {
601 wusb_usage("-h and -d used together");
603 fields
|= WUSB_LIST_HOST
;
606 if (fields
& WUSB_LIST_HOST
) {
607 wusb_usage("-h and -d used together");
609 if (fields
& WUSB_LIST_DEV
) {
610 wusb_usage("too many -d specified");
612 fields
|= WUSB_LIST_DEV
;
615 if (strlen(optarg
) > 63) {
616 wusb_usage("options too long");
618 (void) parse_option(&fields
, optarg
);
621 wusb_opterr(optopt
, c
);
627 wusb_usage("unrecognized options:%s", argv
[optind
++]);
630 /* if no option specified,print out all fields */
631 fields
|= (fields
& WUSB_LIST_HD
)? 0x00:WUSB_LIST_HD
;
632 fields
|= (fields
& WUSB_LIST_ALL
)? 0x00:WUSB_LIST_ALL
;
639 * Print the header for list subcommand.
640 * Each title is right aligned with length of WUSB_FIELD_WIDTH
641 * The following titles will be printed if the relative tags
642 * marked in the fields option.
646 wusb_prt_titles(char fields
)
650 for (option
= WUSB_LIST_ID
;
651 option
<= WUSB_LIST_STATE
;
653 if (fields
& option
) {
654 wusb_prt("%-*s", WUSB_FIELD_WIDTH
,
655 WUSB_LIST_HEADER
[i
]);
659 (void) putchar('\n');
663 * Append the host-id / dev-id to the output buf.
664 * host-id - 2 digits number (XX)
665 * dev-id - 5 digits number (XX.XXX)
666 * See wusbadm (1M) for more
669 append_id(char *buf
, wusb_device_info_t
*devinfo
)
671 char tmp
[WUSB_MAX_LEN
] = {'\0'};
674 (void) snprintf(tmp
, WUSB_MAX_LEN
, "%02d.%03d",
675 devinfo
->host
, devinfo
->dev
);
677 (void) snprintf(tmp
, WUSB_MAX_LEN
, "%02d", devinfo
->host
);
679 (void) snprintf(buf
, WUSB_MAX_LEN
, "%s%-*s",
680 buf
, WUSB_FIELD_WIDTH
, tmp
);
683 * Append state to the output buf.
684 * host - enabled/disabled
685 * device - connected/disconnected
686 * See wusbadm (1M) for more
689 append_state(char *buf
, wusb_device_info_t
*devinfo
)
691 const char *WUSB_DEV_STATE_MSG
[] = {
692 "disconnected", /* WUSB_STATE_UNCONNTED */
693 "connected", /* WUSB_STATE_CONNTING */
694 "connected", /* WUSB_STATE_UNAUTHENTICATED */
695 "connected", /* WUSB_STATE_DEFAULT */
696 "connected", /* WUSB_STATE_ADDRESSED */
697 "connected", /* WUSB_STATE_CONFIGURED */
698 "connected", /* WUSB_STATE_SLEEPING */
699 "connected", /* WUSB_STATE_RECONNTING */
702 const char *WUSB_HOST_STATE_MSG
[] = {
703 "disconnected", /* WUSB_HC_DISCONNTED */
704 "disabled", /* WUSB_HC_STOPPED */
705 "enabled", /* WUSB_HC_STARTED */
706 "disabled", /* WUSB_HC_CH_STOPPED */
709 char tmp
[WUSB_MAX_LEN
] = {'\0'};
713 /* append the state for device */
714 if (devinfo
->stat
> WUSB_STATE_RECONNTING
) {
715 (void) snprintf(tmp
, WUSB_MAX_LEN
, "%s", "unknown");
717 (void) snprintf(tmp
, WUSB_MAX_LEN
, "%s",
718 WUSB_DEV_STATE_MSG
[devinfo
->stat
]);
721 /* append the state for host */
722 if (devinfo
->stat
> WUSB_HC_CH_STOPPED
) {
723 (void) snprintf(tmp
, WUSB_MAX_LEN
, "%s", "unknown");
725 (void) snprintf(tmp
, WUSB_MAX_LEN
, "%s",
726 WUSB_HOST_STATE_MSG
[devinfo
->stat
]);
729 (void) snprintf(buf
, WUSB_MAX_LEN
, "%s%-*s",
730 buf
, WUSB_FIELD_WIDTH
, tmp
);
735 * Appenend host/dev type to the ouput buf string
736 * Currently map the file name to specific types
737 * TODO: how to define the type
740 append_type(char *buf
, wusb_device_info_t
*devinfo
)
742 (void) snprintf(buf
, WUSB_MAX_LEN
, "%s%-*s", buf
, WUSB_FIELD_WIDTH
,
748 * This is core func to print wireless device list on systems.
749 * Print the devinfo list entry with option field
752 wusb_prt_lists(char fields
, wusb_device_info_t
*devinfo
)
754 char buf
[WUSB_MAX_LEN
+1] = {'\0'};
757 void (*append_funcs
[])(char *, wusb_device_info_t
*) = {
764 /* check if dev or host need to be print out */
765 if ((devinfo
->dev
&& !(fields
& WUSB_LIST_DEV
)) ||
766 (!devinfo
->dev
&& !(fields
& WUSB_LIST_HOST
))) {
770 /* Append all the enabled fields to the output buf */
771 for (i
= 0, opt
= WUSB_LIST_ID
;
772 opt
<= WUSB_LIST_STATE
;
775 append_funcs
[i
](buf
, devinfo
);
779 wusb_prt("%s\n", buf
);
783 * wusb association option parser
784 * wusbadmin association [-h host-id] [[-c [-f] | -n] [-o]
785 * Note:Only cable association is supported now
788 do_asso_args(int argc
, char **argv
, wusb_asso_ctrl_t
*asso_ctrl
)
793 while ((c
= getopt_long(argc
, argv
, ":h:cfno", wusb_asso_opts
, 0))
797 parse_host_id(optarg
, &(asso_ctrl
->host
));
800 asso_ctrl
->type
|= ASSO_TYPE_CABLE
;
803 asso_ctrl
->type
|= ASSO_TYPE_NUMERIC
;
809 asso_ctrl
->onetime
= 1;
812 wusb_opterr(optopt
, c
);
818 wusb_usage("unrecognized options:%s", argv
[optind
++]);
821 /* TODO: support cable association */
822 if (asso_ctrl
->type
& ASSO_TYPE_NUMERIC
) {
824 wusb_fail("Numeric association not supported");
827 /* get user input host id */
828 if (!asso_ctrl
->host
) {
829 (void) input_host_id(&asso_ctrl
->host
);
832 /* get user input association type */
833 if (!asso_ctrl
->type
) {
834 asso_ctrl
->type
|= ASSO_TYPE_CABLE
;
835 /* Todo: Will be enabled after Numberic Assocation support */
837 #ifdef NUMERIC_ENABLED
838 (void) input_asso_type(&asso_ctrl
->type
);
842 /* get user input cable device to associate */
843 if (asso_ctrl
->type
== ASSO_TYPE_CABLE
) {
844 (void) select_cable_device(asso_ctrl
->path
);
847 /* confirm with user to continue or not */
849 wusb_prt("Associate device (%s) with host (%02d) via cable\n",
850 asso_ctrl
->path
, asso_ctrl
->host
);
851 user_confirm("Continue ");
856 * Convert a string to an id (host-id/dev-id/cable-dev-id)
857 * Fail if 0 returned, since each id is indexed from 1.
858 * Widely used to handle user input ids.
865 /* check the string and generate int result */
867 if (*arg
< '0' || *arg
> '9') {
871 id
= id
*10+(*arg
-'0');
879 parse_host_id(char *arg
, uint8_t *host
) {
880 int len
= strlen(arg
);
882 if ((len
> WUSB_HOSTID_LEN
) || (len
== 0)) {
883 wusb_fail("host-id should be 2 digits");
885 if ((*host
= str2id(arg
)) == 0) {
886 wusb_fail("invalid host id:%s", arg
);
888 if (find_dev_id(*host
, 0) < 0) {
889 wusb_fail("host-id does not exist: %02d ", *host
);
896 * Get the host from user input.
897 * 1. list all the host id from the daemon
898 * 2. Ask user to input the host id
899 * 3. Check host id and return
902 input_host_id(uint8_t *host
)
905 char fields
= WUSB_LIST_HOST
| WUSB_LIST_ALL
;
906 char buf
[WUSB_MAX_LEN
] = {'\0'};
911 /* show avaialbe host id to usr */
912 wusb_prt_titles(fields
);
913 for (i
= 0; i
< cnt
; i
++) {
914 wusb_prt_lists(fields
, &dev_lists
[i
]);
917 /* get user input of host id */
918 user_input("Please select 2 digits host-id:", buf
, WUSB_MAX_LEN
-1);
919 parse_host_id(buf
, host
);
921 return (WUSBA_SUCCESS
);
924 input_dev_id(wusb_dev_ctrl_t
*devctrl
)
927 char fields
= WUSB_LIST_DEV
| WUSB_LIST_ALL
;
928 char buf
[WUSB_MAX_LEN
] = {'\0'};
933 /* show avaialbe host id to usr */
934 wusb_prt_titles(fields
);
935 for (i
= 0; i
< cnt
; i
++) {
936 wusb_prt_lists(fields
, &dev_lists
[i
]);
939 /* get user input of host id */
940 user_input("Please select dev-id:", buf
, WUSB_MAX_LEN
-1);
942 parse_dev_id(buf
, devctrl
);
945 find_dev_id(uint8_t host
, uint16_t dev
)
947 int rval
= WUSBA_FAILURE
;
950 for (i
= 0; i
< cnt
; i
++) {
951 if ((dev_lists
[i
].dev
== dev
) &&
952 (dev_lists
[i
].host
== host
)) {
953 rval
= WUSBA_SUCCESS
;
963 * Select assocation type.
965 * - Numeric Not supported
967 #ifdef NUMERIC_ENABLED
969 input_asso_type(uint8_t *asso_type
)
971 char buf
[15] = {'\0'};
973 user_input("Select association type (c/n) :", buf
, 14);
974 if (strcasecmp(buf
, "c") == 0) {
975 *asso_type
= ASSO_TYPE_CABLE
;
977 } else if (strcasecmp(buf
, "n") == 0) {
978 *asso_type
= ASSO_TYPE_NUMERIC
;
982 wusb_usage("invalid association type");
984 return (WUSBA_SUCCESS
);
989 * Create a list contains all the cable devices on the system
992 init_cable_devices(dev_list_t
**dev_lists
, int *num
)
994 struct dirent
*entry
= NULL
;
995 dev_list_t
*_devlist
= NULL
;
997 DIR *dirp
= opendir(WUSB_HOST_PATH
);
998 char filename
[MAXPATHLEN
] = {'\0'};
1002 * walk on all the filename in the /dev/usb, check the filename
1003 * to see if it is a cable asso filename and add it to the devinfo
1007 wusb_fail("cable device not available");
1009 while ((entry
= readdir(dirp
)) != NULL
) {
1010 /* searching for cable node */
1011 if (strstr(entry
->d_name
, ASSO_CABLE_NAME
) == NULL
) {
1014 (void) snprintf(filename
, MAXPATHLEN
, "%s/%s",
1015 WUSB_HOST_PATH
, entry
->d_name
);
1017 /* add the filename to the dev list */
1018 if (_devlist
== NULL
) {
1019 _devlist
= malloc(sizeof (dev_list_t
));
1020 *dev_lists
= _devlist
;
1022 _devlist
->next
= malloc(sizeof (dev_list_t
));
1023 _devlist
= _devlist
->next
;
1025 /* this need to be freed */
1026 (void) snprintf(_devlist
->path
, MAXPATHLEN
,
1029 _devlist
->next
= NULL
;
1031 /* increase the list number */
1034 (void) closedir(dirp
);
1036 /* Free the devlist created for cable device */
1038 free_devlist(dev_list_t
*dev_list
)
1040 dev_list_t
*head
= dev_list
;
1042 head
= dev_list
->next
;
1048 /* find the cable dev with the user-inputed index */
1050 get_cable_dev(dev_list_t
*dev_list
, int index
)
1053 while ((i
!= index
) && dev_list
) {
1054 dev_list
= dev_list
->next
;
1060 /* print the cable devlist with index */
1062 show_devlist(dev_list_t
*dev_list
)
1064 /* show all the cable devices to user */
1066 wusb_prt("Cable devices on the system:\n");
1068 wusb_prt("%03d. %s\n", index
, dev_list
->path
);
1069 dev_list
= dev_list
->next
;
1075 * when doing association, all the cable devices on the system
1076 * should be print out to the user
1079 select_cable_device(char *device
)
1081 /* cable association */
1085 dev_list_t
*head
= NULL
;
1086 dev_list_t
*tmp
= NULL
;
1089 /* get all the cable dev on the system */
1090 init_cable_devices(&head
, &devnum
);
1092 /* Get the device name as user input */
1094 wusb_fail("no cable devices found ");
1100 /* get the user input of the cable dev index */
1101 user_input("Select cable device to associate:", buf
, 19);
1102 if (strlen(buf
) != 3) {
1103 wusb_fail("cable device id should be 3 digits");
1105 cableid
= str2id(buf
);
1107 /* check user iput */
1108 if ((cableid
<= 0) || (cableid
> devnum
)) {
1111 wusb_fail("invalid cable device ");
1115 /* if only one dev exist, use it without asking user */
1119 /* find the device to associate */
1120 tmp
= get_cable_dev(head
, cableid
);
1121 (void) snprintf(device
, MAXPATHLEN
, "%s", tmp
->path
);
1126 return (WUSBA_SUCCESS
);
1130 * Parse the -o option for wusbadm list
1133 parse_option(char *fields
, const char *optarg
)
1136 char *lasts
= NULL
, *token
= NULL
;
1137 char buf
[64] = { '\0' };
1139 (void) snprintf(buf
, 64, "%s", optarg
);
1140 if ((token
= strtok_r(buf
, ",", &lasts
)) != 0) {
1141 parse_subopts(fields
, token
);
1142 while ((token
= strtok_r(NULL
, ",", &lasts
))) {
1143 parse_subopts(fields
, token
);
1147 return (WUSBA_SUCCESS
);
1153 * parse the sub option extracted from -o options
1156 parse_subopts(char *fields
, const char *str
)
1160 for (i
= 0, opt
= WUSB_LIST_ID
; opt
<= WUSB_LIST_STATE
; i
++) {
1161 if (strcasecmp(str
, WUSB_LIST_HEADER
[i
]) == 0) {
1168 if (opt
> WUSB_LIST_STATE
) {
1170 wusb_usage("unrecognized options:%s", str
);
1176 * Device id parser for remove-dev
1177 * dev id is 5 digits with format XX.XXX
1180 parse_dev_id(const char *arg
, wusb_dev_ctrl_t
*devctrl
)
1182 char buf
[WUSB_DEVID_LEN
+1] = {'\0'};
1185 if (strlen(arg
) > WUSB_DEVID_LEN
) goto fail
;
1187 (void) snprintf(buf
, WUSB_DEVID_LEN
+1, "%s", arg
);
1189 if ((tmp
= strchr(buf
, '.')) == NULL
) goto fail
;
1192 if ((devctrl
->host
= str2id(buf
)) == 0) {
1197 if ((devctrl
->dev
= str2id(tmp
+1)) == 0) {
1201 if (find_dev_id(devctrl
->host
, devctrl
->dev
) < 0) {
1202 wusb_fail("dev-id does not exist: %02d.%03d ",
1203 devctrl
->host
, devctrl
->dev
);
1208 wusb_fail("unknown device id:%s", arg
);
1212 * remove-dev options parser
1213 * remove-dev [[-d dev-id] | [-h host-id]] [-f]
1216 do_remove_dev_args(int argc
, char **argv
, wusb_dev_ctrl_t
*devctrl
)
1220 bzero(devctrl
, sizeof (wusb_dev_ctrl_t
));
1222 while ((c
= getopt_long(argc
, argv
, ":h:d:f",
1223 wusb_rmdev_opts
, NULL
)) != -1) {
1227 wusb_usage("-h -d can not be"
1230 if (devctrl
->host
) {
1231 wusb_usage("multi -h is not allowed");
1234 /* get 2 digit host id */
1235 parse_host_id(optarg
, &(devctrl
->host
));
1241 wusb_usage("multi -d is not allowed");
1243 if (devctrl
->host
) {
1244 wusb_usage("-h -d can not be"
1248 (void) parse_dev_id(optarg
, devctrl
);
1254 wusb_opterr(optopt
, c
);
1260 if (optind
< argc
) {
1261 wusb_usage("unrecognized options:%s", argv
[optind
++]);
1263 if ((devctrl
->host
== 0) && (devctrl
->dev
== 0)) {
1264 input_dev_id(devctrl
);
1267 /* confirm with user to continue or not */
1270 wusb_prt("Remove the device's association information"
1271 " of device (%02d.%03d) from system.\nThis device"
1272 " can not be connected with the host until it is"
1273 " associated again.\n",
1274 devctrl
->host
, devctrl
->dev
);
1276 wusb_prt("Remove the information of all the devices "
1277 "associated with host (%02d) from the system\n"
1278 "All the devices asociated with the host can not"
1279 " be connected with it until they are associated"
1280 " again.\n", devctrl
->host
);
1282 user_confirm("Continue ");
1286 * Confirm with user continue or not
1287 * info: the information shown to user before input
1290 user_confirm(char *info
)
1295 user_input("(yes/no): ", yesorno
, 19);
1296 if (strcasecmp(yesorno
, "no") == 0) {
1299 if (strcasecmp(yesorno
, "n") == 0) {
1302 if (strcasecmp(yesorno
, "yes") == 0) {
1305 if (strcasecmp(yesorno
, "y") == 0) {
1308 wusb_fail("illegal input: %s", yesorno
);
1312 * msg(in): infor shown to user before input
1313 * length(in): buf size to save uer input
1314 * buf(out): user input saved in buffer
1317 user_input(char *msg
, char *buf
, int length
)
1325 if (b
== '\n' || b
== '\0' || b
== EOF
) {
1340 * do host options parser
1341 * remove-host [-h host-id] [-f]
1342 * enable-host [-h host-id]
1343 * disable-host [-h host-id] [-f]
1346 do_host_args(int argc
, char **argv
, int cmd
, wusb_dev_ctrl_t
*hostctrl
)
1351 while ((c
= getopt_long(argc
, argv
, ":h:f",
1352 wusb_host_opts
, NULL
)) != -1) {
1355 if (hostctrl
->host
) {
1356 wusb_usage("multi -h is not allowed");
1358 /* 2 digits host id */
1359 parse_host_id(optarg
, &(hostctrl
->host
));
1364 /* enable host does not need -f */
1365 if (cmd
== WUSB_DCMD_ENABLE_HOST
) {
1366 wusb_opterr(optopt
, c
);
1371 wusb_opterr(optopt
, c
);
1376 if (optind
< argc
) {
1377 wusb_usage("unrecognized options:%s", argv
[optind
++]);
1380 * all the host related command can be used without a specific
1381 * host-id, so list all the hosts avalable to users for selection
1383 if (hostctrl
->host
== 0) {
1384 (void) input_host_id(&(hostctrl
->host
));
1388 /* confirm with user to continue or not */
1389 if (!force
&& (cmd
!= WUSB_DCMD_ENABLE_HOST
)) {
1391 case WUSB_DCMD_DISABLE_HOST
:
1392 wusb_prt("Disable host (%02d).\nAll the"
1393 " devices connected with the host will be"
1394 " disconnected\n", hostctrl
->host
);
1397 case WUSB_DCMD_REMOVE_HOST
:
1398 wusb_prt("Remove host (%02d).\nAll the"
1399 " association with the host will be"
1400 " removed\n", hostctrl
->host
);
1405 user_confirm("Continue");
1411 wusb_check_auth(const char *auth
) {
1413 uid_t uid
= geteuid();
1414 if (chk_auths(uid
, auth
) < 0) {
1415 wusb_fail("%s", wusb_strerror(WUSBADM_AUTH_FAILURE
));
1420 * wusb exit helper funcstion
1421 * wusb_fail or wusb_usage
1424 wusb_fail(const char *format
, ...)
1428 format
= gettext(format
);
1429 (void) fprintf(stderr
, gettext("wusbadm: "));
1430 va_start(alist
, format
);
1431 (void) vfprintf(stderr
, format
, alist
);
1433 (void) fprintf(stderr
, "\n");
1435 wusb_free_list(dev_lists
);
1436 exit(WUSB_EXIT_FAILURE
);
1439 wusb_usage(const char *format
, ...)
1443 format
= gettext(format
);
1444 (void) fprintf(stderr
, gettext("wusbadm: "));
1445 va_start(alist
, format
);
1446 (void) vfprintf(stderr
, format
, alist
);
1448 (void) fprintf(stderr
, "\n");
1451 wusb_free_list(dev_lists
);
1452 exit(WUSB_EXIT_USAGE
);
1456 /* wusb print helper func */
1458 wusb_prt(const char *format
, ...)
1462 format
= gettext(format
);
1463 va_start(alist
, format
);
1464 (void) vfprintf(stdout
, format
, alist
);
1468 /* wusb option failuer func */
1470 wusb_opterr(int opt
, int opterr
)
1474 wusb_usage("option '-%c' requires a value", opt
);
1478 wusb_usage("unrecognized option '-%c'", opt
);