17b840e52Sphitran /***************************************************************************
27b840e52Sphitran  *
37b840e52Sphitran  * devinfo_acpi : acpi devices
47b840e52Sphitran  *
5d2ec54f7Sphitran  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
67b840e52Sphitran  * Use is subject to license terms.
77b840e52Sphitran  *
87b840e52Sphitran  * Licensed under the Academic Free License version 2.1
97b840e52Sphitran  *
107b840e52Sphitran  **************************************************************************/
117b840e52Sphitran 
127b840e52Sphitran #ifdef HAVE_CONFIG_H
137b840e52Sphitran #include <config.h>
147b840e52Sphitran #endif
157b840e52Sphitran 
167b840e52Sphitran #include <stdio.h>
177b840e52Sphitran #include <string.h>
187b840e52Sphitran #include <sys/utsname.h>
197b840e52Sphitran #include <libdevinfo.h>
207b840e52Sphitran #include <sys/mkdev.h>
217b840e52Sphitran #include <sys/stat.h>
227b840e52Sphitran #include <unistd.h>
23d2ec54f7Sphitran #include <sys/sysevent/dev.h>
24d2ec54f7Sphitran #include <sys/sysevent/pwrctl.h>
257b840e52Sphitran 
267b840e52Sphitran #include "../osspec.h"
277b840e52Sphitran #include "../logger.h"
287b840e52Sphitran #include "../hald.h"
297b840e52Sphitran #include "../hald_dbus.h"
307b840e52Sphitran #include "../device_info.h"
317b840e52Sphitran #include "../util.h"
327b840e52Sphitran #include "../hald_runner.h"
337b840e52Sphitran #include "devinfo_acpi.h"
347b840e52Sphitran 
35*076d97abSPhi Tran #define		DEVINFO_PROBE_ACPI_TIMEOUT	30000
367b840e52Sphitran 
377b840e52Sphitran static HalDevice *devinfo_acpi_add(HalDevice *, di_node_t, char *, char *);
38d2ec54f7Sphitran static HalDevice *devinfo_power_button_add(HalDevice *parent, di_node_t node,
39d2ec54f7Sphitran     char *devfs_path, char *device_type);
40d2ec54f7Sphitran static void devinfo_battery_rescan_probing_done(HalDevice *d, guint32 exit_type,
41d2ec54f7Sphitran     gint return_code, char **error, gpointer userdata1, gpointer userdata2);
427b840e52Sphitran 
437b840e52Sphitran DevinfoDevHandler devinfo_acpi_handler = {
447b840e52Sphitran 	devinfo_acpi_add,
457b840e52Sphitran 	NULL,
467b840e52Sphitran 	NULL,
477b840e52Sphitran 	NULL,
487b840e52Sphitran 	NULL,
4959066d3cSphitran 	devinfo_acpi_get_prober
507b840e52Sphitran };
517b840e52Sphitran 
52d2ec54f7Sphitran DevinfoDevHandler devinfo_power_button_handler = {
53d2ec54f7Sphitran 	devinfo_power_button_add,
54d2ec54f7Sphitran 	NULL,
55d2ec54f7Sphitran 	NULL,
56d2ec54f7Sphitran 	NULL,
57d2ec54f7Sphitran 	NULL,
58d2ec54f7Sphitran 	NULL
59d2ec54f7Sphitran };
60d2ec54f7Sphitran 
617b840e52Sphitran static HalDevice *
devinfo_acpi_add(HalDevice * parent,di_node_t node,char * devfs_path,char * device_type)627b840e52Sphitran devinfo_acpi_add(HalDevice *parent, di_node_t node, char *devfs_path,
637b840e52Sphitran     char *device_type)
647b840e52Sphitran {
657b840e52Sphitran 	HalDevice *d, *computer;
667b840e52Sphitran 	char	*driver_name;
677b840e52Sphitran 	di_devlink_handle_t devlink_hdl;
687b840e52Sphitran 	int	major;
697b840e52Sphitran 	di_minor_t minor;
707b840e52Sphitran 	dev_t   dev;
717b840e52Sphitran 	char    *minor_path = NULL;
727b840e52Sphitran 	char    *devpath;
737b840e52Sphitran 
747b840e52Sphitran 	driver_name = di_driver_name(node);
75d2ec54f7Sphitran 	if ((driver_name == NULL) || (strcmp(driver_name, "acpi_drv") != 0)) {
767b840e52Sphitran 		return (NULL);
777b840e52Sphitran 	}
787b840e52Sphitran 
797b840e52Sphitran 	d = hal_device_new();
807b840e52Sphitran 
817b840e52Sphitran 	if ((computer = hal_device_store_find(hald_get_gdl(),
827b840e52Sphitran 	    "/org/freedesktop/Hal/devices/computer")) ||
837b840e52Sphitran 	    (computer = hal_device_store_find(hald_get_tdl(),
847b840e52Sphitran 	    "/org/freedesktop/Hal/devices/computer"))) {
857b840e52Sphitran 		hal_device_property_set_string(computer,
867b840e52Sphitran 		    "system.formfactor", "laptop");
8759066d3cSphitran 		hal_device_property_set_string(computer,
8859066d3cSphitran 		    "power_management.type", "acpi");
897b840e52Sphitran 	}
907b840e52Sphitran 	devinfo_set_default_properties(d, parent, node, devfs_path);
9159066d3cSphitran 	devinfo_add_enqueue(d, devfs_path, &devinfo_acpi_handler);
927b840e52Sphitran 
937b840e52Sphitran 	major = di_driver_major(node);
947b840e52Sphitran 	if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
957b840e52Sphitran 		return (d);
967b840e52Sphitran 	}
977b840e52Sphitran 	minor = DI_MINOR_NIL;
987b840e52Sphitran 	while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
997b840e52Sphitran 		dev = di_minor_devt(minor);
1007b840e52Sphitran 		if ((major != major(dev)) ||
1017b840e52Sphitran 		    (di_minor_type(minor) != DDM_MINOR) ||
1027b840e52Sphitran 		    (di_minor_spectype(minor) != S_IFCHR) ||
1037b840e52Sphitran 		    ((minor_path = di_devfs_minor_path(minor)) == NULL)) {
1047b840e52Sphitran 			continue;
1057b840e52Sphitran 		}
1067b840e52Sphitran 
1077b840e52Sphitran 		if (hal_device_store_match_key_value_string(hald_get_gdl(),
1087b840e52Sphitran 		    "solaris.devfs_path", minor_path) == NULL) {
10959066d3cSphitran 			devinfo_acpi_add_minor(d, node, minor_path, dev);
1107b840e52Sphitran 		}
1117b840e52Sphitran 
1127b840e52Sphitran 		di_devfs_path_free(minor_path);
1137b840e52Sphitran 	}
1147b840e52Sphitran 	di_devlink_fini(&devlink_hdl);
1157b840e52Sphitran 
1167b840e52Sphitran 	return (d);
1177b840e52Sphitran }
1187b840e52Sphitran 
1197b840e52Sphitran void
devinfo_acpi_add_minor(HalDevice * parent,di_node_t node,char * minor_path,dev_t dev)12059066d3cSphitran devinfo_acpi_add_minor(HalDevice *parent, di_node_t node, char *minor_path,
1217b840e52Sphitran     dev_t dev)
1227b840e52Sphitran {
1237b840e52Sphitran 	HalDevice *d;
1247b840e52Sphitran 
1257b840e52Sphitran 	d = hal_device_new();
1267b840e52Sphitran 	devinfo_set_default_properties(d, parent, node, minor_path);
12759066d3cSphitran 	devinfo_add_enqueue(d, minor_path, &devinfo_acpi_handler);
1287b840e52Sphitran }
1297b840e52Sphitran 
130d2ec54f7Sphitran static HalDevice *
devinfo_power_button_add(HalDevice * parent,di_node_t node,char * devfs_path,char * device_type)131d2ec54f7Sphitran devinfo_power_button_add(HalDevice *parent, di_node_t node, char *devfs_path,
132d2ec54f7Sphitran     char *device_type)
133d2ec54f7Sphitran {
134d2ec54f7Sphitran 	HalDevice *d;
135d2ec54f7Sphitran 	char *driver_name;
136d2ec54f7Sphitran 
137d2ec54f7Sphitran 	driver_name = di_driver_name(node);
138d2ec54f7Sphitran 	if ((driver_name == NULL) || (strcmp(driver_name, "power") != 0)) {
139d2ec54f7Sphitran 		return (NULL);
140d2ec54f7Sphitran 	}
141d2ec54f7Sphitran 
142d2ec54f7Sphitran 	d = hal_device_new();
143d2ec54f7Sphitran 
144d2ec54f7Sphitran 	devinfo_set_default_properties(d, parent, node, devfs_path);
145d2ec54f7Sphitran 	hal_device_add_capability(d, "button");
146d2ec54f7Sphitran 	hal_device_property_set_bool(d, "button.has_state", FALSE);
147d2ec54f7Sphitran 	hal_device_property_set_string(d, "info.category", "input");
148d2ec54f7Sphitran 	hal_device_property_set_string(d, "button.type", "power");
149d2ec54f7Sphitran 	hal_device_property_set_string(d, "info.product", "Power Button");
150d2ec54f7Sphitran 
151d2ec54f7Sphitran 	devinfo_add_enqueue(d, devfs_path, &devinfo_power_button_handler);
152d2ec54f7Sphitran 
153d2ec54f7Sphitran 	return (d);
154d2ec54f7Sphitran }
155d2ec54f7Sphitran 
156d2ec54f7Sphitran void
devinfo_power_button_event(void)157*076d97abSPhi Tran devinfo_power_button_event(void)
158d2ec54f7Sphitran {
159d2ec54f7Sphitran 	HalDevice *d = NULL;
160d2ec54f7Sphitran 	HalDeviceStore *store = hald_get_gdl();
161d2ec54f7Sphitran 
162d2ec54f7Sphitran 	d = hal_device_store_match_key_value_string (store, "button.type",
163d2ec54f7Sphitran 	    "power");
164d2ec54f7Sphitran 	if (d != NULL) {
165d2ec54f7Sphitran 		device_send_signal_condition(d, "ButtonPressed", "power");
166d2ec54f7Sphitran 	}
167d2ec54f7Sphitran }
168d2ec54f7Sphitran 
169d2ec54f7Sphitran void
devinfo_brightness_hotkeys_event(char * subclass)170*076d97abSPhi Tran devinfo_brightness_hotkeys_event(char *subclass)
171d2ec54f7Sphitran {
172d2ec54f7Sphitran 	HalDevice *d = NULL;
173d2ec54f7Sphitran 
174d2ec54f7Sphitran 	if ((d = hal_device_store_find(hald_get_gdl(),
175d2ec54f7Sphitran 	    "/org/freedesktop/Hal/devices/computer")) ||
176d2ec54f7Sphitran 	    (d = hal_device_store_find(hald_get_tdl(),
177d2ec54f7Sphitran 	    "/org/freedesktop/Hal/devices/computer"))) {
178d2ec54f7Sphitran 		if (strcmp(subclass, ESC_PWRCTL_BRIGHTNESS_UP) == 0) {
179d2ec54f7Sphitran 			device_send_signal_condition(d, "ButtonPressed",
180d2ec54f7Sphitran 			    "brightness-up");
181d2ec54f7Sphitran 		} else {
182d2ec54f7Sphitran 			device_send_signal_condition(d, "ButtonPressed",
183d2ec54f7Sphitran 			    "brightness-down");
184d2ec54f7Sphitran 		}
185*076d97abSPhi Tran 	}
186d2ec54f7Sphitran }
187d2ec54f7Sphitran 
1887b840e52Sphitran void
devinfo_battery_rescan(char * parent_devfs_path,gchar * udi)189*076d97abSPhi Tran devinfo_battery_rescan(char *parent_devfs_path, gchar *udi)
1907b840e52Sphitran {
1917b840e52Sphitran 	HalDevice *d = NULL;
1927b840e52Sphitran 
1937b840e52Sphitran 	d = hal_device_store_find(hald_get_gdl(), udi);
1947b840e52Sphitran 	if (d == NULL) {
1957b840e52Sphitran 		HAL_INFO(("device not found %s", udi));
1967b840e52Sphitran 		return;
1977b840e52Sphitran 	}
1987b840e52Sphitran 
199d2ec54f7Sphitran 	hald_runner_run(d, "hald-probe-acpi", NULL,
200*076d97abSPhi Tran 	    DEVINFO_PROBE_ACPI_TIMEOUT, devinfo_battery_rescan_probing_done,
2017b840e52Sphitran 	    NULL, NULL);
2027b840e52Sphitran }
2037b840e52Sphitran 
204d2ec54f7Sphitran void
devinfo_lid_event(char * subclass,gchar * udi)205*076d97abSPhi Tran devinfo_lid_event(char *subclass, gchar *udi)
206d2ec54f7Sphitran {
207d2ec54f7Sphitran 	HalDevice *d = NULL;
208d2ec54f7Sphitran 
209d2ec54f7Sphitran 	d = hal_device_store_find(hald_get_gdl(), udi);
210d2ec54f7Sphitran 	if (d == NULL) {
211d2ec54f7Sphitran 		HAL_INFO(("device not found %s", udi));
212d2ec54f7Sphitran 		return;
213d2ec54f7Sphitran 	}
214d2ec54f7Sphitran 
215d2ec54f7Sphitran 	hal_device_property_set_bool(d, "button.state.value",
216*076d97abSPhi Tran 	    (strcmp(subclass, ESC_PWRCTL_REMOVE) == 0));
217d2ec54f7Sphitran 	device_send_signal_condition(d, "ButtonPressed", "lid");
218d2ec54f7Sphitran }
219d2ec54f7Sphitran 
220*076d97abSPhi Tran gboolean
devinfo_lid_rescan(HalDevice * d)221*076d97abSPhi Tran devinfo_lid_rescan(HalDevice *d)
222*076d97abSPhi Tran {
223*076d97abSPhi Tran 	if (hal_device_property_get_bool(d, "button.workaround")) {
224*076d97abSPhi Tran 		/* Set lid state to open for workaround */
225*076d97abSPhi Tran 		hal_device_property_set_bool(d, "button.state.value", FALSE);
226*076d97abSPhi Tran 	} else {
227*076d97abSPhi Tran 		hald_runner_run(d, "hald-probe-acpi", NULL,
228*076d97abSPhi Tran 		    DEVINFO_PROBE_ACPI_TIMEOUT,
229*076d97abSPhi Tran 		    devinfo_battery_rescan_probing_done, NULL, NULL);
230*076d97abSPhi Tran 	}
231*076d97abSPhi Tran 
232*076d97abSPhi Tran 	return (TRUE);
233*076d97abSPhi Tran }
234*076d97abSPhi Tran 
2357b840e52Sphitran static void
devinfo_battery_rescan_probing_done(HalDevice * d,guint32 exit_type,gint return_code,char ** error,gpointer userdata1,gpointer userdata2)2367b840e52Sphitran devinfo_battery_rescan_probing_done(HalDevice *d, guint32 exit_type,
2377b840e52Sphitran     gint return_code, char **error, gpointer userdata1, gpointer userdata2)
2387b840e52Sphitran {
2397b840e52Sphitran 	/* hald_runner_run() requires this function since cannot pass NULL */
2407b840e52Sphitran }
2417b840e52Sphitran 
2427b840e52Sphitran const gchar *
devinfo_acpi_get_prober(HalDevice * d,int * timeout)24359066d3cSphitran devinfo_acpi_get_prober(HalDevice *d, int *timeout)
2447b840e52Sphitran {
245*076d97abSPhi Tran 	*timeout = DEVINFO_PROBE_ACPI_TIMEOUT;    /* 30 second timeout */
246d2ec54f7Sphitran 	return ("hald-probe-acpi");
2477b840e52Sphitran }
248