14035Sphitran /***************************************************************************
24035Sphitran  *
34035Sphitran  * devinfo_acpi : acpi devices
44035Sphitran  *
5*6573Sphitran  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
64035Sphitran  * Use is subject to license terms.
74035Sphitran  *
84035Sphitran  * Licensed under the Academic Free License version 2.1
94035Sphitran  *
104035Sphitran  **************************************************************************/
114035Sphitran 
124035Sphitran #pragma ident	"%Z%%M%	%I%	%E% SMI"
134035Sphitran 
144035Sphitran #ifdef HAVE_CONFIG_H
154035Sphitran #include <config.h>
164035Sphitran #endif
174035Sphitran 
184035Sphitran #include <stdio.h>
194035Sphitran #include <string.h>
204035Sphitran #include <sys/utsname.h>
214035Sphitran #include <libdevinfo.h>
224035Sphitran #include <sys/mkdev.h>
234035Sphitran #include <sys/stat.h>
244035Sphitran #include <unistd.h>
25*6573Sphitran #include <sys/sysevent/dev.h>
26*6573Sphitran #include <sys/sysevent/pwrctl.h>
274035Sphitran 
284035Sphitran #include "../osspec.h"
294035Sphitran #include "../logger.h"
304035Sphitran #include "../hald.h"
314035Sphitran #include "../hald_dbus.h"
324035Sphitran #include "../device_info.h"
334035Sphitran #include "../util.h"
344035Sphitran #include "../hald_runner.h"
354035Sphitran #include "devinfo_acpi.h"
364035Sphitran 
374035Sphitran #define		DEVINFO_PROBE_BATTERY_TIMEOUT	30000
384035Sphitran 
394035Sphitran static HalDevice *devinfo_acpi_add(HalDevice *, di_node_t, char *, char *);
404035Sphitran static HalDevice *devinfo_battery_add(HalDevice *, di_node_t, char *, char *);
41*6573Sphitran static HalDevice *devinfo_power_button_add(HalDevice *parent, di_node_t node,
42*6573Sphitran     char *devfs_path, char *device_type);
43*6573Sphitran static void devinfo_battery_rescan_probing_done(HalDevice *d, guint32 exit_type,
44*6573Sphitran     gint return_code, char **error, gpointer userdata1, gpointer userdata2);
454035Sphitran 
464035Sphitran DevinfoDevHandler devinfo_acpi_handler = {
474035Sphitran 	devinfo_acpi_add,
484035Sphitran 	NULL,
494035Sphitran 	NULL,
504035Sphitran 	NULL,
514035Sphitran 	NULL,
524035Sphitran 	NULL
534035Sphitran };
544035Sphitran 
554035Sphitran DevinfoDevHandler devinfo_battery_handler = {
564035Sphitran 	devinfo_battery_add,
574035Sphitran 	NULL,
584035Sphitran 	NULL,
594035Sphitran 	NULL,
604035Sphitran 	NULL,
614035Sphitran 	devinfo_battery_get_prober
624035Sphitran };
634035Sphitran 
64*6573Sphitran DevinfoDevHandler devinfo_power_button_handler = {
65*6573Sphitran 	devinfo_power_button_add,
66*6573Sphitran 	NULL,
67*6573Sphitran 	NULL,
68*6573Sphitran 	NULL,
69*6573Sphitran 	NULL,
70*6573Sphitran 	NULL
71*6573Sphitran };
72*6573Sphitran 
734035Sphitran static HalDevice *
744035Sphitran devinfo_acpi_add(HalDevice *parent, di_node_t node, char *devfs_path,
754035Sphitran     char *device_type)
764035Sphitran {
774035Sphitran 	HalDevice *d, *computer;
784035Sphitran 
794035Sphitran 	if (strcmp(devfs_path, "/acpi") != 0) {
804035Sphitran 		return (NULL);
814035Sphitran 	}
824035Sphitran 
834035Sphitran 	d = hal_device_new();
844035Sphitran 
854035Sphitran 	if ((computer = hal_device_store_find(hald_get_gdl(),
864035Sphitran 	    "/org/freedesktop/Hal/devices/computer")) ||
874035Sphitran 	    (computer = hal_device_store_find(hald_get_tdl(),
884035Sphitran 	    "/org/freedesktop/Hal/devices/computer"))) {
894035Sphitran 		hal_device_property_set_string(computer,
904035Sphitran 		    "power_management.type", "acpi");
914035Sphitran 	}
924035Sphitran 	devinfo_set_default_properties(d, parent, node, devfs_path);
934035Sphitran 	devinfo_add_enqueue(d, devfs_path, &devinfo_acpi_handler);
944035Sphitran 
954035Sphitran 	return (d);
964035Sphitran }
974035Sphitran 
984035Sphitran static HalDevice *
994035Sphitran devinfo_battery_add(HalDevice *parent, di_node_t node, char *devfs_path,
1004035Sphitran     char *device_type)
1014035Sphitran {
1024035Sphitran 	HalDevice *d, *computer;
1034035Sphitran 	char	*driver_name;
1044035Sphitran 	di_devlink_handle_t devlink_hdl;
1054035Sphitran 	int	major;
1064035Sphitran 	di_minor_t minor;
1074035Sphitran 	dev_t   dev;
1084035Sphitran 	char    *minor_path = NULL;
1094035Sphitran 	char    *devpath;
1104035Sphitran 
1114035Sphitran 	driver_name = di_driver_name(node);
112*6573Sphitran 	if ((driver_name == NULL) || (strcmp(driver_name, "acpi_drv") != 0)) {
1134035Sphitran 		return (NULL);
1144035Sphitran 	}
1154035Sphitran 
1164035Sphitran 	d = hal_device_new();
1174035Sphitran 
1184035Sphitran 	if ((computer = hal_device_store_find(hald_get_gdl(),
1194035Sphitran 	    "/org/freedesktop/Hal/devices/computer")) ||
1204035Sphitran 	    (computer = hal_device_store_find(hald_get_tdl(),
1214035Sphitran 	    "/org/freedesktop/Hal/devices/computer"))) {
1224035Sphitran 		hal_device_property_set_string(computer,
1234035Sphitran 		    "system.formfactor", "laptop");
1244035Sphitran 	}
1254035Sphitran 	devinfo_set_default_properties(d, parent, node, devfs_path);
1264035Sphitran 	devinfo_add_enqueue(d, devfs_path, &devinfo_battery_handler);
1274035Sphitran 
1284035Sphitran 	major = di_driver_major(node);
1294035Sphitran 	if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
1304035Sphitran 		return (d);
1314035Sphitran 	}
1324035Sphitran 	minor = DI_MINOR_NIL;
1334035Sphitran 	while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
1344035Sphitran 		dev = di_minor_devt(minor);
1354035Sphitran 		if ((major != major(dev)) ||
1364035Sphitran 		    (di_minor_type(minor) != DDM_MINOR) ||
1374035Sphitran 		    (di_minor_spectype(minor) != S_IFCHR) ||
1384035Sphitran 		    ((minor_path = di_devfs_minor_path(minor)) == NULL)) {
1394035Sphitran 			continue;
1404035Sphitran 		}
1414035Sphitran 
1424035Sphitran 		if (hal_device_store_match_key_value_string(hald_get_gdl(),
1434035Sphitran 		    "solaris.devfs_path", minor_path) == NULL) {
1444035Sphitran 			devinfo_battery_add_minor(d, node, minor_path, dev);
1454035Sphitran 		}
1464035Sphitran 
1474035Sphitran 		di_devfs_path_free(minor_path);
1484035Sphitran 	}
1494035Sphitran 	di_devlink_fini(&devlink_hdl);
1504035Sphitran 
1514035Sphitran 	return (d);
1524035Sphitran }
1534035Sphitran 
1544035Sphitran void
1554035Sphitran devinfo_battery_add_minor(HalDevice *parent, di_node_t node, char *minor_path,
1564035Sphitran     dev_t dev)
1574035Sphitran {
1584035Sphitran 	HalDevice *d;
1594035Sphitran 
1604035Sphitran 	d = hal_device_new();
1614035Sphitran 	devinfo_set_default_properties(d, parent, node, minor_path);
1624035Sphitran 	devinfo_add_enqueue(d, minor_path, &devinfo_battery_handler);
1634035Sphitran }
1644035Sphitran 
165*6573Sphitran static HalDevice *
166*6573Sphitran devinfo_power_button_add(HalDevice *parent, di_node_t node, char *devfs_path,
167*6573Sphitran     char *device_type)
168*6573Sphitran {
169*6573Sphitran 	HalDevice *d;
170*6573Sphitran 	char *driver_name;
171*6573Sphitran 
172*6573Sphitran 	driver_name = di_driver_name(node);
173*6573Sphitran 	if ((driver_name == NULL) || (strcmp(driver_name, "power") != 0)) {
174*6573Sphitran 		return (NULL);
175*6573Sphitran 	}
176*6573Sphitran 
177*6573Sphitran 	d = hal_device_new();
178*6573Sphitran 
179*6573Sphitran 	devinfo_set_default_properties(d, parent, node, devfs_path);
180*6573Sphitran 	hal_device_add_capability(d, "button");
181*6573Sphitran 	hal_device_property_set_bool(d, "button.has_state", FALSE);
182*6573Sphitran 	hal_device_property_set_string(d, "info.category", "input");
183*6573Sphitran 	hal_device_property_set_string(d, "button.type", "power");
184*6573Sphitran 	hal_device_property_set_string(d, "info.product", "Power Button");
185*6573Sphitran 
186*6573Sphitran 	devinfo_add_enqueue(d, devfs_path, &devinfo_power_button_handler);
187*6573Sphitran 
188*6573Sphitran 	return (d);
189*6573Sphitran }
190*6573Sphitran 
191*6573Sphitran void
192*6573Sphitran devinfo_power_button_rescan(void)
193*6573Sphitran {
194*6573Sphitran 	HalDevice *d = NULL;
195*6573Sphitran 	HalDeviceStore *store = hald_get_gdl();
196*6573Sphitran 
197*6573Sphitran 	d = hal_device_store_match_key_value_string (store, "button.type",
198*6573Sphitran 	    "power");
199*6573Sphitran 	if (d != NULL) {
200*6573Sphitran 		device_send_signal_condition(d, "ButtonPressed", "power");
201*6573Sphitran 	}
202*6573Sphitran }
203*6573Sphitran 
204*6573Sphitran void
205*6573Sphitran devinfo_brightness_hotkeys_rescan(char *subclass)
206*6573Sphitran {
207*6573Sphitran 	HalDevice *d = NULL;
208*6573Sphitran 
209*6573Sphitran 	if ((d = hal_device_store_find(hald_get_gdl(),
210*6573Sphitran 	    "/org/freedesktop/Hal/devices/computer")) ||
211*6573Sphitran 	    (d = hal_device_store_find(hald_get_tdl(),
212*6573Sphitran 	    "/org/freedesktop/Hal/devices/computer"))) {
213*6573Sphitran 		if (strcmp(subclass, ESC_PWRCTL_BRIGHTNESS_UP) == 0) {
214*6573Sphitran 			device_send_signal_condition(d, "ButtonPressed",
215*6573Sphitran 			    "brightness-up");
216*6573Sphitran 		} else {
217*6573Sphitran 			device_send_signal_condition(d, "ButtonPressed",
218*6573Sphitran 			    "brightness-down");
219*6573Sphitran 		}
220*6573Sphitran         }
221*6573Sphitran }
222*6573Sphitran 
2234035Sphitran void
2244035Sphitran devinfo_battery_device_rescan(char *parent_devfs_path, gchar *udi)
2254035Sphitran {
2264035Sphitran 	HalDevice *d = NULL;
2274035Sphitran 
2284035Sphitran 	d = hal_device_store_find(hald_get_gdl(), udi);
2294035Sphitran 	if (d == NULL) {
2304035Sphitran 		HAL_INFO(("device not found %s", udi));
2314035Sphitran 		return;
2324035Sphitran 	}
2334035Sphitran 
234*6573Sphitran 	hald_runner_run(d, "hald-probe-acpi", NULL,
2354035Sphitran 	    DEVINFO_PROBE_BATTERY_TIMEOUT, devinfo_battery_rescan_probing_done,
2364035Sphitran 	    NULL, NULL);
2374035Sphitran }
2384035Sphitran 
239*6573Sphitran void
240*6573Sphitran devinfo_lid_device_rescan(char *subclass, gchar *udi)
241*6573Sphitran {
242*6573Sphitran 	HalDevice *d = NULL;
243*6573Sphitran 
244*6573Sphitran 	d = hal_device_store_find(hald_get_gdl(), udi);
245*6573Sphitran 	if (d == NULL) {
246*6573Sphitran 		HAL_INFO(("device not found %s", udi));
247*6573Sphitran 		return;
248*6573Sphitran 	}
249*6573Sphitran 
250*6573Sphitran 	hal_device_property_set_bool(d, "button.state.value",
251*6573Sphitran 		(strcmp(subclass, ESC_PWRCTL_REMOVE) == 0));
252*6573Sphitran 	device_send_signal_condition(d, "ButtonPressed", "lid");
253*6573Sphitran }
254*6573Sphitran 
2554035Sphitran static void
2564035Sphitran devinfo_battery_rescan_probing_done(HalDevice *d, guint32 exit_type,
2574035Sphitran     gint return_code, char **error, gpointer userdata1, gpointer userdata2)
2584035Sphitran {
2594035Sphitran 	/* hald_runner_run() requires this function since cannot pass NULL */
2604035Sphitran }
2614035Sphitran 
2624035Sphitran const gchar *
2634035Sphitran devinfo_battery_get_prober(HalDevice *d, int *timeout)
2644035Sphitran {
2654035Sphitran 	*timeout = DEVINFO_PROBE_BATTERY_TIMEOUT;    /* 30 second timeout */
266*6573Sphitran 	return ("hald-probe-acpi");
2674035Sphitran }
268