5 * Copyright (C) 2007-2013 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
32 enum timezone_updates {
33 TIMEZONE_UPDATES_UNKNOWN = 0,
34 TIMEZONE_UPDATES_MANUAL = 1,
35 TIMEZONE_UPDATES_AUTO = 2,
38 static enum time_updates time_updates_config = TIME_UPDATES_AUTO;
39 static enum timezone_updates timezone_updates_config = TIMEZONE_UPDATES_AUTO;
41 static char *timezone_config = NULL;
43 static const char *time_updates2string(enum time_updates value)
46 case TIME_UPDATES_UNKNOWN:
48 case TIME_UPDATES_MANUAL:
50 case TIME_UPDATES_AUTO:
57 static enum time_updates string2time_updates(const char *value)
59 if (g_strcmp0(value, "manual") == 0)
60 return TIME_UPDATES_MANUAL;
61 else if (g_strcmp0(value, "auto") == 0)
62 return TIME_UPDATES_AUTO;
64 return TIME_UPDATES_UNKNOWN;
67 static const char *timezone_updates2string(enum timezone_updates value)
70 case TIMEZONE_UPDATES_UNKNOWN:
72 case TIMEZONE_UPDATES_MANUAL:
74 case TIMEZONE_UPDATES_AUTO:
81 static enum timezone_updates string2timezone_updates(const char *value)
83 if (g_strcmp0(value, "manual") == 0)
84 return TIMEZONE_UPDATES_MANUAL;
85 else if (g_strcmp0(value, "auto") == 0)
86 return TIMEZONE_UPDATES_AUTO;
88 return TIMEZONE_UPDATES_UNKNOWN;
91 static void clock_properties_load(void)
95 enum time_updates time_value;
96 enum timezone_updates timezone_value;
98 keyfile = __connman_storage_load_global();
102 str = g_key_file_get_string(keyfile, "global", "TimeUpdates", NULL);
104 time_value = string2time_updates(str);
105 if (time_value != TIME_UPDATES_UNKNOWN)
106 time_updates_config = time_value;
110 str = g_key_file_get_string(keyfile, "global", "TimezoneUpdates",
113 timezone_value = string2timezone_updates(str);
114 if (timezone_value != TIMEZONE_UPDATES_UNKNOWN)
115 timezone_updates_config = timezone_value;
119 g_key_file_free(keyfile);
122 static void clock_properties_save(void)
127 keyfile = __connman_storage_load_global();
129 keyfile = g_key_file_new();
131 str = time_updates2string(time_updates_config);
133 g_key_file_set_string(keyfile, "global", "TimeUpdates", str);
135 g_key_file_remove_key(keyfile, "global", "TimeUpdates", NULL);
137 str = timezone_updates2string(timezone_updates_config);
139 g_key_file_set_string(keyfile, "global", "TimezoneUpdates",
142 g_key_file_remove_key(keyfile, "global", "TimezoneUpdates",
145 __connman_storage_save_global(keyfile);
147 g_key_file_free(keyfile);
150 enum time_updates __connman_clock_timeupdates(void)
152 return time_updates_config;
155 static void append_timeservers(DBusMessageIter *iter, void *user_data)
158 char **timeservers = __connman_timeserver_system_get();
163 for (i = 0; timeservers[i]; i++) {
164 dbus_message_iter_append_basic(iter,
165 DBUS_TYPE_STRING, ×ervers[i]);
168 g_strfreev(timeservers);
171 static DBusMessage *get_properties(DBusConnection *conn,
172 DBusMessage *msg, void *data)
175 DBusMessageIter array, dict;
176 dbus_bool_t is_synced;
180 DBG("conn %p", conn);
182 reply = dbus_message_new_method_return(msg);
186 dbus_message_iter_init_append(reply, &array);
188 connman_dbus_dict_open(&array, &dict);
190 if (gettimeofday(&tv, NULL) == 0) {
191 dbus_uint64_t val = tv.tv_sec;
193 connman_dbus_dict_append_basic(&dict, "Time",
194 DBUS_TYPE_UINT64, &val);
197 str = time_updates2string(time_updates_config);
199 connman_dbus_dict_append_basic(&dict, "TimeUpdates",
200 DBUS_TYPE_STRING, &str);
203 connman_dbus_dict_append_basic(&dict, "Timezone",
204 DBUS_TYPE_STRING, &timezone_config);
206 str = timezone_updates2string(timezone_updates_config);
208 connman_dbus_dict_append_basic(&dict, "TimezoneUpdates",
209 DBUS_TYPE_STRING, &str);
211 connman_dbus_dict_append_array(&dict, "Timeservers",
212 DBUS_TYPE_STRING, append_timeservers, NULL);
214 is_synced = __connman_timeserver_is_synced();
215 connman_dbus_dict_append_basic(&dict, "TimeserverSynced",
216 DBUS_TYPE_BOOLEAN, &is_synced);
218 connman_dbus_dict_close(&array, &dict);
223 static DBusMessage *set_property(DBusConnection *conn,
224 DBusMessage *msg, void *data)
226 DBusMessageIter iter, value;
230 DBG("conn %p", conn);
232 if (!dbus_message_iter_init(msg, &iter))
233 return __connman_error_invalid_arguments(msg);
235 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
236 return __connman_error_invalid_arguments(msg);
238 dbus_message_iter_get_basic(&iter, &name);
239 dbus_message_iter_next(&iter);
241 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
242 return __connman_error_invalid_arguments(msg);
244 dbus_message_iter_recurse(&iter, &value);
246 type = dbus_message_iter_get_arg_type(&value);
248 if (g_str_equal(name, "Time")) {
250 dbus_uint64_t newval;
252 if (type != DBUS_TYPE_UINT64)
253 return __connman_error_invalid_arguments(msg);
255 if (time_updates_config != TIME_UPDATES_MANUAL)
256 return __connman_error_permission_denied(msg);
258 dbus_message_iter_get_basic(&value, &newval);
263 if (settimeofday(&tv, NULL) < 0)
264 return __connman_error_invalid_arguments(msg);
266 __connman_timeserver_set_synced(false);
267 connman_dbus_property_changed_basic(CONNMAN_MANAGER_PATH,
268 CONNMAN_CLOCK_INTERFACE, "Time",
269 DBUS_TYPE_UINT64, &newval);
270 } else if (g_str_equal(name, "TimeUpdates")) {
272 enum time_updates newval;
274 if (type != DBUS_TYPE_STRING)
275 return __connman_error_invalid_arguments(msg);
277 dbus_message_iter_get_basic(&value, &strval);
278 newval = string2time_updates(strval);
280 if (newval == TIME_UPDATES_UNKNOWN)
281 return __connman_error_invalid_arguments(msg);
283 if (newval == time_updates_config)
284 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
286 time_updates_config = newval;
288 clock_properties_save();
289 connman_dbus_property_changed_basic(CONNMAN_MANAGER_PATH,
290 CONNMAN_CLOCK_INTERFACE, "TimeUpdates",
291 DBUS_TYPE_STRING, &strval);
293 if (newval == TIME_UPDATES_AUTO) {
294 struct connman_service *service;
296 service = connman_service_get_default();
297 __connman_timeserver_conf_update(service);
299 } else if (g_str_equal(name, "Timezone")) {
302 if (type != DBUS_TYPE_STRING)
303 return __connman_error_invalid_arguments(msg);
305 if (timezone_updates_config != TIMEZONE_UPDATES_MANUAL)
306 return __connman_error_permission_denied(msg);
308 dbus_message_iter_get_basic(&value, &strval);
310 if (__connman_timezone_change(strval) < 0)
311 return __connman_error_invalid_arguments(msg);
312 } else if (g_str_equal(name, "TimezoneUpdates")) {
314 enum timezone_updates newval;
316 if (type != DBUS_TYPE_STRING)
317 return __connman_error_invalid_arguments(msg);
319 dbus_message_iter_get_basic(&value, &strval);
320 newval = string2timezone_updates(strval);
322 if (newval == TIMEZONE_UPDATES_UNKNOWN)
323 return __connman_error_invalid_arguments(msg);
325 if (newval == timezone_updates_config)
326 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
328 timezone_updates_config = newval;
330 clock_properties_save();
331 connman_dbus_property_changed_basic(CONNMAN_MANAGER_PATH,
332 CONNMAN_CLOCK_INTERFACE, "TimezoneUpdates",
333 DBUS_TYPE_STRING, &strval);
334 } else if (g_str_equal(name, "Timeservers")) {
335 DBusMessageIter entry;
340 if (type != DBUS_TYPE_ARRAY)
341 return __connman_error_invalid_arguments(msg);
343 dbus_message_iter_recurse(&value, &entry);
345 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
349 dbus_message_iter_get_basic(&entry, &val);
351 new_head = __connman_timeserver_add_list(list, val);
352 if (list != new_head) {
357 dbus_message_iter_next(&entry);
361 str = g_new0(char *, count+1);
365 str[count] = list->data;
366 list = g_slist_delete_link(list, list);
370 __connman_timeserver_system_set(str);
375 connman_dbus_property_changed_array(CONNMAN_MANAGER_PATH,
376 CONNMAN_CLOCK_INTERFACE, "Timeservers",
377 DBUS_TYPE_STRING, append_timeservers, NULL);
378 } else if (g_str_equal(name, "TimeserverSynced")) {
379 return __connman_error_permission_denied(msg);
381 return __connman_error_invalid_property(msg);
383 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
386 static const GDBusMethodTable clock_methods[] = {
387 { GDBUS_METHOD("GetProperties",
388 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
390 { GDBUS_METHOD("SetProperty",
391 GDBUS_ARGS({ "name", "s" }, { "value", "v" }), NULL,
396 static const GDBusSignalTable clock_signals[] = {
397 { GDBUS_SIGNAL("PropertyChanged",
398 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
402 static DBusConnection *connection = NULL;
404 void __connman_clock_update_timezone(void)
408 g_free(timezone_config);
409 timezone_config = __connman_timezone_lookup();
411 if (!timezone_config)
414 connman_dbus_property_changed_basic(CONNMAN_MANAGER_PATH,
415 CONNMAN_CLOCK_INTERFACE, "Timezone",
416 DBUS_TYPE_STRING, &timezone_config);
419 int __connman_clock_init(void)
423 connection = connman_dbus_get_connection();
427 __connman_timezone_init();
429 timezone_config = __connman_timezone_lookup();
431 g_dbus_register_interface(connection, CONNMAN_MANAGER_PATH,
432 CONNMAN_CLOCK_INTERFACE,
433 clock_methods, clock_signals,
436 clock_properties_load();
440 void __connman_clock_cleanup(void)
447 g_dbus_unregister_interface(connection, CONNMAN_MANAGER_PATH,
448 CONNMAN_CLOCK_INTERFACE);
450 dbus_connection_unref(connection);
452 __connman_timezone_cleanup();
454 g_free(timezone_config);