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