6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 *
25 * Copyright 2014 Garrett D'Amore <garrett@damore.org>
26 */
27
28
29 /*
30 * USBA: Solaris USB Architecture support
31 */
32 #define USBA_FRAMEWORK
33 #include <sys/usb/usba/usba_impl.h>
34 #include <sys/usb/usba/hcdi_impl.h>
35 #include <sys/usb/hubd/hub.h>
36 #include <sys/fs/dv_node.h>
37
38 static int usba_str_startcmp(char *, char *);
39
40 /*
41 * USBA private variables and tunables
42 */
43 static kmutex_t usba_mutex;
44
45 /* mutex to protect usba_root_hubs */
46 static kmutex_t usba_hub_mutex;
47
48 typedef struct usba_root_hub_ent {
49 dev_info_t *dip;
50 struct usba_root_hub_ent *next;
51 }usba_root_hub_ent_t;
52
53 static usba_root_hub_ent_t *usba_root_hubs = NULL;
54
55 /*
56 * ddivs forced binding:
57 *
58 * usbc usbc_xhubs usbc_xaddress node name
59 *
250 "?USB %x.%x %s (%s) operating at %s on "
251 "USB %x.%x %s hub: "
252 "%s@%s, %s%d at bus address %d\n",
253 (usba_device->usb_dev_descr->bcdUSB & 0xff00) >> 8,
254 usba_device->usb_dev_descr->bcdUSB & 0xff,
255 (usb_owns_device(rdip) ? "device" :
256 ((usba_owns_ia(rdip) ? "interface-association" :
257 "interface"))),
258 compat_name, speed,
259 (hub_usba_device->usb_dev_descr->bcdUSB &
260 0xff00) >> 8,
261 hub_usba_device->usb_dev_descr->bcdUSB & 0xff,
262 usba_is_root_hub(hubdip) ? "root" : "external",
263 ddi_node_name(rdip), ddi_get_name_addr(rdip),
264 ddi_driver_name(rdip),
265 ddi_get_instance(rdip), usba_device->usb_addr);
266
267 name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
268 (void) usba_get_mfg_prod_sn_str(rdip, name, MAXNAMELEN);
269 if (name[0] != '\0') {
270 cmn_err(CE_CONT, "?\t%s\n", name);
271 }
272 kmem_free(name, MAXNAMELEN);
273
274 } else { /* harden USBA against this case; if it happens */
275
276 cmn_err(CE_CONT,
277 "?USB-device: %s@%s, %s%d\n",
278 ddi_node_name(rdip), ddi_get_name_addr(rdip),
279 ddi_driver_name(rdip), ddi_get_instance(rdip));
280 }
281
282 return (DDI_SUCCESS);
283 }
284
285 case DDI_CTLOPS_INITCHILD:
286 {
287 int usb_addr;
288 uint_t n;
289 char name[32];
290 int *data;
2813 if ((ud->usb_serialno_str == NULL) && usb_dev_descr->iSerialNumber &&
2814 (usb_get_string_descr(dip, USB_LANG_ID,
2815 usb_dev_descr->iSerialNumber, tmpbuf, USB_MAXSTRINGLEN) ==
2816 USB_SUCCESS)) {
2817
2818 l = strlen(tmpbuf);
2819 if (l > 0) {
2820 str = kmem_zalloc(l + 1, KM_SLEEP);
2821 mutex_enter(&ud->usb_mutex);
2822 ud->usb_serialno_str = str;
2823 (void) strcpy(ud->usb_serialno_str, tmpbuf);
2824 mutex_exit(&ud->usb_mutex);
2825 }
2826 }
2827
2828 kmem_free(tmpbuf, USB_MAXSTRINGLEN);
2829 }
2830
2831
2832 /*
2833 * usba_str_startcmp:
2834 * Return the number of characters duplicated from the beginning of the
2835 * string. Return -1 if a complete duplicate.
2836 *
2837 * Arguments:
2838 * Two strings to compare.
2839 */
2840 static int usba_str_startcmp(char *first, char *second)
2841 {
2842 int num_same_chars = 0;
2843 while (*first == *second++) {
2844 if (*first++ == '\0') {
2845 return (-1);
2846 }
2847 num_same_chars++;
2848 }
2849
2850 return (num_same_chars);
2851 }
2852
2853
2854 /*
2855 * usba_get_mfg_prod_sn_str:
2856 * Return a string containing mfg, product, serial number strings.
2857 * Remove duplicates if some strings are the same.
2858 *
2859 * Arguments:
2860 * dip - pointer to dev info
2861 * buffer - Where string is returned
2862 * buflen - Length of buffer
2863 *
2864 * Returns:
2865 * Same as second arg.
2866 */
2867 char *
2868 usba_get_mfg_prod_sn_str(
2869 dev_info_t *dip,
2870 char *buffer,
2871 int buflen)
2872 {
2873 usba_device_t *usba_device = usba_get_usba_device(dip);
2874 int return_len = 0;
2875 int len = 0;
2876 int duplen;
2877
2878 buffer[0] = '\0';
2879 buffer[buflen-1] = '\0';
2880
2881 if ((usba_device->usb_mfg_str) &&
2882 ((len = strlen(usba_device->usb_mfg_str)) != 0)) {
2883 (void) strncpy(buffer, usba_device->usb_mfg_str, buflen - 1);
2884 return_len = min(buflen - 1, len);
2885 }
2886
2887 /* Product string exists to append. */
2888 if ((usba_device->usb_product_str) &&
2889 ((len = strlen(usba_device->usb_product_str)) != 0)) {
2890
2891 /* Append only parts of string that don't match mfg string. */
2892 duplen = usba_str_startcmp(buffer,
2893 usba_device->usb_product_str);
2894
2895 if (duplen != -1) { /* Not a complete match. */
2896 if (return_len > 0) {
2897 buffer[return_len++] = ' ';
2898 }
2899
2900 /* Skip over the dup part of the concat'ed string. */
2901 len -= duplen;
2902 (void) strncpy(&buffer[return_len],
2903 &usba_device->usb_product_str[duplen],
2904 buflen - return_len - 1);
2905 return_len = min(buflen - 1, return_len + len);
2906 }
2907 }
2908
2909 if ((usba_device->usb_serialno_str) &&
2910 ((len = strlen(usba_device->usb_serialno_str)) != 0)) {
2911 if (return_len > 0) {
2912 buffer[return_len++] = ' ';
2913 }
2914 (void) strncpy(&buffer[return_len],
2915 usba_device->usb_serialno_str,
2916 buflen - return_len - 1);
2917 }
2918
2919 return (buffer);
2920 }
2921
2922
2923 /*
2924 * USB enumeration statistic functions
2925 */
2926
2927 /*
2928 * Increments the hotplug statistics based on flags.
|
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 *
25 * Copyright 2014 Garrett D'Amore <garrett@damore.org>
26 * Copyright 2016 James S. Blachly, MD <james.blachly@gmail.com>
27 */
28
29
30 /*
31 * USBA: Solaris USB Architecture support
32 */
33 #define USBA_FRAMEWORK
34 #include <sys/usb/usba/usba_impl.h>
35 #include <sys/usb/usba/hcdi_impl.h>
36 #include <sys/usb/hubd/hub.h>
37 #include <sys/fs/dv_node.h>
38
39 /*
40 * USBA private variables and tunables
41 */
42 static kmutex_t usba_mutex;
43
44 /* mutex to protect usba_root_hubs */
45 static kmutex_t usba_hub_mutex;
46
47 typedef struct usba_root_hub_ent {
48 dev_info_t *dip;
49 struct usba_root_hub_ent *next;
50 }usba_root_hub_ent_t;
51
52 static usba_root_hub_ent_t *usba_root_hubs = NULL;
53
54 /*
55 * ddivs forced binding:
56 *
57 * usbc usbc_xhubs usbc_xaddress node name
58 *
249 "?USB %x.%x %s (%s) operating at %s on "
250 "USB %x.%x %s hub: "
251 "%s@%s, %s%d at bus address %d\n",
252 (usba_device->usb_dev_descr->bcdUSB & 0xff00) >> 8,
253 usba_device->usb_dev_descr->bcdUSB & 0xff,
254 (usb_owns_device(rdip) ? "device" :
255 ((usba_owns_ia(rdip) ? "interface-association" :
256 "interface"))),
257 compat_name, speed,
258 (hub_usba_device->usb_dev_descr->bcdUSB &
259 0xff00) >> 8,
260 hub_usba_device->usb_dev_descr->bcdUSB & 0xff,
261 usba_is_root_hub(hubdip) ? "root" : "external",
262 ddi_node_name(rdip), ddi_get_name_addr(rdip),
263 ddi_driver_name(rdip),
264 ddi_get_instance(rdip), usba_device->usb_addr);
265
266 name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
267 (void) usba_get_mfg_prod_sn_str(rdip, name, MAXNAMELEN);
268 if (name[0] != '\0') {
269 cmn_err(CE_CONT, "?%s\n", name);
270 }
271 kmem_free(name, MAXNAMELEN);
272
273 } else { /* harden USBA against this case; if it happens */
274
275 cmn_err(CE_CONT,
276 "?USB-device: %s@%s, %s%d\n",
277 ddi_node_name(rdip), ddi_get_name_addr(rdip),
278 ddi_driver_name(rdip), ddi_get_instance(rdip));
279 }
280
281 return (DDI_SUCCESS);
282 }
283
284 case DDI_CTLOPS_INITCHILD:
285 {
286 int usb_addr;
287 uint_t n;
288 char name[32];
289 int *data;
2812 if ((ud->usb_serialno_str == NULL) && usb_dev_descr->iSerialNumber &&
2813 (usb_get_string_descr(dip, USB_LANG_ID,
2814 usb_dev_descr->iSerialNumber, tmpbuf, USB_MAXSTRINGLEN) ==
2815 USB_SUCCESS)) {
2816
2817 l = strlen(tmpbuf);
2818 if (l > 0) {
2819 str = kmem_zalloc(l + 1, KM_SLEEP);
2820 mutex_enter(&ud->usb_mutex);
2821 ud->usb_serialno_str = str;
2822 (void) strcpy(ud->usb_serialno_str, tmpbuf);
2823 mutex_exit(&ud->usb_mutex);
2824 }
2825 }
2826
2827 kmem_free(tmpbuf, USB_MAXSTRINGLEN);
2828 }
2829
2830
2831 /*
2832 * usba_get_mfg_prod_sn_str:
2833 * Return a string containing mfg, product, serial number strings.
2834 * Remove duplicates if some strings are the same.
2835 *
2836 * Arguments:
2837 * dip - pointer to dev info
2838 * buffer - Where string is returned
2839 * buflen - Length of buffer
2840 *
2841 * Returns:
2842 * Same as second arg.
2843 */
2844 char *
2845 usba_get_mfg_prod_sn_str(
2846 dev_info_t *dip,
2847 char *buffer,
2848 int buflen)
2849 {
2850 usba_device_t *usba_device = usba_get_usba_device(dip);
2851 int return_len = 0;
2852 int len = 0;
2853
2854 buffer[0] = '\0';
2855 buffer[buflen-1] = '\0';
2856
2857 /* Manufacturer string exists. */
2858 if ((usba_device->usb_mfg_str) &&
2859 ((len = strlen(usba_device->usb_mfg_str)) != 0)) {
2860 (void) strncpy(buffer, usba_device->usb_mfg_str, buflen - 1);
2861 return_len = min(buflen - 1, len);
2862 }
2863
2864 /* Product string exists to append. */
2865 if ((usba_device->usb_product_str) &&
2866 ((len = strlen(usba_device->usb_product_str)) != 0)) {
2867 if (return_len > 0) {
2868 buffer[return_len++] = ' ';
2869 }
2870 (void) strncpy(&buffer[return_len],
2871 usba_device->usb_product_str, buflen - return_len - 1);
2872 return_len = min(buflen - 1, return_len + len);
2873 }
2874
2875 /* Serial number string exists to append. */
2876 if ((usba_device->usb_serialno_str) &&
2877 ((len = strlen(usba_device->usb_serialno_str)) != 0)) {
2878 if (return_len > 0) {
2879 buffer[return_len++] = ' ';
2880 }
2881 (void) strncpy(&buffer[return_len],
2882 usba_device->usb_serialno_str,
2883 buflen - return_len - 1);
2884 }
2885
2886 return (buffer);
2887 }
2888
2889
2890 /*
2891 * USB enumeration statistic functions
2892 */
2893
2894 /*
2895 * Increments the hotplug statistics based on flags.
|