118c2aff7Sartem /*************************************************************************** 218c2aff7Sartem * 318c2aff7Sartem * sysevent.c : Solaris sysevents 418c2aff7Sartem * 5*112cd14aSqz * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 618c2aff7Sartem * Use is subject to license terms. 718c2aff7Sartem * 818c2aff7Sartem * Licensed under the Academic Free License version 2.1 918c2aff7Sartem * 1018c2aff7Sartem **************************************************************************/ 1118c2aff7Sartem 1292f38132Sartem #pragma ident "%Z%%M% %I% %E% SMI" 1318c2aff7Sartem 1400687e57Sartem #ifdef HAVE_CONFIG_H 1500687e57Sartem # include <config.h> 1600687e57Sartem #endif 1700687e57Sartem 1818c2aff7Sartem #include <stdio.h> 1918c2aff7Sartem #include <unistd.h> 2018c2aff7Sartem #include <stdlib.h> 2118c2aff7Sartem #include <string.h> 2218c2aff7Sartem #include <errno.h> 2318c2aff7Sartem #include <fcntl.h> 2418c2aff7Sartem #include <sys/dkio.h> 2518c2aff7Sartem #include <sys/stat.h> 2618c2aff7Sartem #include <libdevinfo.h> 2718c2aff7Sartem #include <libsysevent.h> 2818c2aff7Sartem #include <sys/sysevent/dev.h> 297b840e52Sphitran #include <sys/sysevent/acpiev.h> 3018c2aff7Sartem #include <glib.h> 3118c2aff7Sartem 3218c2aff7Sartem #include "../osspec.h" 3318c2aff7Sartem #include "../logger.h" 3418c2aff7Sartem #include "../hald.h" 3518c2aff7Sartem #include "../hald_dbus.h" 3618c2aff7Sartem #include "../device_info.h" 3718c2aff7Sartem #include "../util.h" 3818c2aff7Sartem #include "osspec_solaris.h" 3918c2aff7Sartem #include "hotplug.h" 4018c2aff7Sartem #include "devinfo.h" 4118c2aff7Sartem #include "devinfo_storage.h" 427b840e52Sphitran #include "devinfo_acpi.h" 43*112cd14aSqz #include "devinfo_usb.h" 4418c2aff7Sartem #include "sysevent.h" 4518c2aff7Sartem 4618c2aff7Sartem #ifndef ESC_LOFI 47*112cd14aSqz #define ESC_LOFI "lofi" 4818c2aff7Sartem #endif 4918c2aff7Sartem 5018c2aff7Sartem static void sysevent_dev_handler(sysevent_t *); 5118c2aff7Sartem static gboolean sysevent_iochannel_data(GIOChannel *, GIOCondition, gpointer); 5218c2aff7Sartem static void sysevent_dev_add(gchar *, gchar *); 5318c2aff7Sartem static void sysevent_dev_remove(gchar *, gchar *); 5418c2aff7Sartem static void sysevent_dev_branch(gchar *); 5518c2aff7Sartem static void sysevent_lofi_add(gchar *, gchar *); 5618c2aff7Sartem static void sysevent_lofi_remove(gchar *, gchar *); 57*112cd14aSqz static void sysevent_devfs_add(gchar *); 5818c2aff7Sartem 5918c2aff7Sartem static sysevent_handle_t *shp; 6018c2aff7Sartem 6118c2aff7Sartem static int sysevent_pipe_fds[2]; 6218c2aff7Sartem static GIOChannel *sysevent_iochannel; 6318c2aff7Sartem static guint sysevent_source_id; 6418c2aff7Sartem 6518c2aff7Sartem gboolean 6618c2aff7Sartem sysevent_init(void) 6718c2aff7Sartem { 6818c2aff7Sartem GError *err = NULL; 6942a7bdedSjacobs const char *subcl[3]; 7018c2aff7Sartem 71*112cd14aSqz /* 7218c2aff7Sartem * pipe used to serialize sysevents through the main loop 73*112cd14aSqz */ 74*112cd14aSqz if (pipe (sysevent_pipe_fds) != 0) { 75*112cd14aSqz HAL_INFO (("pipe() failed errno=%d", errno)); 7618c2aff7Sartem return (FALSE); 77*112cd14aSqz } 78*112cd14aSqz sysevent_iochannel = g_io_channel_unix_new (sysevent_pipe_fds[0]); 7918c2aff7Sartem if (sysevent_iochannel == NULL) { 80*112cd14aSqz HAL_INFO (("g_io_channel_unix_new failed")); 8118c2aff7Sartem return (FALSE); 8218c2aff7Sartem } 8318c2aff7Sartem g_io_channel_set_flags (sysevent_iochannel, G_IO_FLAG_NONBLOCK, &err); 84*112cd14aSqz sysevent_source_id = g_io_add_watch ( 85*112cd14aSqz sysevent_iochannel, G_IO_IN, sysevent_iochannel_data, NULL); 8618c2aff7Sartem 8718c2aff7Sartem shp = sysevent_bind_handle(sysevent_dev_handler); 8818c2aff7Sartem if (shp == NULL) { 8918c2aff7Sartem HAL_INFO (("sysevent_bind_handle failed %d", errno)); 9018c2aff7Sartem return (FALSE); 9118c2aff7Sartem } 9218c2aff7Sartem 9318c2aff7Sartem subcl[0] = ESC_DISK; 9418c2aff7Sartem subcl[1] = ESC_LOFI; 9542a7bdedSjacobs subcl[2] = ESC_PRINTER; 9642a7bdedSjacobs if (sysevent_subscribe_event(shp, EC_DEV_ADD, subcl, 3) != 0) { 9718c2aff7Sartem HAL_INFO (("subscribe(dev_add) failed %d", errno)); 9818c2aff7Sartem sysevent_unbind_handle(shp); 9918c2aff7Sartem return (FALSE); 10018c2aff7Sartem } 10142a7bdedSjacobs if (sysevent_subscribe_event(shp, EC_DEV_REMOVE, subcl, 3) != 0) { 10218c2aff7Sartem HAL_INFO (("subscribe(dev_remove) failed %d", errno)); 10318c2aff7Sartem sysevent_unbind_handle(shp); 10418c2aff7Sartem return (FALSE); 10518c2aff7Sartem } 10618c2aff7Sartem 10718c2aff7Sartem subcl[0] = ESC_DEV_BRANCH_REMOVE; 10818c2aff7Sartem if (sysevent_subscribe_event(shp, EC_DEV_BRANCH, subcl, 1) != 0) { 10918c2aff7Sartem HAL_INFO (("subscribe(dev_branch) failed %d", errno)); 11018c2aff7Sartem sysevent_unbind_handle(shp); 11118c2aff7Sartem return (FALSE); 11218c2aff7Sartem } 11318c2aff7Sartem 1147b840e52Sphitran subcl[0] = ESC_ACPIEV_ADD; 115*112cd14aSqz subcl[1] = ESC_ACPIEV_REMOVE; 116*112cd14aSqz subcl[2] = ESC_ACPIEV_STATE_CHANGE; 1177b840e52Sphitran if (sysevent_subscribe_event(shp, EC_ACPIEV, subcl, 3) != 0) { 118*112cd14aSqz HAL_INFO(("subscribe(dev_add) failed %d", errno)); 119*112cd14aSqz sysevent_unbind_handle(shp); 120*112cd14aSqz return (FALSE); 121*112cd14aSqz } 122*112cd14aSqz 123*112cd14aSqz subcl[0] = ESC_DEVFS_DEVI_ADD; 124*112cd14aSqz if (sysevent_subscribe_event(shp, EC_DEVFS, subcl, 1) != 0) { 125*112cd14aSqz HAL_INFO (("subscribe(EC_DEVFS) failed %d", errno)); 126*112cd14aSqz sysevent_unbind_handle(shp); 127*112cd14aSqz return (FALSE); 128*112cd14aSqz } 1297b840e52Sphitran 13018c2aff7Sartem return (B_TRUE); 13118c2aff7Sartem } 13218c2aff7Sartem 13318c2aff7Sartem void 13418c2aff7Sartem sysevent_fini(void) 13518c2aff7Sartem { 13618c2aff7Sartem sysevent_unbind_handle(shp); 13718c2aff7Sartem shp = NULL; 13818c2aff7Sartem } 13918c2aff7Sartem 14018c2aff7Sartem static void 14118c2aff7Sartem sysevent_dev_handler(sysevent_t *ev) 14218c2aff7Sartem { 14318c2aff7Sartem char *class; 14418c2aff7Sartem char *subclass; 14518c2aff7Sartem nvlist_t *attr_list; 14618c2aff7Sartem char *phys_path; 14718c2aff7Sartem char *dev_name; 1487b840e52Sphitran char *dev_hid; 1497b840e52Sphitran char *dev_uid; 1507b840e52Sphitran uint_t dev_index; 15118c2aff7Sartem char s[1024]; 15218c2aff7Sartem ssize_t nwritten; 15318c2aff7Sartem 15418c2aff7Sartem if ((class = sysevent_get_class_name(ev)) == NULL) 15518c2aff7Sartem return; 15618c2aff7Sartem 15718c2aff7Sartem if ((subclass = sysevent_get_subclass_name(ev)) == NULL) 15818c2aff7Sartem return; 15918c2aff7Sartem 16018c2aff7Sartem if (sysevent_get_attr_list(ev, &attr_list) != 0) 16118c2aff7Sartem return; 16218c2aff7Sartem 163*112cd14aSqz if (strcmp(class, EC_DEVFS) == 0) { 164*112cd14aSqz if (nvlist_lookup_string(attr_list, DEVFS_PATHNAME, &phys_path) != 0) { 165*112cd14aSqz goto out; 166*112cd14aSqz } 167*112cd14aSqz 168*112cd14aSqz snprintf(s, sizeof (s), "%s %s %s\n", 169*112cd14aSqz class, subclass, phys_path); 170*112cd14aSqz nwritten = write(sysevent_pipe_fds[1], s, strlen(s) + 1); 171*112cd14aSqz 172*112cd14aSqz HAL_INFO (("sysevent_dev_handler: wrote %d bytes", nwritten)); 173*112cd14aSqz goto out; 174*112cd14aSqz } 175*112cd14aSqz 176*112cd14aSqz if (strcmp(class, EC_ACPIEV) == 0) { 1777b840e52Sphitran if (nvlist_lookup_string(attr_list, ACPIEV_DEV_PHYS_PATH, 1787b840e52Sphitran &phys_path) != 0) { 1797b840e52Sphitran goto out; 1807b840e52Sphitran } 1817b840e52Sphitran } else if (nvlist_lookup_string(attr_list, DEV_PHYS_PATH, &phys_path) 1827b840e52Sphitran != 0) { 18318c2aff7Sartem goto out; 1847b840e52Sphitran } 1857b840e52Sphitran 1867b840e52Sphitran if (nvlist_lookup_string(attr_list, DEV_NAME, &dev_name) != 0) { 1877b840e52Sphitran if (strcmp(class, EC_ACPIEV) == 0) { 1887b840e52Sphitran dev_name = "noname"; 1897b840e52Sphitran } else { 1907b840e52Sphitran dev_name = ""; 1917b840e52Sphitran } 1927b840e52Sphitran } 19318c2aff7Sartem 1947b840e52Sphitran if (nvlist_lookup_string(attr_list, ACPIEV_DEV_HID, &dev_hid) != 0) { 195*112cd14aSqz dev_hid = ""; 1967b840e52Sphitran } 197*112cd14aSqz if (nvlist_lookup_string(attr_list, ACPIEV_DEV_UID, &dev_uid) != 0) { 198*112cd14aSqz dev_uid = ""; 1997b840e52Sphitran } 200*112cd14aSqz if (nvlist_lookup_uint32(attr_list, ACPIEV_DEV_INDEX, &dev_index) 2017b840e52Sphitran != 0) { 202*112cd14aSqz dev_index = 0; 2037b840e52Sphitran } 20418c2aff7Sartem 2057b840e52Sphitran snprintf(s, sizeof (s), "%s %s %s %s %s %s %d\n", 2067b840e52Sphitran class, subclass, phys_path, dev_name, dev_hid, dev_uid, dev_index); 20718c2aff7Sartem nwritten = write(sysevent_pipe_fds[1], s, strlen(s) + 1); 20818c2aff7Sartem 20918c2aff7Sartem HAL_INFO (("sysevent_dev_handler: wrote %d bytes", nwritten)); 21018c2aff7Sartem 21118c2aff7Sartem out: 21218c2aff7Sartem nvlist_free(attr_list); 21318c2aff7Sartem } 21418c2aff7Sartem 21518c2aff7Sartem static gboolean 21618c2aff7Sartem sysevent_iochannel_data (GIOChannel *source, 217*112cd14aSqz GIOCondition condition, 218*112cd14aSqz gpointer user_data) 21918c2aff7Sartem { 220*112cd14aSqz GError *err = NULL; 22118c2aff7Sartem gchar *s = NULL; 22218c2aff7Sartem gsize len; 22318c2aff7Sartem int matches; 22418c2aff7Sartem gchar class[1024]; 22518c2aff7Sartem gchar subclass[1024]; 22618c2aff7Sartem gchar phys_path[1024]; 22718c2aff7Sartem gchar dev_name[1024]; 228*112cd14aSqz gchar dev_uid[1024]; 229*112cd14aSqz gchar dev_hid[1024]; 230*112cd14aSqz gchar udi[1024]; 2317b840e52Sphitran uint_t dev_index; 23218c2aff7Sartem 23318c2aff7Sartem HAL_INFO (("sysevent_iochannel_data")); 23418c2aff7Sartem 23518c2aff7Sartem while (g_io_channel_read_line (sysevent_iochannel, &s, &len, NULL, 236*112cd14aSqz &err) == G_IO_STATUS_NORMAL) { 23718c2aff7Sartem if (len == 0) { 23818c2aff7Sartem break; 23918c2aff7Sartem } 24018c2aff7Sartem 2417b840e52Sphitran class[0] = subclass[0] = phys_path[0] = dev_name[0] = 2427b840e52Sphitran dev_hid[0] = dev_uid[0] = '\0'; 2437b840e52Sphitran matches = sscanf(s, "%s %s %s %s %s %s %d", class, subclass, 2447b840e52Sphitran phys_path, dev_name, dev_hid, dev_uid, &dev_index); 24518c2aff7Sartem g_free (s); 24618c2aff7Sartem s = NULL; 24718c2aff7Sartem if (matches < 3) { 24818c2aff7Sartem continue; 24918c2aff7Sartem } 25018c2aff7Sartem HAL_INFO (("sysevent: class=%s, sub=%s", class, subclass)); 25118c2aff7Sartem 25218c2aff7Sartem if (strcmp(class, EC_DEV_ADD) == 0) { 25342a7bdedSjacobs if ((strcmp(subclass, ESC_DISK) == 0) || 25442a7bdedSjacobs (strcmp(subclass, ESC_PRINTER) == 0)) { 25518c2aff7Sartem sysevent_dev_add(phys_path, dev_name); 25618c2aff7Sartem } else if (strcmp(subclass, ESC_LOFI) == 0) { 25718c2aff7Sartem sysevent_lofi_add(phys_path, dev_name); 25818c2aff7Sartem } 25918c2aff7Sartem } else if (strcmp(class, EC_DEV_REMOVE) == 0) { 26042a7bdedSjacobs if ((strcmp(subclass, ESC_DISK) == 0) || 26142a7bdedSjacobs (strcmp(subclass, ESC_PRINTER) == 0)) { 26218c2aff7Sartem sysevent_dev_remove(phys_path, dev_name); 26318c2aff7Sartem } else if (strcmp(subclass, ESC_LOFI) == 0) { 26418c2aff7Sartem sysevent_lofi_remove(phys_path, dev_name); 26518c2aff7Sartem } 26618c2aff7Sartem } else if (strcmp(class, EC_DEV_BRANCH) == 0) { 26718c2aff7Sartem sysevent_dev_branch(phys_path); 2687b840e52Sphitran } else if (strcmp(class, EC_ACPIEV) == 0) { 2697b840e52Sphitran if (strcmp(dev_hid, "PNP0C0A") == 0) { 2707b840e52Sphitran snprintf(udi, sizeof(udi), 2717b840e52Sphitran "/org/freedesktop/Hal/devices/pseudo/" 2727b840e52Sphitran "battery_0_battery%d_0", dev_index); 2737b840e52Sphitran } else if (strcmp(dev_hid, "ACPI0003") == 0) { 2747b840e52Sphitran snprintf(udi, sizeof(udi), 2757b840e52Sphitran "/org/freedesktop/Hal/devices/pseudo/" 2767b840e52Sphitran "battery_0_ac%d_0", dev_index); 277*112cd14aSqz } else { 2787b840e52Sphitran HAL_INFO(("dev_hid %s unknown", dev_hid)); 2797b840e52Sphitran continue; 2807b840e52Sphitran } 2817b840e52Sphitran devinfo_battery_device_rescan(phys_path, udi); 282*112cd14aSqz } else if (strcmp(class, EC_DEVFS) == 0) { 283*112cd14aSqz if (strcmp(subclass, ESC_DEVFS_DEVI_ADD) == 0) { 284*112cd14aSqz sysevent_devfs_add(phys_path); 285*112cd14aSqz } 286*112cd14aSqz } 28718c2aff7Sartem } 28818c2aff7Sartem 28918c2aff7Sartem if (err) { 29018c2aff7Sartem g_error_free (err); 29118c2aff7Sartem } 29218c2aff7Sartem 29318c2aff7Sartem return (TRUE); 29418c2aff7Sartem } 29518c2aff7Sartem 29618c2aff7Sartem static void 29718c2aff7Sartem sysevent_dev_add(gchar *devfs_path, gchar *name) 29818c2aff7Sartem { 29918c2aff7Sartem gchar *parent_devfs_path, *hotplug_devfs_path; 30018c2aff7Sartem HalDevice *parent; 30118c2aff7Sartem 30218c2aff7Sartem HAL_INFO (("dev_add: %s %s", name, devfs_path)); 30318c2aff7Sartem 304*112cd14aSqz parent = hal_util_find_closest_ancestor (devfs_path, &parent_devfs_path, &hotplug_devfs_path); 30518c2aff7Sartem if (parent == NULL) { 30618c2aff7Sartem return; 30718c2aff7Sartem } 30818c2aff7Sartem 30918c2aff7Sartem HAL_INFO (("dev_add: parent=%s", parent_devfs_path)); 31018c2aff7Sartem HAL_INFO (("dev_add: real=%s", hotplug_devfs_path)); 31118c2aff7Sartem 31218c2aff7Sartem devinfo_add (parent, hotplug_devfs_path); 31318c2aff7Sartem 31418c2aff7Sartem g_free (parent_devfs_path); 31518c2aff7Sartem g_free (hotplug_devfs_path); 31618c2aff7Sartem 31718c2aff7Sartem hotplug_event_process_queue (); 31818c2aff7Sartem } 31918c2aff7Sartem 32018c2aff7Sartem static void 32118c2aff7Sartem sysevent_dev_remove(gchar *devfs_path, gchar *name) 32218c2aff7Sartem { 32318c2aff7Sartem HAL_INFO (("dev_remove: %s %s", name, devfs_path)); 32418c2aff7Sartem 32518c2aff7Sartem devinfo_remove_branch (devfs_path, NULL); 32618c2aff7Sartem hotplug_event_process_queue (); 32718c2aff7Sartem } 32818c2aff7Sartem 32918c2aff7Sartem static void 33018c2aff7Sartem sysevent_dev_branch(gchar *devfs_path) 33118c2aff7Sartem { 33218c2aff7Sartem HAL_INFO (("branch_remove: %s", devfs_path)); 33318c2aff7Sartem 33418c2aff7Sartem devinfo_remove_branch (devfs_path, NULL); 33518c2aff7Sartem hotplug_event_process_queue (); 33618c2aff7Sartem } 33718c2aff7Sartem 33818c2aff7Sartem static void 33918c2aff7Sartem sysevent_lofi_add(gchar *devfs_path, gchar *name) 34018c2aff7Sartem { 34118c2aff7Sartem di_node_t node; 34218c2aff7Sartem const char *parent_udi; 34318c2aff7Sartem HalDevice *d, *parent; 34418c2aff7Sartem 34518c2aff7Sartem HAL_INFO (("lofi_add: %s %s", name, devfs_path)); 34618c2aff7Sartem 34718c2aff7Sartem if ((d = hal_device_store_match_key_value_string (hald_get_gdl (), 34818c2aff7Sartem "solaris.devfs_path", devfs_path)) == NULL) { 34918c2aff7Sartem HAL_INFO (("device not found in GDL %s", devfs_path)); 35018c2aff7Sartem return; 35118c2aff7Sartem } 35218c2aff7Sartem parent_udi = hal_device_property_get_string (d, "info.parent"); 35318c2aff7Sartem if ((parent_udi == NULL) || (strlen(parent_udi) == 0)) { 35418c2aff7Sartem HAL_INFO (("parent not found in GDL %s", parent_udi)); 35518c2aff7Sartem return; 35618c2aff7Sartem } 35718c2aff7Sartem if ((parent = hal_device_store_match_key_value_string (hald_get_gdl (), 35818c2aff7Sartem "info.udi", parent_udi)) == NULL) { 35918c2aff7Sartem HAL_INFO (("parent not found in GDL %s", parent_udi)); 36018c2aff7Sartem return; 36118c2aff7Sartem } 36218c2aff7Sartem 36318c2aff7Sartem if ((node = di_init (devfs_path, DINFOCPYALL)) == DI_NODE_NIL) { 36418c2aff7Sartem HAL_INFO (("device not found in devinfo %s", devfs_path)); 36518c2aff7Sartem return; 36618c2aff7Sartem } 36718c2aff7Sartem 36800687e57Sartem HAL_INFO (("device %s parent %s", hal_device_get_udi (d), parent_udi)); 36918c2aff7Sartem devinfo_lofi_add_major (parent, node, devfs_path, NULL, TRUE, d); 37018c2aff7Sartem 37118c2aff7Sartem di_fini (node); 37218c2aff7Sartem 37318c2aff7Sartem hotplug_event_process_queue (); 37418c2aff7Sartem } 37518c2aff7Sartem 37618c2aff7Sartem static void 37718c2aff7Sartem sysevent_lofi_remove(gchar *parent_devfs_path, gchar *name) 37818c2aff7Sartem { 37918c2aff7Sartem devinfo_lofi_remove_minor(parent_devfs_path, name); 38018c2aff7Sartem hotplug_event_process_queue (); 38118c2aff7Sartem } 382*112cd14aSqz 383*112cd14aSqz static HalDevice * 384*112cd14aSqz lookup_parent(char *devfs_path) 385*112cd14aSqz { 386*112cd14aSqz gchar *path = NULL; 387*112cd14aSqz HalDevice *parent = NULL; 388*112cd14aSqz char *p; 389*112cd14aSqz 390*112cd14aSqz path = strdup (devfs_path); 391*112cd14aSqz p = strrchr (path, '/'); 392*112cd14aSqz if (p == NULL) { 393*112cd14aSqz free (path); 394*112cd14aSqz return (NULL); 395*112cd14aSqz } 396*112cd14aSqz *p = '\0'; 397*112cd14aSqz 398*112cd14aSqz /* Look up the parent node in the gdl. */ 399*112cd14aSqz parent = hal_device_store_match_key_value_string (hald_get_gdl (), 400*112cd14aSqz "solaris.devfs_path", path); 401*112cd14aSqz 402*112cd14aSqz if (parent == NULL) { 403*112cd14aSqz /* Look up the parent node in the tdl. */ 404*112cd14aSqz parent = hal_device_store_match_key_value_string (hald_get_tdl (), 405*112cd14aSqz "solaris.devfs_path", path); 406*112cd14aSqz } 407*112cd14aSqz 408*112cd14aSqz free (path); 409*112cd14aSqz return (parent); 410*112cd14aSqz } 411*112cd14aSqz 412*112cd14aSqz /* 413*112cd14aSqz * Handle the USB bus devices hot plugging events. 414*112cd14aSqz */ 415*112cd14aSqz static void 416*112cd14aSqz sysevent_devfs_add(gchar *devfs_path) 417*112cd14aSqz { 418*112cd14aSqz di_node_t node; 419*112cd14aSqz HalDevice *parent; 420*112cd14aSqz char *driver_name; 421*112cd14aSqz 422*112cd14aSqz HAL_INFO (("devfs_handle: %s", devfs_path)); 423*112cd14aSqz 424*112cd14aSqz if ((node = di_init (devfs_path, DINFOCPYALL)) == DI_NODE_NIL) { 425*112cd14aSqz HAL_INFO (("device not found in devinfo %s", devfs_path)); 426*112cd14aSqz return; 427*112cd14aSqz } 428*112cd14aSqz 429*112cd14aSqz if ((driver_name = di_driver_name (node)) == NULL) 430*112cd14aSqz goto out; 431*112cd14aSqz 432*112cd14aSqz /* The disk and printer devices are handled by EC_DEV_ADD class. */ 433*112cd14aSqz if ((strcmp (driver_name, "scsa2usb") == 0) || 434*112cd14aSqz (strcmp (driver_name, "usbprn") == 0)) 435*112cd14aSqz goto out; 436*112cd14aSqz 437*112cd14aSqz if ((parent = lookup_parent (devfs_path)) == NULL) 438*112cd14aSqz goto out; 439*112cd14aSqz 440*112cd14aSqz devinfo_usb_add (parent, node, devfs_path, NULL); 441*112cd14aSqz 442*112cd14aSqz di_fini (node); 443*112cd14aSqz 444*112cd14aSqz hotplug_event_process_queue (); 445*112cd14aSqz 446*112cd14aSqz return; 447*112cd14aSqz 448*112cd14aSqz out: 449*112cd14aSqz di_fini (node); 450*112cd14aSqz } 451