1 /***************************************************************************
2  *
3  * devinfo_acpi : acpi devices
4  *
5  * Copyright 2007 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 
26 #include "../osspec.h"
27 #include "../logger.h"
28 #include "../hald.h"
29 #include "../hald_dbus.h"
30 #include "../device_info.h"
31 #include "../util.h"
32 #include "../hald_runner.h"
33 #include "devinfo_acpi.h"
34 
35 #define		DEVINFO_PROBE_BATTERY_TIMEOUT	30000
36 
37 static HalDevice *devinfo_acpi_add(HalDevice *, di_node_t, char *, char *);
38 static HalDevice *devinfo_battery_add(HalDevice *, di_node_t, char *, char *);
39 
40 DevinfoDevHandler devinfo_acpi_handler = {
41 	devinfo_acpi_add,
42 	NULL,
43 	NULL,
44 	NULL,
45 	NULL,
46 	NULL
47 };
48 
49 DevinfoDevHandler devinfo_battery_handler = {
50 	devinfo_battery_add,
51 	NULL,
52 	NULL,
53 	NULL,
54 	NULL,
55 	devinfo_battery_get_prober
56 };
57 
58 static HalDevice *
59 devinfo_acpi_add(HalDevice *parent, di_node_t node, char *devfs_path,
60     char *device_type)
61 {
62 	HalDevice *d, *computer;
63 
64 	if (strcmp(devfs_path, "/acpi") != 0) {
65 		return (NULL);
66 	}
67 
68 	d = hal_device_new();
69 
70 	if ((computer = hal_device_store_find(hald_get_gdl(),
71 	    "/org/freedesktop/Hal/devices/computer")) ||
72 	    (computer = hal_device_store_find(hald_get_tdl(),
73 	    "/org/freedesktop/Hal/devices/computer"))) {
74 		hal_device_property_set_string(computer,
75 		    "power_management.type", "acpi");
76 	}
77 	devinfo_set_default_properties(d, parent, node, devfs_path);
78 	devinfo_add_enqueue(d, devfs_path, &devinfo_acpi_handler);
79 
80 	return (d);
81 }
82 
83 static HalDevice *
84 devinfo_battery_add(HalDevice *parent, di_node_t node, char *devfs_path,
85     char *device_type)
86 {
87 	HalDevice *d, *computer;
88 	char	*driver_name;
89 	di_devlink_handle_t devlink_hdl;
90 	int	major;
91 	di_minor_t minor;
92 	dev_t   dev;
93 	char    *minor_path = NULL;
94 	char    *devpath;
95 
96 	driver_name = di_driver_name(node);
97 	if ((driver_name == NULL) || (strcmp(driver_name, "battery") != 0)) {
98 		return (NULL);
99 	}
100 
101 	d = hal_device_new();
102 
103 	if ((computer = hal_device_store_find(hald_get_gdl(),
104 	    "/org/freedesktop/Hal/devices/computer")) ||
105 	    (computer = hal_device_store_find(hald_get_tdl(),
106 	    "/org/freedesktop/Hal/devices/computer"))) {
107 		hal_device_property_set_string(computer,
108 		    "system.formfactor", "laptop");
109 	}
110 	devinfo_set_default_properties(d, parent, node, devfs_path);
111 	devinfo_add_enqueue(d, devfs_path, &devinfo_battery_handler);
112 
113 	major = di_driver_major(node);
114 	if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
115 		return (d);
116 	}
117 	minor = DI_MINOR_NIL;
118 	while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
119 		dev = di_minor_devt(minor);
120 		if ((major != major(dev)) ||
121 		    (di_minor_type(minor) != DDM_MINOR) ||
122 		    (di_minor_spectype(minor) != S_IFCHR) ||
123 		    ((minor_path = di_devfs_minor_path(minor)) == NULL)) {
124 			continue;
125 		}
126 
127 		if (hal_device_store_match_key_value_string(hald_get_gdl(),
128 		    "solaris.devfs_path", minor_path) == NULL) {
129 			devinfo_battery_add_minor(d, node, minor_path, dev);
130 		}
131 
132 		di_devfs_path_free(minor_path);
133 	}
134 	di_devlink_fini(&devlink_hdl);
135 
136 	return (d);
137 }
138 
139 void
140 devinfo_battery_add_minor(HalDevice *parent, di_node_t node, char *minor_path,
141     dev_t dev)
142 {
143 	HalDevice *d;
144 
145 	d = hal_device_new();
146 	devinfo_set_default_properties(d, parent, node, minor_path);
147 	devinfo_add_enqueue(d, minor_path, &devinfo_battery_handler);
148 }
149 
150 void
151 devinfo_battery_device_rescan(char *parent_devfs_path, gchar *udi)
152 {
153 	HalDevice *d = NULL;
154 
155 	d = hal_device_store_find(hald_get_gdl(), udi);
156 	if (d == NULL) {
157 		HAL_INFO(("device not found %s", udi));
158 		return;
159 	}
160 
161 	hald_runner_run(d, "hald-probe-battery", NULL,
162 	    DEVINFO_PROBE_BATTERY_TIMEOUT, devinfo_battery_rescan_probing_done,
163 	    NULL, NULL);
164 }
165 
166 static void
167 devinfo_battery_rescan_probing_done(HalDevice *d, guint32 exit_type,
168     gint return_code, char **error, gpointer userdata1, gpointer userdata2)
169 {
170 	/* hald_runner_run() requires this function since cannot pass NULL */
171 }
172 
173 const gchar *
174 devinfo_battery_get_prober(HalDevice *d, int *timeout)
175 {
176 	*timeout = DEVINFO_PROBE_BATTERY_TIMEOUT;    /* 30 second timeout */
177 	return ("hald-probe-battery");
178 }
179