| @@ -1,249 +1,249 @@ | | | @@ -1,249 +1,249 @@ |
1 | /* $NetBSD: envsys.c,v 1.5 2009/03/01 18:22:31 jmcneill Exp $ */ | | 1 | /* $NetBSD: envsys.c,v 1.6 2010/12/16 11:34:51 ahoka Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2008 Jared D. McNeill <jmcneill@invisible.ca> | | 4 | * Copyright (c) 2008 Jared D. McNeill <jmcneill@invisible.ca> |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
15 | * | | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 16 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
17 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 17 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
20 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 20 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
26 | * POSSIBILITY OF SUCH DAMAGE. | | 26 | * POSSIBILITY OF SUCH DAMAGE. |
27 | */ | | 27 | */ |
28 | | | 28 | |
29 | #ifdef HAVE_CONFIG_H | | 29 | #ifdef HAVE_CONFIG_H |
30 | # include <config.h> | | 30 | # include <config.h> |
31 | #endif | | 31 | #endif |
32 | | | 32 | |
33 | #include <sys/types.h> | | 33 | #include <sys/types.h> |
34 | #include <sys/ioctl.h> | | 34 | #include <sys/ioctl.h> |
35 | #include <sys/envsys.h> | | 35 | #include <sys/envsys.h> |
36 | | | 36 | |
37 | #include <prop/proplib.h> | | 37 | #include <prop/proplib.h> |
38 | | | 38 | |
39 | #include <errno.h> | | 39 | #include <errno.h> |
40 | #include <fcntl.h> | | 40 | #include <fcntl.h> |
41 | #include <stdbool.h> | | 41 | #include <stdbool.h> |
42 | #include <stdlib.h> | | 42 | #include <stdlib.h> |
43 | #include <string.h> | | 43 | #include <string.h> |
44 | #include <unistd.h> | | 44 | #include <unistd.h> |
45 | | | 45 | |
46 | #include "../osspec.h" | | 46 | #include "../osspec.h" |
47 | #include "../logger.h" | | 47 | #include "../logger.h" |
48 | #include "../hald.h" | | 48 | #include "../hald.h" |
49 | #include "../hald_dbus.h" | | 49 | #include "../hald_dbus.h" |
50 | #include "../device_info.h" | | 50 | #include "../device_info.h" |
51 | #include "../util.h" | | 51 | #include "../util.h" |
52 | #include "devinfo.h" | | 52 | #include "devinfo.h" |
53 | #include "envsys.h" | | 53 | #include "envsys.h" |
54 | | | 54 | |
55 | #define _DEV_SYSMON "/dev/sysmon" | | 55 | #define _DEV_SYSMON "/dev/sysmon" |
56 | | | 56 | |
57 | static int envsys_fd = -1; | | 57 | static int envsys_fd = -1; |
58 | | | 58 | |
59 | static gboolean envsys_timeout(gpointer user_data); | | 59 | static gboolean envsys_timeout(gpointer user_data); |
60 | static void envsys_handle_devnode(const char *devnode, prop_array_t properties); | | 60 | static void envsys_handle_devnode(const char *devnode, prop_array_t properties); |
61 | | | 61 | |
62 | static void envsys_acadapter_handler(HalDevice *d, prop_array_t properties); | | 62 | static void envsys_acadapter_handler(HalDevice *d, prop_array_t properties); |
63 | static void envsys_battery_handler(HalDevice *d, prop_array_t properties); | | 63 | static void envsys_battery_handler(HalDevice *d, prop_array_t properties); |
64 | | | 64 | |
65 | enum battery_state { | | 65 | enum battery_state { |
66 | CHARGING, | | 66 | CHARGING, |
67 | DISCHARGING, | | 67 | DISCHARGING, |
68 | NORMAL | | 68 | NORMAL |
69 | }; | | 69 | }; |
70 | | | 70 | |
71 | static struct envsys_devmap { | | 71 | static struct envsys_devmap { |
72 | const char *capability; | | 72 | const char *capability; |
73 | void (*handler)(HalDevice *d, prop_array_t properties); | | 73 | void (*handler)(HalDevice *d, prop_array_t properties); |
74 | } devmap[] = { | | 74 | } devmap[] = { |
75 | { "ac_adapter", envsys_acadapter_handler }, | | 75 | { "ac_adapter", envsys_acadapter_handler }, |
76 | { "battery", envsys_battery_handler }, | | 76 | { "battery", envsys_battery_handler }, |
77 | }; | | 77 | }; |
78 | | | 78 | |
79 | void | | 79 | void |
80 | envsys_init(void) | | 80 | envsys_init(void) |
81 | { | | 81 | { |
82 | envsys_fd = open (_DEV_SYSMON, O_RDONLY); | | 82 | envsys_fd = open (_DEV_SYSMON, O_RDONLY); |
83 | if (envsys_fd == -1) { | | 83 | if (envsys_fd == -1) { |
84 | HAL_WARNING (("Couldn't open " _DEV_SYSMON ": %s", strerror(errno))); | | 84 | HAL_WARNING (("Couldn't open " _DEV_SYSMON ": %s", strerror(errno))); |
85 | return; | | 85 | return; |
86 | } | | 86 | } |
87 | | | 87 | |
88 | g_timeout_add (1000, envsys_timeout, NULL); | | 88 | g_timeout_add (1000, envsys_timeout, NULL); |
89 | } | | 89 | } |
90 | | | 90 | |
91 | static gboolean | | 91 | static gboolean |
92 | envsys_timeout(gpointer user_data) | | 92 | envsys_timeout(gpointer user_data) |
93 | { | | 93 | { |
94 | prop_dictionary_t global_dict; | | 94 | prop_dictionary_t global_dict; |
95 | prop_array_t global_array; | | 95 | prop_array_t global_array; |
96 | prop_object_iterator_t iter; | | 96 | prop_object_iterator_t iter; |
97 | prop_dictionary_keysym_t keysym; | | 97 | prop_dictionary_keysym_t keysym; |
98 | int status; | | 98 | int status; |
99 | | | 99 | |
100 | status = prop_dictionary_recv_ioctl (envsys_fd, ENVSYS_GETDICTIONARY, &global_dict); | | 100 | status = prop_dictionary_recv_ioctl (envsys_fd, ENVSYS_GETDICTIONARY, &global_dict); |
101 | if (status) { | | 101 | if (status) { |
102 | HAL_WARNING (("envsys_timeout: ENVSYS_GETDICTIONARY failed: %s", strerror(status))); | | 102 | HAL_WARNING (("envsys_timeout: ENVSYS_GETDICTIONARY failed: %s", strerror(status))); |
103 | return FALSE; | | 103 | return FALSE; |
104 | } | | 104 | } |
105 | | | 105 | |
106 | global_array = prop_dictionary_all_keys (global_dict); | | 106 | global_array = prop_dictionary_all_keys (global_dict); |
107 | if (global_array == NULL) { | | 107 | if (global_array == NULL) { |
108 | HAL_WARNING (("envsys_timeout: prop_dictionary_all_keys returned NULL")); | | 108 | HAL_WARNING (("envsys_timeout: prop_dictionary_all_keys returned NULL")); |
109 | return FALSE; | | 109 | return FALSE; |
110 | } | | 110 | } |
111 | iter = prop_array_iterator (global_array); | | 111 | iter = prop_array_iterator (global_array); |
112 | while ((keysym = (prop_dictionary_keysym_t)prop_object_iterator_next (iter)) != NULL) { | | 112 | while ((keysym = (prop_dictionary_keysym_t)prop_object_iterator_next (iter)) != NULL) { |
113 | const char *devnode; | | 113 | const char *devnode; |
114 | prop_object_t obj; | | 114 | prop_object_t obj; |
115 | | | 115 | |
116 | devnode = prop_dictionary_keysym_cstring_nocopy (keysym); | | 116 | devnode = prop_dictionary_keysym_cstring_nocopy (keysym); |
117 | obj = prop_dictionary_get_keysym (global_dict, keysym); | | 117 | obj = prop_dictionary_get_keysym (global_dict, keysym); |
118 | if (obj == NULL || prop_object_type (obj) != PROP_TYPE_ARRAY) | | 118 | if (obj == NULL || prop_object_type (obj) != PROP_TYPE_ARRAY) |
119 | continue; | | 119 | continue; |
120 | | | 120 | |
121 | envsys_handle_devnode (devnode, (prop_array_t)obj); | | 121 | envsys_handle_devnode (devnode, (prop_array_t)obj); |
122 | } | | 122 | } |
123 | prop_object_iterator_release (iter); | | 123 | prop_object_iterator_release (iter); |
124 | | | 124 | |
125 | prop_object_release (global_array); | | 125 | prop_object_release (global_array); |
126 | prop_object_release (global_dict); | | 126 | prop_object_release (global_dict); |
127 | return TRUE; | | 127 | return TRUE; |
128 | } | | 128 | } |
129 | | | 129 | |
130 | static void | | 130 | static void |
131 | envsys_handle_devnode(const char *devnode, prop_array_t properties) | | 131 | envsys_handle_devnode(const char *devnode, prop_array_t properties) |
132 | { | | 132 | { |
133 | HalDevice *d; | | 133 | HalDevice *d; |
134 | unsigned int i; | | 134 | unsigned int i; |
135 | | | 135 | |
136 | d = hal_device_store_match_key_value_string (hald_get_gdl (), "netbsd.device", devnode); | | 136 | d = hal_device_store_match_key_value_string (hald_get_gdl (), "netbsd.device", devnode); |
137 | if (d == NULL) | | 137 | if (d == NULL) |
138 | return; | | 138 | return; |
139 | | | 139 | |
140 | for (i = 0; i < __arraycount (devmap); i++) { | | 140 | for (i = 0; i < __arraycount (devmap); i++) { |
141 | if (!hal_device_has_capability (d, devmap[i].capability)) | | 141 | if (!hal_device_has_capability (d, devmap[i].capability)) |
142 | continue; | | 142 | continue; |
143 | devmap[i].handler (d, properties); | | 143 | devmap[i].handler (d, properties); |
144 | } | | 144 | } |
145 | | | 145 | |
146 | return; | | 146 | return; |
147 | } | | 147 | } |
148 | | | 148 | |
149 | static void | | 149 | static void |
150 | envsys_acadapter_handler(HalDevice *d, prop_array_t properties) | | 150 | envsys_acadapter_handler(HalDevice *d, prop_array_t properties) |
151 | { | | 151 | { |
152 | prop_object_iterator_t iter; | | 152 | prop_object_iterator_t iter; |
153 | prop_dictionary_t prop; | | 153 | prop_dictionary_t prop; |
154 | | | 154 | |
155 | iter = prop_array_iterator (properties); | | 155 | iter = prop_array_iterator (properties); |
156 | while ((prop = (prop_dictionary_t)prop_object_iterator_next (iter)) != NULL) { | | 156 | while ((prop = (prop_dictionary_t)prop_object_iterator_next (iter)) != NULL) { |
157 | const char *descr; | | 157 | const char *descr; |
158 | uint8_t connected; | | 158 | uint8_t connected; |
159 | | | 159 | |
160 | if (prop_dictionary_get_cstring_nocopy (prop, "description", &descr) == false) | | 160 | if (prop_dictionary_get_cstring_nocopy (prop, "description", &descr) == false) |
161 | continue; | | 161 | continue; |
162 | | | 162 | |
163 | if (strcmp (descr, "connected") != 0) | | 163 | if (strcmp (descr, "connected") != 0) |
164 | continue; | | 164 | continue; |
165 | | | 165 | |
166 | if (prop_dictionary_get_uint8 (prop, "cur-value", &connected) == false) | | 166 | if (prop_dictionary_get_uint8 (prop, "cur-value", &connected) == false) |
167 | continue; | | 167 | continue; |
168 | | | 168 | |
169 | hal_device_property_set_bool (d, "ac_adapter.present", connected); | | 169 | hal_device_property_set_bool (d, "ac_adapter.present", connected); |
170 | } | | 170 | } |
171 | | | 171 | |
172 | prop_object_iterator_release (iter); | | 172 | prop_object_iterator_release (iter); |
173 | } | | 173 | } |
174 | | | 174 | |
175 | static void | | 175 | static void |
176 | envsys_battery_handler(HalDevice *d, prop_array_t properties) | | 176 | envsys_battery_handler(HalDevice *d, prop_array_t properties) |
177 | { | | 177 | { |
178 | prop_object_iterator_t iter; | | 178 | prop_object_iterator_t iter; |
179 | prop_dictionary_t prop; | | 179 | prop_dictionary_t prop; |
180 | enum battery_state battstate = NORMAL; | | 180 | enum battery_state battstate = NORMAL; |
181 | | | 181 | |
182 | device_property_atomic_update_begin (); | | 182 | device_property_atomic_update_begin (); |
183 | | | 183 | |
184 | hal_device_property_set_bool (d, "battery.is_rechargeable", TRUE); | | 184 | hal_device_property_set_bool (d, "battery.is_rechargeable", TRUE); |
185 | | | 185 | |
186 | iter = prop_array_iterator (properties); | | 186 | iter = prop_array_iterator (properties); |
187 | while ((prop = (prop_dictionary_t)prop_object_iterator_next (iter)) != NULL) { | | 187 | while ((prop = (prop_dictionary_t)prop_object_iterator_next (iter)) != NULL) { |
188 | const char *descr; | | 188 | const char *descr; |
189 | const char *valid; | | 189 | const char *valid; |
190 | int64_t intval; | | 190 | int64_t intval; |
191 | | | 191 | |
192 | if (prop_dictionary_get_cstring_nocopy (prop, "description", &descr) == false || | | 192 | if (prop_dictionary_get_cstring_nocopy (prop, "description", &descr) == false || |
193 | prop_dictionary_get_int64 (prop, "cur-value", &intval) == false || | | 193 | prop_dictionary_get_int64 (prop, "cur-value", &intval) == false || |
194 | prop_dictionary_get_cstring_nocopy (prop, "state", &valid) == false || | | 194 | prop_dictionary_get_cstring_nocopy (prop, "state", &valid) == false || |
195 | strcmp (valid, "valid") != 0) | | 195 | strcmp (valid, "valid") != 0) |
196 | continue; | | 196 | continue; |
197 | | | 197 | |
198 | if (strcmp (descr, "present") == 0) | | 198 | if (strcmp (descr, "present") == 0) |
199 | hal_device_property_set_bool (d, "battery.present", intval); | | 199 | hal_device_property_set_bool (d, "battery.present", intval); |
200 | else if (strcmp (descr, "design cap") == 0) | | 200 | else if (strcmp (descr, "design cap") == 0) |
201 | hal_device_property_set_int (d, "battery.charge_level.design", intval); | | 201 | hal_device_property_set_int (d, "battery.charge_level.design", intval); |
202 | else if (strcmp (descr, "last full cap") == 0) | | 202 | else if (strcmp (descr, "last full cap") == 0) |
203 | hal_device_property_set_int (d, "battery.charge_level.last_full", intval); | | 203 | hal_device_property_set_int (d, "battery.charge_level.last_full", intval); |
204 | else if (strcmp (descr, "charge") == 0) { | | 204 | else if (strcmp (descr, "charge") == 0) { |
205 | int64_t maxval; | | 205 | int64_t maxval; |
206 | const char *type; | | 206 | const char *type; |
207 | | | 207 | |
208 | if (prop_dictionary_get_cstring_nocopy (prop, "type", &type)) | | 208 | if (prop_dictionary_get_cstring_nocopy (prop, "type", &type)) |
209 | if (strcmp (type, "Ampere hour") == 0) { | | 209 | if (strcmp (type, "Ampere hour") == 0) { |
210 | /* HAL 0.5.12 spec discourages this, but what can we do about it? */ | | 210 | /* HAL 0.5.12 spec discourages this, but what can we do about it? */ |
211 | hal_device_property_set_string (d, "battery.charge_level.unit", "mAh"); | | 211 | hal_device_property_set_string (d, "battery.charge_level.unit", "mAh"); |
212 | } | | 212 | } |
213 | | | 213 | |
214 | hal_device_property_set_int (d, "battery.charge_level.current", intval); | | 214 | hal_device_property_set_int (d, "battery.charge_level.current", intval); |
215 | | | 215 | |
216 | if (prop_dictionary_get_int64 (prop, "max-value", &maxval) && maxval > 0) | | 216 | if (prop_dictionary_get_int64 (prop, "max-value", &maxval) && maxval > 0) |
217 | hal_device_property_set_int (d, "battery.charge_level.percentage", intval * 100 / maxval); | | 217 | hal_device_property_set_int (d, "battery.charge_level.percentage", intval * 100 / maxval); |
218 | else | | 218 | else |
219 | hal_device_property_set_int (d, "battery.charge_level.percentage", 0); | | 219 | hal_device_property_set_int (d, "battery.charge_level.percentage", 0); |
220 | } | | 220 | } |
221 | else if (strcmp (descr, "charge rate") == 0) { | | 221 | else if (strcmp (descr, "charge rate") == 0) { |
222 | battstate = CHARGING; | | 222 | battstate = CHARGING; |
223 | hal_device_property_set_int (d, "battery.charge_level.rate", intval / 3600); | | 223 | hal_device_property_set_int (d, "battery.charge_level.rate", intval); |
224 | } else if (strcmp (descr, "discharge rate") == 0) { | | 224 | } else if (strcmp (descr, "discharge rate") == 0) { |
225 | battstate = DISCHARGING; | | 225 | battstate = DISCHARGING; |
226 | hal_device_property_set_int (d, "battery.charge_level.rate", intval / 3600); | | 226 | hal_device_property_set_int (d, "battery.charge_level.rate", intval); |
227 | } | | 227 | } |
228 | } | | 228 | } |
229 | | | 229 | |
230 | switch (battstate) { | | 230 | switch (battstate) { |
231 | case NORMAL: | | 231 | case NORMAL: |
232 | hal_device_property_set_bool (d, "battery.rechargeable.is_charging", FALSE); | | 232 | hal_device_property_set_bool (d, "battery.rechargeable.is_charging", FALSE); |
233 | hal_device_property_set_bool (d, "battery.rechargeable.is_discharging", FALSE); | | 233 | hal_device_property_set_bool (d, "battery.rechargeable.is_discharging", FALSE); |
234 | hal_device_property_set_int (d, "battery.charge_level.rate", 0); | | 234 | hal_device_property_set_int (d, "battery.charge_level.rate", 0); |
235 | break; | | 235 | break; |
236 | case CHARGING: | | 236 | case CHARGING: |
237 | hal_device_property_set_bool (d, "battery.rechargeable.is_charging", TRUE); | | 237 | hal_device_property_set_bool (d, "battery.rechargeable.is_charging", TRUE); |
238 | hal_device_property_set_bool (d, "battery.rechargeable.is_discharging", FALSE); | | 238 | hal_device_property_set_bool (d, "battery.rechargeable.is_discharging", FALSE); |
239 | break; | | 239 | break; |
240 | case DISCHARGING: | | 240 | case DISCHARGING: |
241 | hal_device_property_set_bool (d, "battery.rechargeable.is_charging", FALSE); | | 241 | hal_device_property_set_bool (d, "battery.rechargeable.is_charging", FALSE); |
242 | hal_device_property_set_bool (d, "battery.rechargeable.is_discharging", TRUE); | | 242 | hal_device_property_set_bool (d, "battery.rechargeable.is_discharging", TRUE); |
243 | break; | | 243 | break; |
244 | } | | 244 | } |
245 | | | 245 | |
246 | device_property_atomic_update_end (); | | 246 | device_property_atomic_update_end (); |
247 | | | 247 | |
248 | prop_object_iterator_release (iter); | | 248 | prop_object_iterator_release (iter); |
249 | } | | 249 | } |