17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5d29f5a71Szhigang lu - Sun Microsystems - Beijing China * Common Development and Distribution License (the "License"). 6d29f5a71Szhigang lu - Sun Microsystems - Beijing China * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22d29f5a71Szhigang lu - Sun Microsystems - Beijing China * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 24*cf252232SAndy Fiddaman * Copyright 2018 OmniOS Community Edition (OmniOSce) Association. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include "cfga_usb.h" 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate /* function prototypes */ 327c478bd9Sstevel@tonic-gate cfga_err_t usb_err_msg(char **, cfga_usb_ret_t, const char *, int); 337c478bd9Sstevel@tonic-gate extern cfga_usb_ret_t usb_rcm_offline(const char *, char **, char *, 347c478bd9Sstevel@tonic-gate cfga_flags_t); 357c478bd9Sstevel@tonic-gate extern cfga_usb_ret_t usb_rcm_online(const char *, char **, char *, 367c478bd9Sstevel@tonic-gate cfga_flags_t); 377c478bd9Sstevel@tonic-gate extern cfga_usb_ret_t usb_rcm_remove(const char *, char **, char *, 387c478bd9Sstevel@tonic-gate cfga_flags_t); 397c478bd9Sstevel@tonic-gate static int usb_confirm(struct cfga_confirm *, char *); 40*cf252232SAndy Fiddaman static char *usb_get_devicepath(const char *); 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate /* 437c478bd9Sstevel@tonic-gate * This file contains the entry points to the plugin as defined in the 447c478bd9Sstevel@tonic-gate * config_admin(3X) man page. 457c478bd9Sstevel@tonic-gate */ 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate /* 487c478bd9Sstevel@tonic-gate * Set the version number for the cfgadm library's use. 497c478bd9Sstevel@tonic-gate */ 507c478bd9Sstevel@tonic-gate int cfga_version = CFGA_HSL_V2; 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate #define HELP_HEADER 1 537c478bd9Sstevel@tonic-gate #define HELP_CONFIG 2 547c478bd9Sstevel@tonic-gate #define HELP_RESET_SLOT 3 557c478bd9Sstevel@tonic-gate #define HELP_CONFIG_SLOT 4 567c478bd9Sstevel@tonic-gate #define HELP_UNKNOWN 5 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate /* Help messages */ 597c478bd9Sstevel@tonic-gate static char * 607c478bd9Sstevel@tonic-gate usb_help[] = { 617c478bd9Sstevel@tonic-gate NULL, 627c478bd9Sstevel@tonic-gate "USB specific commands:\n", 637c478bd9Sstevel@tonic-gate " cfgadm -c [configure|unconfigure|disconnect] ap_id [ap_id...]\n", 647c478bd9Sstevel@tonic-gate " cfgadm -x usb_reset ap_id [ap_id...]\n", 657c478bd9Sstevel@tonic-gate " cfgadm -x usb_config -o config=<index of desired configuration> ap_id\n", 667c478bd9Sstevel@tonic-gate "\tunknown command or option: ", 677c478bd9Sstevel@tonic-gate NULL 687c478bd9Sstevel@tonic-gate }; /* End help messages */ 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate /* Error messages */ 717c478bd9Sstevel@tonic-gate static msgcvt_t 727c478bd9Sstevel@tonic-gate usb_error_msgs[] = { 737c478bd9Sstevel@tonic-gate /* CFGA_USB_OK */ 747c478bd9Sstevel@tonic-gate { CVT, CFGA_OK, "ok" }, 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate /* CFGA_USB_UNKNOWN */ 777c478bd9Sstevel@tonic-gate { CVT, CFGA_LIB_ERROR, "Unknown message; internal error" }, 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate /* CFGA_USB_INTERNAL_ERROR */ 807c478bd9Sstevel@tonic-gate { CVT, CFGA_LIB_ERROR, "Internal error" }, 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate /* CFGA_USB_OPTIONS */ 837c478bd9Sstevel@tonic-gate { CVT, CFGA_ERROR, "Hardware specific options not supported" }, 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate /* CFGA_USB_DYNAMIC_AP */ 867c478bd9Sstevel@tonic-gate { CVT, CFGA_INVAL, "Dynamic attachment points not supported" }, 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate /* CFGA_USB_AP */ 897c478bd9Sstevel@tonic-gate { CVT, CFGA_APID_NOEXIST, "" }, 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate /* CFGA_USB_PORT */ 927c478bd9Sstevel@tonic-gate { CVT, CFGA_LIB_ERROR, "Cannot determine hub port number for " }, 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate /* CFGA_USB_DEVCTL */ 957c478bd9Sstevel@tonic-gate { CVT, CFGA_ERROR, "Cannot issue devctl to " }, 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate /* CFGA_USB_NOT_CONNECTED */ 987c478bd9Sstevel@tonic-gate { CVT, CFGA_INVAL, "No device connected to " }, 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate /* CFGA_USB_NOT_CONFIGURED */ 1017c478bd9Sstevel@tonic-gate { CVT, CFGA_INVAL, "No device configured to " }, 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate /* CFGA_USB_ALREADY_CONNECTED */ 1047c478bd9Sstevel@tonic-gate { CVT, CFGA_INSUFFICENT_CONDITION, 1057c478bd9Sstevel@tonic-gate "Device already connected; cannot connect again " }, 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate /* CFGA_USB_ALREADY_CONFIGURED */ 1087c478bd9Sstevel@tonic-gate { CVT, CFGA_INVAL, "device already configured for " }, 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate /* CFGA_USB_OPEN */ 1117c478bd9Sstevel@tonic-gate { CVT, CFGA_LIB_ERROR, "Cannot open " }, 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate /* CFGA_USB_IOCTL */ 1147c478bd9Sstevel@tonic-gate { CVT, CFGA_ERROR, "Driver ioctl failed " }, 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate /* CFGA_USB_BUSY */ 1177c478bd9Sstevel@tonic-gate { CVT, CFGA_SYSTEM_BUSY, "" }, 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate /* CFGA_USB_ALLOC_FAIL */ 1207c478bd9Sstevel@tonic-gate { CVT, CFGA_LIB_ERROR, "Memory allocation failure" }, 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate /* CFGA_USB_OPNOTSUPP */ 1237c478bd9Sstevel@tonic-gate { CVT, CFGA_OPNOTSUPP, "Operation not supported" }, 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate /* CFGA_USB_DEVLINK */ 1267c478bd9Sstevel@tonic-gate { CVT, CFGA_LIB_ERROR, "Could not find /dev/cfg link for " }, 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate /* CFGA_USB_STATE */ 1297c478bd9Sstevel@tonic-gate { CVT, CFGA_LIB_ERROR, "Internal error: Unrecognized ap state" }, 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate /* CFGA_USB_CONFIG_INVAL */ 1327c478bd9Sstevel@tonic-gate { CVT, CFGA_ERROR, 1337c478bd9Sstevel@tonic-gate "Specified configuration index unrecognized or exceeds " 1347c478bd9Sstevel@tonic-gate "maximum available" }, 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate /* CFGA_USB_PRIV */ 1377c478bd9Sstevel@tonic-gate { CVT, CFGA_PRIV, "" }, 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate /* CFGA_USB_NVLIST */ 1407c478bd9Sstevel@tonic-gate { CVT, CFGA_ERROR, "Internal error (nvlist)" }, 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate /* CFGA_USB_ZEROLEN */ 1437c478bd9Sstevel@tonic-gate { CVT, CFGA_ERROR, "Internal error (zerolength string)" }, 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate /* CFGA_USB_CONFIG_FILE */ 1467c478bd9Sstevel@tonic-gate { CVT, CFGA_ERROR, 1477c478bd9Sstevel@tonic-gate "Cannot open/fstat/read USB system configuration file" }, 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate /* CFGA_USB_LOCK_FILE */ 1507c478bd9Sstevel@tonic-gate { CVT, CFGA_ERROR, "Cannot lock USB system configuration file" }, 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate /* CFGA_USB_UNLOCK_FILE */ 1537c478bd9Sstevel@tonic-gate { CVT, CFGA_ERROR, "Cannot unlock USB system configuration file" }, 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate /* CFGA_USB_ONE_CONFIG */ 1567c478bd9Sstevel@tonic-gate { CVT, CFGA_ERROR, 1577c478bd9Sstevel@tonic-gate "Operation not supported for devices with one configuration" }, 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate /* CFGA_USB_RCM_HANDLE Errors */ 1607c478bd9Sstevel@tonic-gate { CVT, CFGA_ERROR, "cannot get RCM handle"}, 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate /* CFGA_USB_RCM_ONLINE */ 1637c478bd9Sstevel@tonic-gate { CVT, CFGA_SYSTEM_BUSY, "failed to online: "}, 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate /* CFGA_USB_RCM_OFFLINE */ 1667c478bd9Sstevel@tonic-gate { CVT, CFGA_SYSTEM_BUSY, "failed to offline: "}, 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate /* CFGA_USB_RCM_INFO */ 1697c478bd9Sstevel@tonic-gate { CVT, CFGA_ERROR, "failed to query: "} 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate }; /* End error messages */ 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate /* ========================================================================= */ 1757c478bd9Sstevel@tonic-gate /* 1767c478bd9Sstevel@tonic-gate * The next two funcs imported verbatim from cfgadm_scsi. 1777c478bd9Sstevel@tonic-gate * physpath_to_devlink is the only func directly used by cfgadm_usb. 1787c478bd9Sstevel@tonic-gate * get_link supports it. 1797c478bd9Sstevel@tonic-gate */ 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate /* 1827c478bd9Sstevel@tonic-gate * Routine to search the /dev directory or a subtree of /dev. 1837c478bd9Sstevel@tonic-gate */ 1847c478bd9Sstevel@tonic-gate static int 1857c478bd9Sstevel@tonic-gate get_link(di_devlink_t devlink, void *arg) 1867c478bd9Sstevel@tonic-gate { 1877c478bd9Sstevel@tonic-gate walk_link_t *larg = (walk_link_t *)arg; 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate /* 1907c478bd9Sstevel@tonic-gate * When path is specified, it's the node path without minor 1917c478bd9Sstevel@tonic-gate * name. Therefore, the ../.. prefixes needs to be stripped. 1927c478bd9Sstevel@tonic-gate */ 1937c478bd9Sstevel@tonic-gate if (larg->path) { 1947c478bd9Sstevel@tonic-gate char *content = (char *)di_devlink_content(devlink); 1957c478bd9Sstevel@tonic-gate char *start = strstr(content, "/devices/"); 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate /* line content must have minor node */ 1987c478bd9Sstevel@tonic-gate if (start == NULL || 1997c478bd9Sstevel@tonic-gate strncmp(start, larg->path, larg->len) != 0 || 2007c478bd9Sstevel@tonic-gate start[larg->len] != ':') { 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 2037c478bd9Sstevel@tonic-gate } 2047c478bd9Sstevel@tonic-gate } 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate *(larg->linkpp) = strdup(di_devlink_path(devlink)); 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate return (DI_WALK_TERMINATE); 2097c478bd9Sstevel@tonic-gate } 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2137c478bd9Sstevel@tonic-gate static ucfga_ret_t 2147c478bd9Sstevel@tonic-gate physpath_to_devlink( 2157c478bd9Sstevel@tonic-gate const char *basedir, 2167c478bd9Sstevel@tonic-gate const char *node_path, 2177c478bd9Sstevel@tonic-gate char **logpp, 2187c478bd9Sstevel@tonic-gate int *l_errnop, 2197c478bd9Sstevel@tonic-gate int match_minor) 2207c478bd9Sstevel@tonic-gate { 2217c478bd9Sstevel@tonic-gate walk_link_t larg; 2227c478bd9Sstevel@tonic-gate di_devlink_handle_t hdl; 2237c478bd9Sstevel@tonic-gate char *minor_path; 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate if ((hdl = di_devlink_init(NULL, 0)) == NULL) { 2267c478bd9Sstevel@tonic-gate *l_errnop = errno; 2277c478bd9Sstevel@tonic-gate return (UCFGA_LIB_ERR); 2287c478bd9Sstevel@tonic-gate } 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate *logpp = NULL; 2317c478bd9Sstevel@tonic-gate larg.linkpp = logpp; 2327c478bd9Sstevel@tonic-gate if (match_minor) { 2337c478bd9Sstevel@tonic-gate minor_path = (char *)node_path + strlen("/devices"); 2347c478bd9Sstevel@tonic-gate larg.path = NULL; 2357c478bd9Sstevel@tonic-gate } else { 2367c478bd9Sstevel@tonic-gate minor_path = NULL; 2377c478bd9Sstevel@tonic-gate larg.len = strlen(node_path); 2387c478bd9Sstevel@tonic-gate larg.path = (char *)node_path; 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate (void) di_devlink_walk(hdl, "^cfg/", minor_path, DI_PRIMARY_LINK, 2427c478bd9Sstevel@tonic-gate (void *)&larg, get_link); 2437c478bd9Sstevel@tonic-gate 244d29f5a71Szhigang lu - Sun Microsystems - Beijing China (void) di_devlink_fini(&hdl); 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate if (*logpp == NULL) { 2477c478bd9Sstevel@tonic-gate *l_errnop = errno; 2487c478bd9Sstevel@tonic-gate return (UCFGA_LIB_ERR); 2497c478bd9Sstevel@tonic-gate } 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate return (UCFGA_OK); 2527c478bd9Sstevel@tonic-gate } 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate /* ========================================================================= */ 2567c478bd9Sstevel@tonic-gate /* Utilities */ 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate /* 2597c478bd9Sstevel@tonic-gate * Given the index into a table (msgcvt_t) of messages, get the message 2607c478bd9Sstevel@tonic-gate * string, converting it to the proper locale if necessary. 2617c478bd9Sstevel@tonic-gate * NOTE: See cfga_usb.h 2627c478bd9Sstevel@tonic-gate */ 2637c478bd9Sstevel@tonic-gate static const char * 2647c478bd9Sstevel@tonic-gate get_msg(uint_t msg_index, msgcvt_t *msg_tbl, uint_t tbl_size) 2657c478bd9Sstevel@tonic-gate { 2667c478bd9Sstevel@tonic-gate if (msg_index >= tbl_size) { 2677c478bd9Sstevel@tonic-gate DPRINTF("get_error_msg: bad error msg index: %d\n", msg_index); 2687c478bd9Sstevel@tonic-gate msg_index = CFGA_USB_UNKNOWN; 2697c478bd9Sstevel@tonic-gate } 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate return ((msg_tbl[msg_index].intl) ? 2727c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, msg_tbl[msg_index].msgstr) : 2737c478bd9Sstevel@tonic-gate msg_tbl[msg_index].msgstr); 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate /* 2787c478bd9Sstevel@tonic-gate * Allocates and creates a message string (in *ret_str), 2797c478bd9Sstevel@tonic-gate * by concatenating all the (char *) args together, in order. 2807c478bd9Sstevel@tonic-gate * Last arg MUST be NULL. 2817c478bd9Sstevel@tonic-gate */ 2827c478bd9Sstevel@tonic-gate static void 2837c478bd9Sstevel@tonic-gate set_msg(char **ret_str, ...) 2847c478bd9Sstevel@tonic-gate { 2857c478bd9Sstevel@tonic-gate char *str; 2867c478bd9Sstevel@tonic-gate size_t total_len; 2877c478bd9Sstevel@tonic-gate va_list valist; 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate va_start(valist, ret_str); 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate total_len = (*ret_str == NULL) ? 0 : strlen(*ret_str); 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate while ((str = va_arg(valist, char *)) != NULL) { 2947c478bd9Sstevel@tonic-gate size_t len = strlen(str); 2957c478bd9Sstevel@tonic-gate char *old_str = *ret_str; 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate *ret_str = (char *)realloc(*ret_str, total_len + len + 1); 2987c478bd9Sstevel@tonic-gate if (*ret_str == NULL) { 2997c478bd9Sstevel@tonic-gate /* We're screwed */ 3007c478bd9Sstevel@tonic-gate free(old_str); 3017c478bd9Sstevel@tonic-gate DPRINTF("set_msg: realloc failed.\n"); 3027c478bd9Sstevel@tonic-gate va_end(valist); 3037c478bd9Sstevel@tonic-gate return; 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate 306d29f5a71Szhigang lu - Sun Microsystems - Beijing China (void) strcpy(*ret_str + total_len, str); 3077c478bd9Sstevel@tonic-gate total_len += len; 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate va_end(valist); 3117c478bd9Sstevel@tonic-gate } 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate /* 3157c478bd9Sstevel@tonic-gate * Error message handling. 3167c478bd9Sstevel@tonic-gate * For the rv passed in, looks up the corresponding error message string(s), 3177c478bd9Sstevel@tonic-gate * internationalized it if necessary, and concatenates it into a new 3187c478bd9Sstevel@tonic-gate * memory buffer, and points *errstring to it. 3197c478bd9Sstevel@tonic-gate * Note not all rvs will result in an error message return, as not all 3207c478bd9Sstevel@tonic-gate * error conditions warrant a USB-specific error message. 3217c478bd9Sstevel@tonic-gate * 3227c478bd9Sstevel@tonic-gate * Some messages may display ap_id or errno, which is why they are passed 3237c478bd9Sstevel@tonic-gate * in. 3247c478bd9Sstevel@tonic-gate */ 3257c478bd9Sstevel@tonic-gate cfga_err_t 3267c478bd9Sstevel@tonic-gate usb_err_msg(char **errstring, cfga_usb_ret_t rv, const char *ap_id, int l_errno) 3277c478bd9Sstevel@tonic-gate { 3287c478bd9Sstevel@tonic-gate if (errstring == NULL) { 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate return (usb_error_msgs[rv].cfga_err); 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate /* 3347c478bd9Sstevel@tonic-gate * Generate the appropriate USB-specific error message(s) (if any). 3357c478bd9Sstevel@tonic-gate */ 3367c478bd9Sstevel@tonic-gate switch (rv) { 3377c478bd9Sstevel@tonic-gate case CFGA_USB_OK: 3387c478bd9Sstevel@tonic-gate /* Special case - do nothing. */ 3397c478bd9Sstevel@tonic-gate break; 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate case CFGA_USB_UNKNOWN: 3427c478bd9Sstevel@tonic-gate case CFGA_USB_DYNAMIC_AP: 3437c478bd9Sstevel@tonic-gate case CFGA_USB_INTERNAL_ERROR: 3447c478bd9Sstevel@tonic-gate case CFGA_USB_OPTIONS: 3457c478bd9Sstevel@tonic-gate case CFGA_USB_ALLOC_FAIL: 3467c478bd9Sstevel@tonic-gate case CFGA_USB_STATE: 3477c478bd9Sstevel@tonic-gate case CFGA_USB_CONFIG_INVAL: 3487c478bd9Sstevel@tonic-gate case CFGA_USB_PRIV: 3497c478bd9Sstevel@tonic-gate case CFGA_USB_OPNOTSUPP: 3507c478bd9Sstevel@tonic-gate /* These messages require no additional strings passed. */ 3517c478bd9Sstevel@tonic-gate set_msg(errstring, ERR_STR(rv), NULL); 3527c478bd9Sstevel@tonic-gate break; 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate case CFGA_USB_AP: 3557c478bd9Sstevel@tonic-gate case CFGA_USB_PORT: 3567c478bd9Sstevel@tonic-gate case CFGA_USB_NOT_CONNECTED: 3577c478bd9Sstevel@tonic-gate case CFGA_USB_NOT_CONFIGURED: 3587c478bd9Sstevel@tonic-gate case CFGA_USB_ALREADY_CONNECTED: 3597c478bd9Sstevel@tonic-gate case CFGA_USB_ALREADY_CONFIGURED: 3607c478bd9Sstevel@tonic-gate case CFGA_USB_BUSY: 3617c478bd9Sstevel@tonic-gate case CFGA_USB_DEVLINK: 3627c478bd9Sstevel@tonic-gate case CFGA_USB_RCM_HANDLE: 3637c478bd9Sstevel@tonic-gate case CFGA_USB_RCM_ONLINE: 3647c478bd9Sstevel@tonic-gate case CFGA_USB_RCM_OFFLINE: 3657c478bd9Sstevel@tonic-gate case CFGA_USB_RCM_INFO: 3667c478bd9Sstevel@tonic-gate case CFGA_USB_DEVCTL: 3677c478bd9Sstevel@tonic-gate /* These messages also print ap_id. */ 368d29f5a71Szhigang lu - Sun Microsystems - Beijing China (void) set_msg(errstring, ERR_STR(rv), 369d29f5a71Szhigang lu - Sun Microsystems - Beijing China "ap_id: ", ap_id, "", NULL); 3707c478bd9Sstevel@tonic-gate break; 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate case CFGA_USB_IOCTL: 3737c478bd9Sstevel@tonic-gate case CFGA_USB_NVLIST: 3747c478bd9Sstevel@tonic-gate case CFGA_USB_CONFIG_FILE: 3757c478bd9Sstevel@tonic-gate case CFGA_USB_ONE_CONFIG: 3767c478bd9Sstevel@tonic-gate /* These messages also print errno. */ 3777c478bd9Sstevel@tonic-gate { 3787c478bd9Sstevel@tonic-gate char *errno_str = l_errno ? strerror(l_errno) : ""; 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate set_msg(errstring, ERR_STR(rv), errno_str, 3817c478bd9Sstevel@tonic-gate l_errno ? "\n" : "", NULL); 3827c478bd9Sstevel@tonic-gate break; 3837c478bd9Sstevel@tonic-gate } 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate case CFGA_USB_OPEN: 3867c478bd9Sstevel@tonic-gate /* These messages also apid and errno. */ 3877c478bd9Sstevel@tonic-gate { 3887c478bd9Sstevel@tonic-gate char *errno_str = l_errno ? strerror(l_errno) : ""; 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate set_msg(errstring, ERR_STR(rv), "ap_id: ", ap_id, "\n", 3917c478bd9Sstevel@tonic-gate errno_str, l_errno ? "\n" : "", NULL); 3927c478bd9Sstevel@tonic-gate break; 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate default: 3967c478bd9Sstevel@tonic-gate DPRINTF("usb_err_msg: Unrecognized message index: %d\n", rv); 3977c478bd9Sstevel@tonic-gate set_msg(errstring, ERR_STR(CFGA_USB_INTERNAL_ERROR), NULL); 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate } /* end switch */ 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate /* 4027c478bd9Sstevel@tonic-gate * Determine the proper error code to send back to the cfgadm library. 4037c478bd9Sstevel@tonic-gate */ 4047c478bd9Sstevel@tonic-gate return (usb_error_msgs[rv].cfga_err); 4057c478bd9Sstevel@tonic-gate } 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate /* 4097c478bd9Sstevel@tonic-gate * Ensure the ap_id passed is in the correct (physical ap_id) form: 4107c478bd9Sstevel@tonic-gate * path/device:xx[.xx]+ 4117c478bd9Sstevel@tonic-gate * where xx is a one or two-digit number. 4127c478bd9Sstevel@tonic-gate * 4137c478bd9Sstevel@tonic-gate * Note the library always calls the plugin with a physical ap_id. 4147c478bd9Sstevel@tonic-gate */ 4157c478bd9Sstevel@tonic-gate static int 4167c478bd9Sstevel@tonic-gate verify_valid_apid(const char *ap_id) 4177c478bd9Sstevel@tonic-gate { 4187c478bd9Sstevel@tonic-gate char *l_ap_id; 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate if (ap_id == NULL) { 4217c478bd9Sstevel@tonic-gate return (-1); 4227c478bd9Sstevel@tonic-gate } 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate l_ap_id = strrchr(ap_id, *MINOR_SEP); 4257c478bd9Sstevel@tonic-gate l_ap_id++; 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate if (strspn(l_ap_id, "0123456789.") != strlen(l_ap_id)) { 4287c478bd9Sstevel@tonic-gate /* Bad characters in the ap_id. */ 4297c478bd9Sstevel@tonic-gate return (-1); 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate if (strstr(l_ap_id, "..") != NULL) { 4337c478bd9Sstevel@tonic-gate /* ap_id has 1..2 or more than 2 dots */ 4347c478bd9Sstevel@tonic-gate return (-1); 4357c478bd9Sstevel@tonic-gate } 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate return (0); 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate /* 4427c478bd9Sstevel@tonic-gate * Verify the params passed in are valid. 4437c478bd9Sstevel@tonic-gate */ 4447c478bd9Sstevel@tonic-gate static cfga_usb_ret_t 4457c478bd9Sstevel@tonic-gate verify_params( 4467c478bd9Sstevel@tonic-gate const char *ap_id, 4477c478bd9Sstevel@tonic-gate const char *options, 4487c478bd9Sstevel@tonic-gate char **errstring) 4497c478bd9Sstevel@tonic-gate { 4507c478bd9Sstevel@tonic-gate if (errstring != NULL) { 4517c478bd9Sstevel@tonic-gate *errstring = NULL; 4527c478bd9Sstevel@tonic-gate } 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate if (options != NULL) { 4557c478bd9Sstevel@tonic-gate DPRINTF("verify_params: hardware-specific options not " 4567c478bd9Sstevel@tonic-gate "supported.\n"); 4577c478bd9Sstevel@tonic-gate return (CFGA_USB_OPTIONS); 4587c478bd9Sstevel@tonic-gate } 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate /* Dynamic attachment points not supported (yet). */ 4617c478bd9Sstevel@tonic-gate if (GET_DYN(ap_id) != NULL) { 4627c478bd9Sstevel@tonic-gate DPRINTF("verify_params: dynamic ap_id passed\n"); 4637c478bd9Sstevel@tonic-gate return (CFGA_USB_DYNAMIC_AP); 4647c478bd9Sstevel@tonic-gate } 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate if (verify_valid_apid(ap_id) != 0) { 4677c478bd9Sstevel@tonic-gate DPRINTF("verify_params: not a USB ap_id.\n"); 4687c478bd9Sstevel@tonic-gate return (CFGA_USB_AP); 4697c478bd9Sstevel@tonic-gate } 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate return (CFGA_USB_OK); 4727c478bd9Sstevel@tonic-gate } 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate /* 4767c478bd9Sstevel@tonic-gate * Takes a validated ap_id and extracts the port number. 4777c478bd9Sstevel@tonic-gate */ 4787c478bd9Sstevel@tonic-gate static cfga_usb_ret_t 4797c478bd9Sstevel@tonic-gate get_port_num(const char *ap_id, uint_t *port) 4807c478bd9Sstevel@tonic-gate { 4817c478bd9Sstevel@tonic-gate char *port_nbr_str; 4827c478bd9Sstevel@tonic-gate char *temp; 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate port_nbr_str = strrchr(ap_id, *MINOR_SEP) + strlen(MINOR_SEP); 4857c478bd9Sstevel@tonic-gate if ((temp = strrchr(ap_id, (int)*PORT_SEPERATOR)) != 0) { 4867c478bd9Sstevel@tonic-gate port_nbr_str = temp + strlen(PORT_SEPERATOR); 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate errno = 0; 4907c478bd9Sstevel@tonic-gate *port = strtol(port_nbr_str, NULL, 10); 4917c478bd9Sstevel@tonic-gate if (errno) { 4927c478bd9Sstevel@tonic-gate DPRINTF("get_port_num: conversion of port str failed\n"); 4937c478bd9Sstevel@tonic-gate return (CFGA_USB_PORT); 4947c478bd9Sstevel@tonic-gate } 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate return (CFGA_USB_OK); 4977c478bd9Sstevel@tonic-gate } 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate /* 5017c478bd9Sstevel@tonic-gate * Pair of routines to set up for/clean up after a devctl_ap_* lib call. 5027c478bd9Sstevel@tonic-gate */ 5037c478bd9Sstevel@tonic-gate static void 5047c478bd9Sstevel@tonic-gate cleanup_after_devctl_cmd(devctl_hdl_t devctl_hdl, nvlist_t *user_nvlist) 5057c478bd9Sstevel@tonic-gate { 5067c478bd9Sstevel@tonic-gate if (user_nvlist != NULL) { 5077c478bd9Sstevel@tonic-gate nvlist_free(user_nvlist); 5087c478bd9Sstevel@tonic-gate } 5097c478bd9Sstevel@tonic-gate if (devctl_hdl != NULL) { 5107c478bd9Sstevel@tonic-gate devctl_release(devctl_hdl); 5117c478bd9Sstevel@tonic-gate } 5127c478bd9Sstevel@tonic-gate } 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate static cfga_usb_ret_t 5167c478bd9Sstevel@tonic-gate setup_for_devctl_cmd(const char *ap_id, devctl_hdl_t *devctl_hdl, 5177c478bd9Sstevel@tonic-gate nvlist_t **user_nvlistp, uint_t oflag) 5187c478bd9Sstevel@tonic-gate { 5197c478bd9Sstevel@tonic-gate uint32_t port; 5207c478bd9Sstevel@tonic-gate cfga_usb_ret_t rv = CFGA_USB_OK; 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate DPRINTF("setup_for_devctl_cmd: oflag=%d\n", oflag); 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate /* Get a handle to the ap */ 5257c478bd9Sstevel@tonic-gate if ((*devctl_hdl = devctl_ap_acquire((char *)ap_id, oflag)) == NULL) { 5267c478bd9Sstevel@tonic-gate DPRINTF("setup_for_devctl_cmd: devctl_ap_acquire failed with " 5277c478bd9Sstevel@tonic-gate "errno: %d\n", errno); 5287c478bd9Sstevel@tonic-gate rv = CFGA_USB_DEVCTL; 5297c478bd9Sstevel@tonic-gate goto bailout; 5307c478bd9Sstevel@tonic-gate } 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate /* Set up to pass port number down to driver */ 5337c478bd9Sstevel@tonic-gate if (nvlist_alloc(user_nvlistp, NV_UNIQUE_NAME_TYPE, NULL) != 0) { 5347c478bd9Sstevel@tonic-gate DPRINTF("setup_for_devctl: nvlist_alloc failed, errno: %d\n", 5357c478bd9Sstevel@tonic-gate errno); 5367c478bd9Sstevel@tonic-gate *user_nvlistp = NULL; /* Prevent possible incorrect free in */ 5377c478bd9Sstevel@tonic-gate /* cleanup_after_devctl_cmd */ 5387c478bd9Sstevel@tonic-gate rv = CFGA_USB_NVLIST; 5397c478bd9Sstevel@tonic-gate goto bailout; 5407c478bd9Sstevel@tonic-gate } 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate if ((rv = get_port_num(ap_id, &port)) != CFGA_USB_OK) { 5437c478bd9Sstevel@tonic-gate DPRINTF("setup_for_devctl_cmd: get_port_num, errno: %d\n", 5447c478bd9Sstevel@tonic-gate errno); 5457c478bd9Sstevel@tonic-gate goto bailout; 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate /* creates an int32_t entry */ 5497c478bd9Sstevel@tonic-gate if (nvlist_add_int32(*user_nvlistp, PORT, port) == -1) { 5507c478bd9Sstevel@tonic-gate DPRINTF("setup_for_devctl_cmd: nvlist_add_int32 failed. " 5517c478bd9Sstevel@tonic-gate "errno: %d\n", errno); 5527c478bd9Sstevel@tonic-gate rv = CFGA_USB_NVLIST; 5537c478bd9Sstevel@tonic-gate goto bailout; 5547c478bd9Sstevel@tonic-gate } 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate return (rv); 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate bailout: 5597c478bd9Sstevel@tonic-gate cleanup_after_devctl_cmd(*devctl_hdl, *user_nvlistp); 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate return (rv); 5627c478bd9Sstevel@tonic-gate } 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate /* 5667c478bd9Sstevel@tonic-gate * Ensure that there's a device actually connected to the ap 5677c478bd9Sstevel@tonic-gate */ 5687c478bd9Sstevel@tonic-gate static cfga_usb_ret_t 5697c478bd9Sstevel@tonic-gate device_configured(devctl_hdl_t hdl, nvlist_t *nvl, ap_rstate_t *rstate) 5707c478bd9Sstevel@tonic-gate { 5717c478bd9Sstevel@tonic-gate cfga_usb_ret_t rv; 5727c478bd9Sstevel@tonic-gate devctl_ap_state_t devctl_ap_state; 5737c478bd9Sstevel@tonic-gate 5747c478bd9Sstevel@tonic-gate DPRINTF("device_configured:\n"); 5757c478bd9Sstevel@tonic-gate if (devctl_ap_getstate(hdl, nvl, &devctl_ap_state) == -1) { 5767c478bd9Sstevel@tonic-gate DPRINTF("devctl_ap_getstate failed, errno: %d\n", errno); 5777c478bd9Sstevel@tonic-gate return (CFGA_USB_DEVCTL); 5787c478bd9Sstevel@tonic-gate } 5797c478bd9Sstevel@tonic-gate 5807c478bd9Sstevel@tonic-gate rv = CFGA_USB_ALREADY_CONFIGURED; 5817c478bd9Sstevel@tonic-gate *rstate = devctl_ap_state.ap_rstate; 5827c478bd9Sstevel@tonic-gate if (devctl_ap_state.ap_ostate != AP_OSTATE_CONFIGURED) { 5837c478bd9Sstevel@tonic-gate return (CFGA_USB_NOT_CONFIGURED); 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate return (rv); 5877c478bd9Sstevel@tonic-gate } 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate /* 5917c478bd9Sstevel@tonic-gate * Ensure that there's a device actually connected to the ap 5927c478bd9Sstevel@tonic-gate */ 5937c478bd9Sstevel@tonic-gate static cfga_usb_ret_t 5947c478bd9Sstevel@tonic-gate device_connected(devctl_hdl_t hdl, nvlist_t *list, ap_ostate_t *ostate) 5957c478bd9Sstevel@tonic-gate { 5967c478bd9Sstevel@tonic-gate cfga_usb_ret_t rv = CFGA_USB_ALREADY_CONNECTED; 5977c478bd9Sstevel@tonic-gate devctl_ap_state_t devctl_ap_state; 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate DPRINTF("device_connected:\n"); 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate if (devctl_ap_getstate(hdl, list, &devctl_ap_state) == -1) { 6027c478bd9Sstevel@tonic-gate DPRINTF("devctl_ap_getstate failed, errno: %d\n", errno); 6037c478bd9Sstevel@tonic-gate return (CFGA_USB_DEVCTL); 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate *ostate = devctl_ap_state.ap_ostate; 6077c478bd9Sstevel@tonic-gate if (devctl_ap_state.ap_rstate != AP_RSTATE_CONNECTED) { 6087c478bd9Sstevel@tonic-gate return (CFGA_USB_NOT_CONNECTED); 6097c478bd9Sstevel@tonic-gate } 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate return (rv); 6127c478bd9Sstevel@tonic-gate } 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate /* 6167c478bd9Sstevel@tonic-gate * Given a subcommand to the DEVCTL_AP_CONTROL ioctl, rquest the size of 6177c478bd9Sstevel@tonic-gate * the data to be returned, allocate a buffer, then get the data. 6187c478bd9Sstevel@tonic-gate * Returns *descrp (which must be freed) and size. 6197c478bd9Sstevel@tonic-gate * 6207c478bd9Sstevel@tonic-gate * Note USB_DESCR_TYPE_STRING returns an ASCII NULL-terminated string, 6217c478bd9Sstevel@tonic-gate * not a string descr. 6227c478bd9Sstevel@tonic-gate */ 6237c478bd9Sstevel@tonic-gate cfga_usb_ret_t 6247c478bd9Sstevel@tonic-gate do_control_ioctl(const char *ap_id, uint_t subcommand, uint_t arg, 625*cf252232SAndy Fiddaman void **descrp, size_t *sizep) 6267c478bd9Sstevel@tonic-gate { 6277c478bd9Sstevel@tonic-gate int fd = -1; 6287c478bd9Sstevel@tonic-gate uint_t port; 6297c478bd9Sstevel@tonic-gate uint32_t local_size; 6307c478bd9Sstevel@tonic-gate cfga_usb_ret_t rv = CFGA_USB_OK; 6317c478bd9Sstevel@tonic-gate struct hubd_ioctl_data ioctl_data; 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate assert(descrp != NULL); 6347c478bd9Sstevel@tonic-gate *descrp = NULL; 6357c478bd9Sstevel@tonic-gate assert(sizep != NULL); 6367c478bd9Sstevel@tonic-gate 6377c478bd9Sstevel@tonic-gate if ((rv = get_port_num(ap_id, &port)) != CFGA_USB_OK) { 6387c478bd9Sstevel@tonic-gate goto bailout; 6397c478bd9Sstevel@tonic-gate } 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate if ((fd = open(ap_id, O_RDONLY)) == -1) { 6427c478bd9Sstevel@tonic-gate DPRINTF("do_control_ioctl: open failed: errno:%d\n", errno); 6437c478bd9Sstevel@tonic-gate rv = CFGA_USB_OPEN; 6447c478bd9Sstevel@tonic-gate if (errno == EBUSY) { 6457c478bd9Sstevel@tonic-gate rv = CFGA_USB_BUSY; 6467c478bd9Sstevel@tonic-gate } 6477c478bd9Sstevel@tonic-gate goto bailout; 6487c478bd9Sstevel@tonic-gate } 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate ioctl_data.cmd = subcommand; 6517c478bd9Sstevel@tonic-gate ioctl_data.port = port; 6527c478bd9Sstevel@tonic-gate ioctl_data.misc_arg = (uint_t)arg; 6537c478bd9Sstevel@tonic-gate 6547c478bd9Sstevel@tonic-gate /* 6557c478bd9Sstevel@tonic-gate * Find out how large a buf we need to get the data. 6567c478bd9Sstevel@tonic-gate * 6577c478bd9Sstevel@tonic-gate * Note the ioctls only accept/return a 32-bit int for a get_size 6587c478bd9Sstevel@tonic-gate * to avoid 32/64 and BE/LE issues. 6597c478bd9Sstevel@tonic-gate */ 6607c478bd9Sstevel@tonic-gate ioctl_data.get_size = B_TRUE; 6617c478bd9Sstevel@tonic-gate ioctl_data.buf = (caddr_t)&local_size; 6627c478bd9Sstevel@tonic-gate ioctl_data.bufsiz = sizeof (local_size); 6637c478bd9Sstevel@tonic-gate 6647c478bd9Sstevel@tonic-gate if (ioctl(fd, DEVCTL_AP_CONTROL, &ioctl_data) != 0) { 6657c478bd9Sstevel@tonic-gate DPRINTF("do_control_ioctl: size ioctl failed: errno:%d\n", 6667c478bd9Sstevel@tonic-gate errno); 6677c478bd9Sstevel@tonic-gate rv = CFGA_USB_IOCTL; 6687c478bd9Sstevel@tonic-gate goto bailout; 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate *sizep = local_size; 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate if (subcommand == USB_DESCR_TYPE_STRING && 6737c478bd9Sstevel@tonic-gate arg == HUBD_CFG_DESCR_STR && local_size == 0) { 6747c478bd9Sstevel@tonic-gate /* Zero-length data - nothing to do. */ 6757c478bd9Sstevel@tonic-gate rv = CFGA_USB_ZEROLEN; 6767c478bd9Sstevel@tonic-gate goto bailout; 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate if (subcommand == HUBD_REFRESH_DEVDB) { 6797c478bd9Sstevel@tonic-gate /* Already done - no data transfer; nothing left to do. */ 6807c478bd9Sstevel@tonic-gate goto bailout; 6817c478bd9Sstevel@tonic-gate } 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate if ((*descrp = malloc(*sizep)) == NULL) { 6847c478bd9Sstevel@tonic-gate DPRINTF("do_control_ioctl: malloc failed\n"); 6857c478bd9Sstevel@tonic-gate rv = CFGA_USB_ALLOC_FAIL; 6867c478bd9Sstevel@tonic-gate goto bailout; 6877c478bd9Sstevel@tonic-gate } 6887c478bd9Sstevel@tonic-gate 6897c478bd9Sstevel@tonic-gate /* Get the data */ 6907c478bd9Sstevel@tonic-gate ioctl_data.get_size = B_FALSE; 6917c478bd9Sstevel@tonic-gate ioctl_data.buf = *descrp; 6927c478bd9Sstevel@tonic-gate ioctl_data.bufsiz = *sizep; 6937c478bd9Sstevel@tonic-gate 6947c478bd9Sstevel@tonic-gate if (ioctl(fd, DEVCTL_AP_CONTROL, &ioctl_data) != 0) { 6957c478bd9Sstevel@tonic-gate DPRINTF("do_control_ioctl: ioctl failed: errno:%d\n", 6967c478bd9Sstevel@tonic-gate errno); 6977c478bd9Sstevel@tonic-gate rv = CFGA_USB_IOCTL; 6987c478bd9Sstevel@tonic-gate goto bailout; 6997c478bd9Sstevel@tonic-gate } 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate (void) close(fd); 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate return (rv); 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate 7067c478bd9Sstevel@tonic-gate bailout: 7077c478bd9Sstevel@tonic-gate if (fd != -1) { 7087c478bd9Sstevel@tonic-gate (void) close(fd); 7097c478bd9Sstevel@tonic-gate } 7107c478bd9Sstevel@tonic-gate if (*descrp != NULL) { 7117c478bd9Sstevel@tonic-gate free(*descrp); 7127c478bd9Sstevel@tonic-gate *descrp = NULL; 7137c478bd9Sstevel@tonic-gate } 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate if (rv == CFGA_USB_IOCTL && errno == EBUSY) { 7167c478bd9Sstevel@tonic-gate rv = CFGA_USB_BUSY; /* Provide more useful msg */ 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate return (rv); 7207c478bd9Sstevel@tonic-gate } 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate /* ========================================================================= */ 7247c478bd9Sstevel@tonic-gate /* 7257c478bd9Sstevel@tonic-gate * Support funcs called directly from cfga_* entry points. 7267c478bd9Sstevel@tonic-gate */ 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate /* 7307c478bd9Sstevel@tonic-gate * Invoked from cfga_private_func. 7317c478bd9Sstevel@tonic-gate * Modify the USB persistant configuration file so that the device 7327c478bd9Sstevel@tonic-gate * represented by ap_id will henceforth be initialized to the desired 7337c478bd9Sstevel@tonic-gate * configuration setting (configuration index). 7347c478bd9Sstevel@tonic-gate */ 7357c478bd9Sstevel@tonic-gate static cfga_usb_ret_t 7367c478bd9Sstevel@tonic-gate set_configuration(const char *ap_id, uint_t config, char *driver, 7377c478bd9Sstevel@tonic-gate usb_dev_descr_t *descrp, char **errstring) 7387c478bd9Sstevel@tonic-gate { 7397c478bd9Sstevel@tonic-gate char *serial_no = NULL; 7407c478bd9Sstevel@tonic-gate char *dev_path = NULL; 7417c478bd9Sstevel@tonic-gate char *tmp; 7427c478bd9Sstevel@tonic-gate size_t size; 7437c478bd9Sstevel@tonic-gate cfga_usb_ret_t rv = CFGA_USB_OK; 7447c478bd9Sstevel@tonic-gate 7457c478bd9Sstevel@tonic-gate DPRINTF("set_configuration: ap_id: %s, config:%d\n", ap_id, config); 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate /* Only one bNumConfigurations, don't allow this operation */ 7487c478bd9Sstevel@tonic-gate if (descrp->bNumConfigurations == 1) { 7497c478bd9Sstevel@tonic-gate DPRINTF("device supports %d configurations\n", 7507c478bd9Sstevel@tonic-gate descrp->bNumConfigurations); 7517c478bd9Sstevel@tonic-gate rv = CFGA_USB_ONE_CONFIG; 7527c478bd9Sstevel@tonic-gate goto bailout; 7537c478bd9Sstevel@tonic-gate } 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate /* get the serial number string if it exists */ 7567c478bd9Sstevel@tonic-gate if (descrp->iSerialNumber != 0) { 7577c478bd9Sstevel@tonic-gate if ((rv = do_control_ioctl(ap_id, USB_DESCR_TYPE_STRING, 7587c478bd9Sstevel@tonic-gate HUBD_SERIALNO_STR, (void **)&serial_no, &size)) != 7597c478bd9Sstevel@tonic-gate CFGA_USB_OK) { 7607c478bd9Sstevel@tonic-gate if (rv != CFGA_USB_ZEROLEN) { 7617c478bd9Sstevel@tonic-gate DPRINTF("set_configuration: get serial " 7627c478bd9Sstevel@tonic-gate "no string failed\n"); 7637c478bd9Sstevel@tonic-gate goto bailout; 7647c478bd9Sstevel@tonic-gate } 7657c478bd9Sstevel@tonic-gate } 7667c478bd9Sstevel@tonic-gate } 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate dev_path = usb_get_devicepath(ap_id); 7697c478bd9Sstevel@tonic-gate if (dev_path == NULL) { 7707c478bd9Sstevel@tonic-gate DPRINTF("get device path failed\n"); 7717c478bd9Sstevel@tonic-gate rv = CFGA_USB_DEVCTL; 7727c478bd9Sstevel@tonic-gate goto bailout; 7737c478bd9Sstevel@tonic-gate } 7747c478bd9Sstevel@tonic-gate 7757c478bd9Sstevel@tonic-gate DPRINTF("calling add_entry: vid: 0x%x pid:0x%x config:0x%x,", 7767c478bd9Sstevel@tonic-gate descrp->idVendor, descrp->idProduct, config); 7777c478bd9Sstevel@tonic-gate DPRINTF("serial_no: %s\n\tdev_path: %s\n\tdriver: %s\n", serial_no ? 7787c478bd9Sstevel@tonic-gate serial_no : "", dev_path ? dev_path : "", driver ? driver : ""); 7797c478bd9Sstevel@tonic-gate 7807c478bd9Sstevel@tonic-gate /* 7817c478bd9Sstevel@tonic-gate * the devicepath should be an absolute path. 7827c478bd9Sstevel@tonic-gate * So, if path has leading "/devices" - nuke it. 7837c478bd9Sstevel@tonic-gate */ 7847c478bd9Sstevel@tonic-gate if (strncmp(dev_path, "/devices/", 9) == 0) { 7857c478bd9Sstevel@tonic-gate tmp = dev_path + 8; 7867c478bd9Sstevel@tonic-gate } else { 7877c478bd9Sstevel@tonic-gate tmp = dev_path; 7887c478bd9Sstevel@tonic-gate } 7897c478bd9Sstevel@tonic-gate 7907c478bd9Sstevel@tonic-gate /* Save an entry in the USBCONF_FILE */ 7917c478bd9Sstevel@tonic-gate if ((rv = add_entry( 7927c478bd9Sstevel@tonic-gate "enable", /* Always to "enable" */ 7937c478bd9Sstevel@tonic-gate descrp->idVendor, /* vendorId */ 7947c478bd9Sstevel@tonic-gate descrp->idProduct, /* ProductId */ 7957c478bd9Sstevel@tonic-gate config, /* new cfgndx */ 7967c478bd9Sstevel@tonic-gate serial_no, /* serial no string */ 7977c478bd9Sstevel@tonic-gate tmp, /* device path */ 7987c478bd9Sstevel@tonic-gate driver, /* Driver (optional) */ 7997c478bd9Sstevel@tonic-gate errstring)) 8007c478bd9Sstevel@tonic-gate != CFGA_USB_OK) { 8017c478bd9Sstevel@tonic-gate DPRINTF("set_configuration: add_entry failed\n"); 8027c478bd9Sstevel@tonic-gate goto bailout; 8037c478bd9Sstevel@tonic-gate } 8047c478bd9Sstevel@tonic-gate 8057c478bd9Sstevel@tonic-gate /* Notify hubd that it needs to refresh its db. */ 8067c478bd9Sstevel@tonic-gate if ((rv = do_control_ioctl(ap_id, HUBD_REFRESH_DEVDB, NULL, 8077c478bd9Sstevel@tonic-gate (void **)&dev_path, &size)) != CFGA_USB_OK) { 8087c478bd9Sstevel@tonic-gate DPRINTF("set_configuration: HUBD_REFRESH_DEVDB failed\n"); 8097c478bd9Sstevel@tonic-gate goto bailout; 8107c478bd9Sstevel@tonic-gate } 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate bailout: 8137c478bd9Sstevel@tonic-gate if (dev_path) { 8147c478bd9Sstevel@tonic-gate free(dev_path); 8157c478bd9Sstevel@tonic-gate } 8167c478bd9Sstevel@tonic-gate if (serial_no) { 8177c478bd9Sstevel@tonic-gate free(serial_no); 8187c478bd9Sstevel@tonic-gate } 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate return (rv); 8217c478bd9Sstevel@tonic-gate } 8227c478bd9Sstevel@tonic-gate 8237c478bd9Sstevel@tonic-gate 8247c478bd9Sstevel@tonic-gate /* 8257c478bd9Sstevel@tonic-gate * Invoked from cfga_private_func() and fill_in_ap_info(). 8267c478bd9Sstevel@tonic-gate * Call into USBA and get the current configuration setting for this device, 8277c478bd9Sstevel@tonic-gate */ 8287c478bd9Sstevel@tonic-gate static cfga_usb_ret_t 8297c478bd9Sstevel@tonic-gate get_config(const char *ap_id, uint_t *config) 8307c478bd9Sstevel@tonic-gate { 8317c478bd9Sstevel@tonic-gate size_t size; 8327c478bd9Sstevel@tonic-gate uint_t *config_val = NULL; 8337c478bd9Sstevel@tonic-gate cfga_usb_ret_t rv; 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate if ((rv = do_control_ioctl(ap_id, HUBD_GET_CURRENT_CONFIG, NULL, 8367c478bd9Sstevel@tonic-gate (void **)&config_val, &size)) != CFGA_USB_OK) { 8377c478bd9Sstevel@tonic-gate DPRINTF("get_config: get current config descr failed\n"); 8387c478bd9Sstevel@tonic-gate goto bailout; 8397c478bd9Sstevel@tonic-gate } 8407c478bd9Sstevel@tonic-gate *config = *config_val; 8417c478bd9Sstevel@tonic-gate 8427c478bd9Sstevel@tonic-gate bailout: 8437c478bd9Sstevel@tonic-gate free(config_val); 8447c478bd9Sstevel@tonic-gate return (rv); 8457c478bd9Sstevel@tonic-gate } 8467c478bd9Sstevel@tonic-gate 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate /* 8497c478bd9Sstevel@tonic-gate * Invoked from cfga_private_func. 8507c478bd9Sstevel@tonic-gate * it does an unconfigure of the device followed by a configure, 8517c478bd9Sstevel@tonic-gate * thus essentially resetting the device. 8527c478bd9Sstevel@tonic-gate */ 8537c478bd9Sstevel@tonic-gate static cfga_usb_ret_t 8547c478bd9Sstevel@tonic-gate reset_device(devctl_hdl_t devctl_hdl, nvlist_t *nvl) 8557c478bd9Sstevel@tonic-gate { 8567c478bd9Sstevel@tonic-gate cfga_usb_ret_t rv; 8577c478bd9Sstevel@tonic-gate 8587c478bd9Sstevel@tonic-gate DPRINTF("reset_device: \n"); 8597c478bd9Sstevel@tonic-gate 8607c478bd9Sstevel@tonic-gate /* 8617c478bd9Sstevel@tonic-gate * Disconnect and reconfigure the device. 8627c478bd9Sstevel@tonic-gate * Note this forces the new default config to take effect. 8637c478bd9Sstevel@tonic-gate */ 8647c478bd9Sstevel@tonic-gate if (devctl_ap_disconnect(devctl_hdl, nvl) != 0) { 8657c478bd9Sstevel@tonic-gate DPRINTF("devctl_ap_unconfigure failed, errno: %d\n", errno); 8667c478bd9Sstevel@tonic-gate rv = CFGA_USB_DEVCTL; 8677c478bd9Sstevel@tonic-gate if (errno == EBUSY) { 8687c478bd9Sstevel@tonic-gate rv = CFGA_USB_BUSY; /* Provide more useful msg */ 8697c478bd9Sstevel@tonic-gate } 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate return (rv); 8727c478bd9Sstevel@tonic-gate } 8737c478bd9Sstevel@tonic-gate 8747c478bd9Sstevel@tonic-gate if (devctl_ap_configure(devctl_hdl, nvl) != 0) { 8757c478bd9Sstevel@tonic-gate DPRINTF(" devctl_ap_configure failed, errno = %d\n", errno); 8767c478bd9Sstevel@tonic-gate return (CFGA_USB_DEVCTL); 8777c478bd9Sstevel@tonic-gate } 8787c478bd9Sstevel@tonic-gate 8797c478bd9Sstevel@tonic-gate return (CFGA_USB_OK); 8807c478bd9Sstevel@tonic-gate } 8817c478bd9Sstevel@tonic-gate 8827c478bd9Sstevel@tonic-gate 8837c478bd9Sstevel@tonic-gate /* 8847c478bd9Sstevel@tonic-gate * Called from cfga_list_ext. 8857c478bd9Sstevel@tonic-gate * Fills in the 'misc_info' field in the cfga buffer (displayed with -lv). 8867c478bd9Sstevel@tonic-gate */ 8877c478bd9Sstevel@tonic-gate static cfga_usb_ret_t 8887c478bd9Sstevel@tonic-gate fill_in_ap_info(const char *ap_id, char *info_buf, size_t info_size) 8897c478bd9Sstevel@tonic-gate { 8907c478bd9Sstevel@tonic-gate char *mfg_str = NULL; /* iManufacturer */ 8917c478bd9Sstevel@tonic-gate char *prod_str = NULL; /* iProduct */ 8927c478bd9Sstevel@tonic-gate char *cfg_descr = NULL; /* iConfiguration */ 8937c478bd9Sstevel@tonic-gate uint_t config; /* curr cfg index */ 8947c478bd9Sstevel@tonic-gate size_t size; /* tmp stuff */ 8957c478bd9Sstevel@tonic-gate boolean_t flag; /* wether to print ":" or not */ 8967c478bd9Sstevel@tonic-gate boolean_t free_mfg_str = B_FALSE; 8977c478bd9Sstevel@tonic-gate boolean_t free_prod_str = B_FALSE; 8987c478bd9Sstevel@tonic-gate boolean_t free_cfg_str = B_FALSE; 8997c478bd9Sstevel@tonic-gate cfga_usb_ret_t rv = CFGA_USB_OK; 9007c478bd9Sstevel@tonic-gate usb_dev_descr_t *dev_descrp = NULL; /* device descriptor */ 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate DPRINTF("fill_in_ap_info:\n"); 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate if ((rv = do_control_ioctl(ap_id, USB_DESCR_TYPE_DEV, NULL, 9057c478bd9Sstevel@tonic-gate (void **)&dev_descrp, &size)) != CFGA_USB_OK) { 9067c478bd9Sstevel@tonic-gate DPRINTF("fill_in_ap_info: get dev descr failed\n"); 9077c478bd9Sstevel@tonic-gate return (rv); 9087c478bd9Sstevel@tonic-gate } 9097c478bd9Sstevel@tonic-gate 9107c478bd9Sstevel@tonic-gate /* iManufacturer */ 9117c478bd9Sstevel@tonic-gate mfg_str = USB_UNDEF_STR; 9127c478bd9Sstevel@tonic-gate if (dev_descrp->iManufacturer != 0) { 9137c478bd9Sstevel@tonic-gate if ((rv = do_control_ioctl(ap_id, USB_DESCR_TYPE_STRING, 9147c478bd9Sstevel@tonic-gate HUBD_MFG_STR, (void **)&mfg_str, &size)) != CFGA_USB_OK) { 9157c478bd9Sstevel@tonic-gate if (rv == CFGA_USB_ZEROLEN) { 9167c478bd9Sstevel@tonic-gate rv = CFGA_USB_OK; 9177c478bd9Sstevel@tonic-gate } else { 9187c478bd9Sstevel@tonic-gate DPRINTF("get iManufacturer failed\n"); 9197c478bd9Sstevel@tonic-gate goto bailout; 9207c478bd9Sstevel@tonic-gate } 9217c478bd9Sstevel@tonic-gate } 9227c478bd9Sstevel@tonic-gate free_mfg_str = B_TRUE; 9237c478bd9Sstevel@tonic-gate } 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate /* iProduct */ 9267c478bd9Sstevel@tonic-gate prod_str = USB_UNDEF_STR; 9277c478bd9Sstevel@tonic-gate if (dev_descrp->iProduct != 0) { 9287c478bd9Sstevel@tonic-gate if ((rv = do_control_ioctl(ap_id, USB_DESCR_TYPE_STRING, 9297c478bd9Sstevel@tonic-gate HUBD_PRODUCT_STR, (void **)&prod_str, 9307c478bd9Sstevel@tonic-gate &size)) != CFGA_USB_OK) { 9317c478bd9Sstevel@tonic-gate if (rv == CFGA_USB_ZEROLEN) { 9327c478bd9Sstevel@tonic-gate rv = CFGA_USB_OK; 9337c478bd9Sstevel@tonic-gate } else { 9347c478bd9Sstevel@tonic-gate DPRINTF("getting iProduct failed\n"); 9357c478bd9Sstevel@tonic-gate goto bailout; 9367c478bd9Sstevel@tonic-gate } 9377c478bd9Sstevel@tonic-gate } 9387c478bd9Sstevel@tonic-gate free_prod_str = B_TRUE; 9397c478bd9Sstevel@tonic-gate } 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate /* Current conifguration */ 9427c478bd9Sstevel@tonic-gate if ((rv = get_config(ap_id, &config)) != CFGA_USB_OK) { 9437c478bd9Sstevel@tonic-gate DPRINTF("get_config failed\n"); 9447c478bd9Sstevel@tonic-gate goto bailout; 9457c478bd9Sstevel@tonic-gate } 9467c478bd9Sstevel@tonic-gate 9477c478bd9Sstevel@tonic-gate /* Configuration string descriptor */ 9487c478bd9Sstevel@tonic-gate cfg_descr = USB_NO_CFG_STR; 9497c478bd9Sstevel@tonic-gate if ((rv = do_control_ioctl(ap_id, USB_DESCR_TYPE_STRING, 9507c478bd9Sstevel@tonic-gate HUBD_CFG_DESCR_STR, (void **)&cfg_descr, &size)) != CFGA_USB_OK) { 9517c478bd9Sstevel@tonic-gate if (rv == CFGA_USB_ZEROLEN) { 9527c478bd9Sstevel@tonic-gate rv = CFGA_USB_OK; 9537c478bd9Sstevel@tonic-gate flag = B_TRUE; 9547c478bd9Sstevel@tonic-gate } else { 9557c478bd9Sstevel@tonic-gate DPRINTF("HUBD_CFG_DESCR_STR failed\n"); 9567c478bd9Sstevel@tonic-gate goto bailout; 9577c478bd9Sstevel@tonic-gate } 9587c478bd9Sstevel@tonic-gate } 9597c478bd9Sstevel@tonic-gate 9607c478bd9Sstevel@tonic-gate /* add ": " to output coz PSARC case says so */ 9617c478bd9Sstevel@tonic-gate if ((cfg_descr != (char *)NULL) && rv != CFGA_USB_ZEROLEN) { 9627c478bd9Sstevel@tonic-gate flag = B_TRUE; 9637c478bd9Sstevel@tonic-gate free_cfg_str = B_TRUE; 9647c478bd9Sstevel@tonic-gate } else { 9657c478bd9Sstevel@tonic-gate flag = B_FALSE; 9667c478bd9Sstevel@tonic-gate cfg_descr = USB_NO_CFG_STR; 9677c478bd9Sstevel@tonic-gate } 9687c478bd9Sstevel@tonic-gate 9697c478bd9Sstevel@tonic-gate /* Dump local buf into passed-in buf. */ 9707c478bd9Sstevel@tonic-gate (void) snprintf(info_buf, info_size, 9717c478bd9Sstevel@tonic-gate "Mfg: %s Product: %s NConfigs: %d Config: %d %s%s", mfg_str, 9727c478bd9Sstevel@tonic-gate prod_str, dev_descrp->bNumConfigurations, config, 9737c478bd9Sstevel@tonic-gate (flag == B_TRUE) ? ": " : "", cfg_descr); 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate bailout: 9767c478bd9Sstevel@tonic-gate if (dev_descrp) { 9777c478bd9Sstevel@tonic-gate free(dev_descrp); 9787c478bd9Sstevel@tonic-gate } 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate if ((free_mfg_str == B_TRUE) && mfg_str) { 9817c478bd9Sstevel@tonic-gate free(mfg_str); 9827c478bd9Sstevel@tonic-gate } 9837c478bd9Sstevel@tonic-gate 9847c478bd9Sstevel@tonic-gate if ((free_prod_str == B_TRUE) && prod_str) { 9857c478bd9Sstevel@tonic-gate free(prod_str); 9867c478bd9Sstevel@tonic-gate } 9877c478bd9Sstevel@tonic-gate 9887c478bd9Sstevel@tonic-gate if ((free_cfg_str == B_TRUE) && cfg_descr) { 9897c478bd9Sstevel@tonic-gate free(cfg_descr); 9907c478bd9Sstevel@tonic-gate } 9917c478bd9Sstevel@tonic-gate 9927c478bd9Sstevel@tonic-gate return (rv); 9937c478bd9Sstevel@tonic-gate } 9947c478bd9Sstevel@tonic-gate 9957c478bd9Sstevel@tonic-gate 9967c478bd9Sstevel@tonic-gate /* ========================================================================== */ 9977c478bd9Sstevel@tonic-gate /* Entry points */ 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate 10007c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 10017c478bd9Sstevel@tonic-gate cfga_err_t 10027c478bd9Sstevel@tonic-gate cfga_change_state( 10037c478bd9Sstevel@tonic-gate cfga_cmd_t state_change_cmd, 10047c478bd9Sstevel@tonic-gate const char *ap_id, 10057c478bd9Sstevel@tonic-gate const char *options, 10067c478bd9Sstevel@tonic-gate struct cfga_confirm *confp, 10077c478bd9Sstevel@tonic-gate struct cfga_msg *msgp, 10087c478bd9Sstevel@tonic-gate char **errstring, 10097c478bd9Sstevel@tonic-gate cfga_flags_t flags) 10107c478bd9Sstevel@tonic-gate { 10117c478bd9Sstevel@tonic-gate int ret; 10127c478bd9Sstevel@tonic-gate int len; 10137c478bd9Sstevel@tonic-gate char *msg; 10147c478bd9Sstevel@tonic-gate char *devpath; 10157c478bd9Sstevel@tonic-gate nvlist_t *nvl = NULL; 10167c478bd9Sstevel@tonic-gate ap_rstate_t rstate; 10177c478bd9Sstevel@tonic-gate ap_ostate_t ostate; 10187c478bd9Sstevel@tonic-gate devctl_hdl_t hdl = NULL; 10197c478bd9Sstevel@tonic-gate cfga_usb_ret_t rv = CFGA_USB_OK; 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate DPRINTF("cfga_change_state:\n"); 10227c478bd9Sstevel@tonic-gate 10237c478bd9Sstevel@tonic-gate if ((rv = verify_params(ap_id, options, errstring)) != CFGA_USB_OK) { 10247c478bd9Sstevel@tonic-gate (void) cfga_help(msgp, options, flags); 10257c478bd9Sstevel@tonic-gate goto bailout; 10267c478bd9Sstevel@tonic-gate } 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate /* 10297c478bd9Sstevel@tonic-gate * All subcommands which can change state of device require 10307c478bd9Sstevel@tonic-gate * root privileges. 10317c478bd9Sstevel@tonic-gate */ 10327c478bd9Sstevel@tonic-gate if (geteuid() != 0) { 10337c478bd9Sstevel@tonic-gate rv = CFGA_USB_PRIV; 10347c478bd9Sstevel@tonic-gate goto bailout; 10357c478bd9Sstevel@tonic-gate } 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate if ((rv = setup_for_devctl_cmd(ap_id, &hdl, &nvl, 0)) != 10387c478bd9Sstevel@tonic-gate CFGA_USB_OK) { 10397c478bd9Sstevel@tonic-gate goto bailout; 10407c478bd9Sstevel@tonic-gate } 10417c478bd9Sstevel@tonic-gate 10427c478bd9Sstevel@tonic-gate switch (state_change_cmd) { 10437c478bd9Sstevel@tonic-gate case CFGA_CMD_CONFIGURE: 10447c478bd9Sstevel@tonic-gate if ((rv = device_configured(hdl, nvl, &rstate)) != 10457c478bd9Sstevel@tonic-gate CFGA_USB_NOT_CONFIGURED) { 10467c478bd9Sstevel@tonic-gate goto bailout; 10477c478bd9Sstevel@tonic-gate } 10487c478bd9Sstevel@tonic-gate 10497c478bd9Sstevel@tonic-gate if (rstate == AP_RSTATE_EMPTY) { 10507c478bd9Sstevel@tonic-gate goto bailout; 10517c478bd9Sstevel@tonic-gate } 10527c478bd9Sstevel@tonic-gate rv = CFGA_USB_OK; /* Other statuses don't matter */ 10537c478bd9Sstevel@tonic-gate 10547c478bd9Sstevel@tonic-gate if (devctl_ap_configure(hdl, nvl) != 0) { 10557c478bd9Sstevel@tonic-gate DPRINTF("cfga_change_state: devctl_ap_configure " 10567c478bd9Sstevel@tonic-gate "failed. errno: %d\n", errno); 10577c478bd9Sstevel@tonic-gate rv = CFGA_USB_DEVCTL; 10587c478bd9Sstevel@tonic-gate } 10597c478bd9Sstevel@tonic-gate 10607c478bd9Sstevel@tonic-gate devpath = usb_get_devicepath(ap_id); 10617c478bd9Sstevel@tonic-gate if (devpath == NULL) { 10627c478bd9Sstevel@tonic-gate int i; 10637c478bd9Sstevel@tonic-gate /* 10647c478bd9Sstevel@tonic-gate * try for some time as USB hotplug thread 10657c478bd9Sstevel@tonic-gate * takes a while to create the path 10667c478bd9Sstevel@tonic-gate * and then eventually give up 10677c478bd9Sstevel@tonic-gate */ 10687c478bd9Sstevel@tonic-gate for (i = 0; i < 12 && (devpath == NULL); i++) { 1069d29f5a71Szhigang lu - Sun Microsystems - Beijing China (void) sleep(6); 10707c478bd9Sstevel@tonic-gate devpath = usb_get_devicepath(ap_id); 10717c478bd9Sstevel@tonic-gate } 10727c478bd9Sstevel@tonic-gate 10737c478bd9Sstevel@tonic-gate if (devpath == NULL) { 10747c478bd9Sstevel@tonic-gate DPRINTF("cfga_change_state: get device " 10757c478bd9Sstevel@tonic-gate "path failed i = %d\n", i); 10767c478bd9Sstevel@tonic-gate rv = CFGA_USB_DEVCTL; 10777c478bd9Sstevel@tonic-gate break; 10787c478bd9Sstevel@tonic-gate } 10797c478bd9Sstevel@tonic-gate } 10807c478bd9Sstevel@tonic-gate S_FREE(devpath); 10817c478bd9Sstevel@tonic-gate break; 10827c478bd9Sstevel@tonic-gate case CFGA_CMD_UNCONFIGURE: 10837c478bd9Sstevel@tonic-gate if ((rv = device_connected(hdl, nvl, &ostate)) != 10847c478bd9Sstevel@tonic-gate CFGA_USB_ALREADY_CONNECTED) { 10857c478bd9Sstevel@tonic-gate goto bailout; 10867c478bd9Sstevel@tonic-gate } 10877c478bd9Sstevel@tonic-gate 10887c478bd9Sstevel@tonic-gate /* check if it is already unconfigured */ 10897c478bd9Sstevel@tonic-gate if ((rv = device_configured(hdl, nvl, &rstate)) == 10907c478bd9Sstevel@tonic-gate CFGA_USB_NOT_CONFIGURED) { 10917c478bd9Sstevel@tonic-gate goto bailout; 10927c478bd9Sstevel@tonic-gate } 10937c478bd9Sstevel@tonic-gate rv = CFGA_USB_OK; /* Other statuses don't matter */ 10947c478bd9Sstevel@tonic-gate 10957c478bd9Sstevel@tonic-gate len = strlen(USB_CONFIRM_0) + strlen(USB_CONFIRM_1) + 1096d29f5a71Szhigang lu - Sun Microsystems - Beijing China strlen("Unconfigure") + strlen(ap_id); 10977c478bd9Sstevel@tonic-gate if ((msg = (char *)calloc(len + 3, 1)) != NULL) { 10987c478bd9Sstevel@tonic-gate (void) snprintf(msg, len + 3, "Unconfigure %s%s\n%s", 10997c478bd9Sstevel@tonic-gate USB_CONFIRM_0, ap_id, USB_CONFIRM_1); 11007c478bd9Sstevel@tonic-gate } 11017c478bd9Sstevel@tonic-gate if (!usb_confirm(confp, msg)) { 11027c478bd9Sstevel@tonic-gate free(msg); 11037c478bd9Sstevel@tonic-gate cleanup_after_devctl_cmd(hdl, nvl); 11047c478bd9Sstevel@tonic-gate return (CFGA_NACK); 11057c478bd9Sstevel@tonic-gate } 11067c478bd9Sstevel@tonic-gate free(msg); 11077c478bd9Sstevel@tonic-gate 11087c478bd9Sstevel@tonic-gate devpath = usb_get_devicepath(ap_id); 11097c478bd9Sstevel@tonic-gate if (devpath == NULL) { 11107c478bd9Sstevel@tonic-gate DPRINTF("cfga_change_state: get device path failed\n"); 11117c478bd9Sstevel@tonic-gate rv = CFGA_USB_DEVCTL; 11127c478bd9Sstevel@tonic-gate break; 11137c478bd9Sstevel@tonic-gate } 11147c478bd9Sstevel@tonic-gate 11157c478bd9Sstevel@tonic-gate if ((rv = usb_rcm_offline(ap_id, errstring, devpath, flags)) != 11167c478bd9Sstevel@tonic-gate CFGA_USB_OK) { 11177c478bd9Sstevel@tonic-gate break; 11187c478bd9Sstevel@tonic-gate } 11197c478bd9Sstevel@tonic-gate 11207c478bd9Sstevel@tonic-gate ret = devctl_ap_unconfigure(hdl, nvl); 11217c478bd9Sstevel@tonic-gate if (ret != 0) { 11227c478bd9Sstevel@tonic-gate DPRINTF("cfga_change_state: devctl_ap_unconfigure " 11237c478bd9Sstevel@tonic-gate "failed with errno: %d\n", errno); 11247c478bd9Sstevel@tonic-gate rv = CFGA_USB_DEVCTL; 11257c478bd9Sstevel@tonic-gate if (errno == EBUSY) { 11267c478bd9Sstevel@tonic-gate rv = CFGA_USB_BUSY; 11277c478bd9Sstevel@tonic-gate } 11287c478bd9Sstevel@tonic-gate (void) usb_rcm_online(ap_id, errstring, devpath, flags); 11297c478bd9Sstevel@tonic-gate } else { 11307c478bd9Sstevel@tonic-gate (void) usb_rcm_remove(ap_id, errstring, devpath, flags); 11317c478bd9Sstevel@tonic-gate } 11327c478bd9Sstevel@tonic-gate S_FREE(devpath); 11337c478bd9Sstevel@tonic-gate break; 11347c478bd9Sstevel@tonic-gate case CFGA_CMD_DISCONNECT: 11357c478bd9Sstevel@tonic-gate if ((rv = device_connected(hdl, nvl, &ostate)) != 11367c478bd9Sstevel@tonic-gate CFGA_USB_ALREADY_CONNECTED) { 11377c478bd9Sstevel@tonic-gate /* 11387c478bd9Sstevel@tonic-gate * special case handling for 11397c478bd9Sstevel@tonic-gate * SLM based cfgadm disconnects 11407c478bd9Sstevel@tonic-gate */ 11417c478bd9Sstevel@tonic-gate if (ostate == AP_OSTATE_UNCONFIGURED) 11427c478bd9Sstevel@tonic-gate goto bailout; 11437c478bd9Sstevel@tonic-gate } 11447c478bd9Sstevel@tonic-gate rv = CFGA_USB_OK; /* Other statuses don't matter */ 11457c478bd9Sstevel@tonic-gate 11467c478bd9Sstevel@tonic-gate len = strlen(USB_CONFIRM_0) + strlen(USB_CONFIRM_1) + 1147d29f5a71Szhigang lu - Sun Microsystems - Beijing China strlen("Disconnect") + strlen(ap_id); 11487c478bd9Sstevel@tonic-gate if ((msg = (char *)calloc(len + 3, 1)) != NULL) { 11497c478bd9Sstevel@tonic-gate (void) snprintf(msg, len + 3, "Disconnect %s%s\n%s", 11507c478bd9Sstevel@tonic-gate USB_CONFIRM_0, ap_id, USB_CONFIRM_1); 11517c478bd9Sstevel@tonic-gate } 11527c478bd9Sstevel@tonic-gate if (!usb_confirm(confp, msg)) { 11537c478bd9Sstevel@tonic-gate free(msg); 11547c478bd9Sstevel@tonic-gate cleanup_after_devctl_cmd(hdl, nvl); 11557c478bd9Sstevel@tonic-gate return (CFGA_NACK); 11567c478bd9Sstevel@tonic-gate } 11577c478bd9Sstevel@tonic-gate free(msg); 11587c478bd9Sstevel@tonic-gate 11597c478bd9Sstevel@tonic-gate devpath = usb_get_devicepath(ap_id); 11607c478bd9Sstevel@tonic-gate if (devpath == NULL) { 11617c478bd9Sstevel@tonic-gate DPRINTF("cfga_change_state: get device path failed\n"); 11627c478bd9Sstevel@tonic-gate rv = CFGA_USB_DEVCTL; 11637c478bd9Sstevel@tonic-gate break; 11647c478bd9Sstevel@tonic-gate } 11657c478bd9Sstevel@tonic-gate 11667c478bd9Sstevel@tonic-gate /* only call rcm_offline iff the state was CONFIGURED */ 11677c478bd9Sstevel@tonic-gate if (ostate == AP_OSTATE_CONFIGURED) { 11687c478bd9Sstevel@tonic-gate if ((rv = usb_rcm_offline(ap_id, errstring, 11697c478bd9Sstevel@tonic-gate devpath, flags)) != CFGA_USB_OK) { 11707c478bd9Sstevel@tonic-gate break; 11717c478bd9Sstevel@tonic-gate } 11727c478bd9Sstevel@tonic-gate } 11737c478bd9Sstevel@tonic-gate 11747c478bd9Sstevel@tonic-gate ret = devctl_ap_disconnect(hdl, nvl); 11757c478bd9Sstevel@tonic-gate if (ret != 0) { 11767c478bd9Sstevel@tonic-gate DPRINTF("cfga_change_state: devctl_ap_disconnect " 11777c478bd9Sstevel@tonic-gate "failed with errno: %d\n", errno); 11787c478bd9Sstevel@tonic-gate rv = CFGA_USB_DEVCTL; 11797c478bd9Sstevel@tonic-gate if (errno == EBUSY) { 11807c478bd9Sstevel@tonic-gate rv = CFGA_USB_BUSY; 11817c478bd9Sstevel@tonic-gate } 11827c478bd9Sstevel@tonic-gate if (ostate == AP_OSTATE_CONFIGURED) { 11837c478bd9Sstevel@tonic-gate (void) usb_rcm_online(ap_id, errstring, 11847c478bd9Sstevel@tonic-gate devpath, flags); 11857c478bd9Sstevel@tonic-gate } 11867c478bd9Sstevel@tonic-gate } else { 11877c478bd9Sstevel@tonic-gate if (ostate == AP_OSTATE_CONFIGURED) { 11887c478bd9Sstevel@tonic-gate (void) usb_rcm_remove(ap_id, errstring, 11897c478bd9Sstevel@tonic-gate devpath, flags); 11907c478bd9Sstevel@tonic-gate } 11917c478bd9Sstevel@tonic-gate } 11927c478bd9Sstevel@tonic-gate S_FREE(devpath); 11937c478bd9Sstevel@tonic-gate break; 11947c478bd9Sstevel@tonic-gate case CFGA_CMD_CONNECT: 11957c478bd9Sstevel@tonic-gate case CFGA_CMD_LOAD: 11967c478bd9Sstevel@tonic-gate case CFGA_CMD_UNLOAD: 11977c478bd9Sstevel@tonic-gate (void) cfga_help(msgp, options, flags); 11987c478bd9Sstevel@tonic-gate rv = CFGA_USB_OPNOTSUPP; 11997c478bd9Sstevel@tonic-gate break; 12007c478bd9Sstevel@tonic-gate case CFGA_CMD_NONE: 12017c478bd9Sstevel@tonic-gate default: 12027c478bd9Sstevel@tonic-gate (void) cfga_help(msgp, options, flags); 12037c478bd9Sstevel@tonic-gate rv = CFGA_USB_INTERNAL_ERROR; 12047c478bd9Sstevel@tonic-gate } 12057c478bd9Sstevel@tonic-gate 12067c478bd9Sstevel@tonic-gate bailout: 12077c478bd9Sstevel@tonic-gate cleanup_after_devctl_cmd(hdl, nvl); 12087c478bd9Sstevel@tonic-gate 12097c478bd9Sstevel@tonic-gate return (usb_err_msg(errstring, rv, ap_id, errno)); 12107c478bd9Sstevel@tonic-gate } 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate 12137c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 12147c478bd9Sstevel@tonic-gate cfga_err_t 12157c478bd9Sstevel@tonic-gate cfga_private_func( 12167c478bd9Sstevel@tonic-gate const char *func, 12177c478bd9Sstevel@tonic-gate const char *ap_id, 12187c478bd9Sstevel@tonic-gate const char *options, 12197c478bd9Sstevel@tonic-gate struct cfga_confirm *confp, 12207c478bd9Sstevel@tonic-gate struct cfga_msg *msgp, 12217c478bd9Sstevel@tonic-gate char **errstring, 12227c478bd9Sstevel@tonic-gate cfga_flags_t flags) 12237c478bd9Sstevel@tonic-gate { 12247c478bd9Sstevel@tonic-gate int len; 12257c478bd9Sstevel@tonic-gate char *msg; 12267c478bd9Sstevel@tonic-gate nvlist_t *list = NULL; 12277c478bd9Sstevel@tonic-gate ap_ostate_t ostate; 1228*cf252232SAndy Fiddaman devctl_hdl_t hdl = NULL; 12297c478bd9Sstevel@tonic-gate cfga_usb_ret_t rv; 12307c478bd9Sstevel@tonic-gate usb_dev_descr_t *dev_descrp = NULL; 12317c478bd9Sstevel@tonic-gate char *driver = NULL; 12327c478bd9Sstevel@tonic-gate 12337c478bd9Sstevel@tonic-gate DPRINTF("cfga_private_func:\n"); 12347c478bd9Sstevel@tonic-gate 12357c478bd9Sstevel@tonic-gate if ((rv = verify_params(ap_id, NULL, errstring)) != CFGA_USB_OK) { 12367c478bd9Sstevel@tonic-gate (void) cfga_help(msgp, options, flags); 12377c478bd9Sstevel@tonic-gate return (usb_err_msg(errstring, rv, ap_id, errno)); 12387c478bd9Sstevel@tonic-gate } 12397c478bd9Sstevel@tonic-gate 12407c478bd9Sstevel@tonic-gate /* 12417c478bd9Sstevel@tonic-gate * All subcommands which can change state of device require 12427c478bd9Sstevel@tonic-gate * root privileges. 12437c478bd9Sstevel@tonic-gate */ 12447c478bd9Sstevel@tonic-gate if (geteuid() != 0) { 12457c478bd9Sstevel@tonic-gate rv = CFGA_USB_PRIV; 12467c478bd9Sstevel@tonic-gate goto bailout; 12477c478bd9Sstevel@tonic-gate } 12487c478bd9Sstevel@tonic-gate 12497c478bd9Sstevel@tonic-gate if (func == NULL) { 12507c478bd9Sstevel@tonic-gate rv = CFGA_USB_INTERNAL_ERROR; 12517c478bd9Sstevel@tonic-gate goto bailout; 12527c478bd9Sstevel@tonic-gate } 12537c478bd9Sstevel@tonic-gate 12547c478bd9Sstevel@tonic-gate if ((rv = setup_for_devctl_cmd(ap_id, &hdl, &list, 0)) != 12557c478bd9Sstevel@tonic-gate CFGA_USB_OK) { 12567c478bd9Sstevel@tonic-gate goto bailout; 12577c478bd9Sstevel@tonic-gate } 12587c478bd9Sstevel@tonic-gate 12597c478bd9Sstevel@tonic-gate if ((rv = device_connected(hdl, list, &ostate)) != 12607c478bd9Sstevel@tonic-gate CFGA_USB_ALREADY_CONNECTED) { 12617c478bd9Sstevel@tonic-gate goto bailout; 12627c478bd9Sstevel@tonic-gate } 12637c478bd9Sstevel@tonic-gate rv = CFGA_USB_OK; 12647c478bd9Sstevel@tonic-gate 12657c478bd9Sstevel@tonic-gate if (strcmp(func, RESET_DEVICE) == 0) { /* usb_reset? */ 12667c478bd9Sstevel@tonic-gate len = strlen(USB_CONFIRM_0) + strlen(USB_CONFIRM_1) + 1267d29f5a71Szhigang lu - Sun Microsystems - Beijing China strlen("Reset") + strlen(ap_id); 12687c478bd9Sstevel@tonic-gate if ((msg = (char *)calloc(len + 3, 1)) != NULL) { 12697c478bd9Sstevel@tonic-gate (void) snprintf(msg, len + 3, "Reset %s%s\n%s", 12707c478bd9Sstevel@tonic-gate USB_CONFIRM_0, ap_id, USB_CONFIRM_1); 12717c478bd9Sstevel@tonic-gate } else { 12727c478bd9Sstevel@tonic-gate cleanup_after_devctl_cmd(hdl, list); 12737c478bd9Sstevel@tonic-gate return (CFGA_NACK); 12747c478bd9Sstevel@tonic-gate } 12757c478bd9Sstevel@tonic-gate 12767c478bd9Sstevel@tonic-gate if (!usb_confirm(confp, msg)) { 12777c478bd9Sstevel@tonic-gate cleanup_after_devctl_cmd(hdl, list); 12787c478bd9Sstevel@tonic-gate return (CFGA_NACK); 12797c478bd9Sstevel@tonic-gate } 12807c478bd9Sstevel@tonic-gate 12817c478bd9Sstevel@tonic-gate if ((rv = reset_device(hdl, list)) != CFGA_USB_OK) { 12827c478bd9Sstevel@tonic-gate goto bailout; 12837c478bd9Sstevel@tonic-gate } 12847c478bd9Sstevel@tonic-gate } else if (strncmp(func, USB_CONFIG, sizeof (USB_CONFIG)) == 0) { 12857c478bd9Sstevel@tonic-gate uint_t config = 0; 12867c478bd9Sstevel@tonic-gate uint_t actual_config; 12877c478bd9Sstevel@tonic-gate size_t size; 12887c478bd9Sstevel@tonic-gate char *subopts, *value; 12897c478bd9Sstevel@tonic-gate uint_t cfg_opt_flag = B_FALSE; 12907c478bd9Sstevel@tonic-gate 12917c478bd9Sstevel@tonic-gate /* these are the only valid options */ 12927c478bd9Sstevel@tonic-gate char *cfg_opts[] = { 12937c478bd9Sstevel@tonic-gate "config", /* 0 */ 12947c478bd9Sstevel@tonic-gate "drv", /* 1 */ 12957c478bd9Sstevel@tonic-gate NULL 12967c478bd9Sstevel@tonic-gate }; 12977c478bd9Sstevel@tonic-gate 12987c478bd9Sstevel@tonic-gate /* return error if no options are specified */ 12997c478bd9Sstevel@tonic-gate subopts = (char *)options; 13007c478bd9Sstevel@tonic-gate if (subopts == (char *)NULL) { 13017c478bd9Sstevel@tonic-gate DPRINTF("cfga_private_func: no options\n"); 13027c478bd9Sstevel@tonic-gate rv = CFGA_USB_OPNOTSUPP; 13037c478bd9Sstevel@tonic-gate (void) cfga_help(msgp, options, flags); 13047c478bd9Sstevel@tonic-gate goto bailout; 13057c478bd9Sstevel@tonic-gate } 13067c478bd9Sstevel@tonic-gate 13077c478bd9Sstevel@tonic-gate /* parse options specified */ 13087c478bd9Sstevel@tonic-gate while (*subopts != '\0') { 13097c478bd9Sstevel@tonic-gate switch (getsubopt(&subopts, cfg_opts, &value)) { 1310d29f5a71Szhigang lu - Sun Microsystems - Beijing China case 0: /* config */ 1311d29f5a71Szhigang lu - Sun Microsystems - Beijing China if (value == NULL) { 1312d29f5a71Szhigang lu - Sun Microsystems - Beijing China rv = CFGA_USB_OPNOTSUPP; 1313d29f5a71Szhigang lu - Sun Microsystems - Beijing China (void) cfga_help(msgp, 1314d29f5a71Szhigang lu - Sun Microsystems - Beijing China options, flags); 1315d29f5a71Szhigang lu - Sun Microsystems - Beijing China goto bailout; 1316d29f5a71Szhigang lu - Sun Microsystems - Beijing China } else { 1317d29f5a71Szhigang lu - Sun Microsystems - Beijing China errno = 0; 1318d29f5a71Szhigang lu - Sun Microsystems - Beijing China config = strtol(value, 1319d29f5a71Szhigang lu - Sun Microsystems - Beijing China (char **)NULL, 10); 1320d29f5a71Szhigang lu - Sun Microsystems - Beijing China if (errno) { 1321d29f5a71Szhigang lu - Sun Microsystems - Beijing China DPRINTF( 1322d29f5a71Szhigang lu - Sun Microsystems - Beijing China "config conversion" 1323d29f5a71Szhigang lu - Sun Microsystems - Beijing China "failed\n"); 1324d29f5a71Szhigang lu - Sun Microsystems - Beijing China rv = 1325d29f5a71Szhigang lu - Sun Microsystems - Beijing China CFGA_USB_CONFIG_INVAL; 13267c478bd9Sstevel@tonic-gate goto bailout; 13277c478bd9Sstevel@tonic-gate } 1328d29f5a71Szhigang lu - Sun Microsystems - Beijing China } 1329d29f5a71Szhigang lu - Sun Microsystems - Beijing China cfg_opt_flag = B_TRUE; 1330d29f5a71Szhigang lu - Sun Microsystems - Beijing China break; 13317c478bd9Sstevel@tonic-gate 1332d29f5a71Szhigang lu - Sun Microsystems - Beijing China case 1: /* drv */ 1333d29f5a71Szhigang lu - Sun Microsystems - Beijing China if (value == NULL) { 13347c478bd9Sstevel@tonic-gate rv = CFGA_USB_OPNOTSUPP; 1335d29f5a71Szhigang lu - Sun Microsystems - Beijing China (void) cfga_help(msgp, 1336d29f5a71Szhigang lu - Sun Microsystems - Beijing China options, flags); 13377c478bd9Sstevel@tonic-gate goto bailout; 1338d29f5a71Szhigang lu - Sun Microsystems - Beijing China } else { 1339d29f5a71Szhigang lu - Sun Microsystems - Beijing China S_FREE(driver); 1340d29f5a71Szhigang lu - Sun Microsystems - Beijing China driver = strdup(value); 1341d29f5a71Szhigang lu - Sun Microsystems - Beijing China if (driver == NULL) { 1342d29f5a71Szhigang lu - Sun Microsystems - Beijing China rv = 1343d29f5a71Szhigang lu - Sun Microsystems - Beijing China CFGA_USB_INTERNAL_ERROR; 1344d29f5a71Szhigang lu - Sun Microsystems - Beijing China goto bailout; 1345d29f5a71Szhigang lu - Sun Microsystems - Beijing China } 1346d29f5a71Szhigang lu - Sun Microsystems - Beijing China } 1347d29f5a71Szhigang lu - Sun Microsystems - Beijing China break; 1348d29f5a71Szhigang lu - Sun Microsystems - Beijing China 1349d29f5a71Szhigang lu - Sun Microsystems - Beijing China default: 1350d29f5a71Szhigang lu - Sun Microsystems - Beijing China rv = CFGA_USB_OPNOTSUPP; 1351d29f5a71Szhigang lu - Sun Microsystems - Beijing China (void) cfga_help(msgp, options, flags); 1352d29f5a71Szhigang lu - Sun Microsystems - Beijing China goto bailout; 13537c478bd9Sstevel@tonic-gate } 13547c478bd9Sstevel@tonic-gate } 13557c478bd9Sstevel@tonic-gate 13567c478bd9Sstevel@tonic-gate /* config is mandatory */ 13577c478bd9Sstevel@tonic-gate if (cfg_opt_flag != B_TRUE) { 13587c478bd9Sstevel@tonic-gate rv = CFGA_USB_OPNOTSUPP; 13597c478bd9Sstevel@tonic-gate (void) cfga_help(msgp, options, flags); 13607c478bd9Sstevel@tonic-gate goto bailout; 13617c478bd9Sstevel@tonic-gate } 13627c478bd9Sstevel@tonic-gate DPRINTF("config = %x\n", config); 13637c478bd9Sstevel@tonic-gate 13647c478bd9Sstevel@tonic-gate len = strlen(USB_CONFIRM_0) + strlen(USB_CONFIRM_1) + 1365d29f5a71Szhigang lu - Sun Microsystems - Beijing China strlen("Setting") + strlen(ap_id) + 1366d29f5a71Szhigang lu - Sun Microsystems - Beijing China strlen("to USB configuration"); 13677c478bd9Sstevel@tonic-gate /* len + 8 to account for config, \n and white space */ 13687c478bd9Sstevel@tonic-gate if ((msg = (char *)calloc(len + 8, 1)) != NULL) { 13697c478bd9Sstevel@tonic-gate (void) snprintf(msg, len + 8, 13707c478bd9Sstevel@tonic-gate "Setting %s%s\nto USB configuration %d\n%s", 13717c478bd9Sstevel@tonic-gate USB_CONFIRM_0, ap_id, config, USB_CONFIRM_1); 13727c478bd9Sstevel@tonic-gate } else { 13737c478bd9Sstevel@tonic-gate rv = CFGA_USB_INTERNAL_ERROR; 13747c478bd9Sstevel@tonic-gate goto bailout; 13757c478bd9Sstevel@tonic-gate } 13767c478bd9Sstevel@tonic-gate 13777c478bd9Sstevel@tonic-gate if (!usb_confirm(confp, msg)) { 13787c478bd9Sstevel@tonic-gate S_FREE(driver); 13797c478bd9Sstevel@tonic-gate cleanup_after_devctl_cmd(hdl, list); 13807c478bd9Sstevel@tonic-gate return (CFGA_NACK); 13817c478bd9Sstevel@tonic-gate } 13827c478bd9Sstevel@tonic-gate 13837c478bd9Sstevel@tonic-gate /* 13847c478bd9Sstevel@tonic-gate * Check that the option setting selected is in range. 13857c478bd9Sstevel@tonic-gate */ 13867c478bd9Sstevel@tonic-gate if ((rv = do_control_ioctl(ap_id, USB_DESCR_TYPE_DEV, NULL, 13877c478bd9Sstevel@tonic-gate (void **)&dev_descrp, &size)) != CFGA_USB_OK) { 13887c478bd9Sstevel@tonic-gate DPRINTF("cfga_private_func: get dev descr failed\n"); 13897c478bd9Sstevel@tonic-gate goto bailout; 13907c478bd9Sstevel@tonic-gate } 13917c478bd9Sstevel@tonic-gate 13927c478bd9Sstevel@tonic-gate if (config > dev_descrp->bNumConfigurations - 1) { 13937c478bd9Sstevel@tonic-gate DPRINTF("cfga_private_func: config index requested " 13947c478bd9Sstevel@tonic-gate "(%d) exceeds bNumConfigurations - 1 (%d)\n", 13957c478bd9Sstevel@tonic-gate config, dev_descrp->bNumConfigurations - 1); 13967c478bd9Sstevel@tonic-gate rv = CFGA_USB_CONFIG_INVAL; 13977c478bd9Sstevel@tonic-gate goto bailout; 13987c478bd9Sstevel@tonic-gate } 13997c478bd9Sstevel@tonic-gate 14007c478bd9Sstevel@tonic-gate /* Pass current setting to set_configuration */ 14017c478bd9Sstevel@tonic-gate if ((rv = get_config(ap_id, &actual_config)) != CFGA_USB_OK) { 14027c478bd9Sstevel@tonic-gate goto bailout; 14037c478bd9Sstevel@tonic-gate } 14047c478bd9Sstevel@tonic-gate 14057c478bd9Sstevel@tonic-gate /* check if they match - yes, then nothing to do */ 14067c478bd9Sstevel@tonic-gate if (actual_config == config) { 14077c478bd9Sstevel@tonic-gate DPRINTF("cfga_private_func: config index requested " 14087c478bd9Sstevel@tonic-gate "(%d) matches the actual config value %d\n", 14097c478bd9Sstevel@tonic-gate config, actual_config); 14107c478bd9Sstevel@tonic-gate rv = CFGA_USB_OK; 14117c478bd9Sstevel@tonic-gate goto bailout; 14127c478bd9Sstevel@tonic-gate } 14137c478bd9Sstevel@tonic-gate 14147c478bd9Sstevel@tonic-gate /* Save the configuration settings */ 14157c478bd9Sstevel@tonic-gate if ((rv = set_configuration(ap_id, config, driver, 14167c478bd9Sstevel@tonic-gate dev_descrp, errstring)) != CFGA_USB_OK) { 14177c478bd9Sstevel@tonic-gate goto bailout; 14187c478bd9Sstevel@tonic-gate } 14197c478bd9Sstevel@tonic-gate 14207c478bd9Sstevel@tonic-gate /* Reset device to force new config to take effect */ 14217c478bd9Sstevel@tonic-gate if ((rv = reset_device(hdl, list)) != CFGA_USB_OK) { 14227c478bd9Sstevel@tonic-gate goto bailout; 14237c478bd9Sstevel@tonic-gate } 14247c478bd9Sstevel@tonic-gate 14257c478bd9Sstevel@tonic-gate } else { 14267c478bd9Sstevel@tonic-gate DPRINTF("cfga_private_func: unrecognized command.\n"); 14277c478bd9Sstevel@tonic-gate (void) cfga_help(msgp, options, flags); 14287c478bd9Sstevel@tonic-gate errno = EINVAL; 14297c478bd9Sstevel@tonic-gate 14307c478bd9Sstevel@tonic-gate return (CFGA_INVAL); 14317c478bd9Sstevel@tonic-gate } 14327c478bd9Sstevel@tonic-gate 14337c478bd9Sstevel@tonic-gate bailout: 14347c478bd9Sstevel@tonic-gate S_FREE(dev_descrp); 14357c478bd9Sstevel@tonic-gate S_FREE(driver); 14367c478bd9Sstevel@tonic-gate cleanup_after_devctl_cmd(hdl, list); 14377c478bd9Sstevel@tonic-gate 14387c478bd9Sstevel@tonic-gate return (usb_err_msg(errstring, rv, ap_id, errno)); 14397c478bd9Sstevel@tonic-gate } 14407c478bd9Sstevel@tonic-gate 14417c478bd9Sstevel@tonic-gate 14427c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 14437c478bd9Sstevel@tonic-gate cfga_err_t 14447c478bd9Sstevel@tonic-gate cfga_test( 14457c478bd9Sstevel@tonic-gate const char *ap_id, 14467c478bd9Sstevel@tonic-gate const char *options, 14477c478bd9Sstevel@tonic-gate struct cfga_msg *msgp, 14487c478bd9Sstevel@tonic-gate char **errstring, 14497c478bd9Sstevel@tonic-gate cfga_flags_t flags) 14507c478bd9Sstevel@tonic-gate { 14517c478bd9Sstevel@tonic-gate (void) cfga_help(msgp, options, flags); 14527c478bd9Sstevel@tonic-gate return (CFGA_OPNOTSUPP); 14537c478bd9Sstevel@tonic-gate } 14547c478bd9Sstevel@tonic-gate 14557c478bd9Sstevel@tonic-gate 14567c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 14577c478bd9Sstevel@tonic-gate cfga_err_t 14587c478bd9Sstevel@tonic-gate cfga_list_ext( 14597c478bd9Sstevel@tonic-gate const char *ap_id, 14607c478bd9Sstevel@tonic-gate cfga_list_data_t **ap_id_list, 14617c478bd9Sstevel@tonic-gate int *nlistp, 14627c478bd9Sstevel@tonic-gate const char *options, 14637c478bd9Sstevel@tonic-gate const char *listopts, 14647c478bd9Sstevel@tonic-gate char **errstring, 14657c478bd9Sstevel@tonic-gate cfga_flags_t flags) 14667c478bd9Sstevel@tonic-gate { 14677c478bd9Sstevel@tonic-gate int l_errno; 14687c478bd9Sstevel@tonic-gate char *ap_id_log = NULL; 14697c478bd9Sstevel@tonic-gate size_t size; 14707c478bd9Sstevel@tonic-gate nvlist_t *user_nvlist = NULL; 14717c478bd9Sstevel@tonic-gate devctl_hdl_t devctl_hdl = NULL; 14727c478bd9Sstevel@tonic-gate cfga_usb_ret_t rv = CFGA_USB_OK; 14737c478bd9Sstevel@tonic-gate devctl_ap_state_t devctl_ap_state; 14747c478bd9Sstevel@tonic-gate 14757c478bd9Sstevel@tonic-gate DPRINTF("cfga_list_ext:\n"); 14767c478bd9Sstevel@tonic-gate 14777c478bd9Sstevel@tonic-gate if ((rv = verify_params(ap_id, options, errstring)) != CFGA_USB_OK) { 14787c478bd9Sstevel@tonic-gate goto bailout; 14797c478bd9Sstevel@tonic-gate } 14807c478bd9Sstevel@tonic-gate 14817c478bd9Sstevel@tonic-gate if (ap_id_list == NULL || nlistp == NULL) { 14827c478bd9Sstevel@tonic-gate DPRINTF("cfga_list_ext: list = NULL or nlistp = NULL\n"); 14837c478bd9Sstevel@tonic-gate rv = CFGA_USB_INTERNAL_ERROR; 14847c478bd9Sstevel@tonic-gate goto bailout; 14857c478bd9Sstevel@tonic-gate } 14867c478bd9Sstevel@tonic-gate 14877c478bd9Sstevel@tonic-gate /* Get ap status */ 14887c478bd9Sstevel@tonic-gate if ((rv = setup_for_devctl_cmd(ap_id, &devctl_hdl, &user_nvlist, 14897c478bd9Sstevel@tonic-gate DC_RDONLY)) != CFGA_USB_OK) { 14907c478bd9Sstevel@tonic-gate goto bailout; 14917c478bd9Sstevel@tonic-gate } 14927c478bd9Sstevel@tonic-gate 14937c478bd9Sstevel@tonic-gate if (devctl_ap_getstate(devctl_hdl, user_nvlist, &devctl_ap_state) == 14947c478bd9Sstevel@tonic-gate -1) { 14957c478bd9Sstevel@tonic-gate DPRINTF("cfga_list_ext: devctl_ap_getstate failed. errno: %d\n", 14967c478bd9Sstevel@tonic-gate errno); 14977c478bd9Sstevel@tonic-gate cleanup_after_devctl_cmd(devctl_hdl, user_nvlist); 14987c478bd9Sstevel@tonic-gate rv = CFGA_USB_DEVCTL; 14997c478bd9Sstevel@tonic-gate goto bailout; 15007c478bd9Sstevel@tonic-gate } 15017c478bd9Sstevel@tonic-gate cleanup_after_devctl_cmd(devctl_hdl, user_nvlist); 15027c478bd9Sstevel@tonic-gate 15037c478bd9Sstevel@tonic-gate /* 15047c478bd9Sstevel@tonic-gate * Create cfga_list_data_t struct. 15057c478bd9Sstevel@tonic-gate */ 15067c478bd9Sstevel@tonic-gate if ((*ap_id_list = 15077c478bd9Sstevel@tonic-gate (cfga_list_data_t *)malloc(sizeof (**ap_id_list))) == NULL) { 15087c478bd9Sstevel@tonic-gate DPRINTF("cfga_list_ext: malloc for cfga_list_data_t failed. " 15097c478bd9Sstevel@tonic-gate "errno: %d\n", errno); 15107c478bd9Sstevel@tonic-gate rv = CFGA_USB_ALLOC_FAIL; 15117c478bd9Sstevel@tonic-gate goto bailout; 15127c478bd9Sstevel@tonic-gate } 15137c478bd9Sstevel@tonic-gate *nlistp = 1; 15147c478bd9Sstevel@tonic-gate 15157c478bd9Sstevel@tonic-gate 15167c478bd9Sstevel@tonic-gate /* 15177c478bd9Sstevel@tonic-gate * Rest of the code fills in the cfga_list_data_t struct. 15187c478bd9Sstevel@tonic-gate */ 15197c478bd9Sstevel@tonic-gate 15207c478bd9Sstevel@tonic-gate /* Get /dev/cfg path to corresponding to the physical ap_id */ 15217c478bd9Sstevel@tonic-gate /* Remember ap_id_log must be freed */ 15227c478bd9Sstevel@tonic-gate rv = (cfga_usb_ret_t)physpath_to_devlink(CFGA_DEV_DIR, (char *)ap_id, 15237c478bd9Sstevel@tonic-gate &ap_id_log, &l_errno, MATCH_MINOR_NAME); 15247c478bd9Sstevel@tonic-gate if (rv != 0) { 15257c478bd9Sstevel@tonic-gate rv = CFGA_USB_DEVLINK; 15267c478bd9Sstevel@tonic-gate goto bailout; 15277c478bd9Sstevel@tonic-gate } 15287c478bd9Sstevel@tonic-gate assert(ap_id_log != NULL); 15297c478bd9Sstevel@tonic-gate 15307c478bd9Sstevel@tonic-gate /* Get logical ap-id corresponding to the physical */ 15317c478bd9Sstevel@tonic-gate if (strstr(ap_id_log, CFGA_DEV_DIR) == NULL) { 15327c478bd9Sstevel@tonic-gate DPRINTF("cfga_list_ext: devlink doesn't contain /dev/cfg\n"); 15337c478bd9Sstevel@tonic-gate rv = CFGA_USB_DEVLINK; 15347c478bd9Sstevel@tonic-gate goto bailout; 15357c478bd9Sstevel@tonic-gate } 15367c478bd9Sstevel@tonic-gate (void) strlcpy((*ap_id_list)->ap_log_id, 15377c478bd9Sstevel@tonic-gate /* Strip off /dev/cfg/ */ ap_id_log + strlen(CFGA_DEV_DIR)+ 1, 15387c478bd9Sstevel@tonic-gate sizeof ((*ap_id_list)->ap_log_id)); 15397c478bd9Sstevel@tonic-gate free(ap_id_log); 15407c478bd9Sstevel@tonic-gate ap_id_log = NULL; 15417c478bd9Sstevel@tonic-gate 15427c478bd9Sstevel@tonic-gate (void) strlcpy((*ap_id_list)->ap_phys_id, ap_id, 15437c478bd9Sstevel@tonic-gate sizeof ((*ap_id_list)->ap_phys_id)); 15447c478bd9Sstevel@tonic-gate 15457c478bd9Sstevel@tonic-gate switch (devctl_ap_state.ap_rstate) { 15467c478bd9Sstevel@tonic-gate case AP_RSTATE_EMPTY: 15477c478bd9Sstevel@tonic-gate (*ap_id_list)->ap_r_state = CFGA_STAT_EMPTY; 15487c478bd9Sstevel@tonic-gate break; 15497c478bd9Sstevel@tonic-gate case AP_RSTATE_DISCONNECTED: 15507c478bd9Sstevel@tonic-gate (*ap_id_list)->ap_r_state = CFGA_STAT_DISCONNECTED; 15517c478bd9Sstevel@tonic-gate break; 15527c478bd9Sstevel@tonic-gate case AP_RSTATE_CONNECTED: 15537c478bd9Sstevel@tonic-gate (*ap_id_list)->ap_r_state = CFGA_STAT_CONNECTED; 15547c478bd9Sstevel@tonic-gate break; 15557c478bd9Sstevel@tonic-gate default: 15567c478bd9Sstevel@tonic-gate rv = CFGA_USB_STATE; 15577c478bd9Sstevel@tonic-gate goto bailout; 15587c478bd9Sstevel@tonic-gate } 15597c478bd9Sstevel@tonic-gate 15607c478bd9Sstevel@tonic-gate switch (devctl_ap_state.ap_ostate) { 15617c478bd9Sstevel@tonic-gate case AP_OSTATE_CONFIGURED: 15627c478bd9Sstevel@tonic-gate (*ap_id_list)->ap_o_state = CFGA_STAT_CONFIGURED; 15637c478bd9Sstevel@tonic-gate break; 15647c478bd9Sstevel@tonic-gate case AP_OSTATE_UNCONFIGURED: 15657c478bd9Sstevel@tonic-gate (*ap_id_list)->ap_o_state = CFGA_STAT_UNCONFIGURED; 15667c478bd9Sstevel@tonic-gate break; 15677c478bd9Sstevel@tonic-gate default: 15687c478bd9Sstevel@tonic-gate rv = CFGA_USB_STATE; 15697c478bd9Sstevel@tonic-gate goto bailout; 15707c478bd9Sstevel@tonic-gate } 15717c478bd9Sstevel@tonic-gate 15727c478bd9Sstevel@tonic-gate switch (devctl_ap_state.ap_condition) { 15737c478bd9Sstevel@tonic-gate case AP_COND_OK: 15747c478bd9Sstevel@tonic-gate (*ap_id_list)->ap_cond = CFGA_COND_OK; 15757c478bd9Sstevel@tonic-gate break; 15767c478bd9Sstevel@tonic-gate case AP_COND_FAILING: 15777c478bd9Sstevel@tonic-gate (*ap_id_list)->ap_cond = CFGA_COND_FAILING; 15787c478bd9Sstevel@tonic-gate break; 15797c478bd9Sstevel@tonic-gate case AP_COND_FAILED: 15807c478bd9Sstevel@tonic-gate (*ap_id_list)->ap_cond = CFGA_COND_FAILED; 15817c478bd9Sstevel@tonic-gate break; 15827c478bd9Sstevel@tonic-gate case AP_COND_UNUSABLE: 15837c478bd9Sstevel@tonic-gate (*ap_id_list)->ap_cond = CFGA_COND_UNUSABLE; 15847c478bd9Sstevel@tonic-gate break; 15857c478bd9Sstevel@tonic-gate case AP_COND_UNKNOWN: 15867c478bd9Sstevel@tonic-gate (*ap_id_list)->ap_cond = CFGA_COND_UNKNOWN; 15877c478bd9Sstevel@tonic-gate break; 15887c478bd9Sstevel@tonic-gate default: 15897c478bd9Sstevel@tonic-gate rv = CFGA_USB_STATE; 15907c478bd9Sstevel@tonic-gate goto bailout; 15917c478bd9Sstevel@tonic-gate } 15927c478bd9Sstevel@tonic-gate 15937c478bd9Sstevel@tonic-gate (*ap_id_list)->ap_class[0] = '\0'; /* Filled by libcfgadm */ 15947c478bd9Sstevel@tonic-gate (*ap_id_list)->ap_busy = devctl_ap_state.ap_in_transition; 15957c478bd9Sstevel@tonic-gate (*ap_id_list)->ap_status_time = devctl_ap_state.ap_last_change; 15967c478bd9Sstevel@tonic-gate (*ap_id_list)->ap_info[0] = NULL; 15977c478bd9Sstevel@tonic-gate 15987c478bd9Sstevel@tonic-gate if ((*ap_id_list)->ap_r_state == CFGA_STAT_CONNECTED) { 15997c478bd9Sstevel@tonic-gate char *str_p; 16007c478bd9Sstevel@tonic-gate size_t str_len; 16017c478bd9Sstevel@tonic-gate 16027c478bd9Sstevel@tonic-gate /* Fill in the info for the -v option display. */ 16037c478bd9Sstevel@tonic-gate if ((rv = fill_in_ap_info(ap_id, (*ap_id_list)->ap_info, 16047c478bd9Sstevel@tonic-gate sizeof ((*ap_id_list)->ap_info))) != CFGA_USB_OK) { 16057c478bd9Sstevel@tonic-gate DPRINTF("cfga_list_ext: fill_in_ap_info failed\n"); 16067c478bd9Sstevel@tonic-gate goto bailout; 16077c478bd9Sstevel@tonic-gate } 16087c478bd9Sstevel@tonic-gate 16097c478bd9Sstevel@tonic-gate /* Fill in ap_type */ 16107c478bd9Sstevel@tonic-gate if ((rv = do_control_ioctl(ap_id, HUBD_GET_CFGADM_NAME, NULL, 16117c478bd9Sstevel@tonic-gate (void **)&str_p, &size)) != CFGA_USB_OK) { 16127c478bd9Sstevel@tonic-gate DPRINTF("cfga_list_ext: do_control_ioctl failed\n"); 16137c478bd9Sstevel@tonic-gate goto bailout; 16147c478bd9Sstevel@tonic-gate } 16157c478bd9Sstevel@tonic-gate 16167c478bd9Sstevel@tonic-gate (void) strcpy((*ap_id_list)->ap_type, "usb-"); 16177c478bd9Sstevel@tonic-gate str_len = strlen((*ap_id_list)->ap_type); 16187c478bd9Sstevel@tonic-gate 16197c478bd9Sstevel@tonic-gate /* 16207c478bd9Sstevel@tonic-gate * NOTE: In the cfgadm display the "Type" column is only 12 16217c478bd9Sstevel@tonic-gate * chars long. Most USB devices can be displayed here with a 16227c478bd9Sstevel@tonic-gate * "usb-" prefix. Only USB keyboard cannot be displayed in 16237c478bd9Sstevel@tonic-gate * its entirety as "usb-keybaord" is 13 chars in length. 16247c478bd9Sstevel@tonic-gate * It will show up as "usb-kbd". 16257c478bd9Sstevel@tonic-gate */ 16267c478bd9Sstevel@tonic-gate if (strncasecmp(str_p, "keyboard", 8) != 0) { 16277c478bd9Sstevel@tonic-gate (void) strlcpy((*ap_id_list)->ap_type + str_len, str_p, 16287c478bd9Sstevel@tonic-gate sizeof ((*ap_id_list)->ap_type) - str_len); 16297c478bd9Sstevel@tonic-gate } else { 16307c478bd9Sstevel@tonic-gate (void) strlcpy((*ap_id_list)->ap_type + str_len, "kbd", 16317c478bd9Sstevel@tonic-gate sizeof ((*ap_id_list)->ap_type) - str_len); 16327c478bd9Sstevel@tonic-gate } 16337c478bd9Sstevel@tonic-gate 16347c478bd9Sstevel@tonic-gate free(str_p); 16357c478bd9Sstevel@tonic-gate } else { 16367c478bd9Sstevel@tonic-gate (void) strcpy((*ap_id_list)->ap_type, 16377c478bd9Sstevel@tonic-gate USB_CFGADM_DEFAULT_AP_TYPE); 16387c478bd9Sstevel@tonic-gate } 16397c478bd9Sstevel@tonic-gate 16407c478bd9Sstevel@tonic-gate return (usb_err_msg(errstring, rv, ap_id, errno)); 16417c478bd9Sstevel@tonic-gate bailout: 16427c478bd9Sstevel@tonic-gate if (*ap_id_list != NULL) { 16437c478bd9Sstevel@tonic-gate free(*ap_id_list); 16447c478bd9Sstevel@tonic-gate } 16457c478bd9Sstevel@tonic-gate if (ap_id_log != NULL) { 16467c478bd9Sstevel@tonic-gate free(ap_id_log); 16477c478bd9Sstevel@tonic-gate } 16487c478bd9Sstevel@tonic-gate 16497c478bd9Sstevel@tonic-gate return (usb_err_msg(errstring, rv, ap_id, errno)); 16507c478bd9Sstevel@tonic-gate } 16517c478bd9Sstevel@tonic-gate 16527c478bd9Sstevel@tonic-gate 16537c478bd9Sstevel@tonic-gate /* 16547c478bd9Sstevel@tonic-gate * This routine accepts a variable number of message IDs and constructs 16557c478bd9Sstevel@tonic-gate * a corresponding error string which is printed via the message print routine 16567c478bd9Sstevel@tonic-gate * argument. 16577c478bd9Sstevel@tonic-gate */ 16587c478bd9Sstevel@tonic-gate static void 16597c478bd9Sstevel@tonic-gate cfga_msg(struct cfga_msg *msgp, const char *str) 16607c478bd9Sstevel@tonic-gate { 16617c478bd9Sstevel@tonic-gate int len; 16627c478bd9Sstevel@tonic-gate char *q; 16637c478bd9Sstevel@tonic-gate 16647c478bd9Sstevel@tonic-gate if (msgp == NULL || msgp->message_routine == NULL) { 16657c478bd9Sstevel@tonic-gate DPRINTF("cfga_msg: msg\n"); 16667c478bd9Sstevel@tonic-gate return; 16677c478bd9Sstevel@tonic-gate } 16687c478bd9Sstevel@tonic-gate 16697c478bd9Sstevel@tonic-gate if ((len = strlen(str)) == 0) { 16707c478bd9Sstevel@tonic-gate DPRINTF("cfga_msg: null str\n"); 16717c478bd9Sstevel@tonic-gate return; 16727c478bd9Sstevel@tonic-gate } 16737c478bd9Sstevel@tonic-gate 16747c478bd9Sstevel@tonic-gate if ((q = (char *)calloc(len + 1, 1)) == NULL) { 16757c478bd9Sstevel@tonic-gate DPRINTF("cfga_msg: null q\n"); 16767c478bd9Sstevel@tonic-gate return; 16777c478bd9Sstevel@tonic-gate } 16787c478bd9Sstevel@tonic-gate 1679d29f5a71Szhigang lu - Sun Microsystems - Beijing China (void) strcpy(q, str); 16807c478bd9Sstevel@tonic-gate (*msgp->message_routine)(msgp->appdata_ptr, q); 16817c478bd9Sstevel@tonic-gate 16827c478bd9Sstevel@tonic-gate free(q); 16837c478bd9Sstevel@tonic-gate } 16847c478bd9Sstevel@tonic-gate 16857c478bd9Sstevel@tonic-gate 16867c478bd9Sstevel@tonic-gate /* ARGSUSED */ 16877c478bd9Sstevel@tonic-gate cfga_err_t 16887c478bd9Sstevel@tonic-gate cfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags) 16897c478bd9Sstevel@tonic-gate { 16907c478bd9Sstevel@tonic-gate DPRINTF("cfga_help:\n"); 16917c478bd9Sstevel@tonic-gate if (options) { 16927c478bd9Sstevel@tonic-gate cfga_msg(msgp, dgettext(TEXT_DOMAIN, usb_help[HELP_UNKNOWN])); 16937c478bd9Sstevel@tonic-gate cfga_msg(msgp, options); 16947c478bd9Sstevel@tonic-gate } 16957c478bd9Sstevel@tonic-gate 16967c478bd9Sstevel@tonic-gate cfga_msg(msgp, dgettext(TEXT_DOMAIN, usb_help[HELP_HEADER])); 16977c478bd9Sstevel@tonic-gate cfga_msg(msgp, usb_help[HELP_CONFIG]); 16987c478bd9Sstevel@tonic-gate cfga_msg(msgp, usb_help[HELP_RESET_SLOT]); 16997c478bd9Sstevel@tonic-gate cfga_msg(msgp, usb_help[HELP_CONFIG_SLOT]); 17007c478bd9Sstevel@tonic-gate 17017c478bd9Sstevel@tonic-gate return (CFGA_OK); 17027c478bd9Sstevel@tonic-gate } 17037c478bd9Sstevel@tonic-gate 17047c478bd9Sstevel@tonic-gate 17057c478bd9Sstevel@tonic-gate static int 17067c478bd9Sstevel@tonic-gate usb_confirm(struct cfga_confirm *confp, char *msg) 17077c478bd9Sstevel@tonic-gate { 17087c478bd9Sstevel@tonic-gate int rval; 17097c478bd9Sstevel@tonic-gate 17107c478bd9Sstevel@tonic-gate if (confp == NULL || confp->confirm == NULL) { 17117c478bd9Sstevel@tonic-gate return (0); 17127c478bd9Sstevel@tonic-gate } 17137c478bd9Sstevel@tonic-gate 17147c478bd9Sstevel@tonic-gate rval = (*confp->confirm)(confp->appdata_ptr, msg); 17157c478bd9Sstevel@tonic-gate DPRINTF("usb_confirm: %d\n", rval); 17167c478bd9Sstevel@tonic-gate 17177c478bd9Sstevel@tonic-gate return (rval); 17187c478bd9Sstevel@tonic-gate } 17197c478bd9Sstevel@tonic-gate 17207c478bd9Sstevel@tonic-gate 17217c478bd9Sstevel@tonic-gate static char * 17227c478bd9Sstevel@tonic-gate usb_get_devicepath(const char *ap_id) 17237c478bd9Sstevel@tonic-gate { 17247c478bd9Sstevel@tonic-gate char *devpath = NULL; 17257c478bd9Sstevel@tonic-gate size_t size; 17267c478bd9Sstevel@tonic-gate cfga_usb_ret_t rv; 17277c478bd9Sstevel@tonic-gate 17287c478bd9Sstevel@tonic-gate rv = do_control_ioctl(ap_id, HUBD_GET_DEVICE_PATH, NULL, 17297c478bd9Sstevel@tonic-gate (void **)&devpath, &size); 17307c478bd9Sstevel@tonic-gate 17317c478bd9Sstevel@tonic-gate if (rv == CFGA_USB_OK) { 17327c478bd9Sstevel@tonic-gate DPRINTF("usb_get_devicepath: get device path ioctl ok\n"); 17337c478bd9Sstevel@tonic-gate return (devpath); 17347c478bd9Sstevel@tonic-gate } else { 17357c478bd9Sstevel@tonic-gate DPRINTF("usb_get_devicepath: get device path ioctl failed\n"); 17367c478bd9Sstevel@tonic-gate return ((char *)NULL); 17377c478bd9Sstevel@tonic-gate } 17387c478bd9Sstevel@tonic-gate } 1739