xref: /titanic_44/usr/src/cmd/hal/hald/solaris/sysevent.c (revision 076d97abc78bcba2f2216859fe2c6913cc7aff32)
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
sysevent_init(void)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
sysevent_fini(void)15118c2aff7Sartem sysevent_fini(void)
15218c2aff7Sartem {
15318c2aff7Sartem 	sysevent_unbind_handle(shp);
15418c2aff7Sartem 	shp = NULL;
15518c2aff7Sartem }
15618c2aff7Sartem 
15718c2aff7Sartem static void
sysevent_dev_handler(sysevent_t * ev)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
sysevent_iochannel_data(GIOChannel * source,GIOCondition condition,gpointer user_data)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
sysevent_dev_add(gchar * devfs_path,gchar * name)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
sysevent_dev_remove(gchar * devfs_path,gchar * name)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
sysevent_dev_branch(gchar * devfs_path)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
sysevent_lofi_add(gchar * devfs_path,gchar * name)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
sysevent_lofi_remove(gchar * parent_devfs_path,gchar * name)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 *
lookup_parent(char * devfs_path)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
sysevent_devfs_add(gchar * devfs_path)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
sysevent_pwrctl(gchar * class,gchar * subclass,gchar * phys_path,gchar * dev_name,gchar * dev_hid,gchar * dev_uid,uint_t dev_index)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
sysevent_dr_remove_cpu()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
sysevent_dr_insert_cpu(di_node_t node,void * arg)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
sysevent_process_dr(gchar * ap_id,gchar * hint_val)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