xref: /titanic_51/usr/src/cmd/devfsadm/usb_link.c (revision 3fb52c733c5435ce279a4641b57941b1befa5c9f)
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
545916cd2Sjpk  * Common Development and Distribution License (the "License").
645916cd2Sjpk  * 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  *
21ff0e937bSRaymond Chen  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
227c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate #include <devfsadm.h>
267c478bd9Sstevel@tonic-gate #include <stdio.h>
277c478bd9Sstevel@tonic-gate #include <stdlib.h>
287c478bd9Sstevel@tonic-gate #include <limits.h>
297c478bd9Sstevel@tonic-gate #include <string.h>
307c478bd9Sstevel@tonic-gate #include <unistd.h>
317c478bd9Sstevel@tonic-gate #include <sys/types.h>
327c478bd9Sstevel@tonic-gate #include <sys/stat.h>
337c478bd9Sstevel@tonic-gate #include <strings.h>
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate extern char *devfsadm_get_devices_dir();
367c478bd9Sstevel@tonic-gate static int usb_process(di_minor_t minor, di_node_t node);
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate static void ugen_create_link(char *p_path, char *node_name,
397c478bd9Sstevel@tonic-gate     di_node_t node, di_minor_t minor);
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate /* Rules for creating links */
437c478bd9Sstevel@tonic-gate static devfsadm_create_t usb_cbt[] = {
447c478bd9Sstevel@tonic-gate 	{ "usb", NULL, "usb_ac",	DRV_EXACT,
457c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
467c478bd9Sstevel@tonic-gate 	{ "usb", NULL, "usb_as",	DRV_EXACT,
477c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
487c478bd9Sstevel@tonic-gate 	{ "usb", NULL, "ddivs_usbc",	DRV_EXACT,
497c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
50c77a61a7Syz147069 	{ "usb", NULL, "usbvc",		DRV_EXACT,
51c77a61a7Syz147069 						ILEVEL_0, usb_process },
527c478bd9Sstevel@tonic-gate 	{ "usb", NULL, "hid",		DRV_EXACT,
537c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
54ff0e937bSRaymond Chen 	{ "usb", NULL, "hwarc",	DRV_EXACT,
55ff0e937bSRaymond Chen 						ILEVEL_0, usb_process },
56ff0e937bSRaymond Chen 	{ "usb", NULL, "wusb_ca",	DRV_EXACT,
57ff0e937bSRaymond Chen 						ILEVEL_0, usb_process },
587c478bd9Sstevel@tonic-gate 	{ "usb", DDI_NT_NEXUS, "hubd",	DRV_EXACT|TYPE_EXACT,
597c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
607c478bd9Sstevel@tonic-gate 	{ "usb", DDI_NT_NEXUS, "ohci",	DRV_EXACT|TYPE_EXACT,
617c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
627c478bd9Sstevel@tonic-gate 	{ "usb", DDI_NT_NEXUS, "ehci",	DRV_EXACT|TYPE_EXACT,
637c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
647c478bd9Sstevel@tonic-gate 	{ "usb", DDI_NT_SCSI_NEXUS, "scsa2usb",	DRV_EXACT|TYPE_EXACT,
657c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
667c478bd9Sstevel@tonic-gate 	{ "usb", DDI_NT_UGEN, "scsa2usb",	DRV_EXACT|TYPE_EXACT,
677c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
687c478bd9Sstevel@tonic-gate 	{ "usb", DDI_NT_NEXUS, "uhci",	DRV_EXACT|TYPE_EXACT,
697c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
707c478bd9Sstevel@tonic-gate 	{ "usb", DDI_NT_UGEN, "ugen",	DRV_EXACT|TYPE_EXACT,
717c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
727c478bd9Sstevel@tonic-gate 	{ "usb", DDI_NT_NEXUS, "usb_mid", DRV_EXACT|TYPE_EXACT,
737c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
747c478bd9Sstevel@tonic-gate 	{ "usb", DDI_NT_UGEN, "usb_mid", DRV_EXACT|TYPE_EXACT,
757c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
767c478bd9Sstevel@tonic-gate 	{ "usb", DDI_NT_PRINTER, "usbprn", DRV_EXACT|TYPE_EXACT,
777c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
787c478bd9Sstevel@tonic-gate 	{ "usb", DDI_NT_UGEN, "usbprn", DRV_EXACT|TYPE_EXACT,
797c478bd9Sstevel@tonic-gate 						ILEVEL_0, usb_process },
80ff0e937bSRaymond Chen 	{ "usb", DDI_NT_NEXUS, "hwahc", DRV_EXACT|TYPE_EXACT,
81ff0e937bSRaymond Chen 						ILEVEL_0, usb_process },
827c478bd9Sstevel@tonic-gate };
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate /* For debug printing (-V filter) */
857c478bd9Sstevel@tonic-gate static char *debug_mid = "usb_mid";
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate DEVFSADM_CREATE_INIT_V0(usb_cbt);
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate /* USB device links */
907c478bd9Sstevel@tonic-gate #define	USB_LINK_RE_AUDIO	"^usb/audio[0-9]+$"
917c478bd9Sstevel@tonic-gate #define	USB_LINK_RE_AUDIOMUX	"^usb/audio-mux[0-9]+$"
927c478bd9Sstevel@tonic-gate #define	USB_LINK_RE_AUDIOCTL	"^usb/audio-control[0-9]+$"
937c478bd9Sstevel@tonic-gate #define	USB_LINK_RE_AUDIOSTREAM	"^usb/audio-stream[0-9]+$"
947c478bd9Sstevel@tonic-gate #define	USB_LINK_RE_DDIVS_USBC	"^usb/ddivs_usbc[0-9]+$"
95c77a61a7Syz147069 #define	USB_LINK_RE_VIDEO	"^usb/video[0-9]+$"
96c77a61a7Syz147069 #define	USB_LINK_RE_VIDEO2	"^video[0-9]+$"
977c478bd9Sstevel@tonic-gate #define	USB_LINK_RE_DEVICE	"^usb/device[0-9]+$"
987c478bd9Sstevel@tonic-gate #define	USB_LINK_RE_HID		"^usb/hid[0-9]+$"
997c478bd9Sstevel@tonic-gate #define	USB_LINK_RE_HUB		"^usb/hub[0-9]+$"
1007c478bd9Sstevel@tonic-gate #define	USB_LINK_RE_MASS_STORE	"^usb/mass-storage[0-9]+$"
1017c478bd9Sstevel@tonic-gate #define	USB_LINK_RE_UGEN	"^usb/[0-9,a-f]+\\.[0-9,a-f]+/[0-9]+/.+$"
1027c478bd9Sstevel@tonic-gate #define	USB_LINK_RE_USBPRN	"^usb/printer[0-9]+$"
103ff0e937bSRaymond Chen #define	USB_LINK_RE_WHOST	"^usb/whost[0-9]+$"
104ff0e937bSRaymond Chen #define	USB_LINK_RE_HWARC	"^usb/hwarc[0-9]+$"
105ff0e937bSRaymond Chen #define	USB_LINK_RE_WUSB_CA	"^usb/wusb_ca[0-9]+$"
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate /* Rules for removing links */
1087c478bd9Sstevel@tonic-gate static devfsadm_remove_t usb_remove_cbt[] = {
1097c478bd9Sstevel@tonic-gate 	{ "usb", USB_LINK_RE_AUDIO, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
1107c478bd9Sstevel@tonic-gate 			devfsadm_rm_all },
1117c478bd9Sstevel@tonic-gate 	{ "usb", USB_LINK_RE_AUDIOMUX, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
1127c478bd9Sstevel@tonic-gate 			devfsadm_rm_all },
1137c478bd9Sstevel@tonic-gate 	{ "usb", USB_LINK_RE_AUDIOCTL, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
1147c478bd9Sstevel@tonic-gate 			devfsadm_rm_all },
1157c478bd9Sstevel@tonic-gate 	{ "usb", USB_LINK_RE_AUDIOSTREAM, RM_POST | RM_HOT | RM_ALWAYS,
1167c478bd9Sstevel@tonic-gate 			ILEVEL_0, devfsadm_rm_all },
1177c478bd9Sstevel@tonic-gate 	{ "usb", USB_LINK_RE_DDIVS_USBC, RM_POST | RM_HOT | RM_ALWAYS,
1187c478bd9Sstevel@tonic-gate 			ILEVEL_0, devfsadm_rm_all },
119c77a61a7Syz147069 	{ "usb", USB_LINK_RE_VIDEO2, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
120c77a61a7Syz147069 			devfsadm_rm_all },
121*3fb52c73SRaymond Chen 	{ "usb", USB_LINK_RE_VIDEO, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
122*3fb52c73SRaymond Chen 			devfsadm_rm_all },
1237c478bd9Sstevel@tonic-gate 	{ "usb", USB_LINK_RE_DEVICE, RM_POST | RM_HOT, ILEVEL_0,
1247c478bd9Sstevel@tonic-gate 			devfsadm_rm_all },
1257c478bd9Sstevel@tonic-gate 	{ "usb", USB_LINK_RE_HID, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
1267c478bd9Sstevel@tonic-gate 			devfsadm_rm_all },
1277c478bd9Sstevel@tonic-gate 	{ "usb", USB_LINK_RE_HUB, RM_POST | RM_HOT, ILEVEL_0, devfsadm_rm_all },
1287c478bd9Sstevel@tonic-gate 	{ "usb", USB_LINK_RE_MASS_STORE, RM_POST | RM_HOT | RM_ALWAYS,
1297c478bd9Sstevel@tonic-gate 			ILEVEL_0, devfsadm_rm_all },
1307c478bd9Sstevel@tonic-gate 	{ "usb", USB_LINK_RE_UGEN, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
1317c478bd9Sstevel@tonic-gate 			devfsadm_rm_all },
1327c478bd9Sstevel@tonic-gate 	{ "usb", USB_LINK_RE_USBPRN, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
1337c478bd9Sstevel@tonic-gate 			devfsadm_rm_link },
134ff0e937bSRaymond Chen 	{ "usb", USB_LINK_RE_WHOST, RM_POST | RM_HOT, ILEVEL_0,
135ff0e937bSRaymond Chen 			devfsadm_rm_all },
136ff0e937bSRaymond Chen 	{ "usb", USB_LINK_RE_HWARC, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
137ff0e937bSRaymond Chen 			devfsadm_rm_all },
138ff0e937bSRaymond Chen 	{ "usb", USB_LINK_RE_WUSB_CA, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
139ff0e937bSRaymond Chen 			devfsadm_rm_all }
1407c478bd9Sstevel@tonic-gate };
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate /*
1437c478bd9Sstevel@tonic-gate  * Rules for different USB devices except ugen which is dynamically
1447c478bd9Sstevel@tonic-gate  * created
1457c478bd9Sstevel@tonic-gate  */
1467c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t audio_rules[1] =
1477c478bd9Sstevel@tonic-gate 	{"^usb$/^audio([0-9]+)$", 1, MATCH_ALL};
1487c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t audio_mux_rules[1] =
1497c478bd9Sstevel@tonic-gate 	{"^usb$/^audio-mux([0-9]+)$", 1, MATCH_ALL};
1507c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t audio_control_rules[1] =
1517c478bd9Sstevel@tonic-gate 	{"^usb$/^audio-control([0-9]+)$", 1, MATCH_ALL};
1527c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t audio_stream_rules[1] =
1537c478bd9Sstevel@tonic-gate 	{"^usb$/^audio-stream([0-9]+)$", 1, MATCH_ALL};
1547c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t ddivs_usbc_rules[1] =
1557c478bd9Sstevel@tonic-gate 	{"^usb$/^ddivs_usbc([0-9]+)$", 1, MATCH_ALL};
156c77a61a7Syz147069 static devfsadm_enumerate_t video_rules[1] =
157c77a61a7Syz147069 	{"^usb$/^video([0-9]+)$", 1, MATCH_ALL};
1587c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t device_rules[1] =
1597c478bd9Sstevel@tonic-gate 	{"^usb$/^device([0-9]+)$", 1, MATCH_ALL};
1607c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t hid_rules[1] =
1617c478bd9Sstevel@tonic-gate 	{"^usb$/^hid([0-9]+)$", 1, MATCH_ALL};
1627c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t hub_rules[1] =
1637c478bd9Sstevel@tonic-gate 	{"^usb$/^hub([0-9]+)$", 1, MATCH_ALL};
1647c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t mass_storage_rules[1] =
1657c478bd9Sstevel@tonic-gate 	{"^usb$/^mass-storage([0-9]+)$", 1, MATCH_ALL};
1667c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t usbprn_rules[1] =
1677c478bd9Sstevel@tonic-gate 	{"^usb$/^printer([0-9]+)$", 1, MATCH_ALL};
168ff0e937bSRaymond Chen static devfsadm_enumerate_t whost_rules[1] =
169ff0e937bSRaymond Chen 	{"^usb$/^whost([0-9]+)$", 1, MATCH_ALL};
170ff0e937bSRaymond Chen static devfsadm_enumerate_t hwarc_rules[1] =
171ff0e937bSRaymond Chen 	{"^usb$/^hwarc([0-9]+)$", 1, MATCH_ALL};
172ff0e937bSRaymond Chen static devfsadm_enumerate_t wusb_ca_rules[1] =
173ff0e937bSRaymond Chen 	{"^usb$/^wusb_ca([0-9]+)$", 1, MATCH_ALL};
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate DEVFSADM_REMOVE_INIT_V0(usb_remove_cbt);
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate int
1787c478bd9Sstevel@tonic-gate minor_init(void)
1797c478bd9Sstevel@tonic-gate {
1807c478bd9Sstevel@tonic-gate 	devfsadm_print(debug_mid, "usb_link: minor_init\n");
1817c478bd9Sstevel@tonic-gate 	return (DEVFSADM_SUCCESS);
1827c478bd9Sstevel@tonic-gate }
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate int
1857c478bd9Sstevel@tonic-gate minor_fini(void)
1867c478bd9Sstevel@tonic-gate {
1877c478bd9Sstevel@tonic-gate 	devfsadm_print(debug_mid, "usb_link: minor_fini\n");
1887c478bd9Sstevel@tonic-gate 	return (DEVFSADM_SUCCESS);
1897c478bd9Sstevel@tonic-gate }
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate typedef enum {
1927c478bd9Sstevel@tonic-gate 	DRIVER_HUBD	= 0,
1937c478bd9Sstevel@tonic-gate 	DRIVER_OHCI	= 1,
1947c478bd9Sstevel@tonic-gate 	DRIVER_EHCI	= 2,
1957c478bd9Sstevel@tonic-gate 	DRIVER_UHCI	= 3,
1967c478bd9Sstevel@tonic-gate 	DRIVER_USB_AC	= 4,
1977c478bd9Sstevel@tonic-gate 	DRIVER_USB_AS	= 5,
1987c478bd9Sstevel@tonic-gate 	DRIVER_HID	= 6,
1997c478bd9Sstevel@tonic-gate 	DRIVER_USB_MID	= 7,
2007c478bd9Sstevel@tonic-gate 	DRIVER_DDIVS_USBC = 8,
2017c478bd9Sstevel@tonic-gate 	DRIVER_SCSA2USB = 9,
2027c478bd9Sstevel@tonic-gate 	DRIVER_USBPRN	= 10,
2037c478bd9Sstevel@tonic-gate 	DRIVER_UGEN	= 11,
204c77a61a7Syz147069 	DRIVER_VIDEO	= 12,
205ff0e937bSRaymond Chen 	DRIVER_HWAHC	= 13,
206ff0e937bSRaymond Chen 	DRIVER_HWARC	= 14,
207ff0e937bSRaymond Chen 	DRIVER_WUSB_CA	= 15,
208ff0e937bSRaymond Chen 	DRIVER_UNKNOWN	= 16
2097c478bd9Sstevel@tonic-gate } driver_defs_t;
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate typedef struct {
2127c478bd9Sstevel@tonic-gate 	char	*driver_name;
2137c478bd9Sstevel@tonic-gate 	int	index;
2147c478bd9Sstevel@tonic-gate } driver_name_table_entry_t;
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate driver_name_table_entry_t driver_name_table[] = {
2177c478bd9Sstevel@tonic-gate 	{ "hubd",	DRIVER_HUBD },
2187c478bd9Sstevel@tonic-gate 	{ "ohci",	DRIVER_OHCI },
2197c478bd9Sstevel@tonic-gate 	{ "ehci",	DRIVER_EHCI },
2207c478bd9Sstevel@tonic-gate 	{ "uhci",	DRIVER_UHCI },
2217c478bd9Sstevel@tonic-gate 	{ "usb_ac",	DRIVER_USB_AC },
2227c478bd9Sstevel@tonic-gate 	{ "usb_as",	DRIVER_USB_AS },
2237c478bd9Sstevel@tonic-gate 	{ "hid",	DRIVER_HID },
2247c478bd9Sstevel@tonic-gate 	{ "usb_mid",	DRIVER_USB_MID },
2257c478bd9Sstevel@tonic-gate 	{ "ddivs_usbc",	DRIVER_DDIVS_USBC },
2267c478bd9Sstevel@tonic-gate 	{ "scsa2usb",	DRIVER_SCSA2USB },
2277c478bd9Sstevel@tonic-gate 	{ "usbprn",	DRIVER_USBPRN },
2287c478bd9Sstevel@tonic-gate 	{ "ugen",	DRIVER_UGEN },
229c77a61a7Syz147069 	{ "usbvc",	DRIVER_VIDEO },
230ff0e937bSRaymond Chen 	{ "hwahc",	DRIVER_HWAHC },
231ff0e937bSRaymond Chen 	{ "hwarc",	DRIVER_HWARC },
232ff0e937bSRaymond Chen 	{ "wusb_ca",	DRIVER_WUSB_CA },
2337c478bd9Sstevel@tonic-gate 	{ NULL,		DRIVER_UNKNOWN }
2347c478bd9Sstevel@tonic-gate };
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate /*
2377c478bd9Sstevel@tonic-gate  * This function is called for every usb minor node.
2387c478bd9Sstevel@tonic-gate  * Calls enumerate to assign a logical usb id, and then
2397c478bd9Sstevel@tonic-gate  * devfsadm_mklink to make the link.
2407c478bd9Sstevel@tonic-gate  */
2417c478bd9Sstevel@tonic-gate static int
2427c478bd9Sstevel@tonic-gate usb_process(di_minor_t minor, di_node_t node)
2437c478bd9Sstevel@tonic-gate {
2447c478bd9Sstevel@tonic-gate 	devfsadm_enumerate_t rules[1];
2457c478bd9Sstevel@tonic-gate 	char *l_path, *p_path, *buf, *devfspath;
2467c478bd9Sstevel@tonic-gate 	char *minor_nm, *drvr_nm, *name = (char *)NULL;
2477c478bd9Sstevel@tonic-gate 	int i, index;
24845916cd2Sjpk 	int flags = 0;
2497c478bd9Sstevel@tonic-gate 	int create_secondary_link = 0;
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate 	minor_nm = di_minor_name(minor);
2527c478bd9Sstevel@tonic-gate 	drvr_nm = di_driver_name(node);
2537c478bd9Sstevel@tonic-gate 	if ((minor_nm == NULL) || (drvr_nm == NULL)) {
2547c478bd9Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
2557c478bd9Sstevel@tonic-gate 	}
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	devfsadm_print(debug_mid, "usb_process: minor=%s node=%s type=%s\n",
2587c478bd9Sstevel@tonic-gate 	    minor_nm, di_node_name(node), di_minor_nodetype(minor));
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 	devfspath = di_devfs_path(node);
2617c478bd9Sstevel@tonic-gate 	if (devfspath == NULL) {
2627c478bd9Sstevel@tonic-gate 		devfsadm_print(debug_mid,
2637c478bd9Sstevel@tonic-gate 		    "USB_process: devfspath is	NULL\n");
2647c478bd9Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
2657c478bd9Sstevel@tonic-gate 	}
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 	l_path = (char *)malloc(PATH_MAX);
2687c478bd9Sstevel@tonic-gate 	if (l_path == NULL) {
2697c478bd9Sstevel@tonic-gate 		di_devfs_path_free(devfspath);
2707c478bd9Sstevel@tonic-gate 		devfsadm_print(debug_mid, "usb_process: malloc() failed\n");
2717c478bd9Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
2727c478bd9Sstevel@tonic-gate 	}
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	p_path = (char *)malloc(PATH_MAX);
2757c478bd9Sstevel@tonic-gate 	if (p_path == NULL) {
2767c478bd9Sstevel@tonic-gate 		devfsadm_print(debug_mid, "usb_process: malloc() failed\n");
2777c478bd9Sstevel@tonic-gate 		di_devfs_path_free(devfspath);
2787c478bd9Sstevel@tonic-gate 		free(l_path);
2797c478bd9Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
2807c478bd9Sstevel@tonic-gate 	}
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 	(void) strcpy(p_path, devfspath);
2837c478bd9Sstevel@tonic-gate 	(void) strcat(p_path, ":");
2847c478bd9Sstevel@tonic-gate 	(void) strcat(p_path, minor_nm);
2857c478bd9Sstevel@tonic-gate 	di_devfs_path_free(devfspath);
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 	devfsadm_print(debug_mid, "usb_process: path %s\n", p_path);
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	for (i = 0; ; i++) {
2907c478bd9Sstevel@tonic-gate 		if ((driver_name_table[i].driver_name == NULL) ||
2917c478bd9Sstevel@tonic-gate 		    (strcmp(drvr_nm, driver_name_table[i].driver_name) == 0)) {
2927c478bd9Sstevel@tonic-gate 			index = driver_name_table[i].index;
2937c478bd9Sstevel@tonic-gate 			break;
2947c478bd9Sstevel@tonic-gate 		}
2957c478bd9Sstevel@tonic-gate 	}
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	if (strcmp(di_minor_nodetype(minor), DDI_NT_UGEN) == 0) {
2987c478bd9Sstevel@tonic-gate 		ugen_create_link(p_path, minor_nm, node, minor);
2997c478bd9Sstevel@tonic-gate 		free(l_path);
3007c478bd9Sstevel@tonic-gate 		free(p_path);
3017c478bd9Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
3027c478bd9Sstevel@tonic-gate 	}
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 	/* Figure out which rules to apply */
3057c478bd9Sstevel@tonic-gate 	switch (index) {
3067c478bd9Sstevel@tonic-gate 	case DRIVER_HUBD:
3077c478bd9Sstevel@tonic-gate 	case DRIVER_OHCI:
3087c478bd9Sstevel@tonic-gate 	case DRIVER_EHCI:
3097c478bd9Sstevel@tonic-gate 	case DRIVER_UHCI:
3107c478bd9Sstevel@tonic-gate 		rules[0] = hub_rules[0];	/* For HUBs */
3117c478bd9Sstevel@tonic-gate 		name = "hub";
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate 		break;
3147c478bd9Sstevel@tonic-gate 	case DRIVER_USB_AC:
3157c478bd9Sstevel@tonic-gate 		if (strcmp(minor_nm, "sound,audio") == 0) {
3167c478bd9Sstevel@tonic-gate 			rules[0] = audio_rules[0];
3177c478bd9Sstevel@tonic-gate 			name = "audio";		/* For audio */
3187c478bd9Sstevel@tonic-gate 			create_secondary_link = 1;
3197c478bd9Sstevel@tonic-gate 		} else if (strcmp(minor_nm, "sound,audioctl") == 0) {
3207c478bd9Sstevel@tonic-gate 			rules[0] = audio_control_rules[0];
3217c478bd9Sstevel@tonic-gate 			name = "audio-control";		/* For audio */
3227c478bd9Sstevel@tonic-gate 			create_secondary_link = 1;
3237c478bd9Sstevel@tonic-gate 		} else if (strcmp(minor_nm, "mux") == 0) {
3247c478bd9Sstevel@tonic-gate 			rules[0] = audio_mux_rules[0];
3257c478bd9Sstevel@tonic-gate 			name = "audio-mux";		/* For audio */
3267c478bd9Sstevel@tonic-gate 		} else {
3277c478bd9Sstevel@tonic-gate 			free(l_path);
3287c478bd9Sstevel@tonic-gate 			free(p_path);
3297c478bd9Sstevel@tonic-gate 			return (DEVFSADM_CONTINUE);
3307c478bd9Sstevel@tonic-gate 		}
3317c478bd9Sstevel@tonic-gate 		break;
3327c478bd9Sstevel@tonic-gate 	case DRIVER_USB_AS:
3337c478bd9Sstevel@tonic-gate 		rules[0] = audio_stream_rules[0];
3347c478bd9Sstevel@tonic-gate 		name = "audio-stream";		/* For audio */
3357c478bd9Sstevel@tonic-gate 		break;
336c77a61a7Syz147069 	case DRIVER_VIDEO:
337c77a61a7Syz147069 		rules[0] = video_rules[0];
338c77a61a7Syz147069 		name = "video";			/* For video */
339c77a61a7Syz147069 		create_secondary_link = 1;
340c77a61a7Syz147069 		break;
3417c478bd9Sstevel@tonic-gate 	case DRIVER_HID:
3427c478bd9Sstevel@tonic-gate 		rules[0] = hid_rules[0];
3437c478bd9Sstevel@tonic-gate 		name = "hid";			/* For HIDs */
3447c478bd9Sstevel@tonic-gate 		break;
3457c478bd9Sstevel@tonic-gate 	case DRIVER_USB_MID:
3467c478bd9Sstevel@tonic-gate 		rules[0] = device_rules[0];
3477c478bd9Sstevel@tonic-gate 		name = "device";		/* For other USB devices */
3487c478bd9Sstevel@tonic-gate 		break;
3497c478bd9Sstevel@tonic-gate 	case DRIVER_DDIVS_USBC:
3507c478bd9Sstevel@tonic-gate 		rules[0] = ddivs_usbc_rules[0];
3517c478bd9Sstevel@tonic-gate 		name = "device";		/* For other USB devices */
3527c478bd9Sstevel@tonic-gate 		break;
3537c478bd9Sstevel@tonic-gate 	case DRIVER_SCSA2USB:
3547c478bd9Sstevel@tonic-gate 		rules[0] = mass_storage_rules[0];
3557c478bd9Sstevel@tonic-gate 		name = "mass-storage";		/* For mass-storage devices */
3567c478bd9Sstevel@tonic-gate 		break;
3577c478bd9Sstevel@tonic-gate 	case DRIVER_USBPRN:
3587c478bd9Sstevel@tonic-gate 		rules[0] = usbprn_rules[0];
3597c478bd9Sstevel@tonic-gate 		name = "printer";
3607c478bd9Sstevel@tonic-gate 		break;
361ff0e937bSRaymond Chen 	case DRIVER_HWAHC:
362ff0e937bSRaymond Chen 		if (strcmp(minor_nm, "hwahc") == 0) {
363ff0e937bSRaymond Chen 			rules[0] = whost_rules[0];
364ff0e937bSRaymond Chen 			name = "whost";		/* For HWA HC */
365ff0e937bSRaymond Chen 		} else if (strcmp(minor_nm, "hubd") == 0) {
366ff0e937bSRaymond Chen 			rules[0] = hub_rules[0];
367ff0e937bSRaymond Chen 			name = "hub";		/* For HWA HC */
368ff0e937bSRaymond Chen 		} else {
369ff0e937bSRaymond Chen 			free(l_path);
370ff0e937bSRaymond Chen 			free(p_path);
371ff0e937bSRaymond Chen 			return (DEVFSADM_CONTINUE);
372ff0e937bSRaymond Chen 		}
373ff0e937bSRaymond Chen 		break;
374ff0e937bSRaymond Chen 	case DRIVER_HWARC:
375ff0e937bSRaymond Chen 		rules[0] = hwarc_rules[0];
376ff0e937bSRaymond Chen 		name = "hwarc";		/* For UWB HWA Radio Controllers */
377ff0e937bSRaymond Chen 		break;
378ff0e937bSRaymond Chen 	case DRIVER_WUSB_CA:
379ff0e937bSRaymond Chen 		rules[0] = wusb_ca_rules[0];
380ff0e937bSRaymond Chen 		name = "wusb_ca";	/* for wusb cable association */
381ff0e937bSRaymond Chen 		break;
3827c478bd9Sstevel@tonic-gate 	default:
3837c478bd9Sstevel@tonic-gate 		devfsadm_print(debug_mid, "usb_process: unknown driver=%s\n",
3847c478bd9Sstevel@tonic-gate 		    drvr_nm);
3857c478bd9Sstevel@tonic-gate 		free(l_path);
3867c478bd9Sstevel@tonic-gate 		free(p_path);
3877c478bd9Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
3887c478bd9Sstevel@tonic-gate 	}
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 	/*
3917c478bd9Sstevel@tonic-gate 	 *  build the physical path from the components.
3927c478bd9Sstevel@tonic-gate 	 *  find the logical usb id, and stuff it in buf
3937c478bd9Sstevel@tonic-gate 	 */
3947c478bd9Sstevel@tonic-gate 	if (devfsadm_enumerate_int(p_path, 0, &buf, rules, 1)) {
3957c478bd9Sstevel@tonic-gate 		devfsadm_print(debug_mid, "usb_process: exit/continue\n");
3967c478bd9Sstevel@tonic-gate 		free(l_path);
3977c478bd9Sstevel@tonic-gate 		free(p_path);
3987c478bd9Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
3997c478bd9Sstevel@tonic-gate 	}
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	(void) snprintf(l_path, PATH_MAX, "usb/%s%s", name, buf);
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	devfsadm_print(debug_mid, "usb_process: p_path=%s buf=%s\n",
4047c478bd9Sstevel@tonic-gate 	    p_path, buf);
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 	free(buf);
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate 	devfsadm_print(debug_mid, "mklink %s -> %s\n", l_path, p_path);
4097c478bd9Sstevel@tonic-gate 
41045916cd2Sjpk 	(void) devfsadm_mklink(l_path, node, minor, flags);
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate 	if (create_secondary_link) {
4137c478bd9Sstevel@tonic-gate 		/*
4147c478bd9Sstevel@tonic-gate 		 * Create secondary links to make newly hotplugged
4157c478bd9Sstevel@tonic-gate 		 * usb audio device the primary device.
4167c478bd9Sstevel@tonic-gate 		 */
4177c478bd9Sstevel@tonic-gate 		if (strcmp(name, "audio") == 0) {
4187c478bd9Sstevel@tonic-gate 			(void) devfsadm_secondary_link("audio", l_path, 0);
4197c478bd9Sstevel@tonic-gate 		} else if (strcmp(name, "audio-control") == 0) {
4207c478bd9Sstevel@tonic-gate 			(void) devfsadm_secondary_link("audioctl", l_path, 0);
421c77a61a7Syz147069 		} else if (strcmp(name, "video") == 0) {
422c77a61a7Syz147069 			(void) devfsadm_secondary_link(l_path + 4, l_path, 0);
4237c478bd9Sstevel@tonic-gate 		}
4247c478bd9Sstevel@tonic-gate 	}
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 	free(p_path);
4277c478bd9Sstevel@tonic-gate 	free(l_path);
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate 	return (DEVFSADM_CONTINUE);
4307c478bd9Sstevel@tonic-gate }
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate static void
4337c478bd9Sstevel@tonic-gate ugen_create_link(char *p_path, char *node_name,
4347c478bd9Sstevel@tonic-gate     di_node_t node, di_minor_t minor)
4357c478bd9Sstevel@tonic-gate {
4367c478bd9Sstevel@tonic-gate 	char *buf, s[MAXPATHLEN];
4377c478bd9Sstevel@tonic-gate 	char *lasts = s;
4387c478bd9Sstevel@tonic-gate 	char *vid, *pid;
4397c478bd9Sstevel@tonic-gate 	char *minor_name;
4407c478bd9Sstevel@tonic-gate 	char ugen_RE[128];
4417c478bd9Sstevel@tonic-gate 	devfsadm_enumerate_t ugen_rules[1];
4427c478bd9Sstevel@tonic-gate 	char l_path[PATH_MAX];
44345916cd2Sjpk 	int flags = 0;
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 	devfsadm_print(debug_mid, "ugen_create_link: p_path=%s name=%s\n",
4467c478bd9Sstevel@tonic-gate 	    p_path, node_name);
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate 	(void) strlcpy(s, node_name, sizeof (s));
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate 	/* get vid, pid and minor name strings */
4517c478bd9Sstevel@tonic-gate 	vid = strtok_r(lasts, ".", &lasts);
4527c478bd9Sstevel@tonic-gate 	pid = strtok_r(NULL, ".", &lasts);
4537c478bd9Sstevel@tonic-gate 	minor_name = lasts;
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate 	if ((vid == NULL) || (pid == NULL) || (minor_name == NULL)) {
4567c478bd9Sstevel@tonic-gate 		return;
4577c478bd9Sstevel@tonic-gate 	}
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 	/* create regular expression contain vid and pid */
4607c478bd9Sstevel@tonic-gate 	(void) snprintf(ugen_RE, sizeof (ugen_RE),
4617c478bd9Sstevel@tonic-gate 	    "^usb$/^%s\\.%s$/^([0-9]+)$", vid, pid);
4627c478bd9Sstevel@tonic-gate 	devfsadm_print(debug_mid,
4637c478bd9Sstevel@tonic-gate 	    "ugen_create_link: ugen_RE=%s minor_name=%s\n",
4647c478bd9Sstevel@tonic-gate 	    ugen_RE, minor_name);
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 	bzero(ugen_rules, sizeof (ugen_rules));
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 	ugen_rules[0].re = ugen_RE;
4697c478bd9Sstevel@tonic-gate 	ugen_rules[0].subexp = 1;
4707c478bd9Sstevel@tonic-gate 	ugen_rules[0].flags = MATCH_ADDR;
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate 	/*
4737c478bd9Sstevel@tonic-gate 	 *  build the physical path from the components.
4747c478bd9Sstevel@tonic-gate 	 *  find the logical usb id, and stuff it in buf
4757c478bd9Sstevel@tonic-gate 	 */
4767c478bd9Sstevel@tonic-gate 	if (devfsadm_enumerate_int(p_path, 0, &buf, ugen_rules, 1)) {
4777c478bd9Sstevel@tonic-gate 		devfsadm_print(debug_mid, "ugen_create_link: exit/continue\n");
4787c478bd9Sstevel@tonic-gate 		return;
4797c478bd9Sstevel@tonic-gate 	}
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	(void) snprintf(l_path, sizeof (l_path), "usb/%s.%s/%s/%s",
4827c478bd9Sstevel@tonic-gate 	    vid, pid, buf, minor_name);
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 	devfsadm_print(debug_mid, "mklink %s -> %s\n", l_path, p_path);
4857c478bd9Sstevel@tonic-gate 
48645916cd2Sjpk 	(void) devfsadm_mklink(l_path, node, minor, flags);
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 	free(buf);
4897c478bd9Sstevel@tonic-gate }
490