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