/* * add a port monitor entry for device /dev/term/"port" */ static void add_pm_entry(int port) { char cmdline[CMDLEN]; int sac_exitval; add_port_monitor(port); (void) sprintf(cmdline, "/usr/sbin/pmadm -a -p ttymon%d -s %d -i root" " -v `/usr/sbin/ttyadm -V` -f*x -y\"/dev/term/%d\"" " -m \"`/usr/sbin/ttyadm -d /dev/term/%d -s /usr/bin/login" " -l 9600 -p \\\"login: \\\"`\"", PM_NUM(port), port, port, port); if (devfsadm_noupdate() == DEVFSADM_FALSE) { sac_exitval = execute(cmdline); if ((sac_exitval != 0) && (sac_exitval != E_SACNOTRUN)) { devfsadm_print(VERBOSE_MID, "failed to add port monitor entry" " for /dev/term/%d\n", port); devfsadm_print(VERBOSE_MID, "pmadm: (%s) %s\n", SAC_EID(sac_exitval), SAC_EMSG(sac_exitval)); } } pma[port].flags |= PM_HAS_ENTRY; devfsadm_print(VERBOSE_MID, "%s: /dev/term/%d added to sacadm\n", modname, port); }
static void add_port_monitor(int port) { char cmdline[CMDLEN]; int sac_exitval; if ((pma[PM_SLOT(port)].flags & HAS_PORT_MON) != 0) { return; } (void) sprintf(cmdline, "/usr/sbin/sacadm -l -p ttymon%d", PM_NUM(port)); sac_exitval = execute(cmdline); if (sac_exitval == E_NOEXIST) { (void) sprintf(cmdline, "/usr/sbin/sacadm -a -n 2 -p ttymon%d -t ttymon" " -c /usr/lib/saf/ttymon -v \"`/usr/sbin/ttyadm" " -V`\" -y \"Ports %d-%d\"", PM_NUM(port), PM_SLOT(port), PM_SLOT(port) + (PM_GRPSZ - 1)); if (devfsadm_noupdate() == DEVFSADM_FALSE) { if (sac_exitval = execute(cmdline)) { devfsadm_print(VERBOSE_MID, "failed to add port monitor ttymon%d\n", PM_NUM(port)); devfsadm_print(VERBOSE_MID, "sacadm: (%s) %s\n", SAC_EID(sac_exitval), SAC_EMSG(sac_exitval)); } } devfsadm_print(VERBOSE_MID, "%s: port monitor ttymon%d added\n", modname, PM_NUM(port)); } pma[PM_SLOT(port)].flags |= HAS_PORT_MON; }
/* * This function is called for every dcam1394 minor node. * Calls enumerate to assign a logical dcam1394 id, and then * devfsadm_mklink to make the link. */ static int dcam1394_process(di_minor_t minor, di_node_t node) { char m_name[PATH_MAX], restring0[DCAM_RE_STRING_LEN]; char l_path[PATH_MAX], p_path[PATH_MAX], *buf, *devfspath; devfsadm_enumerate_t re[1]; (void) strcpy(m_name, di_minor_name(minor)); if (strcmp(di_driver_name(node), "dcam1394") != 0) { return (DEVFSADM_CONTINUE); } if (strncmp(m_name, "dcamctl", 7) == 0) { (void) snprintf(restring0, DCAM_RE_STRING_LEN, DCAM_CTL_LINK_RE); } else if (strncmp(m_name, "dcam", 4) == 0) { (void) snprintf(restring0, DCAM_RE_STRING_LEN, DCAM_STR_LINK_RE); } else { return (DEVFSADM_CONTINUE); } re[0].re = restring0; re[0].subexp = 1; re[0].flags = MATCH_ALL; devfsadm_print(debug_mid, "dcam1394_process: path %s\n", di_devfs_path(node)); (void) strcpy(p_path, devfspath = di_devfs_path(node)); (void) strcat(p_path, ":"); (void) strcat(p_path, di_minor_name(minor)); di_devfs_path_free(devfspath); /* * Build the physical path from the components, omitting * minor name field. Find the logical dcam1394 id, and * stuff it in buf. */ if (devfsadm_enumerate_int(p_path, 0, &buf, re, 1)) { devfsadm_print(debug_mid, "dcam1394_process: exit/continue\n"); return (DEVFSADM_CONTINUE); } devfsadm_print(debug_mid, "dcam1394_process: p_path=%s buf=%s\n", p_path, buf); if (strncmp(di_minor_name(minor), "dcamctl", 7) == 0) (void) snprintf(l_path, PATH_MAX, "dcamctl%s", buf); else (void) snprintf(l_path, PATH_MAX, "dcam%s", buf); (void) devfsadm_mklink(l_path, node, minor, 0); free(buf); return (DEVFSADM_CONTINUE); }
static void ugen_create_link(char *p_path, char *node_name, di_node_t node, di_minor_t minor) { char *buf, s[MAXPATHLEN]; char *lasts = s; char *vid, *pid; char *minor_name; char ugen_RE[128]; devfsadm_enumerate_t ugen_rules[1]; char l_path[PATH_MAX]; int flags = 0; devfsadm_print(debug_mid, "ugen_create_link: p_path=%s name=%s\n", p_path, node_name); (void) strlcpy(s, node_name, sizeof (s)); /* get vid, pid and minor name strings */ vid = strtok_r(lasts, ".", &lasts); pid = strtok_r(NULL, ".", &lasts); minor_name = lasts; if ((vid == NULL) || (pid == NULL) || (minor_name == NULL)) { return; } /* create regular expression contain vid and pid */ (void) snprintf(ugen_RE, sizeof (ugen_RE), "^usb$/^%s\\.%s$/^([0-9]+)$", vid, pid); devfsadm_print(debug_mid, "ugen_create_link: ugen_RE=%s minor_name=%s\n", ugen_RE, minor_name); bzero(ugen_rules, sizeof (ugen_rules)); ugen_rules[0].re = ugen_RE; ugen_rules[0].subexp = 1; ugen_rules[0].flags = MATCH_ADDR; /* * build the physical path from the components. * find the logical usb id, and stuff it in buf */ if (devfsadm_enumerate_int(p_path, 0, &buf, ugen_rules, 1)) { devfsadm_print(debug_mid, "ugen_create_link: exit/continue\n"); return; } (void) snprintf(l_path, sizeof (l_path), "usb/%s.%s/%s/%s", vid, pid, buf, minor_name); devfsadm_print(debug_mid, "mklink %s -> %s\n", l_path, p_path); (void) devfsadm_mklink(l_path, node, minor, flags); free(buf); }
int minor_init() { devfsadm_print(disk_mid, "%s: minor_init(): Creating disks reserved ID cache\n", modname); return (devfsadm_reserve_id_cache(disks_re_array, NULL)); }
/* * fork and exec a command, waiting for the command to * complete and return it's status */ static int execute(const char *s) { int status; int fd; pid_t pid; pid_t w; /* * fork a single threaded child proc to execute the * sacadm command string */ devfsadm_print(PORT_MID, "%s: execute:\n\t%s\n", modname, s); if ((pid = fork1()) == 0) { (void) close(0); (void) close(1); (void) close(2); fd = open("/dev/null", O_RDWR); (void) dup(fd); (void) dup(fd); (void) execl("/sbin/sh", "sh", "-c", s, 0); /* * return the sacadm exit status (see _exit(2)) */ _exit(127); } /* * wait for child process to terminate */ for (;;) { w = wait(&status); if (w == pid) { devfsadm_print(PORT_MID, "%s:exit status (%d)\n", modname, SAC_EXITVAL(status)); return (SAC_EXITVAL(status)); } if (w == (pid_t)-1) { devfsadm_print(VERBOSE_MID, "%s: exec failed\n", modname); return (-1); } } /* NOTREACHED */ }
/* * delete_port_monitor() * Check for the existence of a port monitor for "port" and remove it if * one exists */ static void delete_port_monitor(int port) { char cmdline[CMDLEN]; int sac_exitval; (void) sprintf(cmdline, "/usr/sbin/sacadm -L -p ttymon%d", PM_NUM(port)); sac_exitval = execute(cmdline); /* clear the PM tag and return if the port monitor is not active */ if (sac_exitval == E_NOEXIST) { pma[PM_SLOT(port)].flags &= ~HAS_PORT_MON; return; } /* some other sacadm(1m) error, log and return */ if (sac_exitval != 0) { devfsadm_print(VERBOSE_MID, "sacadm: (%s) %s\n", SAC_EID(sac_exitval), SAC_EMSG(sac_exitval)); return; } if (devfsadm_noupdate() == DEVFSADM_FALSE) { (void) sprintf(cmdline, "/usr/sbin/sacadm -r -p ttymon%d", PM_NUM(port)); if (sac_exitval = execute(cmdline)) { devfsadm_print(VERBOSE_MID, "failed to remove port monitor ttymon%d\n", PM_NUM(port)); devfsadm_print(VERBOSE_MID, "sacadm: (%s) %s\n", SAC_EID(sac_exitval), SAC_EMSG(sac_exitval)); } } devfsadm_print(VERBOSE_MID, "%s: port monitor ttymon%d removed\n", modname, PM_NUM(port)); pma[PM_SLOT(port)].flags &= ~HAS_PORT_MON; }
static void remove_pm_entry(char *pmtag, int port) { char cmdline[CMDLEN]; int sac_exitval; if (devfsadm_noupdate() == DEVFSADM_FALSE) { (void) snprintf(cmdline, sizeof (cmdline), "/usr/sbin/pmadm -r -p %s -s %d", pmtag, port); sac_exitval = execute(cmdline); if ((sac_exitval != 0) && (sac_exitval != E_SACNOTRUN)) { devfsadm_print(VERBOSE_MID, "failed to remove port monitor entry" " for /dev/term/%d\n", port); devfsadm_print(VERBOSE_MID, "pmadm: (%s) %s\n", SAC_EID(sac_exitval), SAC_EMSG(sac_exitval)); } } pma[port].flags &= ~PM_HAS_ENTRY; devfsadm_print(VERBOSE_MID, "%s: /dev/term/%d removed from sacadm\n", modname, port); }
/* * This function is called for every ieee1394 minor node. * Calls enumerate to assign a logical ieee1394 id, and then * devfsadm_mklink to make the link. */ static int ieee1394_process(di_minor_t minor, di_node_t node) { char *buf, *devfspath; char l_path[PATH_MAX], p_path[PATH_MAX]; devfsadm_enumerate_t re[] = {"^1394/hba([0-9]+)$", 1, MATCH_ALL}; devfspath = di_devfs_path(node); devfsadm_print(debug_mid, "ieee1394_process: path %s\n", devfspath); (void) snprintf(p_path, sizeof (p_path), "%s:%s", devfspath, di_minor_name(minor)); di_devfs_path_free(devfspath); /* * Build the physical path from the components. Find the logical * ieee1394 HBA id, and stuff it in buf */ if (devfsadm_enumerate_int(p_path, 0, &buf, re, 1)) { devfsadm_print(debug_mid, "ieee1394_process: exit/continue\n"); return (DEVFSADM_CONTINUE); } devfsadm_print(debug_mid, "ieee1394_process: p_path=%s buf=%s\n", p_path, buf); (void) snprintf(l_path, sizeof (l_path), "1394/hba%s", buf); free(buf); devfsadm_print(debug_mid, "mklink %s %s\n", l_path, p_path); (void) devfsadm_mklink(l_path, node, minor, 0); return (DEVFSADM_CONTINUE); }
/* * parse port number from string * returns port number if in range [0..maxports] */ static int parse_portno(char *dname) { int pn; if (sscanf(dname, "%d", &pn) != 1) return (-1); if ((pn < 0) || (pn > maxports)) { devfsadm_print(VERBOSE_MID, "%s:parse_portno: %d not in range (0..%d)\n", modname, pn, maxports); return (-1); } return (pn); }
int minor_init() { char *maxport_str; maxport_str = defread("SUNW_port_link.maxports"); if ((maxport_str == NULL) || (sscanf(maxport_str, "%d", &maxports) != 1)) maxports = MAXPORTS_DEFAULT; devfsadm_print(CHATTY_MID, "%s: maximum number of port devices (%d)\n", modname, maxports); if (pma_alloc() == NULL) return (DEVFSADM_FAILURE); return (DEVFSADM_SUCCESS); }
/* * Removes port entries that no longer have devices * backing them * Schedules an update the sacadm (portmon) database */ static void rm_dangling_port(char *devname) { char *portstr; int portnum; devfsadm_print(PORT_MID, "%s:rm_stale_port: %s\n", modname, devname); if ((portstr = strrchr(devname, (int)'/')) == NULL) { devfsadm_errprint("%s: invalid name: %s\n", modname, devname); return; } portstr++; /* * mark for removal from sacadm database */ if ((portnum = parse_portno(portstr)) != -1) pma[portnum].flags |= PORT_REMOVED; devfsadm_rm_all(devname); }
int minor_fini(void) { devfsadm_print(debug_mid, "ramdisk_link: minor_fini\n"); return (DEVFSADM_SUCCESS); }
/* * This function is called for every usb minor node. * Calls enumerate to assign a logical usb id, and then * devfsadm_mklink to make the link. */ static int usb_process(di_minor_t minor, di_node_t node) { devfsadm_enumerate_t rules[1]; char *l_path, *p_path, *buf, *devfspath; char *minor_nm, *drvr_nm, *name = (char *)NULL; int i, index; int flags = 0; int create_secondary_link = 0; minor_nm = di_minor_name(minor); drvr_nm = di_driver_name(node); if ((minor_nm == NULL) || (drvr_nm == NULL)) { return (DEVFSADM_CONTINUE); } devfsadm_print(debug_mid, "usb_process: minor=%s node=%s type=%s\n", minor_nm, di_node_name(node), di_minor_nodetype(minor)); devfspath = di_devfs_path(node); if (devfspath == NULL) { devfsadm_print(debug_mid, "USB_process: devfspath is NULL\n"); return (DEVFSADM_CONTINUE); } l_path = (char *)malloc(PATH_MAX); if (l_path == NULL) { di_devfs_path_free(devfspath); devfsadm_print(debug_mid, "usb_process: malloc() failed\n"); return (DEVFSADM_CONTINUE); } p_path = (char *)malloc(PATH_MAX); if (p_path == NULL) { devfsadm_print(debug_mid, "usb_process: malloc() failed\n"); di_devfs_path_free(devfspath); free(l_path); return (DEVFSADM_CONTINUE); } (void) strcpy(p_path, devfspath); (void) strcat(p_path, ":"); (void) strcat(p_path, minor_nm); di_devfs_path_free(devfspath); devfsadm_print(debug_mid, "usb_process: path %s\n", p_path); for (i = 0; ; i++) { if ((driver_name_table[i].driver_name == NULL) || (strcmp(drvr_nm, driver_name_table[i].driver_name) == 0)) { index = driver_name_table[i].index; break; } } if (strcmp(di_minor_nodetype(minor), DDI_NT_UGEN) == 0) { ugen_create_link(p_path, minor_nm, node, minor); free(l_path); free(p_path); return (DEVFSADM_CONTINUE); } /* Figure out which rules to apply */ switch (index) { case DRIVER_HUBD: case DRIVER_OHCI: case DRIVER_EHCI: case DRIVER_UHCI: rules[0] = hub_rules[0]; /* For HUBs */ name = "hub"; break; case DRIVER_USB_AC: if (strcmp(minor_nm, "sound,audio") == 0) { rules[0] = audio_rules[0]; name = "audio"; /* For audio */ create_secondary_link = 1; } else if (strcmp(minor_nm, "sound,audioctl") == 0) { rules[0] = audio_control_rules[0]; name = "audio-control"; /* For audio */ create_secondary_link = 1; } else if (strcmp(minor_nm, "mux") == 0) { rules[0] = audio_mux_rules[0]; name = "audio-mux"; /* For audio */ } else { free(l_path); free(p_path); return (DEVFSADM_CONTINUE); } break; case DRIVER_USB_AS: rules[0] = audio_stream_rules[0]; name = "audio-stream"; /* For audio */ break; case DRIVER_VIDEO: rules[0] = video_rules[0]; name = "video"; /* For video */ create_secondary_link = 1; break; case DRIVER_HID: rules[0] = hid_rules[0]; name = "hid"; /* For HIDs */ break; case DRIVER_USB_MID: rules[0] = device_rules[0]; name = "device"; /* For other USB devices */ break; case DRIVER_DDIVS_USBC: rules[0] = ddivs_usbc_rules[0]; name = "device"; /* For other USB devices */ break; case DRIVER_SCSA2USB: rules[0] = mass_storage_rules[0]; name = "mass-storage"; /* For mass-storage devices */ break; case DRIVER_USBPRN: rules[0] = usbprn_rules[0]; name = "printer"; break; case DRIVER_HWAHC: if (strcmp(minor_nm, "hwahc") == 0) { rules[0] = whost_rules[0]; name = "whost"; /* For HWA HC */ } else if (strcmp(minor_nm, "hubd") == 0) { rules[0] = hub_rules[0]; name = "hub"; /* For HWA HC */ } else { free(l_path); free(p_path); return (DEVFSADM_CONTINUE); } break; case DRIVER_HWARC: rules[0] = hwarc_rules[0]; name = "hwarc"; /* For UWB HWA Radio Controllers */ break; case DRIVER_WUSB_CA: rules[0] = wusb_ca_rules[0]; name = "wusb_ca"; /* for wusb cable association */ break; default: devfsadm_print(debug_mid, "usb_process: unknown driver=%s\n", drvr_nm); free(l_path); free(p_path); return (DEVFSADM_CONTINUE); } /* * build the physical path from the components. * find the logical usb id, and stuff it in buf */ if (devfsadm_enumerate_int(p_path, 0, &buf, rules, 1)) { devfsadm_print(debug_mid, "usb_process: exit/continue\n"); free(l_path); free(p_path); return (DEVFSADM_CONTINUE); } (void) snprintf(l_path, PATH_MAX, "usb/%s%s", name, buf); devfsadm_print(debug_mid, "usb_process: p_path=%s buf=%s\n", p_path, buf); free(buf); devfsadm_print(debug_mid, "mklink %s -> %s\n", l_path, p_path); (void) devfsadm_mklink(l_path, node, minor, flags); if (create_secondary_link) { /* * Create secondary links to make newly hotplugged * usb audio device the primary device. */ if (strcmp(name, "audio") == 0) { (void) devfsadm_secondary_link("audio", l_path, 0); } else if (strcmp(name, "audio-control") == 0) { (void) devfsadm_secondary_link("audioctl", l_path, 0); } else if (strcmp(name, "video") == 0) { (void) devfsadm_secondary_link(l_path + 4, l_path, 0); } } free(p_path); free(l_path); return (DEVFSADM_CONTINUE); }
int minor_init(void) { devfsadm_print(debug_mid, "usb_link: minor_init\n"); return (DEVFSADM_SUCCESS); }
/* * Determine which port monitor entries already exist by invoking pmadm(1m) * to list all configured 'ttymon' port monitor entries. * Do not explicitly report errors from executing pmadm(1m) or sacadm(1m) * commands to remain compatible with the ports(1m) implementation. */ static int load_ttymondb(void) { char cmdline[CMDLEN]; char cmdbuf[PMTAB_MAXLINE+1]; int sac_exitval; FILE *fs_popen; char *portname; /* pointer to a tty name */ int portnum; char *ptr; char *error_msg = "%s: failed to load port monitor database\n"; (void) strcpy(cmdline, "/usr/sbin/pmadm -L -t ttymon"); fs_popen = popen(cmdline, "r"); if (fs_popen == NULL) { devfsadm_print(VERBOSE_MID, error_msg, modname); return (DEVFSADM_FAILURE); } while (fgets(cmdbuf, PMTAB_MAXLINE, fs_popen) != NULL) { if ((portname = pmtab_parse_portname(cmdbuf)) == NULL) { devfsadm_print(VERBOSE_MID, "load_ttymondb: failed to parse portname\n"); devfsadm_print(VERBOSE_MID, "load_ttymondb: buffer \"%s\"\n", cmdbuf); goto load_failed; } devfsadm_print(PORT_MID, "%s:load_ttymondb: port %s ", modname, portname); /* * skip onboard ports * There is no reliable way to determine if we * should start a port monitor on these lines. */ if ((portnum = parse_portno(portname)) == -1) { devfsadm_print(PORT_MID, "ignored\n"); continue; } /* * the first field of the pmadm output is * the port monitor name for this entry */ if ((ptr = strchr(cmdbuf, PMTAB_SEPR)) == NULL) { devfsadm_print(VERBOSE_MID, "load_ttymondb: no portmon tag\n"); goto load_failed; } *ptr = MN_NULLCHAR; if ((pma[portnum].pm_tag = strdup(cmdbuf)) == NULL) { devfsadm_errprint("load_ttymondb: failed strdup\n"); goto load_failed; } pma[portnum].flags |= PM_HAS_ENTRY; pma[PM_SLOT(portnum)].flags |= HAS_PORT_MON; devfsadm_print(PORT_MID, "present\n"); } (void) pclose(fs_popen); return (DEVFSADM_SUCCESS); load_failed: /* * failed to load the port monitor database */ devfsadm_print(VERBOSE_MID, error_msg, modname); sac_exitval = SAC_EXITVAL(pclose(fs_popen)); if (sac_exitval != 0) { devfsadm_print(VERBOSE_MID, "pmadm: (%s) %s\n", SAC_EID(sac_exitval), SAC_EMSG(sac_exitval)); } return (DEVFSADM_FAILURE); }