1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate * 22*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 23*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 24*7c478bd9Sstevel@tonic-gate */ 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate #include <devfsadm.h> 29*7c478bd9Sstevel@tonic-gate #include <stdio.h> 30*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 31*7c478bd9Sstevel@tonic-gate #include <limits.h> 32*7c478bd9Sstevel@tonic-gate #include <string.h> 33*7c478bd9Sstevel@tonic-gate #include <unistd.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 36*7c478bd9Sstevel@tonic-gate #include <strings.h> 37*7c478bd9Sstevel@tonic-gate 38*7c478bd9Sstevel@tonic-gate extern char *devfsadm_get_devices_dir(); 39*7c478bd9Sstevel@tonic-gate static int usb_process(di_minor_t minor, di_node_t node); 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate static void ugen_create_link(char *p_path, char *node_name, 42*7c478bd9Sstevel@tonic-gate di_node_t node, di_minor_t minor); 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate /* Rules for creating links */ 46*7c478bd9Sstevel@tonic-gate static devfsadm_create_t usb_cbt[] = { 47*7c478bd9Sstevel@tonic-gate { "usb", NULL, "usb_ac", DRV_EXACT, 48*7c478bd9Sstevel@tonic-gate ILEVEL_0, usb_process }, 49*7c478bd9Sstevel@tonic-gate { "usb", NULL, "usb_as", DRV_EXACT, 50*7c478bd9Sstevel@tonic-gate ILEVEL_0, usb_process }, 51*7c478bd9Sstevel@tonic-gate { "usb", NULL, "ddivs_usbc", DRV_EXACT, 52*7c478bd9Sstevel@tonic-gate ILEVEL_0, usb_process }, 53*7c478bd9Sstevel@tonic-gate { "usb", NULL, "hid", DRV_EXACT, 54*7c478bd9Sstevel@tonic-gate ILEVEL_0, usb_process }, 55*7c478bd9Sstevel@tonic-gate { "usb", DDI_NT_NEXUS, "hubd", DRV_EXACT|TYPE_EXACT, 56*7c478bd9Sstevel@tonic-gate ILEVEL_0, usb_process }, 57*7c478bd9Sstevel@tonic-gate { "usb", DDI_NT_NEXUS, "ohci", DRV_EXACT|TYPE_EXACT, 58*7c478bd9Sstevel@tonic-gate ILEVEL_0, usb_process }, 59*7c478bd9Sstevel@tonic-gate { "usb", DDI_NT_NEXUS, "ehci", DRV_EXACT|TYPE_EXACT, 60*7c478bd9Sstevel@tonic-gate ILEVEL_0, usb_process }, 61*7c478bd9Sstevel@tonic-gate { "usb", DDI_NT_SCSI_NEXUS, "scsa2usb", DRV_EXACT|TYPE_EXACT, 62*7c478bd9Sstevel@tonic-gate ILEVEL_0, usb_process }, 63*7c478bd9Sstevel@tonic-gate { "usb", DDI_NT_UGEN, "scsa2usb", DRV_EXACT|TYPE_EXACT, 64*7c478bd9Sstevel@tonic-gate ILEVEL_0, usb_process }, 65*7c478bd9Sstevel@tonic-gate { "usb", DDI_NT_NEXUS, "uhci", DRV_EXACT|TYPE_EXACT, 66*7c478bd9Sstevel@tonic-gate ILEVEL_0, usb_process }, 67*7c478bd9Sstevel@tonic-gate { "usb", DDI_NT_UGEN, "ugen", DRV_EXACT|TYPE_EXACT, 68*7c478bd9Sstevel@tonic-gate ILEVEL_0, usb_process }, 69*7c478bd9Sstevel@tonic-gate { "usb", DDI_NT_NEXUS, "usb_mid", DRV_EXACT|TYPE_EXACT, 70*7c478bd9Sstevel@tonic-gate ILEVEL_0, usb_process }, 71*7c478bd9Sstevel@tonic-gate { "usb", DDI_NT_UGEN, "usb_mid", DRV_EXACT|TYPE_EXACT, 72*7c478bd9Sstevel@tonic-gate ILEVEL_0, usb_process }, 73*7c478bd9Sstevel@tonic-gate { "usb", DDI_NT_PRINTER, "usbprn", DRV_EXACT|TYPE_EXACT, 74*7c478bd9Sstevel@tonic-gate ILEVEL_0, usb_process }, 75*7c478bd9Sstevel@tonic-gate { "usb", DDI_NT_UGEN, "usbprn", DRV_EXACT|TYPE_EXACT, 76*7c478bd9Sstevel@tonic-gate ILEVEL_0, usb_process }, 77*7c478bd9Sstevel@tonic-gate }; 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate /* For debug printing (-V filter) */ 80*7c478bd9Sstevel@tonic-gate static char *debug_mid = "usb_mid"; 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate DEVFSADM_CREATE_INIT_V0(usb_cbt); 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate /* USB device links */ 85*7c478bd9Sstevel@tonic-gate #define USB_LINK_RE_AUDIO "^usb/audio[0-9]+$" 86*7c478bd9Sstevel@tonic-gate #define USB_LINK_RE_AUDIOMUX "^usb/audio-mux[0-9]+$" 87*7c478bd9Sstevel@tonic-gate #define USB_LINK_RE_AUDIOCTL "^usb/audio-control[0-9]+$" 88*7c478bd9Sstevel@tonic-gate #define USB_LINK_RE_AUDIOSTREAM "^usb/audio-stream[0-9]+$" 89*7c478bd9Sstevel@tonic-gate #define USB_LINK_RE_DDIVS_USBC "^usb/ddivs_usbc[0-9]+$" 90*7c478bd9Sstevel@tonic-gate #define USB_LINK_RE_DEVICE "^usb/device[0-9]+$" 91*7c478bd9Sstevel@tonic-gate #define USB_LINK_RE_HID "^usb/hid[0-9]+$" 92*7c478bd9Sstevel@tonic-gate #define USB_LINK_RE_HUB "^usb/hub[0-9]+$" 93*7c478bd9Sstevel@tonic-gate #define USB_LINK_RE_MASS_STORE "^usb/mass-storage[0-9]+$" 94*7c478bd9Sstevel@tonic-gate #define USB_LINK_RE_UGEN "^usb/[0-9,a-f]+\\.[0-9,a-f]+/[0-9]+/.+$" 95*7c478bd9Sstevel@tonic-gate #define USB_LINK_RE_USBPRN "^usb/printer[0-9]+$" 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate /* Rules for removing links */ 98*7c478bd9Sstevel@tonic-gate static devfsadm_remove_t usb_remove_cbt[] = { 99*7c478bd9Sstevel@tonic-gate { "usb", USB_LINK_RE_AUDIO, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0, 100*7c478bd9Sstevel@tonic-gate devfsadm_rm_all }, 101*7c478bd9Sstevel@tonic-gate { "usb", USB_LINK_RE_AUDIOMUX, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0, 102*7c478bd9Sstevel@tonic-gate devfsadm_rm_all }, 103*7c478bd9Sstevel@tonic-gate { "usb", USB_LINK_RE_AUDIOCTL, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0, 104*7c478bd9Sstevel@tonic-gate devfsadm_rm_all }, 105*7c478bd9Sstevel@tonic-gate { "usb", USB_LINK_RE_AUDIOSTREAM, RM_POST | RM_HOT | RM_ALWAYS, 106*7c478bd9Sstevel@tonic-gate ILEVEL_0, devfsadm_rm_all }, 107*7c478bd9Sstevel@tonic-gate { "usb", USB_LINK_RE_DDIVS_USBC, RM_POST | RM_HOT | RM_ALWAYS, 108*7c478bd9Sstevel@tonic-gate ILEVEL_0, devfsadm_rm_all }, 109*7c478bd9Sstevel@tonic-gate { "usb", USB_LINK_RE_DEVICE, RM_POST | RM_HOT, ILEVEL_0, 110*7c478bd9Sstevel@tonic-gate devfsadm_rm_all }, 111*7c478bd9Sstevel@tonic-gate { "usb", USB_LINK_RE_HID, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0, 112*7c478bd9Sstevel@tonic-gate devfsadm_rm_all }, 113*7c478bd9Sstevel@tonic-gate { "usb", USB_LINK_RE_HUB, RM_POST | RM_HOT, ILEVEL_0, devfsadm_rm_all }, 114*7c478bd9Sstevel@tonic-gate { "usb", USB_LINK_RE_MASS_STORE, RM_POST | RM_HOT | RM_ALWAYS, 115*7c478bd9Sstevel@tonic-gate ILEVEL_0, devfsadm_rm_all }, 116*7c478bd9Sstevel@tonic-gate { "usb", USB_LINK_RE_UGEN, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0, 117*7c478bd9Sstevel@tonic-gate devfsadm_rm_all }, 118*7c478bd9Sstevel@tonic-gate { "usb", USB_LINK_RE_USBPRN, RM_POST | RM_HOT | RM_ALWAYS, ILEVEL_0, 119*7c478bd9Sstevel@tonic-gate devfsadm_rm_link }, 120*7c478bd9Sstevel@tonic-gate }; 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate /* 123*7c478bd9Sstevel@tonic-gate * Rules for different USB devices except ugen which is dynamically 124*7c478bd9Sstevel@tonic-gate * created 125*7c478bd9Sstevel@tonic-gate */ 126*7c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t audio_rules[1] = 127*7c478bd9Sstevel@tonic-gate {"^usb$/^audio([0-9]+)$", 1, MATCH_ALL}; 128*7c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t audio_mux_rules[1] = 129*7c478bd9Sstevel@tonic-gate {"^usb$/^audio-mux([0-9]+)$", 1, MATCH_ALL}; 130*7c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t audio_control_rules[1] = 131*7c478bd9Sstevel@tonic-gate {"^usb$/^audio-control([0-9]+)$", 1, MATCH_ALL}; 132*7c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t audio_stream_rules[1] = 133*7c478bd9Sstevel@tonic-gate {"^usb$/^audio-stream([0-9]+)$", 1, MATCH_ALL}; 134*7c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t ddivs_usbc_rules[1] = 135*7c478bd9Sstevel@tonic-gate {"^usb$/^ddivs_usbc([0-9]+)$", 1, MATCH_ALL}; 136*7c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t device_rules[1] = 137*7c478bd9Sstevel@tonic-gate {"^usb$/^device([0-9]+)$", 1, MATCH_ALL}; 138*7c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t hid_rules[1] = 139*7c478bd9Sstevel@tonic-gate {"^usb$/^hid([0-9]+)$", 1, MATCH_ALL}; 140*7c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t hub_rules[1] = 141*7c478bd9Sstevel@tonic-gate {"^usb$/^hub([0-9]+)$", 1, MATCH_ALL}; 142*7c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t mass_storage_rules[1] = 143*7c478bd9Sstevel@tonic-gate {"^usb$/^mass-storage([0-9]+)$", 1, MATCH_ALL}; 144*7c478bd9Sstevel@tonic-gate static devfsadm_enumerate_t usbprn_rules[1] = 145*7c478bd9Sstevel@tonic-gate {"^usb$/^printer([0-9]+)$", 1, MATCH_ALL}; 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate DEVFSADM_REMOVE_INIT_V0(usb_remove_cbt); 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate int 150*7c478bd9Sstevel@tonic-gate minor_init(void) 151*7c478bd9Sstevel@tonic-gate { 152*7c478bd9Sstevel@tonic-gate devfsadm_print(debug_mid, "usb_link: minor_init\n"); 153*7c478bd9Sstevel@tonic-gate return (DEVFSADM_SUCCESS); 154*7c478bd9Sstevel@tonic-gate } 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate int 157*7c478bd9Sstevel@tonic-gate minor_fini(void) 158*7c478bd9Sstevel@tonic-gate { 159*7c478bd9Sstevel@tonic-gate devfsadm_print(debug_mid, "usb_link: minor_fini\n"); 160*7c478bd9Sstevel@tonic-gate return (DEVFSADM_SUCCESS); 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate typedef enum { 164*7c478bd9Sstevel@tonic-gate DRIVER_HUBD = 0, 165*7c478bd9Sstevel@tonic-gate DRIVER_OHCI = 1, 166*7c478bd9Sstevel@tonic-gate DRIVER_EHCI = 2, 167*7c478bd9Sstevel@tonic-gate DRIVER_UHCI = 3, 168*7c478bd9Sstevel@tonic-gate DRIVER_USB_AC = 4, 169*7c478bd9Sstevel@tonic-gate DRIVER_USB_AS = 5, 170*7c478bd9Sstevel@tonic-gate DRIVER_HID = 6, 171*7c478bd9Sstevel@tonic-gate DRIVER_USB_MID = 7, 172*7c478bd9Sstevel@tonic-gate DRIVER_DDIVS_USBC = 8, 173*7c478bd9Sstevel@tonic-gate DRIVER_SCSA2USB = 9, 174*7c478bd9Sstevel@tonic-gate DRIVER_USBPRN = 10, 175*7c478bd9Sstevel@tonic-gate DRIVER_UGEN = 11, 176*7c478bd9Sstevel@tonic-gate DRIVER_UNKNOWN = 12 177*7c478bd9Sstevel@tonic-gate } driver_defs_t; 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate typedef struct { 180*7c478bd9Sstevel@tonic-gate char *driver_name; 181*7c478bd9Sstevel@tonic-gate int index; 182*7c478bd9Sstevel@tonic-gate } driver_name_table_entry_t; 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate driver_name_table_entry_t driver_name_table[] = { 185*7c478bd9Sstevel@tonic-gate { "hubd", DRIVER_HUBD }, 186*7c478bd9Sstevel@tonic-gate { "ohci", DRIVER_OHCI }, 187*7c478bd9Sstevel@tonic-gate { "ehci", DRIVER_EHCI }, 188*7c478bd9Sstevel@tonic-gate { "uhci", DRIVER_UHCI }, 189*7c478bd9Sstevel@tonic-gate { "usb_ac", DRIVER_USB_AC }, 190*7c478bd9Sstevel@tonic-gate { "usb_as", DRIVER_USB_AS }, 191*7c478bd9Sstevel@tonic-gate { "hid", DRIVER_HID }, 192*7c478bd9Sstevel@tonic-gate { "usb_mid", DRIVER_USB_MID }, 193*7c478bd9Sstevel@tonic-gate { "ddivs_usbc", DRIVER_DDIVS_USBC }, 194*7c478bd9Sstevel@tonic-gate { "scsa2usb", DRIVER_SCSA2USB }, 195*7c478bd9Sstevel@tonic-gate { "usbprn", DRIVER_USBPRN }, 196*7c478bd9Sstevel@tonic-gate { "ugen", DRIVER_UGEN }, 197*7c478bd9Sstevel@tonic-gate { NULL, DRIVER_UNKNOWN } 198*7c478bd9Sstevel@tonic-gate }; 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate /* 202*7c478bd9Sstevel@tonic-gate * This function is called for every usb minor node. 203*7c478bd9Sstevel@tonic-gate * Calls enumerate to assign a logical usb id, and then 204*7c478bd9Sstevel@tonic-gate * devfsadm_mklink to make the link. 205*7c478bd9Sstevel@tonic-gate */ 206*7c478bd9Sstevel@tonic-gate static int 207*7c478bd9Sstevel@tonic-gate usb_process(di_minor_t minor, di_node_t node) 208*7c478bd9Sstevel@tonic-gate { 209*7c478bd9Sstevel@tonic-gate devfsadm_enumerate_t rules[1]; 210*7c478bd9Sstevel@tonic-gate char *l_path, *p_path, *buf, *devfspath; 211*7c478bd9Sstevel@tonic-gate char *minor_nm, *drvr_nm, *name = (char *)NULL; 212*7c478bd9Sstevel@tonic-gate int i, index; 213*7c478bd9Sstevel@tonic-gate int create_secondary_link = 0; 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate minor_nm = di_minor_name(minor); 216*7c478bd9Sstevel@tonic-gate drvr_nm = di_driver_name(node); 217*7c478bd9Sstevel@tonic-gate if ((minor_nm == NULL) || (drvr_nm == NULL)) { 218*7c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 219*7c478bd9Sstevel@tonic-gate } 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate devfsadm_print(debug_mid, "usb_process: minor=%s node=%s type=%s\n", 222*7c478bd9Sstevel@tonic-gate minor_nm, di_node_name(node), di_minor_nodetype(minor)); 223*7c478bd9Sstevel@tonic-gate 224*7c478bd9Sstevel@tonic-gate devfspath = di_devfs_path(node); 225*7c478bd9Sstevel@tonic-gate if (devfspath == NULL) { 226*7c478bd9Sstevel@tonic-gate devfsadm_print(debug_mid, 227*7c478bd9Sstevel@tonic-gate "USB_process: devfspath is NULL\n"); 228*7c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 229*7c478bd9Sstevel@tonic-gate } 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate l_path = (char *)malloc(PATH_MAX); 232*7c478bd9Sstevel@tonic-gate if (l_path == NULL) { 233*7c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 234*7c478bd9Sstevel@tonic-gate devfsadm_print(debug_mid, "usb_process: malloc() failed\n"); 235*7c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 236*7c478bd9Sstevel@tonic-gate } 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate p_path = (char *)malloc(PATH_MAX); 239*7c478bd9Sstevel@tonic-gate if (p_path == NULL) { 240*7c478bd9Sstevel@tonic-gate devfsadm_print(debug_mid, "usb_process: malloc() failed\n"); 241*7c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 242*7c478bd9Sstevel@tonic-gate free(l_path); 243*7c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate (void) strcpy(p_path, devfspath); 247*7c478bd9Sstevel@tonic-gate (void) strcat(p_path, ":"); 248*7c478bd9Sstevel@tonic-gate (void) strcat(p_path, minor_nm); 249*7c478bd9Sstevel@tonic-gate di_devfs_path_free(devfspath); 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate devfsadm_print(debug_mid, "usb_process: path %s\n", p_path); 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate for (i = 0; ; i++) { 254*7c478bd9Sstevel@tonic-gate if ((driver_name_table[i].driver_name == NULL) || 255*7c478bd9Sstevel@tonic-gate (strcmp(drvr_nm, driver_name_table[i].driver_name) == 0)) { 256*7c478bd9Sstevel@tonic-gate index = driver_name_table[i].index; 257*7c478bd9Sstevel@tonic-gate break; 258*7c478bd9Sstevel@tonic-gate } 259*7c478bd9Sstevel@tonic-gate } 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate if (strcmp(di_minor_nodetype(minor), DDI_NT_UGEN) == 0) { 262*7c478bd9Sstevel@tonic-gate ugen_create_link(p_path, minor_nm, node, minor); 263*7c478bd9Sstevel@tonic-gate free(l_path); 264*7c478bd9Sstevel@tonic-gate free(p_path); 265*7c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 266*7c478bd9Sstevel@tonic-gate } 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate /* Figure out which rules to apply */ 269*7c478bd9Sstevel@tonic-gate switch (index) { 270*7c478bd9Sstevel@tonic-gate case DRIVER_HUBD: 271*7c478bd9Sstevel@tonic-gate case DRIVER_OHCI: 272*7c478bd9Sstevel@tonic-gate case DRIVER_EHCI: 273*7c478bd9Sstevel@tonic-gate case DRIVER_UHCI: 274*7c478bd9Sstevel@tonic-gate rules[0] = hub_rules[0]; /* For HUBs */ 275*7c478bd9Sstevel@tonic-gate name = "hub"; 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate break; 278*7c478bd9Sstevel@tonic-gate case DRIVER_USB_AC: 279*7c478bd9Sstevel@tonic-gate if (strcmp(minor_nm, "sound,audio") == 0) { 280*7c478bd9Sstevel@tonic-gate rules[0] = audio_rules[0]; 281*7c478bd9Sstevel@tonic-gate name = "audio"; /* For audio */ 282*7c478bd9Sstevel@tonic-gate create_secondary_link = 1; 283*7c478bd9Sstevel@tonic-gate } else if (strcmp(minor_nm, "sound,audioctl") == 0) { 284*7c478bd9Sstevel@tonic-gate rules[0] = audio_control_rules[0]; 285*7c478bd9Sstevel@tonic-gate name = "audio-control"; /* For audio */ 286*7c478bd9Sstevel@tonic-gate create_secondary_link = 1; 287*7c478bd9Sstevel@tonic-gate } else if (strcmp(minor_nm, "mux") == 0) { 288*7c478bd9Sstevel@tonic-gate rules[0] = audio_mux_rules[0]; 289*7c478bd9Sstevel@tonic-gate name = "audio-mux"; /* For audio */ 290*7c478bd9Sstevel@tonic-gate } else { 291*7c478bd9Sstevel@tonic-gate free(l_path); 292*7c478bd9Sstevel@tonic-gate free(p_path); 293*7c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 294*7c478bd9Sstevel@tonic-gate } 295*7c478bd9Sstevel@tonic-gate break; 296*7c478bd9Sstevel@tonic-gate case DRIVER_USB_AS: 297*7c478bd9Sstevel@tonic-gate rules[0] = audio_stream_rules[0]; 298*7c478bd9Sstevel@tonic-gate name = "audio-stream"; /* For audio */ 299*7c478bd9Sstevel@tonic-gate break; 300*7c478bd9Sstevel@tonic-gate case DRIVER_HID: 301*7c478bd9Sstevel@tonic-gate rules[0] = hid_rules[0]; 302*7c478bd9Sstevel@tonic-gate name = "hid"; /* For HIDs */ 303*7c478bd9Sstevel@tonic-gate break; 304*7c478bd9Sstevel@tonic-gate case DRIVER_USB_MID: 305*7c478bd9Sstevel@tonic-gate rules[0] = device_rules[0]; 306*7c478bd9Sstevel@tonic-gate name = "device"; /* For other USB devices */ 307*7c478bd9Sstevel@tonic-gate break; 308*7c478bd9Sstevel@tonic-gate case DRIVER_DDIVS_USBC: 309*7c478bd9Sstevel@tonic-gate rules[0] = ddivs_usbc_rules[0]; 310*7c478bd9Sstevel@tonic-gate name = "device"; /* For other USB devices */ 311*7c478bd9Sstevel@tonic-gate break; 312*7c478bd9Sstevel@tonic-gate case DRIVER_SCSA2USB: 313*7c478bd9Sstevel@tonic-gate rules[0] = mass_storage_rules[0]; 314*7c478bd9Sstevel@tonic-gate name = "mass-storage"; /* For mass-storage devices */ 315*7c478bd9Sstevel@tonic-gate break; 316*7c478bd9Sstevel@tonic-gate case DRIVER_USBPRN: 317*7c478bd9Sstevel@tonic-gate rules[0] = usbprn_rules[0]; 318*7c478bd9Sstevel@tonic-gate name = "printer"; 319*7c478bd9Sstevel@tonic-gate break; 320*7c478bd9Sstevel@tonic-gate default: 321*7c478bd9Sstevel@tonic-gate devfsadm_print(debug_mid, "usb_process: unknown driver=%s\n", 322*7c478bd9Sstevel@tonic-gate drvr_nm); 323*7c478bd9Sstevel@tonic-gate free(l_path); 324*7c478bd9Sstevel@tonic-gate free(p_path); 325*7c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 326*7c478bd9Sstevel@tonic-gate } 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate /* 329*7c478bd9Sstevel@tonic-gate * build the physical path from the components. 330*7c478bd9Sstevel@tonic-gate * find the logical usb id, and stuff it in buf 331*7c478bd9Sstevel@tonic-gate */ 332*7c478bd9Sstevel@tonic-gate if (devfsadm_enumerate_int(p_path, 0, &buf, rules, 1)) { 333*7c478bd9Sstevel@tonic-gate devfsadm_print(debug_mid, "usb_process: exit/continue\n"); 334*7c478bd9Sstevel@tonic-gate free(l_path); 335*7c478bd9Sstevel@tonic-gate free(p_path); 336*7c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate (void) snprintf(l_path, PATH_MAX, "usb/%s%s", name, buf); 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate devfsadm_print(debug_mid, "usb_process: p_path=%s buf=%s\n", 342*7c478bd9Sstevel@tonic-gate p_path, buf); 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate free(buf); 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate devfsadm_print(debug_mid, "mklink %s -> %s\n", l_path, p_path); 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate (void) devfsadm_mklink(l_path, node, minor, 0); 349*7c478bd9Sstevel@tonic-gate 350*7c478bd9Sstevel@tonic-gate if (create_secondary_link) { 351*7c478bd9Sstevel@tonic-gate /* 352*7c478bd9Sstevel@tonic-gate * Create secondary links to make newly hotplugged 353*7c478bd9Sstevel@tonic-gate * usb audio device the primary device. 354*7c478bd9Sstevel@tonic-gate */ 355*7c478bd9Sstevel@tonic-gate if (strcmp(name, "audio") == 0) { 356*7c478bd9Sstevel@tonic-gate (void) devfsadm_secondary_link("audio", l_path, 0); 357*7c478bd9Sstevel@tonic-gate } else if (strcmp(name, "audio-control") == 0) { 358*7c478bd9Sstevel@tonic-gate (void) devfsadm_secondary_link("audioctl", l_path, 0); 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate } 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate free(p_path); 363*7c478bd9Sstevel@tonic-gate free(l_path); 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate return (DEVFSADM_CONTINUE); 366*7c478bd9Sstevel@tonic-gate } 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate static void 369*7c478bd9Sstevel@tonic-gate ugen_create_link(char *p_path, char *node_name, 370*7c478bd9Sstevel@tonic-gate di_node_t node, di_minor_t minor) 371*7c478bd9Sstevel@tonic-gate { 372*7c478bd9Sstevel@tonic-gate char *buf, s[MAXPATHLEN]; 373*7c478bd9Sstevel@tonic-gate char *lasts = s; 374*7c478bd9Sstevel@tonic-gate char *vid, *pid; 375*7c478bd9Sstevel@tonic-gate char *minor_name; 376*7c478bd9Sstevel@tonic-gate char ugen_RE[128]; 377*7c478bd9Sstevel@tonic-gate devfsadm_enumerate_t ugen_rules[1]; 378*7c478bd9Sstevel@tonic-gate char l_path[PATH_MAX]; 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate devfsadm_print(debug_mid, "ugen_create_link: p_path=%s name=%s\n", 381*7c478bd9Sstevel@tonic-gate p_path, node_name); 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate (void) strlcpy(s, node_name, sizeof (s)); 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate /* get vid, pid and minor name strings */ 386*7c478bd9Sstevel@tonic-gate vid = strtok_r(lasts, ".", &lasts); 387*7c478bd9Sstevel@tonic-gate pid = strtok_r(NULL, ".", &lasts); 388*7c478bd9Sstevel@tonic-gate minor_name = lasts; 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate if ((vid == NULL) || (pid == NULL) || (minor_name == NULL)) { 391*7c478bd9Sstevel@tonic-gate return; 392*7c478bd9Sstevel@tonic-gate } 393*7c478bd9Sstevel@tonic-gate 394*7c478bd9Sstevel@tonic-gate /* create regular expression contain vid and pid */ 395*7c478bd9Sstevel@tonic-gate (void) snprintf(ugen_RE, sizeof (ugen_RE), 396*7c478bd9Sstevel@tonic-gate "^usb$/^%s\\.%s$/^([0-9]+)$", vid, pid); 397*7c478bd9Sstevel@tonic-gate devfsadm_print(debug_mid, 398*7c478bd9Sstevel@tonic-gate "ugen_create_link: ugen_RE=%s minor_name=%s\n", 399*7c478bd9Sstevel@tonic-gate ugen_RE, minor_name); 400*7c478bd9Sstevel@tonic-gate 401*7c478bd9Sstevel@tonic-gate bzero(ugen_rules, sizeof (ugen_rules)); 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate ugen_rules[0].re = ugen_RE; 404*7c478bd9Sstevel@tonic-gate ugen_rules[0].subexp = 1; 405*7c478bd9Sstevel@tonic-gate ugen_rules[0].flags = MATCH_ADDR; 406*7c478bd9Sstevel@tonic-gate 407*7c478bd9Sstevel@tonic-gate /* 408*7c478bd9Sstevel@tonic-gate * build the physical path from the components. 409*7c478bd9Sstevel@tonic-gate * find the logical usb id, and stuff it in buf 410*7c478bd9Sstevel@tonic-gate */ 411*7c478bd9Sstevel@tonic-gate if (devfsadm_enumerate_int(p_path, 0, &buf, ugen_rules, 1)) { 412*7c478bd9Sstevel@tonic-gate devfsadm_print(debug_mid, "ugen_create_link: exit/continue\n"); 413*7c478bd9Sstevel@tonic-gate return; 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate (void) snprintf(l_path, sizeof (l_path), "usb/%s.%s/%s/%s", 417*7c478bd9Sstevel@tonic-gate vid, pid, buf, minor_name); 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate devfsadm_print(debug_mid, "mklink %s -> %s\n", l_path, p_path); 420*7c478bd9Sstevel@tonic-gate 421*7c478bd9Sstevel@tonic-gate (void) devfsadm_mklink(l_path, node, minor, 0); 422*7c478bd9Sstevel@tonic-gate 423*7c478bd9Sstevel@tonic-gate free(buf); 424*7c478bd9Sstevel@tonic-gate } 425