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