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 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
31 /* function prototypes */
32 cfga_err_t
usb_err_msg(char **, cfga_usb_ret_t
, const char *, int);
33 extern cfga_usb_ret_t
usb_rcm_offline(const char *, char **, char *,
35 extern cfga_usb_ret_t
usb_rcm_online(const char *, char **, char *,
37 extern cfga_usb_ret_t
usb_rcm_remove(const char *, char **, char *,
39 static int usb_confirm(struct cfga_confirm
*, char *);
40 static char *usb_get_devicepath(const char *);
43 * This file contains the entry points to the plugin as defined in the
44 * config_admin(3X) man page.
48 * Set the version number for the cfgadm library's use.
50 int cfga_version
= CFGA_HSL_V2
;
54 #define HELP_RESET_SLOT 3
55 #define HELP_CONFIG_SLOT 4
56 #define HELP_UNKNOWN 5
62 "USB specific commands:\n",
63 " cfgadm -c [configure|unconfigure|disconnect] ap_id [ap_id...]\n",
64 " cfgadm -x usb_reset ap_id [ap_id...]\n",
65 " cfgadm -x usb_config -o config=<index of desired configuration> ap_id\n",
66 "\tunknown command or option: ",
68 }; /* End help messages */
74 { CVT
, CFGA_OK
, "ok" },
76 /* CFGA_USB_UNKNOWN */
77 { CVT
, CFGA_LIB_ERROR
, "Unknown message; internal error" },
79 /* CFGA_USB_INTERNAL_ERROR */
80 { CVT
, CFGA_LIB_ERROR
, "Internal error" },
82 /* CFGA_USB_OPTIONS */
83 { CVT
, CFGA_ERROR
, "Hardware specific options not supported" },
85 /* CFGA_USB_DYNAMIC_AP */
86 { CVT
, CFGA_INVAL
, "Dynamic attachment points not supported" },
89 { CVT
, CFGA_APID_NOEXIST
, "" },
92 { CVT
, CFGA_LIB_ERROR
, "Cannot determine hub port number for " },
95 { CVT
, CFGA_ERROR
, "Cannot issue devctl to " },
97 /* CFGA_USB_NOT_CONNECTED */
98 { CVT
, CFGA_INVAL
, "No device connected to " },
100 /* CFGA_USB_NOT_CONFIGURED */
101 { CVT
, CFGA_INVAL
, "No device configured to " },
103 /* CFGA_USB_ALREADY_CONNECTED */
104 { CVT
, CFGA_INSUFFICENT_CONDITION
,
105 "Device already connected; cannot connect again " },
107 /* CFGA_USB_ALREADY_CONFIGURED */
108 { CVT
, CFGA_INVAL
, "device already configured for " },
111 { CVT
, CFGA_LIB_ERROR
, "Cannot open " },
114 { CVT
, CFGA_ERROR
, "Driver ioctl failed " },
117 { CVT
, CFGA_SYSTEM_BUSY
, "" },
119 /* CFGA_USB_ALLOC_FAIL */
120 { CVT
, CFGA_LIB_ERROR
, "Memory allocation failure" },
122 /* CFGA_USB_OPNOTSUPP */
123 { CVT
, CFGA_OPNOTSUPP
, "Operation not supported" },
125 /* CFGA_USB_DEVLINK */
126 { CVT
, CFGA_LIB_ERROR
, "Could not find /dev/cfg link for " },
129 { CVT
, CFGA_LIB_ERROR
, "Internal error: Unrecognized ap state" },
131 /* CFGA_USB_CONFIG_INVAL */
133 "Specified configuration index unrecognized or exceeds "
134 "maximum available" },
137 { CVT
, CFGA_PRIV
, "" },
139 /* CFGA_USB_NVLIST */
140 { CVT
, CFGA_ERROR
, "Internal error (nvlist)" },
142 /* CFGA_USB_ZEROLEN */
143 { CVT
, CFGA_ERROR
, "Internal error (zerolength string)" },
145 /* CFGA_USB_CONFIG_FILE */
147 "Cannot open/fstat/read USB system configuration file" },
149 /* CFGA_USB_LOCK_FILE */
150 { CVT
, CFGA_ERROR
, "Cannot lock USB system configuration file" },
152 /* CFGA_USB_UNLOCK_FILE */
153 { CVT
, CFGA_ERROR
, "Cannot unlock USB system configuration file" },
155 /* CFGA_USB_ONE_CONFIG */
157 "Operation not supported for devices with one configuration" },
159 /* CFGA_USB_RCM_HANDLE Errors */
160 { CVT
, CFGA_ERROR
, "cannot get RCM handle"},
162 /* CFGA_USB_RCM_ONLINE */
163 { CVT
, CFGA_SYSTEM_BUSY
, "failed to online: "},
165 /* CFGA_USB_RCM_OFFLINE */
166 { CVT
, CFGA_SYSTEM_BUSY
, "failed to offline: "},
168 /* CFGA_USB_RCM_INFO */
169 { CVT
, CFGA_ERROR
, "failed to query: "}
171 }; /* End error messages */
174 /* ========================================================================= */
176 * The next two funcs imported verbatim from cfgadm_scsi.
177 * physpath_to_devlink is the only func directly used by cfgadm_usb.
178 * get_link supports it.
182 * Routine to search the /dev directory or a subtree of /dev.
185 get_link(di_devlink_t devlink
, void *arg
)
187 walk_link_t
*larg
= (walk_link_t
*)arg
;
190 * When path is specified, it's the node path without minor
191 * name. Therefore, the ../.. prefixes needs to be stripped.
194 char *content
= (char *)di_devlink_content(devlink
);
195 char *start
= strstr(content
, "/devices/");
197 /* line content must have minor node */
199 strncmp(start
, larg
->path
, larg
->len
) != 0 ||
200 start
[larg
->len
] != ':') {
202 return (DI_WALK_CONTINUE
);
206 *(larg
->linkpp
) = strdup(di_devlink_path(devlink
));
208 return (DI_WALK_TERMINATE
);
216 const char *node_path
,
222 di_devlink_handle_t hdl
;
225 if ((hdl
= di_devlink_init(NULL
, 0)) == NULL
) {
227 return (UCFGA_LIB_ERR
);
233 minor_path
= (char *)node_path
+ strlen("/devices");
237 larg
.len
= strlen(node_path
);
238 larg
.path
= (char *)node_path
;
241 (void) di_devlink_walk(hdl
, "^cfg/", minor_path
, DI_PRIMARY_LINK
,
242 (void *)&larg
, get_link
);
244 (void) di_devlink_fini(&hdl
);
246 if (*logpp
== NULL
) {
248 return (UCFGA_LIB_ERR
);
255 /* ========================================================================= */
259 * Given the index into a table (msgcvt_t) of messages, get the message
260 * string, converting it to the proper locale if necessary.
261 * NOTE: See cfga_usb.h
264 get_msg(uint_t msg_index
, msgcvt_t
*msg_tbl
, uint_t tbl_size
)
266 if (msg_index
>= tbl_size
) {
267 DPRINTF("get_error_msg: bad error msg index: %d\n", msg_index
);
268 msg_index
= CFGA_USB_UNKNOWN
;
271 return ((msg_tbl
[msg_index
].intl
) ?
272 dgettext(TEXT_DOMAIN
, msg_tbl
[msg_index
].msgstr
) :
273 msg_tbl
[msg_index
].msgstr
);
278 * Allocates and creates a message string (in *ret_str),
279 * by concatenating all the (char *) args together, in order.
280 * Last arg MUST be NULL.
283 set_msg(char **ret_str
, ...)
289 va_start(valist
, ret_str
);
291 total_len
= (*ret_str
== NULL
) ? 0 : strlen(*ret_str
);
293 while ((str
= va_arg(valist
, char *)) != NULL
) {
294 size_t len
= strlen(str
);
295 char *old_str
= *ret_str
;
297 *ret_str
= (char *)realloc(*ret_str
, total_len
+ len
+ 1);
298 if (*ret_str
== NULL
) {
301 DPRINTF("set_msg: realloc failed.\n");
306 (void) strcpy(*ret_str
+ total_len
, str
);
315 * Error message handling.
316 * For the rv passed in, looks up the corresponding error message string(s),
317 * internationalized it if necessary, and concatenates it into a new
318 * memory buffer, and points *errstring to it.
319 * Note not all rvs will result in an error message return, as not all
320 * error conditions warrant a USB-specific error message.
322 * Some messages may display ap_id or errno, which is why they are passed
326 usb_err_msg(char **errstring
, cfga_usb_ret_t rv
, const char *ap_id
, int l_errno
)
328 if (errstring
== NULL
) {
330 return (usb_error_msgs
[rv
].cfga_err
);
334 * Generate the appropriate USB-specific error message(s) (if any).
338 /* Special case - do nothing. */
341 case CFGA_USB_UNKNOWN
:
342 case CFGA_USB_DYNAMIC_AP
:
343 case CFGA_USB_INTERNAL_ERROR
:
344 case CFGA_USB_OPTIONS
:
345 case CFGA_USB_ALLOC_FAIL
:
347 case CFGA_USB_CONFIG_INVAL
:
349 case CFGA_USB_OPNOTSUPP
:
350 /* These messages require no additional strings passed. */
351 set_msg(errstring
, ERR_STR(rv
), NULL
);
356 case CFGA_USB_NOT_CONNECTED
:
357 case CFGA_USB_NOT_CONFIGURED
:
358 case CFGA_USB_ALREADY_CONNECTED
:
359 case CFGA_USB_ALREADY_CONFIGURED
:
361 case CFGA_USB_DEVLINK
:
362 case CFGA_USB_RCM_HANDLE
:
363 case CFGA_USB_RCM_ONLINE
:
364 case CFGA_USB_RCM_OFFLINE
:
365 case CFGA_USB_RCM_INFO
:
366 case CFGA_USB_DEVCTL
:
367 /* These messages also print ap_id. */
368 (void) set_msg(errstring
, ERR_STR(rv
),
369 "ap_id: ", ap_id
, "", NULL
);
373 case CFGA_USB_NVLIST
:
374 case CFGA_USB_CONFIG_FILE
:
375 case CFGA_USB_ONE_CONFIG
:
376 /* These messages also print errno. */
378 char *errno_str
= l_errno
? strerror(l_errno
) : "";
380 set_msg(errstring
, ERR_STR(rv
), errno_str
,
381 l_errno
? "\n" : "", NULL
);
386 /* These messages also apid and errno. */
388 char *errno_str
= l_errno
? strerror(l_errno
) : "";
390 set_msg(errstring
, ERR_STR(rv
), "ap_id: ", ap_id
, "\n",
391 errno_str
, l_errno
? "\n" : "", NULL
);
396 DPRINTF("usb_err_msg: Unrecognized message index: %d\n", rv
);
397 set_msg(errstring
, ERR_STR(CFGA_USB_INTERNAL_ERROR
), NULL
);
402 * Determine the proper error code to send back to the cfgadm library.
404 return (usb_error_msgs
[rv
].cfga_err
);
409 * Ensure the ap_id passed is in the correct (physical ap_id) form:
410 * path/device:xx[.xx]+
411 * where xx is a one or two-digit number.
413 * Note the library always calls the plugin with a physical ap_id.
416 verify_valid_apid(const char *ap_id
)
424 l_ap_id
= strrchr(ap_id
, *MINOR_SEP
);
427 if (strspn(l_ap_id
, "0123456789.") != strlen(l_ap_id
)) {
428 /* Bad characters in the ap_id. */
432 if (strstr(l_ap_id
, "..") != NULL
) {
433 /* ap_id has 1..2 or more than 2 dots */
442 * Verify the params passed in are valid.
444 static cfga_usb_ret_t
450 if (errstring
!= NULL
) {
454 if (options
!= NULL
) {
455 DPRINTF("verify_params: hardware-specific options not "
457 return (CFGA_USB_OPTIONS
);
460 /* Dynamic attachment points not supported (yet). */
461 if (GET_DYN(ap_id
) != NULL
) {
462 DPRINTF("verify_params: dynamic ap_id passed\n");
463 return (CFGA_USB_DYNAMIC_AP
);
466 if (verify_valid_apid(ap_id
) != 0) {
467 DPRINTF("verify_params: not a USB ap_id.\n");
468 return (CFGA_USB_AP
);
471 return (CFGA_USB_OK
);
476 * Takes a validated ap_id and extracts the port number.
478 static cfga_usb_ret_t
479 get_port_num(const char *ap_id
, uint_t
*port
)
484 port_nbr_str
= strrchr(ap_id
, *MINOR_SEP
) + strlen(MINOR_SEP
);
485 if ((temp
= strrchr(ap_id
, (int)*PORT_SEPERATOR
)) != 0) {
486 port_nbr_str
= temp
+ strlen(PORT_SEPERATOR
);
490 *port
= strtol(port_nbr_str
, NULL
, 10);
492 DPRINTF("get_port_num: conversion of port str failed\n");
493 return (CFGA_USB_PORT
);
496 return (CFGA_USB_OK
);
501 * Pair of routines to set up for/clean up after a devctl_ap_* lib call.
504 cleanup_after_devctl_cmd(devctl_hdl_t devctl_hdl
, nvlist_t
*user_nvlist
)
506 nvlist_free(user_nvlist
);
507 devctl_release(devctl_hdl
);
511 static cfga_usb_ret_t
512 setup_for_devctl_cmd(const char *ap_id
, devctl_hdl_t
*devctl_hdl
,
513 nvlist_t
**user_nvlistp
, uint_t oflag
)
516 cfga_usb_ret_t rv
= CFGA_USB_OK
;
518 DPRINTF("setup_for_devctl_cmd: oflag=%d\n", oflag
);
520 /* Get a handle to the ap */
521 if ((*devctl_hdl
= devctl_ap_acquire((char *)ap_id
, oflag
)) == NULL
) {
522 DPRINTF("setup_for_devctl_cmd: devctl_ap_acquire failed with "
523 "errno: %d\n", errno
);
524 rv
= CFGA_USB_DEVCTL
;
528 /* Set up to pass port number down to driver */
529 if (nvlist_alloc(user_nvlistp
, NV_UNIQUE_NAME_TYPE
, 0) != 0) {
530 DPRINTF("setup_for_devctl: nvlist_alloc failed, errno: %d\n",
532 *user_nvlistp
= NULL
; /* Prevent possible incorrect free in */
533 /* cleanup_after_devctl_cmd */
534 rv
= CFGA_USB_NVLIST
;
538 if ((rv
= get_port_num(ap_id
, &port
)) != CFGA_USB_OK
) {
539 DPRINTF("setup_for_devctl_cmd: get_port_num, errno: %d\n",
544 /* creates an int32_t entry */
545 if (nvlist_add_int32(*user_nvlistp
, PORT
, port
) == -1) {
546 DPRINTF("setup_for_devctl_cmd: nvlist_add_int32 failed. "
547 "errno: %d\n", errno
);
548 rv
= CFGA_USB_NVLIST
;
555 cleanup_after_devctl_cmd(*devctl_hdl
, *user_nvlistp
);
562 * Ensure that there's a device actually connected to the ap
564 static cfga_usb_ret_t
565 device_configured(devctl_hdl_t hdl
, nvlist_t
*nvl
, ap_rstate_t
*rstate
)
568 devctl_ap_state_t devctl_ap_state
;
570 DPRINTF("device_configured:\n");
571 if (devctl_ap_getstate(hdl
, nvl
, &devctl_ap_state
) == -1) {
572 DPRINTF("devctl_ap_getstate failed, errno: %d\n", errno
);
573 return (CFGA_USB_DEVCTL
);
576 rv
= CFGA_USB_ALREADY_CONFIGURED
;
577 *rstate
= devctl_ap_state
.ap_rstate
;
578 if (devctl_ap_state
.ap_ostate
!= AP_OSTATE_CONFIGURED
) {
579 return (CFGA_USB_NOT_CONFIGURED
);
587 * Ensure that there's a device actually connected to the ap
589 static cfga_usb_ret_t
590 device_connected(devctl_hdl_t hdl
, nvlist_t
*list
, ap_ostate_t
*ostate
)
592 cfga_usb_ret_t rv
= CFGA_USB_ALREADY_CONNECTED
;
593 devctl_ap_state_t devctl_ap_state
;
595 DPRINTF("device_connected:\n");
597 if (devctl_ap_getstate(hdl
, list
, &devctl_ap_state
) == -1) {
598 DPRINTF("devctl_ap_getstate failed, errno: %d\n", errno
);
599 return (CFGA_USB_DEVCTL
);
602 *ostate
= devctl_ap_state
.ap_ostate
;
603 if (devctl_ap_state
.ap_rstate
!= AP_RSTATE_CONNECTED
) {
604 return (CFGA_USB_NOT_CONNECTED
);
612 * Given a subcommand to the DEVCTL_AP_CONTROL ioctl, rquest the size of
613 * the data to be returned, allocate a buffer, then get the data.
614 * Returns *descrp (which must be freed) and size.
616 * Note USB_DESCR_TYPE_STRING returns an ASCII NULL-terminated string,
617 * not a string descr.
620 do_control_ioctl(const char *ap_id
, uint_t subcommand
, uint_t arg
,
621 void **descrp
, size_t *sizep
)
626 cfga_usb_ret_t rv
= CFGA_USB_OK
;
627 struct hubd_ioctl_data ioctl_data
;
629 assert(descrp
!= NULL
);
631 assert(sizep
!= NULL
);
633 if ((rv
= get_port_num(ap_id
, &port
)) != CFGA_USB_OK
) {
637 if ((fd
= open(ap_id
, O_RDONLY
)) == -1) {
638 DPRINTF("do_control_ioctl: open failed: errno:%d\n", errno
);
640 if (errno
== EBUSY
) {
646 ioctl_data
.cmd
= subcommand
;
647 ioctl_data
.port
= port
;
648 ioctl_data
.misc_arg
= (uint_t
)arg
;
651 * Find out how large a buf we need to get the data.
653 * Note the ioctls only accept/return a 32-bit int for a get_size
654 * to avoid 32/64 and BE/LE issues.
656 ioctl_data
.get_size
= B_TRUE
;
657 ioctl_data
.buf
= (caddr_t
)&local_size
;
658 ioctl_data
.bufsiz
= sizeof (local_size
);
660 if (ioctl(fd
, DEVCTL_AP_CONTROL
, &ioctl_data
) != 0) {
661 DPRINTF("do_control_ioctl: size ioctl failed: errno:%d\n",
668 if (subcommand
== USB_DESCR_TYPE_STRING
&&
669 arg
== HUBD_CFG_DESCR_STR
&& local_size
== 0) {
670 /* Zero-length data - nothing to do. */
671 rv
= CFGA_USB_ZEROLEN
;
674 if (subcommand
== HUBD_REFRESH_DEVDB
) {
675 /* Already done - no data transfer; nothing left to do. */
679 if ((*descrp
= malloc(*sizep
)) == NULL
) {
680 DPRINTF("do_control_ioctl: malloc failed\n");
681 rv
= CFGA_USB_ALLOC_FAIL
;
686 ioctl_data
.get_size
= B_FALSE
;
687 ioctl_data
.buf
= *descrp
;
688 ioctl_data
.bufsiz
= *sizep
;
690 if (ioctl(fd
, DEVCTL_AP_CONTROL
, &ioctl_data
) != 0) {
691 DPRINTF("do_control_ioctl: ioctl failed: errno:%d\n",
706 if (*descrp
!= NULL
) {
711 if (rv
== CFGA_USB_IOCTL
&& errno
== EBUSY
) {
712 rv
= CFGA_USB_BUSY
; /* Provide more useful msg */
719 /* ========================================================================= */
721 * Support funcs called directly from cfga_* entry points.
726 * Invoked from cfga_private_func.
727 * Modify the USB persistant configuration file so that the device
728 * represented by ap_id will henceforth be initialized to the desired
729 * configuration setting (configuration index).
731 static cfga_usb_ret_t
732 set_configuration(const char *ap_id
, uint_t config
, char *driver
,
733 usb_dev_descr_t
*descrp
, char **errstring
)
735 char *serial_no
= NULL
;
736 char *dev_path
= NULL
;
739 cfga_usb_ret_t rv
= CFGA_USB_OK
;
741 DPRINTF("set_configuration: ap_id: %s, config:%d\n", ap_id
, config
);
743 /* Only one bNumConfigurations, don't allow this operation */
744 if (descrp
->bNumConfigurations
== 1) {
745 DPRINTF("device supports %d configurations\n",
746 descrp
->bNumConfigurations
);
747 rv
= CFGA_USB_ONE_CONFIG
;
751 /* get the serial number string if it exists */
752 if (descrp
->iSerialNumber
!= 0) {
753 if ((rv
= do_control_ioctl(ap_id
, USB_DESCR_TYPE_STRING
,
754 HUBD_SERIALNO_STR
, (void **)&serial_no
, &size
)) !=
756 if (rv
!= CFGA_USB_ZEROLEN
) {
757 DPRINTF("set_configuration: get serial "
758 "no string failed\n");
764 dev_path
= usb_get_devicepath(ap_id
);
765 if (dev_path
== NULL
) {
766 DPRINTF("get device path failed\n");
767 rv
= CFGA_USB_DEVCTL
;
771 DPRINTF("calling add_entry: vid: 0x%x pid:0x%x config:0x%x,",
772 descrp
->idVendor
, descrp
->idProduct
, config
);
773 DPRINTF("serial_no: %s\n\tdev_path: %s\n\tdriver: %s\n", serial_no
?
774 serial_no
: "", dev_path
? dev_path
: "", driver
? driver
: "");
777 * the devicepath should be an absolute path.
778 * So, if path has leading "/devices" - nuke it.
780 if (strncmp(dev_path
, "/devices/", 9) == 0) {
786 /* Save an entry in the USBCONF_FILE */
788 "enable", /* Always to "enable" */
789 descrp
->idVendor
, /* vendorId */
790 descrp
->idProduct
, /* ProductId */
791 config
, /* new cfgndx */
792 serial_no
, /* serial no string */
793 tmp
, /* device path */
794 driver
, /* Driver (optional) */
797 DPRINTF("set_configuration: add_entry failed\n");
801 /* Notify hubd that it needs to refresh its db. */
802 if ((rv
= do_control_ioctl(ap_id
, HUBD_REFRESH_DEVDB
, 0,
803 (void **)&dev_path
, &size
)) != CFGA_USB_OK
) {
804 DPRINTF("set_configuration: HUBD_REFRESH_DEVDB failed\n");
821 * Invoked from cfga_private_func() and fill_in_ap_info().
822 * Call into USBA and get the current configuration setting for this device,
824 static cfga_usb_ret_t
825 get_config(const char *ap_id
, uint_t
*config
)
828 uint_t
*config_val
= NULL
;
831 if ((rv
= do_control_ioctl(ap_id
, HUBD_GET_CURRENT_CONFIG
, 0,
832 (void **)&config_val
, &size
)) != CFGA_USB_OK
) {
833 DPRINTF("get_config: get current config descr failed\n");
836 *config
= *config_val
;
845 * Invoked from cfga_private_func.
846 * it does an unconfigure of the device followed by a configure,
847 * thus essentially resetting the device.
849 static cfga_usb_ret_t
850 reset_device(devctl_hdl_t devctl_hdl
, nvlist_t
*nvl
)
854 DPRINTF("reset_device: \n");
857 * Disconnect and reconfigure the device.
858 * Note this forces the new default config to take effect.
860 if (devctl_ap_disconnect(devctl_hdl
, nvl
) != 0) {
861 DPRINTF("devctl_ap_unconfigure failed, errno: %d\n", errno
);
862 rv
= CFGA_USB_DEVCTL
;
863 if (errno
== EBUSY
) {
864 rv
= CFGA_USB_BUSY
; /* Provide more useful msg */
870 if (devctl_ap_configure(devctl_hdl
, nvl
) != 0) {
871 DPRINTF(" devctl_ap_configure failed, errno = %d\n", errno
);
872 return (CFGA_USB_DEVCTL
);
875 return (CFGA_USB_OK
);
880 * Called from cfga_list_ext.
881 * Fills in the 'misc_info' field in the cfga buffer (displayed with -lv).
883 static cfga_usb_ret_t
884 fill_in_ap_info(const char *ap_id
, char *info_buf
, size_t info_size
)
886 char *mfg_str
= NULL
; /* iManufacturer */
887 char *prod_str
= NULL
; /* iProduct */
888 char *cfg_descr
= NULL
; /* iConfiguration */
889 uint_t config
; /* curr cfg index */
890 size_t size
; /* tmp stuff */
891 boolean_t flag
; /* wether to print ":" or not */
892 boolean_t free_mfg_str
= B_FALSE
;
893 boolean_t free_prod_str
= B_FALSE
;
894 boolean_t free_cfg_str
= B_FALSE
;
895 cfga_usb_ret_t rv
= CFGA_USB_OK
;
896 usb_dev_descr_t
*dev_descrp
= NULL
; /* device descriptor */
898 DPRINTF("fill_in_ap_info:\n");
900 if ((rv
= do_control_ioctl(ap_id
, USB_DESCR_TYPE_DEV
, 0,
901 (void **)&dev_descrp
, &size
)) != CFGA_USB_OK
) {
902 DPRINTF("fill_in_ap_info: get dev descr failed\n");
907 mfg_str
= USB_UNDEF_STR
;
908 if (dev_descrp
->iManufacturer
!= 0) {
909 if ((rv
= do_control_ioctl(ap_id
, USB_DESCR_TYPE_STRING
,
910 HUBD_MFG_STR
, (void **)&mfg_str
, &size
)) != CFGA_USB_OK
) {
911 if (rv
== CFGA_USB_ZEROLEN
) {
914 DPRINTF("get iManufacturer failed\n");
918 free_mfg_str
= B_TRUE
;
922 prod_str
= USB_UNDEF_STR
;
923 if (dev_descrp
->iProduct
!= 0) {
924 if ((rv
= do_control_ioctl(ap_id
, USB_DESCR_TYPE_STRING
,
925 HUBD_PRODUCT_STR
, (void **)&prod_str
,
926 &size
)) != CFGA_USB_OK
) {
927 if (rv
== CFGA_USB_ZEROLEN
) {
930 DPRINTF("getting iProduct failed\n");
934 free_prod_str
= B_TRUE
;
937 /* Current conifguration */
938 if ((rv
= get_config(ap_id
, &config
)) != CFGA_USB_OK
) {
939 DPRINTF("get_config failed\n");
943 /* Configuration string descriptor */
944 cfg_descr
= USB_NO_CFG_STR
;
945 if ((rv
= do_control_ioctl(ap_id
, USB_DESCR_TYPE_STRING
,
946 HUBD_CFG_DESCR_STR
, (void **)&cfg_descr
, &size
)) != CFGA_USB_OK
) {
947 if (rv
== CFGA_USB_ZEROLEN
) {
951 DPRINTF("HUBD_CFG_DESCR_STR failed\n");
956 /* add ": " to output coz PSARC case says so */
957 if ((cfg_descr
!= NULL
) && rv
!= CFGA_USB_ZEROLEN
) {
959 free_cfg_str
= B_TRUE
;
962 cfg_descr
= USB_NO_CFG_STR
;
965 /* Dump local buf into passed-in buf. */
966 (void) snprintf(info_buf
, info_size
,
967 "Mfg: %s Product: %s NConfigs: %d Config: %d %s%s", mfg_str
,
968 prod_str
, dev_descrp
->bNumConfigurations
, config
,
969 (flag
== B_TRUE
) ? ": " : "", cfg_descr
);
976 if ((free_mfg_str
== B_TRUE
) && mfg_str
) {
980 if ((free_prod_str
== B_TRUE
) && prod_str
) {
984 if ((free_cfg_str
== B_TRUE
) && cfg_descr
) {
992 /* ========================================================================== */
999 cfga_cmd_t state_change_cmd
,
1001 const char *options
,
1002 struct cfga_confirm
*confp
,
1003 struct cfga_msg
*msgp
,
1011 nvlist_t
*nvl
= NULL
;
1014 devctl_hdl_t hdl
= NULL
;
1015 cfga_usb_ret_t rv
= CFGA_USB_OK
;
1017 DPRINTF("cfga_change_state:\n");
1019 if ((rv
= verify_params(ap_id
, options
, errstring
)) != CFGA_USB_OK
) {
1020 (void) cfga_help(msgp
, options
, flags
);
1025 * All subcommands which can change state of device require
1028 if (geteuid() != 0) {
1033 if ((rv
= setup_for_devctl_cmd(ap_id
, &hdl
, &nvl
, 0)) !=
1038 switch (state_change_cmd
) {
1039 case CFGA_CMD_CONFIGURE
:
1040 if ((rv
= device_configured(hdl
, nvl
, &rstate
)) !=
1041 CFGA_USB_NOT_CONFIGURED
) {
1045 if (rstate
== AP_RSTATE_EMPTY
) {
1048 rv
= CFGA_USB_OK
; /* Other statuses don't matter */
1050 if (devctl_ap_configure(hdl
, nvl
) != 0) {
1051 DPRINTF("cfga_change_state: devctl_ap_configure "
1052 "failed. errno: %d\n", errno
);
1053 rv
= CFGA_USB_DEVCTL
;
1056 devpath
= usb_get_devicepath(ap_id
);
1057 if (devpath
== NULL
) {
1060 * try for some time as USB hotplug thread
1061 * takes a while to create the path
1062 * and then eventually give up
1064 for (i
= 0; i
< 12 && (devpath
== NULL
); i
++) {
1066 devpath
= usb_get_devicepath(ap_id
);
1069 if (devpath
== NULL
) {
1070 DPRINTF("cfga_change_state: get device "
1071 "path failed i = %d\n", i
);
1072 rv
= CFGA_USB_DEVCTL
;
1078 case CFGA_CMD_UNCONFIGURE
:
1079 if ((rv
= device_connected(hdl
, nvl
, &ostate
)) !=
1080 CFGA_USB_ALREADY_CONNECTED
) {
1084 /* check if it is already unconfigured */
1085 if ((rv
= device_configured(hdl
, nvl
, &rstate
)) ==
1086 CFGA_USB_NOT_CONFIGURED
) {
1089 rv
= CFGA_USB_OK
; /* Other statuses don't matter */
1091 len
= strlen(USB_CONFIRM_0
) + strlen(USB_CONFIRM_1
) +
1092 strlen("Unconfigure") + strlen(ap_id
);
1093 if ((msg
= (char *)calloc(len
+ 3, 1)) != NULL
) {
1094 (void) snprintf(msg
, len
+ 3, "Unconfigure %s%s\n%s",
1095 USB_CONFIRM_0
, ap_id
, USB_CONFIRM_1
);
1097 if (!usb_confirm(confp
, msg
)) {
1099 cleanup_after_devctl_cmd(hdl
, nvl
);
1104 devpath
= usb_get_devicepath(ap_id
);
1105 if (devpath
== NULL
) {
1106 DPRINTF("cfga_change_state: get device path failed\n");
1107 rv
= CFGA_USB_DEVCTL
;
1111 if ((rv
= usb_rcm_offline(ap_id
, errstring
, devpath
, flags
)) !=
1116 ret
= devctl_ap_unconfigure(hdl
, nvl
);
1118 DPRINTF("cfga_change_state: devctl_ap_unconfigure "
1119 "failed with errno: %d\n", errno
);
1120 rv
= CFGA_USB_DEVCTL
;
1121 if (errno
== EBUSY
) {
1124 (void) usb_rcm_online(ap_id
, errstring
, devpath
, flags
);
1126 (void) usb_rcm_remove(ap_id
, errstring
, devpath
, flags
);
1130 case CFGA_CMD_DISCONNECT
:
1131 if ((rv
= device_connected(hdl
, nvl
, &ostate
)) !=
1132 CFGA_USB_ALREADY_CONNECTED
) {
1134 * special case handling for
1135 * SLM based cfgadm disconnects
1137 if (ostate
== AP_OSTATE_UNCONFIGURED
)
1140 rv
= CFGA_USB_OK
; /* Other statuses don't matter */
1142 len
= strlen(USB_CONFIRM_0
) + strlen(USB_CONFIRM_1
) +
1143 strlen("Disconnect") + strlen(ap_id
);
1144 if ((msg
= (char *)calloc(len
+ 3, 1)) != NULL
) {
1145 (void) snprintf(msg
, len
+ 3, "Disconnect %s%s\n%s",
1146 USB_CONFIRM_0
, ap_id
, USB_CONFIRM_1
);
1148 if (!usb_confirm(confp
, msg
)) {
1150 cleanup_after_devctl_cmd(hdl
, nvl
);
1155 devpath
= usb_get_devicepath(ap_id
);
1156 if (devpath
== NULL
) {
1157 DPRINTF("cfga_change_state: get device path failed\n");
1158 rv
= CFGA_USB_DEVCTL
;
1162 /* only call rcm_offline iff the state was CONFIGURED */
1163 if (ostate
== AP_OSTATE_CONFIGURED
) {
1164 if ((rv
= usb_rcm_offline(ap_id
, errstring
,
1165 devpath
, flags
)) != CFGA_USB_OK
) {
1170 ret
= devctl_ap_disconnect(hdl
, nvl
);
1172 DPRINTF("cfga_change_state: devctl_ap_disconnect "
1173 "failed with errno: %d\n", errno
);
1174 rv
= CFGA_USB_DEVCTL
;
1175 if (errno
== EBUSY
) {
1178 if (ostate
== AP_OSTATE_CONFIGURED
) {
1179 (void) usb_rcm_online(ap_id
, errstring
,
1183 if (ostate
== AP_OSTATE_CONFIGURED
) {
1184 (void) usb_rcm_remove(ap_id
, errstring
,
1190 case CFGA_CMD_CONNECT
:
1192 case CFGA_CMD_UNLOAD
:
1193 (void) cfga_help(msgp
, options
, flags
);
1194 rv
= CFGA_USB_OPNOTSUPP
;
1198 (void) cfga_help(msgp
, options
, flags
);
1199 rv
= CFGA_USB_INTERNAL_ERROR
;
1203 cleanup_after_devctl_cmd(hdl
, nvl
);
1205 return (usb_err_msg(errstring
, rv
, ap_id
, errno
));
1214 const char *options
,
1215 struct cfga_confirm
*confp
,
1216 struct cfga_msg
*msgp
,
1222 nvlist_t
*list
= NULL
;
1224 devctl_hdl_t hdl
= NULL
;
1226 usb_dev_descr_t
*dev_descrp
= NULL
;
1227 char *driver
= NULL
;
1229 DPRINTF("cfga_private_func:\n");
1231 if ((rv
= verify_params(ap_id
, NULL
, errstring
)) != CFGA_USB_OK
) {
1232 (void) cfga_help(msgp
, options
, flags
);
1233 return (usb_err_msg(errstring
, rv
, ap_id
, errno
));
1237 * All subcommands which can change state of device require
1240 if (geteuid() != 0) {
1246 rv
= CFGA_USB_INTERNAL_ERROR
;
1250 if ((rv
= setup_for_devctl_cmd(ap_id
, &hdl
, &list
, 0)) !=
1255 if ((rv
= device_connected(hdl
, list
, &ostate
)) !=
1256 CFGA_USB_ALREADY_CONNECTED
) {
1261 if (strcmp(func
, RESET_DEVICE
) == 0) { /* usb_reset? */
1262 len
= strlen(USB_CONFIRM_0
) + strlen(USB_CONFIRM_1
) +
1263 strlen("Reset") + strlen(ap_id
);
1264 if ((msg
= (char *)calloc(len
+ 3, 1)) != NULL
) {
1265 (void) snprintf(msg
, len
+ 3, "Reset %s%s\n%s",
1266 USB_CONFIRM_0
, ap_id
, USB_CONFIRM_1
);
1268 cleanup_after_devctl_cmd(hdl
, list
);
1272 if (!usb_confirm(confp
, msg
)) {
1273 cleanup_after_devctl_cmd(hdl
, list
);
1277 if ((rv
= reset_device(hdl
, list
)) != CFGA_USB_OK
) {
1280 } else if (strncmp(func
, USB_CONFIG
, sizeof (USB_CONFIG
)) == 0) {
1282 uint_t actual_config
;
1284 char *subopts
, *value
;
1285 uint_t cfg_opt_flag
= B_FALSE
;
1287 /* these are the only valid options */
1288 char *cfg_opts
[] = {
1294 /* return error if no options are specified */
1295 subopts
= (char *)options
;
1296 if (subopts
== NULL
) {
1297 DPRINTF("cfga_private_func: no options\n");
1298 rv
= CFGA_USB_OPNOTSUPP
;
1299 (void) cfga_help(msgp
, options
, flags
);
1303 /* parse options specified */
1304 while (*subopts
!= '\0') {
1305 switch (getsubopt(&subopts
, cfg_opts
, &value
)) {
1306 case 0: /* config */
1307 if (value
== NULL
) {
1308 rv
= CFGA_USB_OPNOTSUPP
;
1309 (void) cfga_help(msgp
,
1314 config
= strtol(value
,
1321 CFGA_USB_CONFIG_INVAL
;
1325 cfg_opt_flag
= B_TRUE
;
1329 if (value
== NULL
) {
1330 rv
= CFGA_USB_OPNOTSUPP
;
1331 (void) cfga_help(msgp
,
1336 driver
= strdup(value
);
1337 if (driver
== NULL
) {
1339 CFGA_USB_INTERNAL_ERROR
;
1346 rv
= CFGA_USB_OPNOTSUPP
;
1347 (void) cfga_help(msgp
, options
, flags
);
1352 /* config is mandatory */
1353 if (cfg_opt_flag
!= B_TRUE
) {
1354 rv
= CFGA_USB_OPNOTSUPP
;
1355 (void) cfga_help(msgp
, options
, flags
);
1358 DPRINTF("config = %x\n", config
);
1360 len
= strlen(USB_CONFIRM_0
) + strlen(USB_CONFIRM_1
) +
1361 strlen("Setting") + strlen(ap_id
) +
1362 strlen("to USB configuration");
1363 /* len + 8 to account for config, \n and white space */
1364 if ((msg
= (char *)calloc(len
+ 8, 1)) != NULL
) {
1365 (void) snprintf(msg
, len
+ 8,
1366 "Setting %s%s\nto USB configuration %d\n%s",
1367 USB_CONFIRM_0
, ap_id
, config
, USB_CONFIRM_1
);
1369 rv
= CFGA_USB_INTERNAL_ERROR
;
1373 if (!usb_confirm(confp
, msg
)) {
1375 cleanup_after_devctl_cmd(hdl
, list
);
1380 * Check that the option setting selected is in range.
1382 if ((rv
= do_control_ioctl(ap_id
, USB_DESCR_TYPE_DEV
, 0,
1383 (void **)&dev_descrp
, &size
)) != CFGA_USB_OK
) {
1384 DPRINTF("cfga_private_func: get dev descr failed\n");
1388 if (config
> dev_descrp
->bNumConfigurations
- 1) {
1389 DPRINTF("cfga_private_func: config index requested "
1390 "(%d) exceeds bNumConfigurations - 1 (%d)\n",
1391 config
, dev_descrp
->bNumConfigurations
- 1);
1392 rv
= CFGA_USB_CONFIG_INVAL
;
1396 /* Pass current setting to set_configuration */
1397 if ((rv
= get_config(ap_id
, &actual_config
)) != CFGA_USB_OK
) {
1401 /* check if they match - yes, then nothing to do */
1402 if (actual_config
== config
) {
1403 DPRINTF("cfga_private_func: config index requested "
1404 "(%d) matches the actual config value %d\n",
1405 config
, actual_config
);
1410 /* Save the configuration settings */
1411 if ((rv
= set_configuration(ap_id
, config
, driver
,
1412 dev_descrp
, errstring
)) != CFGA_USB_OK
) {
1416 /* Reset device to force new config to take effect */
1417 if ((rv
= reset_device(hdl
, list
)) != CFGA_USB_OK
) {
1422 DPRINTF("cfga_private_func: unrecognized command.\n");
1423 (void) cfga_help(msgp
, options
, flags
);
1426 return (CFGA_INVAL
);
1432 cleanup_after_devctl_cmd(hdl
, list
);
1434 return (usb_err_msg(errstring
, rv
, ap_id
, errno
));
1442 const char *options
,
1443 struct cfga_msg
*msgp
,
1447 (void) cfga_help(msgp
, options
, flags
);
1448 return (CFGA_OPNOTSUPP
);
1456 cfga_list_data_t
**ap_id_list
,
1458 const char *options
,
1459 const char *listopts
,
1464 char *ap_id_log
= NULL
;
1466 nvlist_t
*user_nvlist
= NULL
;
1467 devctl_hdl_t devctl_hdl
= NULL
;
1468 cfga_usb_ret_t rv
= CFGA_USB_OK
;
1469 devctl_ap_state_t devctl_ap_state
;
1471 DPRINTF("cfga_list_ext:\n");
1473 if ((rv
= verify_params(ap_id
, options
, errstring
)) != CFGA_USB_OK
) {
1477 if (ap_id_list
== NULL
|| nlistp
== NULL
) {
1478 DPRINTF("cfga_list_ext: list = NULL or nlistp = NULL\n");
1479 rv
= CFGA_USB_INTERNAL_ERROR
;
1484 if ((rv
= setup_for_devctl_cmd(ap_id
, &devctl_hdl
, &user_nvlist
,
1485 DC_RDONLY
)) != CFGA_USB_OK
) {
1489 if (devctl_ap_getstate(devctl_hdl
, user_nvlist
, &devctl_ap_state
) ==
1491 DPRINTF("cfga_list_ext: devctl_ap_getstate failed. errno: %d\n",
1493 cleanup_after_devctl_cmd(devctl_hdl
, user_nvlist
);
1494 rv
= CFGA_USB_DEVCTL
;
1497 cleanup_after_devctl_cmd(devctl_hdl
, user_nvlist
);
1500 * Create cfga_list_data_t struct.
1503 (cfga_list_data_t
*)malloc(sizeof (**ap_id_list
))) == NULL
) {
1504 DPRINTF("cfga_list_ext: malloc for cfga_list_data_t failed. "
1505 "errno: %d\n", errno
);
1506 rv
= CFGA_USB_ALLOC_FAIL
;
1513 * Rest of the code fills in the cfga_list_data_t struct.
1516 /* Get /dev/cfg path to corresponding to the physical ap_id */
1517 /* Remember ap_id_log must be freed */
1518 rv
= (cfga_usb_ret_t
)physpath_to_devlink(CFGA_DEV_DIR
, (char *)ap_id
,
1519 &ap_id_log
, &l_errno
, MATCH_MINOR_NAME
);
1521 rv
= CFGA_USB_DEVLINK
;
1524 assert(ap_id_log
!= NULL
);
1526 /* Get logical ap-id corresponding to the physical */
1527 if (strstr(ap_id_log
, CFGA_DEV_DIR
) == NULL
) {
1528 DPRINTF("cfga_list_ext: devlink doesn't contain /dev/cfg\n");
1529 rv
= CFGA_USB_DEVLINK
;
1532 (void) strlcpy((*ap_id_list
)->ap_log_id
,
1533 /* Strip off /dev/cfg/ */ ap_id_log
+ strlen(CFGA_DEV_DIR
)+ 1,
1534 sizeof ((*ap_id_list
)->ap_log_id
));
1538 (void) strlcpy((*ap_id_list
)->ap_phys_id
, ap_id
,
1539 sizeof ((*ap_id_list
)->ap_phys_id
));
1541 switch (devctl_ap_state
.ap_rstate
) {
1542 case AP_RSTATE_EMPTY
:
1543 (*ap_id_list
)->ap_r_state
= CFGA_STAT_EMPTY
;
1545 case AP_RSTATE_DISCONNECTED
:
1546 (*ap_id_list
)->ap_r_state
= CFGA_STAT_DISCONNECTED
;
1548 case AP_RSTATE_CONNECTED
:
1549 (*ap_id_list
)->ap_r_state
= CFGA_STAT_CONNECTED
;
1552 rv
= CFGA_USB_STATE
;
1556 switch (devctl_ap_state
.ap_ostate
) {
1557 case AP_OSTATE_CONFIGURED
:
1558 (*ap_id_list
)->ap_o_state
= CFGA_STAT_CONFIGURED
;
1560 case AP_OSTATE_UNCONFIGURED
:
1561 (*ap_id_list
)->ap_o_state
= CFGA_STAT_UNCONFIGURED
;
1564 rv
= CFGA_USB_STATE
;
1568 switch (devctl_ap_state
.ap_condition
) {
1570 (*ap_id_list
)->ap_cond
= CFGA_COND_OK
;
1572 case AP_COND_FAILING
:
1573 (*ap_id_list
)->ap_cond
= CFGA_COND_FAILING
;
1575 case AP_COND_FAILED
:
1576 (*ap_id_list
)->ap_cond
= CFGA_COND_FAILED
;
1578 case AP_COND_UNUSABLE
:
1579 (*ap_id_list
)->ap_cond
= CFGA_COND_UNUSABLE
;
1581 case AP_COND_UNKNOWN
:
1582 (*ap_id_list
)->ap_cond
= CFGA_COND_UNKNOWN
;
1585 rv
= CFGA_USB_STATE
;
1589 (*ap_id_list
)->ap_class
[0] = '\0'; /* Filled by libcfgadm */
1590 (*ap_id_list
)->ap_busy
= devctl_ap_state
.ap_in_transition
;
1591 (*ap_id_list
)->ap_status_time
= devctl_ap_state
.ap_last_change
;
1592 (*ap_id_list
)->ap_info
[0] = '\0';
1594 if ((*ap_id_list
)->ap_r_state
== CFGA_STAT_CONNECTED
) {
1598 /* Fill in the info for the -v option display. */
1599 if ((rv
= fill_in_ap_info(ap_id
, (*ap_id_list
)->ap_info
,
1600 sizeof ((*ap_id_list
)->ap_info
))) != CFGA_USB_OK
) {
1601 DPRINTF("cfga_list_ext: fill_in_ap_info failed\n");
1605 /* Fill in ap_type */
1606 if ((rv
= do_control_ioctl(ap_id
, HUBD_GET_CFGADM_NAME
, 0,
1607 (void **)&str_p
, &size
)) != CFGA_USB_OK
) {
1608 DPRINTF("cfga_list_ext: do_control_ioctl failed\n");
1612 (void) strcpy((*ap_id_list
)->ap_type
, "usb-");
1613 str_len
= strlen((*ap_id_list
)->ap_type
);
1616 * NOTE: In the cfgadm display the "Type" column is only 12
1617 * chars long. Most USB devices can be displayed here with a
1618 * "usb-" prefix. Only USB keyboard cannot be displayed in
1619 * its entirety as "usb-keybaord" is 13 chars in length.
1620 * It will show up as "usb-kbd".
1622 if (strncasecmp(str_p
, "keyboard", 8) != 0) {
1623 (void) strlcpy((*ap_id_list
)->ap_type
+ str_len
, str_p
,
1624 sizeof ((*ap_id_list
)->ap_type
) - str_len
);
1626 (void) strlcpy((*ap_id_list
)->ap_type
+ str_len
, "kbd",
1627 sizeof ((*ap_id_list
)->ap_type
) - str_len
);
1632 (void) strcpy((*ap_id_list
)->ap_type
,
1633 USB_CFGADM_DEFAULT_AP_TYPE
);
1636 return (usb_err_msg(errstring
, rv
, ap_id
, errno
));
1638 if (*ap_id_list
!= NULL
) {
1641 if (ap_id_log
!= NULL
) {
1645 return (usb_err_msg(errstring
, rv
, ap_id
, errno
));
1650 * This routine accepts a variable number of message IDs and constructs
1651 * a corresponding error string which is printed via the message print routine
1655 cfga_msg(struct cfga_msg
*msgp
, const char *str
)
1660 if (msgp
== NULL
|| msgp
->message_routine
== NULL
) {
1661 DPRINTF("cfga_msg: msg\n");
1665 if ((len
= strlen(str
)) == 0) {
1666 DPRINTF("cfga_msg: null str\n");
1670 if ((q
= (char *)calloc(len
+ 1, 1)) == NULL
) {
1671 DPRINTF("cfga_msg: null q\n");
1675 (void) strcpy(q
, str
);
1676 (*msgp
->message_routine
)(msgp
->appdata_ptr
, q
);
1684 cfga_help(struct cfga_msg
*msgp
, const char *options
, cfga_flags_t flags
)
1686 DPRINTF("cfga_help:\n");
1688 cfga_msg(msgp
, dgettext(TEXT_DOMAIN
, usb_help
[HELP_UNKNOWN
]));
1689 cfga_msg(msgp
, options
);
1692 cfga_msg(msgp
, dgettext(TEXT_DOMAIN
, usb_help
[HELP_HEADER
]));
1693 cfga_msg(msgp
, usb_help
[HELP_CONFIG
]);
1694 cfga_msg(msgp
, usb_help
[HELP_RESET_SLOT
]);
1695 cfga_msg(msgp
, usb_help
[HELP_CONFIG_SLOT
]);
1702 usb_confirm(struct cfga_confirm
*confp
, char *msg
)
1706 if (confp
== NULL
|| confp
->confirm
== NULL
) {
1710 rval
= (*confp
->confirm
)(confp
->appdata_ptr
, msg
);
1711 DPRINTF("usb_confirm: %d\n", rval
);
1718 usb_get_devicepath(const char *ap_id
)
1720 char *devpath
= NULL
;
1724 rv
= do_control_ioctl(ap_id
, HUBD_GET_DEVICE_PATH
, 0,
1725 (void **)&devpath
, &size
);
1727 if (rv
== CFGA_USB_OK
) {
1728 DPRINTF("usb_get_devicepath: get device path ioctl ok\n");
1731 DPRINTF("usb_get_devicepath: get device path ioctl failed\n");