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