xref: /titanic_51/usr/src/cmd/devfsadm/usb_link.c (revision 45916cd2fec6e79bca5dee0421bd39e3c2910d1e)
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
5*45916cd2Sjpk  * Common Development and Distribution License (the "License").
6*45916cd2Sjpk  * 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  *
21*45916cd2Sjpk  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
227c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <devfsadm.h>
287c478bd9Sstevel@tonic-gate #include <stdio.h>
297c478bd9Sstevel@tonic-gate #include <stdlib.h>
307c478bd9Sstevel@tonic-gate #include <limits.h>
317c478bd9Sstevel@tonic-gate #include <string.h>
327c478bd9Sstevel@tonic-gate #include <unistd.h>
337c478bd9Sstevel@tonic-gate #include <sys/types.h>
347c478bd9Sstevel@tonic-gate #include <sys/stat.h>
357c478bd9Sstevel@tonic-gate #include <strings.h>
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate extern char *devfsadm_get_devices_dir();
387c478bd9Sstevel@tonic-gate static int usb_process(di_minor_t minor, di_node_t node);
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate static void ugen_create_link(char *p_path, char *node_name,
417c478bd9Sstevel@tonic-gate     di_node_t node, di_minor_t minor);
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate /* Rules for creating links */
457c478bd9Sstevel@tonic-gate static devfsadm_create_t usb_cbt[] = {
467c478bd9Sstevel@tonic-gate 	{ "usb", NULL, "usb_ac",	DRV_EXACT,
477c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
487c478bd9Sstevel@tonic-gate 	{ "usb", NULL, "usb_as",	DRV_EXACT,
497c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
507c478bd9Sstevel@tonic-gate 	{ "usb", NULL, "ddivs_usbc",	DRV_EXACT,
517c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
527c478bd9Sstevel@tonic-gate 	{ "usb", NULL, "hid",		DRV_EXACT,
537c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
547c478bd9Sstevel@tonic-gate 	{ "usb", DDI_NT_NEXUS, "hubd",	DRV_EXACT|TYPE_EXACT,
557c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
567c478bd9Sstevel@tonic-gate 	{ "usb", DDI_NT_NEXUS, "ohci",	DRV_EXACT|TYPE_EXACT,
577c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
587c478bd9Sstevel@tonic-gate 	{ "usb", DDI_NT_NEXUS, "ehci",	DRV_EXACT|TYPE_EXACT,
597c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
607c478bd9Sstevel@tonic-gate 	{ "usb", DDI_NT_SCSI_NEXUS, "scsa2usb",	DRV_EXACT|TYPE_EXACT,
617c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
627c478bd9Sstevel@tonic-gate 	{ "usb", DDI_NT_UGEN, "scsa2usb",	DRV_EXACT|TYPE_EXACT,
637c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
647c478bd9Sstevel@tonic-gate 	{ "usb", DDI_NT_NEXUS, "uhci",	DRV_EXACT|TYPE_EXACT,
657c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
667c478bd9Sstevel@tonic-gate 	{ "usb", DDI_NT_UGEN, "ugen",	DRV_EXACT|TYPE_EXACT,
677c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
687c478bd9Sstevel@tonic-gate 	{ "usb", DDI_NT_NEXUS, "usb_mid", DRV_EXACT|TYPE_EXACT,
697c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
707c478bd9Sstevel@tonic-gate 	{ "usb", DDI_NT_UGEN, "usb_mid", DRV_EXACT|TYPE_EXACT,
717c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
727c478bd9Sstevel@tonic-gate 	{ "usb", DDI_NT_PRINTER, "usbprn", DRV_EXACT|TYPE_EXACT,
737c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
747c478bd9Sstevel@tonic-gate 	{ "usb", DDI_NT_UGEN, "usbprn", DRV_EXACT|TYPE_EXACT,
757c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
767c478bd9Sstevel@tonic-gate };
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate /* For debug printing (-V filter) */
797c478bd9Sstevel@tonic-gate static char *debug_mid = "usb_mid";
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate DEVFSADM_CREATE_INIT_V0(usb_cbt);
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate /* USB device links */
847c478bd9Sstevel@tonic-gate #define	USB_LINK_RE_AUDIO	"^usb/audio[0-9]+$"
857c478bd9Sstevel@tonic-gate #define	USB_LINK_RE_AUDIOMUX	"^usb/audio-mux[0-9]+$"
867c478bd9Sstevel@tonic-gate #define	USB_LINK_RE_AUDIOCTL	"^usb/audio-control[0-9]+$"
877c478bd9Sstevel@tonic-gate #define	USB_LINK_RE_AUDIOSTREAM	"^usb/audio-stream[0-9]+$"
887c478bd9Sstevel@tonic-gate #define	USB_LINK_RE_DDIVS_USBC	"^usb/ddivs_usbc[0-9]+$"
897c478bd9Sstevel@tonic-gate #define	USB_LINK_RE_DEVICE	"^usb/device[0-9]+$"
907c478bd9Sstevel@tonic-gate #define	USB_LINK_RE_HID		"^usb/hid[0-9]+$"
917c478bd9Sstevel@tonic-gate #define	USB_LINK_RE_HUB		"^usb/hub[0-9]+$"
927c478bd9Sstevel@tonic-gate #define	USB_LINK_RE_MASS_STORE	"^usb/mass-storage[0-9]+$"
937c478bd9Sstevel@tonic-gate #define	USB_LINK_RE_UGEN	"^usb/[0-9,a-f]+\\.[0-9,a-f]+/[0-9]+/.+$"
947c478bd9Sstevel@tonic-gate #define	USB_LINK_RE_USBPRN	"^usb/printer[0-9]+$"
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate /* Rules for removing links */
977c478bd9Sstevel@tonic-gate static devfsadm_remove_t usb_remove_cbt[] = {
987c478bd9Sstevel@tonic-gate 	{ "usb", USB_LINK_RE_AUDIO, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
997c478bd9Sstevel@tonic-gate 			devfsadm_rm_all },
1007c478bd9Sstevel@tonic-gate 	{ "usb", USB_LINK_RE_AUDIOMUX, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
1017c478bd9Sstevel@tonic-gate 			devfsadm_rm_all },
1027c478bd9Sstevel@tonic-gate 	{ "usb", USB_LINK_RE_AUDIOCTL, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
1037c478bd9Sstevel@tonic-gate 			devfsadm_rm_all },
1047c478bd9Sstevel@tonic-gate 	{ "usb", USB_LINK_RE_AUDIOSTREAM, RM_POST | RM_HOT | RM_ALWAYS,
1057c478bd9Sstevel@tonic-gate 			ILEVEL_0, devfsadm_rm_all },
1067c478bd9Sstevel@tonic-gate 	{ "usb", USB_LINK_RE_DDIVS_USBC, RM_POST | RM_HOT | RM_ALWAYS,
1077c478bd9Sstevel@tonic-gate 			ILEVEL_0, devfsadm_rm_all },
1087c478bd9Sstevel@tonic-gate 	{ "usb", USB_LINK_RE_DEVICE, RM_POST | RM_HOT, ILEVEL_0,
1097c478bd9Sstevel@tonic-gate 			devfsadm_rm_all },
1107c478bd9Sstevel@tonic-gate 	{ "usb", USB_LINK_RE_HID, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
1117c478bd9Sstevel@tonic-gate 			devfsadm_rm_all },
1127c478bd9Sstevel@tonic-gate 	{ "usb", USB_LINK_RE_HUB, RM_POST | RM_HOT, ILEVEL_0, devfsadm_rm_all },
1137c478bd9Sstevel@tonic-gate 	{ "usb", USB_LINK_RE_MASS_STORE, RM_POST | RM_HOT | RM_ALWAYS,
1147c478bd9Sstevel@tonic-gate 			ILEVEL_0, devfsadm_rm_all },
1157c478bd9Sstevel@tonic-gate 	{ "usb", USB_LINK_RE_UGEN, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
1167c478bd9Sstevel@tonic-gate 			devfsadm_rm_all },
1177c478bd9Sstevel@tonic-gate 	{ "usb", USB_LINK_RE_USBPRN, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
1187c478bd9Sstevel@tonic-gate 			devfsadm_rm_link },
1197c478bd9Sstevel@tonic-gate };
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate /*
1227c478bd9Sstevel@tonic-gate  * Rules for different USB devices except ugen which is dynamically
1237c478bd9Sstevel@tonic-gate  * created
1247c478bd9Sstevel@tonic-gate  */
1257c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t audio_rules[1] =
1267c478bd9Sstevel@tonic-gate 	{"^usb$/^audio([0-9]+)$", 1, MATCH_ALL};
1277c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t audio_mux_rules[1] =
1287c478bd9Sstevel@tonic-gate 	{"^usb$/^audio-mux([0-9]+)$", 1, MATCH_ALL};
1297c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t audio_control_rules[1] =
1307c478bd9Sstevel@tonic-gate 	{"^usb$/^audio-control([0-9]+)$", 1, MATCH_ALL};
1317c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t audio_stream_rules[1] =
1327c478bd9Sstevel@tonic-gate 	{"^usb$/^audio-stream([0-9]+)$", 1, MATCH_ALL};
1337c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t ddivs_usbc_rules[1] =
1347c478bd9Sstevel@tonic-gate 	{"^usb$/^ddivs_usbc([0-9]+)$", 1, MATCH_ALL};
1357c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t device_rules[1] =
1367c478bd9Sstevel@tonic-gate 	{"^usb$/^device([0-9]+)$", 1, MATCH_ALL};
1377c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t hid_rules[1] =
1387c478bd9Sstevel@tonic-gate 	{"^usb$/^hid([0-9]+)$", 1, MATCH_ALL};
1397c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t hub_rules[1] =
1407c478bd9Sstevel@tonic-gate 	{"^usb$/^hub([0-9]+)$", 1, MATCH_ALL};
1417c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t mass_storage_rules[1] =
1427c478bd9Sstevel@tonic-gate 	{"^usb$/^mass-storage([0-9]+)$", 1, MATCH_ALL};
1437c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t usbprn_rules[1] =
1447c478bd9Sstevel@tonic-gate 	{"^usb$/^printer([0-9]+)$", 1, MATCH_ALL};
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate DEVFSADM_REMOVE_INIT_V0(usb_remove_cbt);
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate int
1497c478bd9Sstevel@tonic-gate minor_init(void)
1507c478bd9Sstevel@tonic-gate {
1517c478bd9Sstevel@tonic-gate 	devfsadm_print(debug_mid, "usb_link: minor_init\n");
1527c478bd9Sstevel@tonic-gate 	return (DEVFSADM_SUCCESS);
1537c478bd9Sstevel@tonic-gate }
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate int
1567c478bd9Sstevel@tonic-gate minor_fini(void)
1577c478bd9Sstevel@tonic-gate {
1587c478bd9Sstevel@tonic-gate 	devfsadm_print(debug_mid, "usb_link: minor_fini\n");
1597c478bd9Sstevel@tonic-gate 	return (DEVFSADM_SUCCESS);
1607c478bd9Sstevel@tonic-gate }
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate typedef enum {
1637c478bd9Sstevel@tonic-gate 	DRIVER_HUBD	= 0,
1647c478bd9Sstevel@tonic-gate 	DRIVER_OHCI	= 1,
1657c478bd9Sstevel@tonic-gate 	DRIVER_EHCI	= 2,
1667c478bd9Sstevel@tonic-gate 	DRIVER_UHCI	= 3,
1677c478bd9Sstevel@tonic-gate 	DRIVER_USB_AC	= 4,
1687c478bd9Sstevel@tonic-gate 	DRIVER_USB_AS	= 5,
1697c478bd9Sstevel@tonic-gate 	DRIVER_HID	= 6,
1707c478bd9Sstevel@tonic-gate 	DRIVER_USB_MID	= 7,
1717c478bd9Sstevel@tonic-gate 	DRIVER_DDIVS_USBC = 8,
1727c478bd9Sstevel@tonic-gate 	DRIVER_SCSA2USB = 9,
1737c478bd9Sstevel@tonic-gate 	DRIVER_USBPRN	= 10,
1747c478bd9Sstevel@tonic-gate 	DRIVER_UGEN	= 11,
1757c478bd9Sstevel@tonic-gate 	DRIVER_UNKNOWN	= 12
1767c478bd9Sstevel@tonic-gate } driver_defs_t;
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate typedef struct {
1797c478bd9Sstevel@tonic-gate 	char	*driver_name;
1807c478bd9Sstevel@tonic-gate 	int	index;
1817c478bd9Sstevel@tonic-gate } driver_name_table_entry_t;
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate driver_name_table_entry_t driver_name_table[] = {
1847c478bd9Sstevel@tonic-gate 	{ "hubd",	DRIVER_HUBD },
1857c478bd9Sstevel@tonic-gate 	{ "ohci",	DRIVER_OHCI },
1867c478bd9Sstevel@tonic-gate 	{ "ehci",	DRIVER_EHCI },
1877c478bd9Sstevel@tonic-gate 	{ "uhci",	DRIVER_UHCI },
1887c478bd9Sstevel@tonic-gate 	{ "usb_ac",	DRIVER_USB_AC },
1897c478bd9Sstevel@tonic-gate 	{ "usb_as",	DRIVER_USB_AS },
1907c478bd9Sstevel@tonic-gate 	{ "hid",	DRIVER_HID },
1917c478bd9Sstevel@tonic-gate 	{ "usb_mid",	DRIVER_USB_MID },
1927c478bd9Sstevel@tonic-gate 	{ "ddivs_usbc",	DRIVER_DDIVS_USBC },
1937c478bd9Sstevel@tonic-gate 	{ "scsa2usb",	DRIVER_SCSA2USB },
1947c478bd9Sstevel@tonic-gate 	{ "usbprn",	DRIVER_USBPRN },
1957c478bd9Sstevel@tonic-gate 	{ "ugen",	DRIVER_UGEN },
1967c478bd9Sstevel@tonic-gate 	{ NULL,		DRIVER_UNKNOWN }
1977c478bd9Sstevel@tonic-gate };
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate /*
2017c478bd9Sstevel@tonic-gate  * This function is called for every usb minor node.
2027c478bd9Sstevel@tonic-gate  * Calls enumerate to assign a logical usb id, and then
2037c478bd9Sstevel@tonic-gate  * devfsadm_mklink to make the link.
2047c478bd9Sstevel@tonic-gate  */
2057c478bd9Sstevel@tonic-gate static int
2067c478bd9Sstevel@tonic-gate usb_process(di_minor_t minor, di_node_t node)
2077c478bd9Sstevel@tonic-gate {
2087c478bd9Sstevel@tonic-gate 	devfsadm_enumerate_t rules[1];
2097c478bd9Sstevel@tonic-gate 	char *l_path, *p_path, *buf, *devfspath;
2107c478bd9Sstevel@tonic-gate 	char *minor_nm, *drvr_nm, *name = (char *)NULL;
2117c478bd9Sstevel@tonic-gate 	int i, index;
212*45916cd2Sjpk 	int flags = 0;
2137c478bd9Sstevel@tonic-gate 	int create_secondary_link = 0;
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 	minor_nm = di_minor_name(minor);
2167c478bd9Sstevel@tonic-gate 	drvr_nm = di_driver_name(node);
2177c478bd9Sstevel@tonic-gate 	if ((minor_nm == NULL) || (drvr_nm == NULL)) {
2187c478bd9Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
2197c478bd9Sstevel@tonic-gate 	}
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 	devfsadm_print(debug_mid, "usb_process: minor=%s node=%s type=%s\n",
2227c478bd9Sstevel@tonic-gate 		minor_nm, di_node_name(node), di_minor_nodetype(minor));
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	devfspath = di_devfs_path(node);
2257c478bd9Sstevel@tonic-gate 	if (devfspath == NULL) {
2267c478bd9Sstevel@tonic-gate 		devfsadm_print(debug_mid,
2277c478bd9Sstevel@tonic-gate 		    "USB_process: devfspath is	NULL\n");
2287c478bd9Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
2297c478bd9Sstevel@tonic-gate 	}
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 	l_path = (char *)malloc(PATH_MAX);
2327c478bd9Sstevel@tonic-gate 	if (l_path == NULL) {
2337c478bd9Sstevel@tonic-gate 		di_devfs_path_free(devfspath);
2347c478bd9Sstevel@tonic-gate 		devfsadm_print(debug_mid, "usb_process: malloc() failed\n");
2357c478bd9Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
2367c478bd9Sstevel@tonic-gate 	}
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	p_path = (char *)malloc(PATH_MAX);
2397c478bd9Sstevel@tonic-gate 	if (p_path == NULL) {
2407c478bd9Sstevel@tonic-gate 		devfsadm_print(debug_mid, "usb_process: malloc() failed\n");
2417c478bd9Sstevel@tonic-gate 		di_devfs_path_free(devfspath);
2427c478bd9Sstevel@tonic-gate 		free(l_path);
2437c478bd9Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
2447c478bd9Sstevel@tonic-gate 	}
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	(void) strcpy(p_path, devfspath);
2477c478bd9Sstevel@tonic-gate 	(void) strcat(p_path, ":");
2487c478bd9Sstevel@tonic-gate 	(void) strcat(p_path, minor_nm);
2497c478bd9Sstevel@tonic-gate 	di_devfs_path_free(devfspath);
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate 	devfsadm_print(debug_mid, "usb_process: path %s\n", p_path);
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 	for (i = 0; ; i++) {
2547c478bd9Sstevel@tonic-gate 		if ((driver_name_table[i].driver_name == NULL) ||
2557c478bd9Sstevel@tonic-gate 		    (strcmp(drvr_nm, driver_name_table[i].driver_name) == 0)) {
2567c478bd9Sstevel@tonic-gate 			index = driver_name_table[i].index;
2577c478bd9Sstevel@tonic-gate 			break;
2587c478bd9Sstevel@tonic-gate 		}
2597c478bd9Sstevel@tonic-gate 	}
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 	if (strcmp(di_minor_nodetype(minor), DDI_NT_UGEN) == 0) {
2627c478bd9Sstevel@tonic-gate 		ugen_create_link(p_path, minor_nm, node, minor);
2637c478bd9Sstevel@tonic-gate 		free(l_path);
2647c478bd9Sstevel@tonic-gate 		free(p_path);
2657c478bd9Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
2667c478bd9Sstevel@tonic-gate 	}
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	/* Figure out which rules to apply */
2697c478bd9Sstevel@tonic-gate 	switch (index) {
2707c478bd9Sstevel@tonic-gate 	case DRIVER_HUBD:
2717c478bd9Sstevel@tonic-gate 	case DRIVER_OHCI:
2727c478bd9Sstevel@tonic-gate 	case DRIVER_EHCI:
2737c478bd9Sstevel@tonic-gate 	case DRIVER_UHCI:
2747c478bd9Sstevel@tonic-gate 		rules[0] = hub_rules[0];	/* For HUBs */
2757c478bd9Sstevel@tonic-gate 		name = "hub";
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 		break;
2787c478bd9Sstevel@tonic-gate 	case DRIVER_USB_AC:
2797c478bd9Sstevel@tonic-gate 		if (strcmp(minor_nm, "sound,audio") == 0) {
2807c478bd9Sstevel@tonic-gate 			rules[0] = audio_rules[0];
2817c478bd9Sstevel@tonic-gate 			name = "audio";		/* For audio */
2827c478bd9Sstevel@tonic-gate 			create_secondary_link = 1;
2837c478bd9Sstevel@tonic-gate 		} else if (strcmp(minor_nm, "sound,audioctl") == 0) {
2847c478bd9Sstevel@tonic-gate 			rules[0] = audio_control_rules[0];
2857c478bd9Sstevel@tonic-gate 			name = "audio-control";		/* For audio */
2867c478bd9Sstevel@tonic-gate 			create_secondary_link = 1;
2877c478bd9Sstevel@tonic-gate 		} else if (strcmp(minor_nm, "mux") == 0) {
2887c478bd9Sstevel@tonic-gate 			rules[0] = audio_mux_rules[0];
2897c478bd9Sstevel@tonic-gate 			name = "audio-mux";		/* For audio */
2907c478bd9Sstevel@tonic-gate 		} else {
2917c478bd9Sstevel@tonic-gate 			free(l_path);
2927c478bd9Sstevel@tonic-gate 			free(p_path);
2937c478bd9Sstevel@tonic-gate 			return (DEVFSADM_CONTINUE);
2947c478bd9Sstevel@tonic-gate 		}
2957c478bd9Sstevel@tonic-gate 		break;
2967c478bd9Sstevel@tonic-gate 	case DRIVER_USB_AS:
2977c478bd9Sstevel@tonic-gate 		rules[0] = audio_stream_rules[0];
2987c478bd9Sstevel@tonic-gate 		name = "audio-stream";		/* For audio */
2997c478bd9Sstevel@tonic-gate 		break;
3007c478bd9Sstevel@tonic-gate 	case DRIVER_HID:
3017c478bd9Sstevel@tonic-gate 		rules[0] = hid_rules[0];
3027c478bd9Sstevel@tonic-gate 		name = "hid";			/* For HIDs */
3037c478bd9Sstevel@tonic-gate 		break;
3047c478bd9Sstevel@tonic-gate 	case DRIVER_USB_MID:
3057c478bd9Sstevel@tonic-gate 		rules[0] = device_rules[0];
3067c478bd9Sstevel@tonic-gate 		name = "device";		/* For other USB devices */
3077c478bd9Sstevel@tonic-gate 		break;
3087c478bd9Sstevel@tonic-gate 	case DRIVER_DDIVS_USBC:
3097c478bd9Sstevel@tonic-gate 		rules[0] = ddivs_usbc_rules[0];
3107c478bd9Sstevel@tonic-gate 		name = "device";		/* For other USB devices */
3117c478bd9Sstevel@tonic-gate 		break;
3127c478bd9Sstevel@tonic-gate 	case DRIVER_SCSA2USB:
3137c478bd9Sstevel@tonic-gate 		rules[0] = mass_storage_rules[0];
3147c478bd9Sstevel@tonic-gate 		name = "mass-storage";		/* For mass-storage devices */
3157c478bd9Sstevel@tonic-gate 		break;
3167c478bd9Sstevel@tonic-gate 	case DRIVER_USBPRN:
3177c478bd9Sstevel@tonic-gate 		rules[0] = usbprn_rules[0];
3187c478bd9Sstevel@tonic-gate 		name = "printer";
3197c478bd9Sstevel@tonic-gate 		break;
3207c478bd9Sstevel@tonic-gate 	default:
3217c478bd9Sstevel@tonic-gate 		devfsadm_print(debug_mid, "usb_process: unknown driver=%s\n",
3227c478bd9Sstevel@tonic-gate 		    drvr_nm);
3237c478bd9Sstevel@tonic-gate 		free(l_path);
3247c478bd9Sstevel@tonic-gate 		free(p_path);
3257c478bd9Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
3267c478bd9Sstevel@tonic-gate 	}
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate 	/*
3297c478bd9Sstevel@tonic-gate 	 *  build the physical path from the components.
3307c478bd9Sstevel@tonic-gate 	 *  find the logical usb id, and stuff it in buf
3317c478bd9Sstevel@tonic-gate 	 */
3327c478bd9Sstevel@tonic-gate 	if (devfsadm_enumerate_int(p_path, 0, &buf, rules, 1)) {
3337c478bd9Sstevel@tonic-gate 		devfsadm_print(debug_mid, "usb_process: exit/continue\n");
3347c478bd9Sstevel@tonic-gate 		free(l_path);
3357c478bd9Sstevel@tonic-gate 		free(p_path);
3367c478bd9Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
3377c478bd9Sstevel@tonic-gate 	}
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 	(void) snprintf(l_path, PATH_MAX, "usb/%s%s", name, buf);
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 	devfsadm_print(debug_mid, "usb_process: p_path=%s buf=%s\n",
3427c478bd9Sstevel@tonic-gate 	    p_path, buf);
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 	free(buf);
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 	devfsadm_print(debug_mid, "mklink %s -> %s\n", l_path, p_path);
3477c478bd9Sstevel@tonic-gate 
348*45916cd2Sjpk 	(void) devfsadm_mklink(l_path, node, minor, flags);
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 	if (create_secondary_link) {
3517c478bd9Sstevel@tonic-gate 		/*
3527c478bd9Sstevel@tonic-gate 		 * Create secondary links to make newly hotplugged
3537c478bd9Sstevel@tonic-gate 		 * usb audio device the primary device.
3547c478bd9Sstevel@tonic-gate 		 */
3557c478bd9Sstevel@tonic-gate 		if (strcmp(name, "audio") == 0) {
3567c478bd9Sstevel@tonic-gate 			(void) devfsadm_secondary_link("audio", l_path, 0);
3577c478bd9Sstevel@tonic-gate 		} else if (strcmp(name, "audio-control") == 0) {
3587c478bd9Sstevel@tonic-gate 			(void) devfsadm_secondary_link("audioctl", l_path, 0);
3597c478bd9Sstevel@tonic-gate 		}
3607c478bd9Sstevel@tonic-gate 	}
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 	free(p_path);
3637c478bd9Sstevel@tonic-gate 	free(l_path);
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 	return (DEVFSADM_CONTINUE);
3667c478bd9Sstevel@tonic-gate }
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate static void
3697c478bd9Sstevel@tonic-gate ugen_create_link(char *p_path, char *node_name,
3707c478bd9Sstevel@tonic-gate     di_node_t node, di_minor_t minor)
3717c478bd9Sstevel@tonic-gate {
3727c478bd9Sstevel@tonic-gate 	char *buf, s[MAXPATHLEN];
3737c478bd9Sstevel@tonic-gate 	char *lasts = s;
3747c478bd9Sstevel@tonic-gate 	char *vid, *pid;
3757c478bd9Sstevel@tonic-gate 	char *minor_name;
3767c478bd9Sstevel@tonic-gate 	char ugen_RE[128];
3777c478bd9Sstevel@tonic-gate 	devfsadm_enumerate_t ugen_rules[1];
3787c478bd9Sstevel@tonic-gate 	char l_path[PATH_MAX];
379*45916cd2Sjpk 	int flags = 0;
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	devfsadm_print(debug_mid, "ugen_create_link: p_path=%s name=%s\n",
3827c478bd9Sstevel@tonic-gate 	    p_path, node_name);
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 	(void) strlcpy(s, node_name, sizeof (s));
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 	/* get vid, pid and minor name strings */
3877c478bd9Sstevel@tonic-gate 	vid = strtok_r(lasts, ".", &lasts);
3887c478bd9Sstevel@tonic-gate 	pid = strtok_r(NULL, ".", &lasts);
3897c478bd9Sstevel@tonic-gate 	minor_name = lasts;
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 	if ((vid == NULL) || (pid == NULL) || (minor_name == NULL)) {
3927c478bd9Sstevel@tonic-gate 		return;
3937c478bd9Sstevel@tonic-gate 	}
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate 	/* create regular expression contain vid and pid */
3967c478bd9Sstevel@tonic-gate 	(void) snprintf(ugen_RE, sizeof (ugen_RE),
3977c478bd9Sstevel@tonic-gate 	    "^usb$/^%s\\.%s$/^([0-9]+)$", vid, pid);
3987c478bd9Sstevel@tonic-gate 	devfsadm_print(debug_mid,
3997c478bd9Sstevel@tonic-gate 	    "ugen_create_link: ugen_RE=%s minor_name=%s\n",
4007c478bd9Sstevel@tonic-gate 	    ugen_RE, minor_name);
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 	bzero(ugen_rules, sizeof (ugen_rules));
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	ugen_rules[0].re = ugen_RE;
4057c478bd9Sstevel@tonic-gate 	ugen_rules[0].subexp = 1;
4067c478bd9Sstevel@tonic-gate 	ugen_rules[0].flags = MATCH_ADDR;
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate 	/*
4097c478bd9Sstevel@tonic-gate 	 *  build the physical path from the components.
4107c478bd9Sstevel@tonic-gate 	 *  find the logical usb id, and stuff it in buf
4117c478bd9Sstevel@tonic-gate 	 */
4127c478bd9Sstevel@tonic-gate 	if (devfsadm_enumerate_int(p_path, 0, &buf, ugen_rules, 1)) {
4137c478bd9Sstevel@tonic-gate 		devfsadm_print(debug_mid, "ugen_create_link: exit/continue\n");
4147c478bd9Sstevel@tonic-gate 		return;
4157c478bd9Sstevel@tonic-gate 	}
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate 	(void) snprintf(l_path, sizeof (l_path), "usb/%s.%s/%s/%s",
4187c478bd9Sstevel@tonic-gate 	    vid, pid, buf, minor_name);
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 	devfsadm_print(debug_mid, "mklink %s -> %s\n", l_path, p_path);
4217c478bd9Sstevel@tonic-gate 
422*45916cd2Sjpk 	(void) devfsadm_mklink(l_path, node, minor, flags);
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 	free(buf);
4257c478bd9Sstevel@tonic-gate }
426