devinfo_acpi.c revision 7137:05a07937d969
1/***************************************************************************
2 *
3 * devinfo_acpi : acpi devices
4 *
5 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
6 * Use is subject to license terms.
7 *
8 * Licensed under the Academic Free License version 2.1
9 *
10 **************************************************************************/
11
12#pragma ident	"%Z%%M%	%I%	%E% SMI"
13
14#ifdef HAVE_CONFIG_H
15#include <config.h>
16#endif
17
18#include <stdio.h>
19#include <string.h>
20#include <sys/utsname.h>
21#include <libdevinfo.h>
22#include <sys/mkdev.h>
23#include <sys/stat.h>
24#include <unistd.h>
25#include <sys/sysevent/dev.h>
26#include <sys/sysevent/pwrctl.h>
27
28#include "../osspec.h"
29#include "../logger.h"
30#include "../hald.h"
31#include "../hald_dbus.h"
32#include "../device_info.h"
33#include "../util.h"
34#include "../hald_runner.h"
35#include "devinfo_acpi.h"
36
37#define		DEVINFO_PROBE_BATTERY_TIMEOUT	30000
38
39static HalDevice *devinfo_acpi_add(HalDevice *, di_node_t, char *, char *);
40static HalDevice *devinfo_power_button_add(HalDevice *parent, di_node_t node,
41    char *devfs_path, char *device_type);
42static void devinfo_battery_rescan_probing_done(HalDevice *d, guint32 exit_type,
43    gint return_code, char **error, gpointer userdata1, gpointer userdata2);
44
45DevinfoDevHandler devinfo_acpi_handler = {
46	devinfo_acpi_add,
47	NULL,
48	NULL,
49	NULL,
50	NULL,
51	devinfo_acpi_get_prober
52};
53
54DevinfoDevHandler devinfo_power_button_handler = {
55	devinfo_power_button_add,
56	NULL,
57	NULL,
58	NULL,
59	NULL,
60	NULL
61};
62
63static HalDevice *
64devinfo_acpi_add(HalDevice *parent, di_node_t node, char *devfs_path,
65    char *device_type)
66{
67	HalDevice *d, *computer;
68	char	*driver_name;
69	di_devlink_handle_t devlink_hdl;
70	int	major;
71	di_minor_t minor;
72	dev_t   dev;
73	char    *minor_path = NULL;
74	char    *devpath;
75
76	driver_name = di_driver_name(node);
77	if ((driver_name == NULL) || (strcmp(driver_name, "acpi_drv") != 0)) {
78		return (NULL);
79	}
80
81	d = hal_device_new();
82
83	if ((computer = hal_device_store_find(hald_get_gdl(),
84	    "/org/freedesktop/Hal/devices/computer")) ||
85	    (computer = hal_device_store_find(hald_get_tdl(),
86	    "/org/freedesktop/Hal/devices/computer"))) {
87		hal_device_property_set_string(computer,
88		    "system.formfactor", "laptop");
89		hal_device_property_set_string(computer,
90		    "power_management.type", "acpi");
91	}
92	devinfo_set_default_properties(d, parent, node, devfs_path);
93	devinfo_add_enqueue(d, devfs_path, &devinfo_acpi_handler);
94
95	major = di_driver_major(node);
96	if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
97		return (d);
98	}
99	minor = DI_MINOR_NIL;
100	while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
101		dev = di_minor_devt(minor);
102		if ((major != major(dev)) ||
103		    (di_minor_type(minor) != DDM_MINOR) ||
104		    (di_minor_spectype(minor) != S_IFCHR) ||
105		    ((minor_path = di_devfs_minor_path(minor)) == NULL)) {
106			continue;
107		}
108
109		if (hal_device_store_match_key_value_string(hald_get_gdl(),
110		    "solaris.devfs_path", minor_path) == NULL) {
111			devinfo_acpi_add_minor(d, node, minor_path, dev);
112		}
113
114		di_devfs_path_free(minor_path);
115	}
116	di_devlink_fini(&devlink_hdl);
117
118	return (d);
119}
120
121void
122devinfo_acpi_add_minor(HalDevice *parent, di_node_t node, char *minor_path,
123    dev_t dev)
124{
125	HalDevice *d;
126
127	d = hal_device_new();
128	devinfo_set_default_properties(d, parent, node, minor_path);
129	devinfo_add_enqueue(d, minor_path, &devinfo_acpi_handler);
130}
131
132static HalDevice *
133devinfo_power_button_add(HalDevice *parent, di_node_t node, char *devfs_path,
134    char *device_type)
135{
136	HalDevice *d;
137	char *driver_name;
138
139	driver_name = di_driver_name(node);
140	if ((driver_name == NULL) || (strcmp(driver_name, "power") != 0)) {
141		return (NULL);
142	}
143
144	d = hal_device_new();
145
146	devinfo_set_default_properties(d, parent, node, devfs_path);
147	hal_device_add_capability(d, "button");
148	hal_device_property_set_bool(d, "button.has_state", FALSE);
149	hal_device_property_set_string(d, "info.category", "input");
150	hal_device_property_set_string(d, "button.type", "power");
151	hal_device_property_set_string(d, "info.product", "Power Button");
152
153	devinfo_add_enqueue(d, devfs_path, &devinfo_power_button_handler);
154
155	return (d);
156}
157
158void
159devinfo_power_button_rescan(void)
160{
161	HalDevice *d = NULL;
162	HalDeviceStore *store = hald_get_gdl();
163
164	d = hal_device_store_match_key_value_string (store, "button.type",
165	    "power");
166	if (d != NULL) {
167		device_send_signal_condition(d, "ButtonPressed", "power");
168	}
169}
170
171void
172devinfo_brightness_hotkeys_rescan(char *subclass)
173{
174	HalDevice *d = NULL;
175
176	if ((d = hal_device_store_find(hald_get_gdl(),
177	    "/org/freedesktop/Hal/devices/computer")) ||
178	    (d = hal_device_store_find(hald_get_tdl(),
179	    "/org/freedesktop/Hal/devices/computer"))) {
180		if (strcmp(subclass, ESC_PWRCTL_BRIGHTNESS_UP) == 0) {
181			device_send_signal_condition(d, "ButtonPressed",
182			    "brightness-up");
183		} else {
184			device_send_signal_condition(d, "ButtonPressed",
185			    "brightness-down");
186		}
187        }
188}
189
190void
191devinfo_battery_device_rescan(char *parent_devfs_path, gchar *udi)
192{
193	HalDevice *d = NULL;
194
195	d = hal_device_store_find(hald_get_gdl(), udi);
196	if (d == NULL) {
197		HAL_INFO(("device not found %s", udi));
198		return;
199	}
200
201	hald_runner_run(d, "hald-probe-acpi", NULL,
202	    DEVINFO_PROBE_BATTERY_TIMEOUT, devinfo_battery_rescan_probing_done,
203	    NULL, NULL);
204}
205
206void
207devinfo_lid_device_rescan(char *subclass, gchar *udi)
208{
209	HalDevice *d = NULL;
210
211	d = hal_device_store_find(hald_get_gdl(), udi);
212	if (d == NULL) {
213		HAL_INFO(("device not found %s", udi));
214		return;
215	}
216
217	hal_device_property_set_bool(d, "button.state.value",
218		(strcmp(subclass, ESC_PWRCTL_REMOVE) == 0));
219	device_send_signal_condition(d, "ButtonPressed", "lid");
220}
221
222static void
223devinfo_battery_rescan_probing_done(HalDevice *d, guint32 exit_type,
224    gint return_code, char **error, gpointer userdata1, gpointer userdata2)
225{
226	/* hald_runner_run() requires this function since cannot pass NULL */
227}
228
229const gchar *
230devinfo_acpi_get_prober(HalDevice *d, int *timeout)
231{
232	*timeout = DEVINFO_PROBE_BATTERY_TIMEOUT;    /* 30 second timeout */
233	return ("hald-probe-acpi");
234}
235