118c2aff7Sartem /*************************************************************************** 218c2aff7Sartem * 318c2aff7Sartem * sysevent.c : Solaris sysevents 418c2aff7Sartem * 5112cd14aSqz150045 * 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 1200687e57Sartem #ifdef HAVE_CONFIG_H 1300687e57Sartem #include <config.h> 1400687e57Sartem #endif 1500687e57Sartem 1618c2aff7Sartem #include <stdio.h> 1718c2aff7Sartem #include <unistd.h> 1818c2aff7Sartem #include <stdlib.h> 1918c2aff7Sartem #include <string.h> 2018c2aff7Sartem #include <errno.h> 2118c2aff7Sartem #include <fcntl.h> 2218c2aff7Sartem #include <sys/dkio.h> 2318c2aff7Sartem #include <sys/stat.h> 2418c2aff7Sartem #include <libdevinfo.h> 2518c2aff7Sartem #include <libsysevent.h> 2618c2aff7Sartem #include <sys/sysevent/dev.h> 27d2ec54f7Sphitran #include <sys/sysevent/pwrctl.h> 28a9da3307Snp146283 #include <sys/sysevent/dr.h> 2918c2aff7Sartem #include <glib.h> 30a9da3307Snp146283 #include <config_admin.h> 31a9da3307Snp146283 #include <kstat.h> 3218c2aff7Sartem 3318c2aff7Sartem #include "../osspec.h" 3418c2aff7Sartem #include "../logger.h" 3518c2aff7Sartem #include "../hald.h" 3618c2aff7Sartem #include "../hald_dbus.h" 3718c2aff7Sartem #include "../device_info.h" 3818c2aff7Sartem #include "../util.h" 3918c2aff7Sartem #include "osspec_solaris.h" 4018c2aff7Sartem #include "hotplug.h" 4118c2aff7Sartem #include "devinfo.h" 4218c2aff7Sartem #include "devinfo_storage.h" 437b840e52Sphitran #include "devinfo_acpi.h" 44112cd14aSqz150045 #include "devinfo_usb.h" 4518c2aff7Sartem #include "sysevent.h" 46a9da3307Snp146283 #include "devinfo_misc.h" 47a9da3307Snp146283 #include "devinfo_cpu.h" 4818c2aff7Sartem 4918c2aff7Sartem #ifndef ESC_LOFI 5018c2aff7Sartem #define ESC_LOFI "lofi" 5118c2aff7Sartem #endif 5218c2aff7Sartem 5318c2aff7Sartem static void sysevent_dev_handler(sysevent_t *); 5418c2aff7Sartem static gboolean sysevent_iochannel_data(GIOChannel *, GIOCondition, gpointer); 5518c2aff7Sartem static void sysevent_dev_add(gchar *, gchar *); 5618c2aff7Sartem static void sysevent_dev_remove(gchar *, gchar *); 5718c2aff7Sartem static void sysevent_dev_branch(gchar *); 5818c2aff7Sartem static void sysevent_lofi_add(gchar *, gchar *); 5918c2aff7Sartem static void sysevent_lofi_remove(gchar *, gchar *); 60112cd14aSqz150045 static void sysevent_devfs_add(gchar *); 61d2ec54f7Sphitran static void sysevent_pwrctl(gchar *, gchar *, gchar *, gchar *, gchar *, 62d2ec54f7Sphitran gchar *, uint_t); 63a9da3307Snp146283 static void sysevent_process_dr(gchar *, gchar *); 6418c2aff7Sartem 6518c2aff7Sartem static sysevent_handle_t *shp; 6618c2aff7Sartem 6718c2aff7Sartem static int sysevent_pipe_fds[2]; 6818c2aff7Sartem static GIOChannel *sysevent_iochannel; 6918c2aff7Sartem static guint sysevent_source_id; 7018c2aff7Sartem 7118c2aff7Sartem gboolean 7218c2aff7Sartem sysevent_init(void) 7318c2aff7Sartem { 7418c2aff7Sartem GError *err = NULL; 75d2ec54f7Sphitran const char *subcl[6]; 7618c2aff7Sartem 7718c2aff7Sartem /* 7818c2aff7Sartem * pipe used to serialize sysevents through the main loop 7918c2aff7Sartem */ 8018c2aff7Sartem if (pipe (sysevent_pipe_fds) != 0) { 8118c2aff7Sartem HAL_INFO (("pipe() failed errno=%d", errno)); 8218c2aff7Sartem return (FALSE); 8318c2aff7Sartem } 8418c2aff7Sartem sysevent_iochannel = g_io_channel_unix_new (sysevent_pipe_fds[0]); 8518c2aff7Sartem if (sysevent_iochannel == NULL) { 8618c2aff7Sartem HAL_INFO (("g_io_channel_unix_new failed")); 8718c2aff7Sartem return (FALSE); 8818c2aff7Sartem } 8918c2aff7Sartem g_io_channel_set_flags (sysevent_iochannel, G_IO_FLAG_NONBLOCK, &err); 9018c2aff7Sartem sysevent_source_id = g_io_add_watch ( 9118c2aff7Sartem sysevent_iochannel, G_IO_IN, sysevent_iochannel_data, NULL); 9218c2aff7Sartem 9318c2aff7Sartem shp = sysevent_bind_handle(sysevent_dev_handler); 9418c2aff7Sartem if (shp == NULL) { 9518c2aff7Sartem HAL_INFO (("sysevent_bind_handle failed %d", errno)); 9618c2aff7Sartem return (FALSE); 9718c2aff7Sartem } 9818c2aff7Sartem 9918c2aff7Sartem subcl[0] = ESC_DISK; 10018c2aff7Sartem subcl[1] = ESC_LOFI; 10142a7bdedSjacobs subcl[2] = ESC_PRINTER; 10242a7bdedSjacobs if (sysevent_subscribe_event(shp, EC_DEV_ADD, subcl, 3) != 0) { 10318c2aff7Sartem HAL_INFO (("subscribe(dev_add) failed %d", errno)); 10418c2aff7Sartem sysevent_unbind_handle(shp); 10518c2aff7Sartem return (FALSE); 10618c2aff7Sartem } 10742a7bdedSjacobs if (sysevent_subscribe_event(shp, EC_DEV_REMOVE, subcl, 3) != 0) { 10818c2aff7Sartem HAL_INFO (("subscribe(dev_remove) failed %d", errno)); 10918c2aff7Sartem sysevent_unbind_handle(shp); 11018c2aff7Sartem return (FALSE); 11118c2aff7Sartem } 11218c2aff7Sartem 11318c2aff7Sartem subcl[0] = ESC_DEV_BRANCH_REMOVE; 11418c2aff7Sartem if (sysevent_subscribe_event(shp, EC_DEV_BRANCH, subcl, 1) != 0) { 11518c2aff7Sartem HAL_INFO (("subscribe(dev_branch) failed %d", errno)); 11618c2aff7Sartem sysevent_unbind_handle(shp); 11718c2aff7Sartem return (FALSE); 11818c2aff7Sartem } 11918c2aff7Sartem 120d2ec54f7Sphitran subcl[0] = ESC_PWRCTL_ADD; 121d2ec54f7Sphitran subcl[1] = ESC_PWRCTL_REMOVE; 122d2ec54f7Sphitran subcl[2] = ESC_PWRCTL_STATE_CHANGE; 123d2ec54f7Sphitran subcl[3] = ESC_PWRCTL_BRIGHTNESS_UP; 124d2ec54f7Sphitran subcl[4] = ESC_PWRCTL_BRIGHTNESS_DOWN; 125d2ec54f7Sphitran subcl[5] = ESC_PWRCTL_POWER_BUTTON; 126d2ec54f7Sphitran if (sysevent_subscribe_event(shp, EC_PWRCTL, subcl, 6) != 0) { 1277b840e52Sphitran HAL_INFO(("subscribe(dev_add) failed %d", errno)); 1287b840e52Sphitran sysevent_unbind_handle(shp); 1297b840e52Sphitran return (FALSE); 1307b840e52Sphitran } 1317b840e52Sphitran 132112cd14aSqz150045 subcl[0] = ESC_DEVFS_DEVI_ADD; 133112cd14aSqz150045 if (sysevent_subscribe_event(shp, EC_DEVFS, subcl, 1) != 0) { 134112cd14aSqz150045 HAL_INFO (("subscribe(EC_DEVFS) failed %d", errno)); 135112cd14aSqz150045 sysevent_unbind_handle(shp); 136112cd14aSqz150045 return (FALSE); 137112cd14aSqz150045 } 138112cd14aSqz150045 139a9da3307Snp146283 subcl[0] = ESC_DR_AP_STATE_CHANGE; 140a9da3307Snp146283 if (sysevent_subscribe_event(shp, EC_DR, subcl, 1) != 0) { 141a9da3307Snp146283 HAL_INFO (("subscribe(dynamic reconfiguration) failed %d", 142a9da3307Snp146283 errno)); 143a9da3307Snp146283 sysevent_unbind_handle(shp); 144a9da3307Snp146283 return (FALSE); 145a9da3307Snp146283 } 146a9da3307Snp146283 14718c2aff7Sartem return (B_TRUE); 14818c2aff7Sartem } 14918c2aff7Sartem 15018c2aff7Sartem void 15118c2aff7Sartem sysevent_fini(void) 15218c2aff7Sartem { 15318c2aff7Sartem sysevent_unbind_handle(shp); 15418c2aff7Sartem shp = NULL; 15518c2aff7Sartem } 15618c2aff7Sartem 15718c2aff7Sartem static void 15818c2aff7Sartem sysevent_dev_handler(sysevent_t *ev) 15918c2aff7Sartem { 16018c2aff7Sartem char *class; 16118c2aff7Sartem char *subclass; 16218c2aff7Sartem nvlist_t *attr_list; 16318c2aff7Sartem char *phys_path; 16418c2aff7Sartem char *dev_name; 1657b840e52Sphitran char *dev_hid; 1667b840e52Sphitran char *dev_uid; 1677b840e52Sphitran uint_t dev_index; 16818c2aff7Sartem char s[1024]; 16918c2aff7Sartem ssize_t nwritten; 17018c2aff7Sartem 17118c2aff7Sartem if ((class = sysevent_get_class_name(ev)) == NULL) 17218c2aff7Sartem return; 17318c2aff7Sartem 17418c2aff7Sartem if ((subclass = sysevent_get_subclass_name(ev)) == NULL) 17518c2aff7Sartem return; 17618c2aff7Sartem 17718c2aff7Sartem if (sysevent_get_attr_list(ev, &attr_list) != 0) 17818c2aff7Sartem return; 17918c2aff7Sartem 180112cd14aSqz150045 if (strcmp(class, EC_DEVFS) == 0) { 181112cd14aSqz150045 if (nvlist_lookup_string(attr_list, DEVFS_PATHNAME, &phys_path) != 0) { 182112cd14aSqz150045 goto out; 183112cd14aSqz150045 } 184112cd14aSqz150045 185112cd14aSqz150045 snprintf(s, sizeof (s), "%s %s %s\n", 186112cd14aSqz150045 class, subclass, phys_path); 187112cd14aSqz150045 nwritten = write(sysevent_pipe_fds[1], s, strlen(s) + 1); 188112cd14aSqz150045 189112cd14aSqz150045 HAL_INFO (("sysevent_dev_handler: wrote %d bytes", nwritten)); 190112cd14aSqz150045 goto out; 191112cd14aSqz150045 } 192112cd14aSqz150045 193d2ec54f7Sphitran if (strcmp(class, EC_PWRCTL) == 0) { 194d2ec54f7Sphitran if (nvlist_lookup_string(attr_list, PWRCTL_DEV_PHYS_PATH, 1957b840e52Sphitran &phys_path) != 0) { 19618c2aff7Sartem goto out; 1977b840e52Sphitran } 198a9da3307Snp146283 } else if (strcmp(class, EC_DR) == 0) { 199a9da3307Snp146283 if (nvlist_lookup_string(attr_list, DR_AP_ID, 200a9da3307Snp146283 &phys_path) != 0) { 201a9da3307Snp146283 goto out; 202a9da3307Snp146283 } 2037b840e52Sphitran } else if (nvlist_lookup_string(attr_list, DEV_PHYS_PATH, &phys_path) 2047b840e52Sphitran != 0) { 2057b840e52Sphitran goto out; 2067b840e52Sphitran } 20718c2aff7Sartem 208a9da3307Snp146283 /* 209a9da3307Snp146283 * In case of EC_DR, use dev_name to store DR_HINT val 210a9da3307Snp146283 */ 211a9da3307Snp146283 if (strcmp(class, EC_DR) == 0) { 212a9da3307Snp146283 if (nvlist_lookup_string(attr_list, DR_HINT, &dev_name) != 0) { 213a9da3307Snp146283 goto out; 214a9da3307Snp146283 } 215a9da3307Snp146283 } else if (nvlist_lookup_string(attr_list, DEV_NAME, &dev_name) != 0) { 216d2ec54f7Sphitran if (strcmp(class, EC_PWRCTL) == 0) { 2177b840e52Sphitran dev_name = "noname"; 2187b840e52Sphitran } else { 21918c2aff7Sartem dev_name = ""; 2207b840e52Sphitran } 2217b840e52Sphitran } 22218c2aff7Sartem 223d2ec54f7Sphitran if (nvlist_lookup_string(attr_list, PWRCTL_DEV_HID, &dev_hid) != 0) { 2247b840e52Sphitran dev_hid = ""; 2257b840e52Sphitran } 226d2ec54f7Sphitran if (nvlist_lookup_string(attr_list, PWRCTL_DEV_UID, &dev_uid) != 0) { 2277b840e52Sphitran dev_uid = ""; 2287b840e52Sphitran } 229d2ec54f7Sphitran if (nvlist_lookup_uint32(attr_list, PWRCTL_DEV_INDEX, &dev_index) 2307b840e52Sphitran != 0) { 2317b840e52Sphitran dev_index = 0; 2327b840e52Sphitran } 2337b840e52Sphitran 2347b840e52Sphitran snprintf(s, sizeof (s), "%s %s %s %s %s %s %d\n", 2357b840e52Sphitran class, subclass, phys_path, dev_name, dev_hid, dev_uid, dev_index); 23618c2aff7Sartem nwritten = write(sysevent_pipe_fds[1], s, strlen(s) + 1); 23718c2aff7Sartem 23818c2aff7Sartem HAL_INFO (("sysevent_dev_handler: wrote %d bytes", nwritten)); 23918c2aff7Sartem 24018c2aff7Sartem out: 24118c2aff7Sartem nvlist_free(attr_list); 24218c2aff7Sartem } 24318c2aff7Sartem 24418c2aff7Sartem static gboolean 24518c2aff7Sartem sysevent_iochannel_data (GIOChannel *source, 24618c2aff7Sartem GIOCondition condition, 24718c2aff7Sartem gpointer user_data) 24818c2aff7Sartem { 24918c2aff7Sartem GError *err = NULL; 25018c2aff7Sartem gchar *s = NULL; 25118c2aff7Sartem gsize len; 25218c2aff7Sartem int matches; 25318c2aff7Sartem gchar class[1024]; 25418c2aff7Sartem gchar subclass[1024]; 25518c2aff7Sartem gchar phys_path[1024]; 25618c2aff7Sartem gchar dev_name[1024]; 2577b840e52Sphitran gchar dev_uid[1024]; 2587b840e52Sphitran gchar dev_hid[1024]; 2597b840e52Sphitran uint_t dev_index; 26018c2aff7Sartem 26118c2aff7Sartem HAL_INFO (("sysevent_iochannel_data")); 26218c2aff7Sartem 26318c2aff7Sartem while (g_io_channel_read_line (sysevent_iochannel, &s, &len, NULL, 26418c2aff7Sartem &err) == G_IO_STATUS_NORMAL) { 26518c2aff7Sartem if (len == 0) { 26618c2aff7Sartem break; 26718c2aff7Sartem } 268a9da3307Snp146283 HAL_INFO (("IOChannel val => %s", s)); 2697b840e52Sphitran class[0] = subclass[0] = phys_path[0] = dev_name[0] = 2707b840e52Sphitran dev_hid[0] = dev_uid[0] = '\0'; 2717b840e52Sphitran matches = sscanf(s, "%s %s %s %s %s %s %d", class, subclass, 2727b840e52Sphitran phys_path, dev_name, dev_hid, dev_uid, &dev_index); 27318c2aff7Sartem g_free (s); 27418c2aff7Sartem s = NULL; 27518c2aff7Sartem if (matches < 3) { 27618c2aff7Sartem continue; 27718c2aff7Sartem } 27818c2aff7Sartem HAL_INFO (("sysevent: class=%s, sub=%s", class, subclass)); 27918c2aff7Sartem 28018c2aff7Sartem if (strcmp(class, EC_DEV_ADD) == 0) { 28142a7bdedSjacobs if ((strcmp(subclass, ESC_DISK) == 0) || 28242a7bdedSjacobs (strcmp(subclass, ESC_PRINTER) == 0)) { 28318c2aff7Sartem sysevent_dev_add(phys_path, dev_name); 28418c2aff7Sartem } else if (strcmp(subclass, ESC_LOFI) == 0) { 28518c2aff7Sartem sysevent_lofi_add(phys_path, dev_name); 28618c2aff7Sartem } 28718c2aff7Sartem } else if (strcmp(class, EC_DEV_REMOVE) == 0) { 28842a7bdedSjacobs if ((strcmp(subclass, ESC_DISK) == 0) || 28942a7bdedSjacobs (strcmp(subclass, ESC_PRINTER) == 0)) { 29018c2aff7Sartem sysevent_dev_remove(phys_path, dev_name); 29118c2aff7Sartem } else if (strcmp(subclass, ESC_LOFI) == 0) { 29218c2aff7Sartem sysevent_lofi_remove(phys_path, dev_name); 29318c2aff7Sartem } 29418c2aff7Sartem } else if (strcmp(class, EC_DEV_BRANCH) == 0) { 29518c2aff7Sartem sysevent_dev_branch(phys_path); 296d2ec54f7Sphitran } else if (strcmp(class, EC_PWRCTL) == 0) { 297d2ec54f7Sphitran sysevent_pwrctl(class, subclass, phys_path, 298d2ec54f7Sphitran dev_name, dev_hid, dev_uid, dev_index); 299112cd14aSqz150045 } else if (strcmp(class, EC_DEVFS) == 0) { 300112cd14aSqz150045 if (strcmp(subclass, ESC_DEVFS_DEVI_ADD) == 0) { 301112cd14aSqz150045 sysevent_devfs_add(phys_path); 302112cd14aSqz150045 } 303a9da3307Snp146283 } else if (strcmp(class, EC_DR) == 0) { 304a9da3307Snp146283 /* 305a9da3307Snp146283 * Note: AP_ID is stored in phys_path and HINT is 306a9da3307Snp146283 * stored in dev_name, to avoid creating seperate 307a9da3307Snp146283 * variables and multiple conditions checking 308a9da3307Snp146283 */ 309a9da3307Snp146283 HAL_DEBUG (("In %s, AP_ID-> %s, Hint-> %s", class, 310a9da3307Snp146283 phys_path, dev_name)); 311a9da3307Snp146283 if (strcmp(subclass, ESC_DR_AP_STATE_CHANGE) == 0) { 312a9da3307Snp146283 sysevent_process_dr(phys_path, dev_name); 313a9da3307Snp146283 } 31418c2aff7Sartem } 31518c2aff7Sartem } 31618c2aff7Sartem 31718c2aff7Sartem if (err) { 31818c2aff7Sartem g_error_free (err); 31918c2aff7Sartem } 32018c2aff7Sartem 32118c2aff7Sartem return (TRUE); 32218c2aff7Sartem } 32318c2aff7Sartem 32418c2aff7Sartem static void 32518c2aff7Sartem sysevent_dev_add(gchar *devfs_path, gchar *name) 32618c2aff7Sartem { 32718c2aff7Sartem gchar *parent_devfs_path, *hotplug_devfs_path; 32818c2aff7Sartem HalDevice *parent; 32918c2aff7Sartem 33018c2aff7Sartem HAL_INFO (("dev_add: %s %s", name, devfs_path)); 33118c2aff7Sartem 33218c2aff7Sartem parent = hal_util_find_closest_ancestor (devfs_path, &parent_devfs_path, &hotplug_devfs_path); 33318c2aff7Sartem if (parent == NULL) { 33418c2aff7Sartem return; 33518c2aff7Sartem } 33618c2aff7Sartem 33718c2aff7Sartem HAL_INFO (("dev_add: parent=%s", parent_devfs_path)); 33818c2aff7Sartem HAL_INFO (("dev_add: real=%s", hotplug_devfs_path)); 33918c2aff7Sartem 34018c2aff7Sartem devinfo_add (parent, hotplug_devfs_path); 34118c2aff7Sartem 34218c2aff7Sartem g_free (parent_devfs_path); 34318c2aff7Sartem g_free (hotplug_devfs_path); 34418c2aff7Sartem 34518c2aff7Sartem hotplug_event_process_queue (); 34618c2aff7Sartem } 34718c2aff7Sartem 34818c2aff7Sartem static void 34918c2aff7Sartem sysevent_dev_remove(gchar *devfs_path, gchar *name) 35018c2aff7Sartem { 35118c2aff7Sartem HAL_INFO (("dev_remove: %s %s", name, devfs_path)); 35218c2aff7Sartem 35318c2aff7Sartem devinfo_remove_branch (devfs_path, NULL); 35418c2aff7Sartem hotplug_event_process_queue (); 35518c2aff7Sartem } 35618c2aff7Sartem 35718c2aff7Sartem static void 35818c2aff7Sartem sysevent_dev_branch(gchar *devfs_path) 35918c2aff7Sartem { 36018c2aff7Sartem HAL_INFO (("branch_remove: %s", devfs_path)); 36118c2aff7Sartem 36218c2aff7Sartem devinfo_remove_branch (devfs_path, NULL); 36318c2aff7Sartem hotplug_event_process_queue (); 36418c2aff7Sartem } 36518c2aff7Sartem 36618c2aff7Sartem static void 36718c2aff7Sartem sysevent_lofi_add(gchar *devfs_path, gchar *name) 36818c2aff7Sartem { 36918c2aff7Sartem di_node_t node; 37018c2aff7Sartem const char *parent_udi; 37118c2aff7Sartem HalDevice *d, *parent; 37218c2aff7Sartem 37318c2aff7Sartem HAL_INFO (("lofi_add: %s %s", name, devfs_path)); 37418c2aff7Sartem 37518c2aff7Sartem if ((d = hal_device_store_match_key_value_string (hald_get_gdl (), 37618c2aff7Sartem "solaris.devfs_path", devfs_path)) == NULL) { 37718c2aff7Sartem HAL_INFO (("device not found in GDL %s", devfs_path)); 37818c2aff7Sartem return; 37918c2aff7Sartem } 38018c2aff7Sartem parent_udi = hal_device_property_get_string (d, "info.parent"); 38118c2aff7Sartem if ((parent_udi == NULL) || (strlen(parent_udi) == 0)) { 38218c2aff7Sartem HAL_INFO (("parent not found in GDL %s", parent_udi)); 38318c2aff7Sartem return; 38418c2aff7Sartem } 38518c2aff7Sartem if ((parent = hal_device_store_match_key_value_string (hald_get_gdl (), 38618c2aff7Sartem "info.udi", parent_udi)) == NULL) { 38718c2aff7Sartem HAL_INFO (("parent not found in GDL %s", parent_udi)); 38818c2aff7Sartem return; 38918c2aff7Sartem } 39018c2aff7Sartem 39118c2aff7Sartem if ((node = di_init (devfs_path, DINFOCPYALL)) == DI_NODE_NIL) { 39218c2aff7Sartem HAL_INFO (("device not found in devinfo %s", devfs_path)); 39318c2aff7Sartem return; 39418c2aff7Sartem } 39518c2aff7Sartem 39600687e57Sartem HAL_INFO (("device %s parent %s", hal_device_get_udi (d), parent_udi)); 39718c2aff7Sartem devinfo_lofi_add_major (parent, node, devfs_path, NULL, TRUE, d); 39818c2aff7Sartem 39918c2aff7Sartem di_fini (node); 40018c2aff7Sartem 40118c2aff7Sartem hotplug_event_process_queue (); 40218c2aff7Sartem } 40318c2aff7Sartem 40418c2aff7Sartem static void 40518c2aff7Sartem sysevent_lofi_remove(gchar *parent_devfs_path, gchar *name) 40618c2aff7Sartem { 40718c2aff7Sartem devinfo_lofi_remove_minor(parent_devfs_path, name); 40818c2aff7Sartem hotplug_event_process_queue (); 40918c2aff7Sartem } 410112cd14aSqz150045 411112cd14aSqz150045 static HalDevice * 412112cd14aSqz150045 lookup_parent(char *devfs_path) 413112cd14aSqz150045 { 414112cd14aSqz150045 gchar *path = NULL; 415112cd14aSqz150045 HalDevice *parent = NULL; 416112cd14aSqz150045 char *p; 417112cd14aSqz150045 418112cd14aSqz150045 path = strdup (devfs_path); 419112cd14aSqz150045 p = strrchr (path, '/'); 420112cd14aSqz150045 if (p == NULL) { 421112cd14aSqz150045 free (path); 422112cd14aSqz150045 return (NULL); 423112cd14aSqz150045 } 424112cd14aSqz150045 *p = '\0'; 425112cd14aSqz150045 426112cd14aSqz150045 /* Look up the parent node in the gdl. */ 427112cd14aSqz150045 parent = hal_device_store_match_key_value_string (hald_get_gdl (), 428112cd14aSqz150045 "solaris.devfs_path", path); 429112cd14aSqz150045 430112cd14aSqz150045 if (parent == NULL) { 431112cd14aSqz150045 /* Look up the parent node in the tdl. */ 432112cd14aSqz150045 parent = hal_device_store_match_key_value_string (hald_get_tdl (), 433112cd14aSqz150045 "solaris.devfs_path", path); 434112cd14aSqz150045 } 435112cd14aSqz150045 436112cd14aSqz150045 free (path); 437112cd14aSqz150045 return (parent); 438112cd14aSqz150045 } 439112cd14aSqz150045 440112cd14aSqz150045 /* 441112cd14aSqz150045 * Handle the USB bus devices hot plugging events. 442112cd14aSqz150045 */ 443112cd14aSqz150045 static void 444112cd14aSqz150045 sysevent_devfs_add(gchar *devfs_path) 445112cd14aSqz150045 { 446112cd14aSqz150045 di_node_t node; 447112cd14aSqz150045 HalDevice *parent; 448112cd14aSqz150045 char *driver_name; 449112cd14aSqz150045 450112cd14aSqz150045 HAL_INFO (("devfs_handle: %s", devfs_path)); 451112cd14aSqz150045 452112cd14aSqz150045 if ((node = di_init (devfs_path, DINFOCPYALL)) == DI_NODE_NIL) { 453112cd14aSqz150045 HAL_INFO (("device not found in devinfo %s", devfs_path)); 454112cd14aSqz150045 return; 455112cd14aSqz150045 } 456112cd14aSqz150045 457112cd14aSqz150045 if ((driver_name = di_driver_name (node)) == NULL) 458112cd14aSqz150045 goto out; 459112cd14aSqz150045 460112cd14aSqz150045 /* The disk and printer devices are handled by EC_DEV_ADD class. */ 461112cd14aSqz150045 if ((strcmp (driver_name, "scsa2usb") == 0) || 462112cd14aSqz150045 (strcmp (driver_name, "usbprn") == 0)) 463112cd14aSqz150045 goto out; 464112cd14aSqz150045 465112cd14aSqz150045 if ((parent = lookup_parent (devfs_path)) == NULL) 466112cd14aSqz150045 goto out; 467112cd14aSqz150045 468112cd14aSqz150045 devinfo_usb_add (parent, node, devfs_path, NULL); 469112cd14aSqz150045 470112cd14aSqz150045 di_fini (node); 471112cd14aSqz150045 472112cd14aSqz150045 hotplug_event_process_queue (); 473112cd14aSqz150045 474112cd14aSqz150045 return; 475112cd14aSqz150045 476112cd14aSqz150045 out: 477112cd14aSqz150045 di_fini (node); 478112cd14aSqz150045 } 479d2ec54f7Sphitran 480d2ec54f7Sphitran static void 481d2ec54f7Sphitran sysevent_pwrctl(gchar *class, gchar *subclass, gchar *phys_path, 482d2ec54f7Sphitran gchar *dev_name, gchar *dev_hid, gchar *dev_uid, uint_t dev_index) 483d2ec54f7Sphitran { 484d2ec54f7Sphitran const gchar prefix[] = "/org/freedesktop/Hal/devices/pseudo/acpi_drv_0"; 485d2ec54f7Sphitran gchar udi[HAL_PATH_MAX]; 486d2ec54f7Sphitran 487d2ec54f7Sphitran if (strcmp(dev_hid, "PNP0C0A") == 0) { 488d2ec54f7Sphitran snprintf(udi, sizeof(udi), "%s_battery%d_0", prefix, dev_index); 489*076d97abSPhi Tran devinfo_battery_rescan(phys_path, udi); 490d2ec54f7Sphitran } else if (strcmp(dev_hid, "ACPI0003") == 0) { 491d2ec54f7Sphitran snprintf(udi, sizeof (udi), "%s_ac%d_0", prefix, dev_index); 492*076d97abSPhi Tran devinfo_battery_rescan(phys_path, udi); 493d2ec54f7Sphitran } else if (strcmp(dev_hid, "PNP0C0D") == 0) { 494d2ec54f7Sphitran snprintf(udi, sizeof (udi), "%s_lid_0", prefix); 495*076d97abSPhi Tran devinfo_lid_event(subclass, udi); 496d2ec54f7Sphitran } else if (strcmp(subclass, ESC_PWRCTL_POWER_BUTTON) == 0) { 497*076d97abSPhi Tran devinfo_power_button_event(); 498d2ec54f7Sphitran } else if ((strcmp(subclass, ESC_PWRCTL_BRIGHTNESS_UP) == 0) || 499d2ec54f7Sphitran (strcmp(subclass, ESC_PWRCTL_BRIGHTNESS_DOWN) == 0)) { 500*076d97abSPhi Tran devinfo_brightness_hotkeys_event(subclass); 501d2ec54f7Sphitran } else { 502d2ec54f7Sphitran HAL_INFO(("Unmatched EC_PWRCTL")); 503d2ec54f7Sphitran } 504d2ec54f7Sphitran } 505a9da3307Snp146283 506a9da3307Snp146283 static void 507a9da3307Snp146283 sysevent_dr_remove_cpu() 508a9da3307Snp146283 { 509a9da3307Snp146283 510a9da3307Snp146283 HalDeviceStore *gdl; 511a9da3307Snp146283 GSList *iter; 512a9da3307Snp146283 HalDevice *d, *del_dev; 513a9da3307Snp146283 int cpu_id, del_cpuid; 514a9da3307Snp146283 kstat_ctl_t *kc; 515a9da3307Snp146283 kstat_t *ksp; 516a9da3307Snp146283 kstat_named_t *ksdata; 517a9da3307Snp146283 const char *cpu_devfs_path; 518a9da3307Snp146283 /* 519a9da3307Snp146283 * Find the CPU's that are DR removed. For each "processor" device in 520a9da3307Snp146283 * HAL device tree, check if it has its corresponding kstat_info. If 521a9da3307Snp146283 * not, then, that cpu has been removed and can remove the entry from 522a9da3307Snp146283 * HAL entry 523a9da3307Snp146283 */ 524a9da3307Snp146283 525a9da3307Snp146283 HAL_DEBUG (("sysevent_dr_remove_cpu()")); 526a9da3307Snp146283 kc = kstat_open (); 527a9da3307Snp146283 if (kc == NULL) { 528a9da3307Snp146283 HAL_INFO (("Error in removing HAL cpu entry during DR. Could" 529a9da3307Snp146283 " not open kstat to get cpu info: %s", strerror (errno))); 530a9da3307Snp146283 return; 531a9da3307Snp146283 } 532a9da3307Snp146283 533a9da3307Snp146283 /* 534a9da3307Snp146283 * Iterate through the HAL device list to get the processor devices 535a9da3307Snp146283 */ 536a9da3307Snp146283 gdl = hald_get_gdl (); 537a9da3307Snp146283 iter = gdl->devices; 538a9da3307Snp146283 539a9da3307Snp146283 while (iter != NULL) { 540a9da3307Snp146283 d = HAL_DEVICE (iter->data); 541a9da3307Snp146283 542a9da3307Snp146283 if (!hal_device_has_property (d, "processor.number")) { 543a9da3307Snp146283 iter = iter->next; 544a9da3307Snp146283 continue; 545a9da3307Snp146283 } 546a9da3307Snp146283 547a9da3307Snp146283 cpu_id = hal_device_property_get_int (d, "processor.number"); 548a9da3307Snp146283 549a9da3307Snp146283 /* 550a9da3307Snp146283 * Check if the above cpu_id has its info in kstat 551a9da3307Snp146283 */ 552a9da3307Snp146283 553a9da3307Snp146283 ksp = kstat_lookup (kc, "cpu_info", cpu_id, NULL); 554a9da3307Snp146283 if (ksp != NULL) { 555a9da3307Snp146283 iter = iter->next; 556a9da3307Snp146283 continue; 557a9da3307Snp146283 } 558a9da3307Snp146283 /* 559a9da3307Snp146283 * kstat info not found. Delete the device entry 560a9da3307Snp146283 */ 561a9da3307Snp146283 HAL_INFO ((" Remove CPU entry: %d", cpu_id)); 562a9da3307Snp146283 iter = iter->next; 563a9da3307Snp146283 cpu_devfs_path = hal_device_property_get_string (d, 564a9da3307Snp146283 "solaris.devfs_path"); 565a9da3307Snp146283 if (cpu_devfs_path == NULL) { 566a9da3307Snp146283 HAL_INFO (("Could not get cpu_devfs_path to " 567a9da3307Snp146283 "remove for cpu_id %d", cpu_id)); 568a9da3307Snp146283 } else { 569a9da3307Snp146283 /* 570a9da3307Snp146283 * Remove the cpu device 571a9da3307Snp146283 */ 572a9da3307Snp146283 HAL_DEBUG (("Queue %s for removal", cpu_devfs_path)); 573a9da3307Snp146283 devinfo_remove_enqueue ((char *)cpu_devfs_path, NULL); 574a9da3307Snp146283 hotplug_event_process_queue (); 575a9da3307Snp146283 } 576a9da3307Snp146283 } 577a9da3307Snp146283 578a9da3307Snp146283 if (kc) { 579a9da3307Snp146283 kstat_close (kc); 580a9da3307Snp146283 } 581a9da3307Snp146283 } 582a9da3307Snp146283 583a9da3307Snp146283 int 584a9da3307Snp146283 sysevent_dr_insert_cpu(di_node_t node, void *arg) 585a9da3307Snp146283 { 586a9da3307Snp146283 char *devfs_path; 587a9da3307Snp146283 char *device_type = NULL; 588a9da3307Snp146283 DevinfoDevHandler *dh; 589a9da3307Snp146283 590a9da3307Snp146283 dh = &devinfo_cpu_handler; 591a9da3307Snp146283 devfs_path = di_devfs_path (node); 592a9da3307Snp146283 593a9da3307Snp146283 (void) di_prop_lookup_strings (DDI_DEV_T_ANY, node, "device_type", 594a9da3307Snp146283 &device_type); 595a9da3307Snp146283 596a9da3307Snp146283 dh->add (NULL, node, devfs_path, device_type); 597a9da3307Snp146283 598a9da3307Snp146283 di_devfs_path_free (devfs_path); 599a9da3307Snp146283 return (DI_WALK_CONTINUE); 600a9da3307Snp146283 } 601a9da3307Snp146283 602a9da3307Snp146283 /* 603a9da3307Snp146283 * Remove/Add the DR event device 604a9da3307Snp146283 * Note: Currently it supports only CPU DR events 605a9da3307Snp146283 */ 606a9da3307Snp146283 static void 607a9da3307Snp146283 sysevent_process_dr(gchar *ap_id, gchar *hint_val) 608a9da3307Snp146283 { 609a9da3307Snp146283 cfga_err_t cfgerr; 610a9da3307Snp146283 cfga_list_data_t *cfg_stat; 611a9da3307Snp146283 int nlist; 612a9da3307Snp146283 char *errstr; 613a9da3307Snp146283 di_node_t root_node; 614a9da3307Snp146283 615a9da3307Snp146283 if ((ap_id == NULL) || (hint_val == NULL)) 616a9da3307Snp146283 return; 617a9da3307Snp146283 HAL_DEBUG (("sysevent_process_dr: %s", ap_id)); 618a9da3307Snp146283 619a9da3307Snp146283 cfgerr = config_list_ext (1, (char *const *)&ap_id, &cfg_stat, &nlist, 620a9da3307Snp146283 NULL, NULL, &errstr, 0); 621a9da3307Snp146283 622a9da3307Snp146283 if (cfgerr != CFGA_OK) { 623a9da3307Snp146283 HAL_INFO (("DR sysevent process %d config_list_ext error: %s", 624a9da3307Snp146283 ap_id, errstr)); 625a9da3307Snp146283 goto out; 626a9da3307Snp146283 } 627a9da3307Snp146283 /* 628a9da3307Snp146283 * Check if the device type is CPU 629a9da3307Snp146283 */ 630a9da3307Snp146283 HAL_DEBUG ((" Ap-Type: %s, State: %d", cfg_stat->ap_type, 631a9da3307Snp146283 cfg_stat->ap_r_state)); 632a9da3307Snp146283 if (strcmp (cfg_stat->ap_type, "CPU") == 0) { 633a9da3307Snp146283 if (strcmp (hint_val, DR_HINT_REMOVE) == 0) { 634a9da3307Snp146283 sysevent_dr_remove_cpu(); 635a9da3307Snp146283 } else if (strcmp (hint_val, DR_HINT_INSERT) == 0) { 636a9da3307Snp146283 /* 637a9da3307Snp146283 * Go through the device list and add the new cpu 638a9da3307Snp146283 * entries into HAL 639a9da3307Snp146283 */ 640a9da3307Snp146283 if ((root_node = 641a9da3307Snp146283 di_init ("/", DINFOCPYALL)) == DI_NODE_NIL) { 642a9da3307Snp146283 HAL_INFO (("di_init failed. "\ 643a9da3307Snp146283 "Cannot insert CPU")); 644a9da3307Snp146283 goto out; 645a9da3307Snp146283 } 646a9da3307Snp146283 di_walk_node (root_node, DI_WALK_CLDFIRST, NULL, 647a9da3307Snp146283 sysevent_dr_insert_cpu); 648a9da3307Snp146283 di_fini (root_node); 649a9da3307Snp146283 hotplug_event_process_queue (); 650a9da3307Snp146283 } 651a9da3307Snp146283 } else { 652a9da3307Snp146283 HAL_INFO (("Not a CPU, so cannot DR")); 653a9da3307Snp146283 } 654a9da3307Snp146283 655a9da3307Snp146283 out: 656a9da3307Snp146283 if (cfg_stat) 657a9da3307Snp146283 free (cfg_stat); 658a9da3307Snp146283 if (errstr) 659a9da3307Snp146283 free (errstr); 660a9da3307Snp146283 } 661