10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51676Sjpk * Common Development and Distribution License (the "License").
61676Sjpk * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate *
219430SRaymond.Chen@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
220Sstevel@tonic-gate * Use is subject to license terms.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate
250Sstevel@tonic-gate #include <devfsadm.h>
260Sstevel@tonic-gate #include <stdio.h>
270Sstevel@tonic-gate #include <stdlib.h>
280Sstevel@tonic-gate #include <limits.h>
290Sstevel@tonic-gate #include <string.h>
300Sstevel@tonic-gate #include <unistd.h>
310Sstevel@tonic-gate #include <sys/types.h>
320Sstevel@tonic-gate #include <sys/stat.h>
330Sstevel@tonic-gate #include <strings.h>
340Sstevel@tonic-gate
350Sstevel@tonic-gate extern char *devfsadm_get_devices_dir();
360Sstevel@tonic-gate static int usb_process(di_minor_t minor, di_node_t node);
370Sstevel@tonic-gate
380Sstevel@tonic-gate static void ugen_create_link(char *p_path, char *node_name,
390Sstevel@tonic-gate di_node_t node, di_minor_t minor);
400Sstevel@tonic-gate
410Sstevel@tonic-gate
420Sstevel@tonic-gate /* Rules for creating links */
430Sstevel@tonic-gate static devfsadm_create_t usb_cbt[] = {
440Sstevel@tonic-gate { "usb", NULL, "usb_ac", DRV_EXACT,
450Sstevel@tonic-gate ILEVEL_0, usb_process },
460Sstevel@tonic-gate { "usb", NULL, "usb_as", DRV_EXACT,
470Sstevel@tonic-gate ILEVEL_0, usb_process },
480Sstevel@tonic-gate { "usb", NULL, "ddivs_usbc", DRV_EXACT,
490Sstevel@tonic-gate ILEVEL_0, usb_process },
503329Syz147069 { "usb", NULL, "usbvc", DRV_EXACT,
513329Syz147069 ILEVEL_0, usb_process },
520Sstevel@tonic-gate { "usb", NULL, "hid", DRV_EXACT,
530Sstevel@tonic-gate ILEVEL_0, usb_process },
549430SRaymond.Chen@Sun.COM { "usb", NULL, "hwarc", DRV_EXACT,
559430SRaymond.Chen@Sun.COM ILEVEL_0, usb_process },
569430SRaymond.Chen@Sun.COM { "usb", NULL, "wusb_ca", DRV_EXACT,
579430SRaymond.Chen@Sun.COM ILEVEL_0, usb_process },
580Sstevel@tonic-gate { "usb", DDI_NT_NEXUS, "hubd", DRV_EXACT|TYPE_EXACT,
590Sstevel@tonic-gate ILEVEL_0, usb_process },
600Sstevel@tonic-gate { "usb", DDI_NT_NEXUS, "ohci", DRV_EXACT|TYPE_EXACT,
610Sstevel@tonic-gate ILEVEL_0, usb_process },
620Sstevel@tonic-gate { "usb", DDI_NT_NEXUS, "ehci", DRV_EXACT|TYPE_EXACT,
630Sstevel@tonic-gate ILEVEL_0, usb_process },
640Sstevel@tonic-gate { "usb", DDI_NT_SCSI_NEXUS, "scsa2usb", DRV_EXACT|TYPE_EXACT,
650Sstevel@tonic-gate ILEVEL_0, usb_process },
660Sstevel@tonic-gate { "usb", DDI_NT_UGEN, "scsa2usb", DRV_EXACT|TYPE_EXACT,
670Sstevel@tonic-gate ILEVEL_0, usb_process },
680Sstevel@tonic-gate { "usb", DDI_NT_NEXUS, "uhci", DRV_EXACT|TYPE_EXACT,
690Sstevel@tonic-gate ILEVEL_0, usb_process },
700Sstevel@tonic-gate { "usb", DDI_NT_UGEN, "ugen", DRV_EXACT|TYPE_EXACT,
710Sstevel@tonic-gate ILEVEL_0, usb_process },
720Sstevel@tonic-gate { "usb", DDI_NT_NEXUS, "usb_mid", DRV_EXACT|TYPE_EXACT,
730Sstevel@tonic-gate ILEVEL_0, usb_process },
740Sstevel@tonic-gate { "usb", DDI_NT_UGEN, "usb_mid", DRV_EXACT|TYPE_EXACT,
750Sstevel@tonic-gate ILEVEL_0, usb_process },
760Sstevel@tonic-gate { "usb", DDI_NT_PRINTER, "usbprn", DRV_EXACT|TYPE_EXACT,
770Sstevel@tonic-gate ILEVEL_0, usb_process },
780Sstevel@tonic-gate { "usb", DDI_NT_UGEN, "usbprn", DRV_EXACT|TYPE_EXACT,
790Sstevel@tonic-gate ILEVEL_0, usb_process },
809430SRaymond.Chen@Sun.COM { "usb", DDI_NT_NEXUS, "hwahc", DRV_EXACT|TYPE_EXACT,
819430SRaymond.Chen@Sun.COM ILEVEL_0, usb_process },
820Sstevel@tonic-gate };
830Sstevel@tonic-gate
840Sstevel@tonic-gate /* For debug printing (-V filter) */
850Sstevel@tonic-gate static char *debug_mid = "usb_mid";
860Sstevel@tonic-gate
870Sstevel@tonic-gate DEVFSADM_CREATE_INIT_V0(usb_cbt);
880Sstevel@tonic-gate
890Sstevel@tonic-gate /* USB device links */
900Sstevel@tonic-gate #define USB_LINK_RE_AUDIO "^usb/audio[0-9]+$"
910Sstevel@tonic-gate #define USB_LINK_RE_AUDIOMUX "^usb/audio-mux[0-9]+$"
920Sstevel@tonic-gate #define USB_LINK_RE_AUDIOCTL "^usb/audio-control[0-9]+$"
930Sstevel@tonic-gate #define USB_LINK_RE_AUDIOSTREAM "^usb/audio-stream[0-9]+$"
940Sstevel@tonic-gate #define USB_LINK_RE_DDIVS_USBC "^usb/ddivs_usbc[0-9]+$"
953329Syz147069 #define USB_LINK_RE_VIDEO "^usb/video[0-9]+$"
963329Syz147069 #define USB_LINK_RE_VIDEO2 "^video[0-9]+$"
970Sstevel@tonic-gate #define USB_LINK_RE_DEVICE "^usb/device[0-9]+$"
980Sstevel@tonic-gate #define USB_LINK_RE_HID "^usb/hid[0-9]+$"
990Sstevel@tonic-gate #define USB_LINK_RE_HUB "^usb/hub[0-9]+$"
1000Sstevel@tonic-gate #define USB_LINK_RE_MASS_STORE "^usb/mass-storage[0-9]+$"
1010Sstevel@tonic-gate #define USB_LINK_RE_UGEN "^usb/[0-9,a-f]+\\.[0-9,a-f]+/[0-9]+/.+$"
1020Sstevel@tonic-gate #define USB_LINK_RE_USBPRN "^usb/printer[0-9]+$"
1039430SRaymond.Chen@Sun.COM #define USB_LINK_RE_WHOST "^usb/whost[0-9]+$"
1049430SRaymond.Chen@Sun.COM #define USB_LINK_RE_HWARC "^usb/hwarc[0-9]+$"
1059430SRaymond.Chen@Sun.COM #define USB_LINK_RE_WUSB_CA "^usb/wusb_ca[0-9]+$"
1060Sstevel@tonic-gate
1070Sstevel@tonic-gate /* Rules for removing links */
1080Sstevel@tonic-gate static devfsadm_remove_t usb_remove_cbt[] = {
1090Sstevel@tonic-gate { "usb", USB_LINK_RE_AUDIO, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
1100Sstevel@tonic-gate devfsadm_rm_all },
1110Sstevel@tonic-gate { "usb", USB_LINK_RE_AUDIOMUX, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
1120Sstevel@tonic-gate devfsadm_rm_all },
1130Sstevel@tonic-gate { "usb", USB_LINK_RE_AUDIOCTL, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
1140Sstevel@tonic-gate devfsadm_rm_all },
1150Sstevel@tonic-gate { "usb", USB_LINK_RE_AUDIOSTREAM, RM_POST | RM_HOT | RM_ALWAYS,
1160Sstevel@tonic-gate ILEVEL_0, devfsadm_rm_all },
1170Sstevel@tonic-gate { "usb", USB_LINK_RE_DDIVS_USBC, RM_POST | RM_HOT | RM_ALWAYS,
1180Sstevel@tonic-gate ILEVEL_0, devfsadm_rm_all },
119*10975SRaymond.Chen@Sun.COM { "usb", USB_LINK_RE_VIDEO2, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
1203329Syz147069 devfsadm_rm_all },
121*10975SRaymond.Chen@Sun.COM { "usb", USB_LINK_RE_VIDEO, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
1223329Syz147069 devfsadm_rm_all },
1230Sstevel@tonic-gate { "usb", USB_LINK_RE_DEVICE, RM_POST | RM_HOT, ILEVEL_0,
1240Sstevel@tonic-gate devfsadm_rm_all },
1250Sstevel@tonic-gate { "usb", USB_LINK_RE_HID, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
1260Sstevel@tonic-gate devfsadm_rm_all },
1270Sstevel@tonic-gate { "usb", USB_LINK_RE_HUB, RM_POST | RM_HOT, ILEVEL_0, devfsadm_rm_all },
1280Sstevel@tonic-gate { "usb", USB_LINK_RE_MASS_STORE, RM_POST | RM_HOT | RM_ALWAYS,
1290Sstevel@tonic-gate ILEVEL_0, devfsadm_rm_all },
1300Sstevel@tonic-gate { "usb", USB_LINK_RE_UGEN, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
1310Sstevel@tonic-gate devfsadm_rm_all },
1320Sstevel@tonic-gate { "usb", USB_LINK_RE_USBPRN, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
1330Sstevel@tonic-gate devfsadm_rm_link },
1349430SRaymond.Chen@Sun.COM { "usb", USB_LINK_RE_WHOST, RM_POST | RM_HOT, ILEVEL_0,
1359430SRaymond.Chen@Sun.COM devfsadm_rm_all },
1369430SRaymond.Chen@Sun.COM { "usb", USB_LINK_RE_HWARC, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
1379430SRaymond.Chen@Sun.COM devfsadm_rm_all },
1389430SRaymond.Chen@Sun.COM { "usb", USB_LINK_RE_WUSB_CA, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0,
1399430SRaymond.Chen@Sun.COM devfsadm_rm_all }
1400Sstevel@tonic-gate };
1410Sstevel@tonic-gate
1420Sstevel@tonic-gate /*
1430Sstevel@tonic-gate * Rules for different USB devices except ugen which is dynamically
1440Sstevel@tonic-gate * created
1450Sstevel@tonic-gate */
1460Sstevel@tonic-gate static devfsadm_enumerate_t audio_rules[1] =
1470Sstevel@tonic-gate {"^usb$/^audio([0-9]+)$", 1, MATCH_ALL};
1480Sstevel@tonic-gate static devfsadm_enumerate_t audio_mux_rules[1] =
1490Sstevel@tonic-gate {"^usb$/^audio-mux([0-9]+)$", 1, MATCH_ALL};
1500Sstevel@tonic-gate static devfsadm_enumerate_t audio_control_rules[1] =
1510Sstevel@tonic-gate {"^usb$/^audio-control([0-9]+)$", 1, MATCH_ALL};
1520Sstevel@tonic-gate static devfsadm_enumerate_t audio_stream_rules[1] =
1530Sstevel@tonic-gate {"^usb$/^audio-stream([0-9]+)$", 1, MATCH_ALL};
1540Sstevel@tonic-gate static devfsadm_enumerate_t ddivs_usbc_rules[1] =
1550Sstevel@tonic-gate {"^usb$/^ddivs_usbc([0-9]+)$", 1, MATCH_ALL};
1563329Syz147069 static devfsadm_enumerate_t video_rules[1] =
1573329Syz147069 {"^usb$/^video([0-9]+)$", 1, MATCH_ALL};
1580Sstevel@tonic-gate static devfsadm_enumerate_t device_rules[1] =
1590Sstevel@tonic-gate {"^usb$/^device([0-9]+)$", 1, MATCH_ALL};
1600Sstevel@tonic-gate static devfsadm_enumerate_t hid_rules[1] =
1610Sstevel@tonic-gate {"^usb$/^hid([0-9]+)$", 1, MATCH_ALL};
1620Sstevel@tonic-gate static devfsadm_enumerate_t hub_rules[1] =
1630Sstevel@tonic-gate {"^usb$/^hub([0-9]+)$", 1, MATCH_ALL};
1640Sstevel@tonic-gate static devfsadm_enumerate_t mass_storage_rules[1] =
1650Sstevel@tonic-gate {"^usb$/^mass-storage([0-9]+)$", 1, MATCH_ALL};
1660Sstevel@tonic-gate static devfsadm_enumerate_t usbprn_rules[1] =
1670Sstevel@tonic-gate {"^usb$/^printer([0-9]+)$", 1, MATCH_ALL};
1689430SRaymond.Chen@Sun.COM static devfsadm_enumerate_t whost_rules[1] =
1699430SRaymond.Chen@Sun.COM {"^usb$/^whost([0-9]+)$", 1, MATCH_ALL};
1709430SRaymond.Chen@Sun.COM static devfsadm_enumerate_t hwarc_rules[1] =
1719430SRaymond.Chen@Sun.COM {"^usb$/^hwarc([0-9]+)$", 1, MATCH_ALL};
1729430SRaymond.Chen@Sun.COM static devfsadm_enumerate_t wusb_ca_rules[1] =
1739430SRaymond.Chen@Sun.COM {"^usb$/^wusb_ca([0-9]+)$", 1, MATCH_ALL};
1740Sstevel@tonic-gate
1750Sstevel@tonic-gate DEVFSADM_REMOVE_INIT_V0(usb_remove_cbt);
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate int
minor_init(void)1780Sstevel@tonic-gate minor_init(void)
1790Sstevel@tonic-gate {
1800Sstevel@tonic-gate devfsadm_print(debug_mid, "usb_link: minor_init\n");
1810Sstevel@tonic-gate return (DEVFSADM_SUCCESS);
1820Sstevel@tonic-gate }
1830Sstevel@tonic-gate
1840Sstevel@tonic-gate int
minor_fini(void)1850Sstevel@tonic-gate minor_fini(void)
1860Sstevel@tonic-gate {
1870Sstevel@tonic-gate devfsadm_print(debug_mid, "usb_link: minor_fini\n");
1880Sstevel@tonic-gate return (DEVFSADM_SUCCESS);
1890Sstevel@tonic-gate }
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate typedef enum {
1920Sstevel@tonic-gate DRIVER_HUBD = 0,
1930Sstevel@tonic-gate DRIVER_OHCI = 1,
1940Sstevel@tonic-gate DRIVER_EHCI = 2,
1950Sstevel@tonic-gate DRIVER_UHCI = 3,
1960Sstevel@tonic-gate DRIVER_USB_AC = 4,
1970Sstevel@tonic-gate DRIVER_USB_AS = 5,
1980Sstevel@tonic-gate DRIVER_HID = 6,
1990Sstevel@tonic-gate DRIVER_USB_MID = 7,
2000Sstevel@tonic-gate DRIVER_DDIVS_USBC = 8,
2010Sstevel@tonic-gate DRIVER_SCSA2USB = 9,
2020Sstevel@tonic-gate DRIVER_USBPRN = 10,
2030Sstevel@tonic-gate DRIVER_UGEN = 11,
2043329Syz147069 DRIVER_VIDEO = 12,
2059430SRaymond.Chen@Sun.COM DRIVER_HWAHC = 13,
2069430SRaymond.Chen@Sun.COM DRIVER_HWARC = 14,
2079430SRaymond.Chen@Sun.COM DRIVER_WUSB_CA = 15,
2089430SRaymond.Chen@Sun.COM DRIVER_UNKNOWN = 16
2090Sstevel@tonic-gate } driver_defs_t;
2100Sstevel@tonic-gate
2110Sstevel@tonic-gate typedef struct {
2120Sstevel@tonic-gate char *driver_name;
2130Sstevel@tonic-gate int index;
2140Sstevel@tonic-gate } driver_name_table_entry_t;
2150Sstevel@tonic-gate
2160Sstevel@tonic-gate driver_name_table_entry_t driver_name_table[] = {
2170Sstevel@tonic-gate { "hubd", DRIVER_HUBD },
2180Sstevel@tonic-gate { "ohci", DRIVER_OHCI },
2190Sstevel@tonic-gate { "ehci", DRIVER_EHCI },
2200Sstevel@tonic-gate { "uhci", DRIVER_UHCI },
2210Sstevel@tonic-gate { "usb_ac", DRIVER_USB_AC },
2220Sstevel@tonic-gate { "usb_as", DRIVER_USB_AS },
2230Sstevel@tonic-gate { "hid", DRIVER_HID },
2240Sstevel@tonic-gate { "usb_mid", DRIVER_USB_MID },
2250Sstevel@tonic-gate { "ddivs_usbc", DRIVER_DDIVS_USBC },
2260Sstevel@tonic-gate { "scsa2usb", DRIVER_SCSA2USB },
2270Sstevel@tonic-gate { "usbprn", DRIVER_USBPRN },
2280Sstevel@tonic-gate { "ugen", DRIVER_UGEN },
2293329Syz147069 { "usbvc", DRIVER_VIDEO },
2309430SRaymond.Chen@Sun.COM { "hwahc", DRIVER_HWAHC },
2319430SRaymond.Chen@Sun.COM { "hwarc", DRIVER_HWARC },
2329430SRaymond.Chen@Sun.COM { "wusb_ca", DRIVER_WUSB_CA },
2330Sstevel@tonic-gate { NULL, DRIVER_UNKNOWN }
2340Sstevel@tonic-gate };
2350Sstevel@tonic-gate
2360Sstevel@tonic-gate /*
2370Sstevel@tonic-gate * This function is called for every usb minor node.
2380Sstevel@tonic-gate * Calls enumerate to assign a logical usb id, and then
2390Sstevel@tonic-gate * devfsadm_mklink to make the link.
2400Sstevel@tonic-gate */
2410Sstevel@tonic-gate static int
usb_process(di_minor_t minor,di_node_t node)2420Sstevel@tonic-gate usb_process(di_minor_t minor, di_node_t node)
2430Sstevel@tonic-gate {
2440Sstevel@tonic-gate devfsadm_enumerate_t rules[1];
2450Sstevel@tonic-gate char *l_path, *p_path, *buf, *devfspath;
2460Sstevel@tonic-gate char *minor_nm, *drvr_nm, *name = (char *)NULL;
2470Sstevel@tonic-gate int i, index;
2481676Sjpk int flags = 0;
2490Sstevel@tonic-gate int create_secondary_link = 0;
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate minor_nm = di_minor_name(minor);
2520Sstevel@tonic-gate drvr_nm = di_driver_name(node);
2530Sstevel@tonic-gate if ((minor_nm == NULL) || (drvr_nm == NULL)) {
2540Sstevel@tonic-gate return (DEVFSADM_CONTINUE);
2550Sstevel@tonic-gate }
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate devfsadm_print(debug_mid, "usb_process: minor=%s node=%s type=%s\n",
2589430SRaymond.Chen@Sun.COM minor_nm, di_node_name(node), di_minor_nodetype(minor));
2590Sstevel@tonic-gate
2600Sstevel@tonic-gate devfspath = di_devfs_path(node);
2610Sstevel@tonic-gate if (devfspath == NULL) {
2620Sstevel@tonic-gate devfsadm_print(debug_mid,
2630Sstevel@tonic-gate "USB_process: devfspath is NULL\n");
2640Sstevel@tonic-gate return (DEVFSADM_CONTINUE);
2650Sstevel@tonic-gate }
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate l_path = (char *)malloc(PATH_MAX);
2680Sstevel@tonic-gate if (l_path == NULL) {
2690Sstevel@tonic-gate di_devfs_path_free(devfspath);
2700Sstevel@tonic-gate devfsadm_print(debug_mid, "usb_process: malloc() failed\n");
2710Sstevel@tonic-gate return (DEVFSADM_CONTINUE);
2720Sstevel@tonic-gate }
2730Sstevel@tonic-gate
2740Sstevel@tonic-gate p_path = (char *)malloc(PATH_MAX);
2750Sstevel@tonic-gate if (p_path == NULL) {
2760Sstevel@tonic-gate devfsadm_print(debug_mid, "usb_process: malloc() failed\n");
2770Sstevel@tonic-gate di_devfs_path_free(devfspath);
2780Sstevel@tonic-gate free(l_path);
2790Sstevel@tonic-gate return (DEVFSADM_CONTINUE);
2800Sstevel@tonic-gate }
2810Sstevel@tonic-gate
2820Sstevel@tonic-gate (void) strcpy(p_path, devfspath);
2830Sstevel@tonic-gate (void) strcat(p_path, ":");
2840Sstevel@tonic-gate (void) strcat(p_path, minor_nm);
2850Sstevel@tonic-gate di_devfs_path_free(devfspath);
2860Sstevel@tonic-gate
2870Sstevel@tonic-gate devfsadm_print(debug_mid, "usb_process: path %s\n", p_path);
2880Sstevel@tonic-gate
2890Sstevel@tonic-gate for (i = 0; ; i++) {
2900Sstevel@tonic-gate if ((driver_name_table[i].driver_name == NULL) ||
2910Sstevel@tonic-gate (strcmp(drvr_nm, driver_name_table[i].driver_name) == 0)) {
2920Sstevel@tonic-gate index = driver_name_table[i].index;
2930Sstevel@tonic-gate break;
2940Sstevel@tonic-gate }
2950Sstevel@tonic-gate }
2960Sstevel@tonic-gate
2970Sstevel@tonic-gate if (strcmp(di_minor_nodetype(minor), DDI_NT_UGEN) == 0) {
2980Sstevel@tonic-gate ugen_create_link(p_path, minor_nm, node, minor);
2990Sstevel@tonic-gate free(l_path);
3000Sstevel@tonic-gate free(p_path);
3010Sstevel@tonic-gate return (DEVFSADM_CONTINUE);
3020Sstevel@tonic-gate }
3030Sstevel@tonic-gate
3040Sstevel@tonic-gate /* Figure out which rules to apply */
3050Sstevel@tonic-gate switch (index) {
3060Sstevel@tonic-gate case DRIVER_HUBD:
3070Sstevel@tonic-gate case DRIVER_OHCI:
3080Sstevel@tonic-gate case DRIVER_EHCI:
3090Sstevel@tonic-gate case DRIVER_UHCI:
3100Sstevel@tonic-gate rules[0] = hub_rules[0]; /* For HUBs */
3110Sstevel@tonic-gate name = "hub";
3120Sstevel@tonic-gate
3130Sstevel@tonic-gate break;
3140Sstevel@tonic-gate case DRIVER_USB_AC:
3150Sstevel@tonic-gate if (strcmp(minor_nm, "sound,audio") == 0) {
3160Sstevel@tonic-gate rules[0] = audio_rules[0];
3170Sstevel@tonic-gate name = "audio"; /* For audio */
3180Sstevel@tonic-gate create_secondary_link = 1;
3190Sstevel@tonic-gate } else if (strcmp(minor_nm, "sound,audioctl") == 0) {
3200Sstevel@tonic-gate rules[0] = audio_control_rules[0];
3210Sstevel@tonic-gate name = "audio-control"; /* For audio */
3220Sstevel@tonic-gate create_secondary_link = 1;
3230Sstevel@tonic-gate } else if (strcmp(minor_nm, "mux") == 0) {
3240Sstevel@tonic-gate rules[0] = audio_mux_rules[0];
3250Sstevel@tonic-gate name = "audio-mux"; /* For audio */
3260Sstevel@tonic-gate } else {
3270Sstevel@tonic-gate free(l_path);
3280Sstevel@tonic-gate free(p_path);
3290Sstevel@tonic-gate return (DEVFSADM_CONTINUE);
3300Sstevel@tonic-gate }
3310Sstevel@tonic-gate break;
3320Sstevel@tonic-gate case DRIVER_USB_AS:
3330Sstevel@tonic-gate rules[0] = audio_stream_rules[0];
3340Sstevel@tonic-gate name = "audio-stream"; /* For audio */
3350Sstevel@tonic-gate break;
3363329Syz147069 case DRIVER_VIDEO:
3373329Syz147069 rules[0] = video_rules[0];
3383329Syz147069 name = "video"; /* For video */
3393329Syz147069 create_secondary_link = 1;
3403329Syz147069 break;
3410Sstevel@tonic-gate case DRIVER_HID:
3420Sstevel@tonic-gate rules[0] = hid_rules[0];
3430Sstevel@tonic-gate name = "hid"; /* For HIDs */
3440Sstevel@tonic-gate break;
3450Sstevel@tonic-gate case DRIVER_USB_MID:
3460Sstevel@tonic-gate rules[0] = device_rules[0];
3470Sstevel@tonic-gate name = "device"; /* For other USB devices */
3480Sstevel@tonic-gate break;
3490Sstevel@tonic-gate case DRIVER_DDIVS_USBC:
3500Sstevel@tonic-gate rules[0] = ddivs_usbc_rules[0];
3510Sstevel@tonic-gate name = "device"; /* For other USB devices */
3520Sstevel@tonic-gate break;
3530Sstevel@tonic-gate case DRIVER_SCSA2USB:
3540Sstevel@tonic-gate rules[0] = mass_storage_rules[0];
3550Sstevel@tonic-gate name = "mass-storage"; /* For mass-storage devices */
3560Sstevel@tonic-gate break;
3570Sstevel@tonic-gate case DRIVER_USBPRN:
3580Sstevel@tonic-gate rules[0] = usbprn_rules[0];
3590Sstevel@tonic-gate name = "printer";
3600Sstevel@tonic-gate break;
3619430SRaymond.Chen@Sun.COM case DRIVER_HWAHC:
3629430SRaymond.Chen@Sun.COM if (strcmp(minor_nm, "hwahc") == 0) {
3639430SRaymond.Chen@Sun.COM rules[0] = whost_rules[0];
3649430SRaymond.Chen@Sun.COM name = "whost"; /* For HWA HC */
3659430SRaymond.Chen@Sun.COM } else if (strcmp(minor_nm, "hubd") == 0) {
3669430SRaymond.Chen@Sun.COM rules[0] = hub_rules[0];
3679430SRaymond.Chen@Sun.COM name = "hub"; /* For HWA HC */
3689430SRaymond.Chen@Sun.COM } else {
3699430SRaymond.Chen@Sun.COM free(l_path);
3709430SRaymond.Chen@Sun.COM free(p_path);
3719430SRaymond.Chen@Sun.COM return (DEVFSADM_CONTINUE);
3729430SRaymond.Chen@Sun.COM }
3739430SRaymond.Chen@Sun.COM break;
3749430SRaymond.Chen@Sun.COM case DRIVER_HWARC:
3759430SRaymond.Chen@Sun.COM rules[0] = hwarc_rules[0];
3769430SRaymond.Chen@Sun.COM name = "hwarc"; /* For UWB HWA Radio Controllers */
3779430SRaymond.Chen@Sun.COM break;
3789430SRaymond.Chen@Sun.COM case DRIVER_WUSB_CA:
3799430SRaymond.Chen@Sun.COM rules[0] = wusb_ca_rules[0];
3809430SRaymond.Chen@Sun.COM name = "wusb_ca"; /* for wusb cable association */
3819430SRaymond.Chen@Sun.COM break;
3820Sstevel@tonic-gate default:
3830Sstevel@tonic-gate devfsadm_print(debug_mid, "usb_process: unknown driver=%s\n",
3840Sstevel@tonic-gate drvr_nm);
3850Sstevel@tonic-gate free(l_path);
3860Sstevel@tonic-gate free(p_path);
3870Sstevel@tonic-gate return (DEVFSADM_CONTINUE);
3880Sstevel@tonic-gate }
3890Sstevel@tonic-gate
3900Sstevel@tonic-gate /*
3910Sstevel@tonic-gate * build the physical path from the components.
3920Sstevel@tonic-gate * find the logical usb id, and stuff it in buf
3930Sstevel@tonic-gate */
3940Sstevel@tonic-gate if (devfsadm_enumerate_int(p_path, 0, &buf, rules, 1)) {
3950Sstevel@tonic-gate devfsadm_print(debug_mid, "usb_process: exit/continue\n");
3960Sstevel@tonic-gate free(l_path);
3970Sstevel@tonic-gate free(p_path);
3980Sstevel@tonic-gate return (DEVFSADM_CONTINUE);
3990Sstevel@tonic-gate }
4000Sstevel@tonic-gate
4010Sstevel@tonic-gate (void) snprintf(l_path, PATH_MAX, "usb/%s%s", name, buf);
4020Sstevel@tonic-gate
4030Sstevel@tonic-gate devfsadm_print(debug_mid, "usb_process: p_path=%s buf=%s\n",
4040Sstevel@tonic-gate p_path, buf);
4050Sstevel@tonic-gate
4060Sstevel@tonic-gate free(buf);
4070Sstevel@tonic-gate
4080Sstevel@tonic-gate devfsadm_print(debug_mid, "mklink %s -> %s\n", l_path, p_path);
4090Sstevel@tonic-gate
4101676Sjpk (void) devfsadm_mklink(l_path, node, minor, flags);
4110Sstevel@tonic-gate
4120Sstevel@tonic-gate if (create_secondary_link) {
4130Sstevel@tonic-gate /*
4140Sstevel@tonic-gate * Create secondary links to make newly hotplugged
4150Sstevel@tonic-gate * usb audio device the primary device.
4160Sstevel@tonic-gate */
4170Sstevel@tonic-gate if (strcmp(name, "audio") == 0) {
4180Sstevel@tonic-gate (void) devfsadm_secondary_link("audio", l_path, 0);
4190Sstevel@tonic-gate } else if (strcmp(name, "audio-control") == 0) {
4200Sstevel@tonic-gate (void) devfsadm_secondary_link("audioctl", l_path, 0);
4213329Syz147069 } else if (strcmp(name, "video") == 0) {
4223329Syz147069 (void) devfsadm_secondary_link(l_path + 4, l_path, 0);
4230Sstevel@tonic-gate }
4240Sstevel@tonic-gate }
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate free(p_path);
4270Sstevel@tonic-gate free(l_path);
4280Sstevel@tonic-gate
4290Sstevel@tonic-gate return (DEVFSADM_CONTINUE);
4300Sstevel@tonic-gate }
4310Sstevel@tonic-gate
4320Sstevel@tonic-gate static void
ugen_create_link(char * p_path,char * node_name,di_node_t node,di_minor_t minor)4330Sstevel@tonic-gate ugen_create_link(char *p_path, char *node_name,
4340Sstevel@tonic-gate di_node_t node, di_minor_t minor)
4350Sstevel@tonic-gate {
4360Sstevel@tonic-gate char *buf, s[MAXPATHLEN];
4370Sstevel@tonic-gate char *lasts = s;
4380Sstevel@tonic-gate char *vid, *pid;
4390Sstevel@tonic-gate char *minor_name;
4400Sstevel@tonic-gate char ugen_RE[128];
4410Sstevel@tonic-gate devfsadm_enumerate_t ugen_rules[1];
4420Sstevel@tonic-gate char l_path[PATH_MAX];
4431676Sjpk int flags = 0;
4440Sstevel@tonic-gate
4450Sstevel@tonic-gate devfsadm_print(debug_mid, "ugen_create_link: p_path=%s name=%s\n",
4460Sstevel@tonic-gate p_path, node_name);
4470Sstevel@tonic-gate
4480Sstevel@tonic-gate (void) strlcpy(s, node_name, sizeof (s));
4490Sstevel@tonic-gate
4500Sstevel@tonic-gate /* get vid, pid and minor name strings */
4510Sstevel@tonic-gate vid = strtok_r(lasts, ".", &lasts);
4520Sstevel@tonic-gate pid = strtok_r(NULL, ".", &lasts);
4530Sstevel@tonic-gate minor_name = lasts;
4540Sstevel@tonic-gate
4550Sstevel@tonic-gate if ((vid == NULL) || (pid == NULL) || (minor_name == NULL)) {
4560Sstevel@tonic-gate return;
4570Sstevel@tonic-gate }
4580Sstevel@tonic-gate
4590Sstevel@tonic-gate /* create regular expression contain vid and pid */
4600Sstevel@tonic-gate (void) snprintf(ugen_RE, sizeof (ugen_RE),
4610Sstevel@tonic-gate "^usb$/^%s\\.%s$/^([0-9]+)$", vid, pid);
4620Sstevel@tonic-gate devfsadm_print(debug_mid,
4630Sstevel@tonic-gate "ugen_create_link: ugen_RE=%s minor_name=%s\n",
4640Sstevel@tonic-gate ugen_RE, minor_name);
4650Sstevel@tonic-gate
4660Sstevel@tonic-gate bzero(ugen_rules, sizeof (ugen_rules));
4670Sstevel@tonic-gate
4680Sstevel@tonic-gate ugen_rules[0].re = ugen_RE;
4690Sstevel@tonic-gate ugen_rules[0].subexp = 1;
4700Sstevel@tonic-gate ugen_rules[0].flags = MATCH_ADDR;
4710Sstevel@tonic-gate
4720Sstevel@tonic-gate /*
4730Sstevel@tonic-gate * build the physical path from the components.
4740Sstevel@tonic-gate * find the logical usb id, and stuff it in buf
4750Sstevel@tonic-gate */
4760Sstevel@tonic-gate if (devfsadm_enumerate_int(p_path, 0, &buf, ugen_rules, 1)) {
4770Sstevel@tonic-gate devfsadm_print(debug_mid, "ugen_create_link: exit/continue\n");
4780Sstevel@tonic-gate return;
4790Sstevel@tonic-gate }
4800Sstevel@tonic-gate
4810Sstevel@tonic-gate (void) snprintf(l_path, sizeof (l_path), "usb/%s.%s/%s/%s",
4820Sstevel@tonic-gate vid, pid, buf, minor_name);
4830Sstevel@tonic-gate
4840Sstevel@tonic-gate devfsadm_print(debug_mid, "mklink %s -> %s\n", l_path, p_path);
4850Sstevel@tonic-gate
4861676Sjpk (void) devfsadm_mklink(l_path, node, minor, flags);
4870Sstevel@tonic-gate
4880Sstevel@tonic-gate free(buf);
4890Sstevel@tonic-gate }
490