5 * Copyright (C) 2011-2013 Samsung Electronics Co., Ltd. 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
33 #define CONNMAN_API_SUBJECT_TO_CHANGE
34 #include <connman/plugin.h>
35 #include <connman/device.h>
36 #include <connman/network.h>
37 #include <connman/ipconfig.h>
38 #include <connman/dbus.h>
39 #include <connman/inet.h>
40 #include <connman/technology.h>
41 #include <connman/log.h>
43 #define PS_DBUS_SERVICE "com.tcore.ps"
45 #define PS_MASTER_INTERFACE PS_DBUS_SERVICE ".master"
46 #define PS_MODEM_INTERFACE PS_DBUS_SERVICE ".modem"
47 #define PS_SERVICE_INTERFACE PS_DBUS_SERVICE ".service"
48 #define PS_CONTEXT_INTERFACE PS_DBUS_SERVICE ".context"
51 #define GET_MODEMS "GetModems"
52 #define GET_SERVICES "GetServices"
53 #define GET_CONTEXTS "GetContexts"
54 #define ACTIVATE_CONTEXT "Activate"
55 #define DEACTIVATE_CONTEXT "Deactivate"
56 #define GET_PROPERTIES "GetProperties"
57 #define SET_PROPERTY "SetProperties"
60 #define MODEM_ADDED "ModemAdded"
61 #define MODEM_REMOVED "ModemRemoved"
62 #define SERVICE_ADDED "ServiceAdded"
63 #define SERVICE_REMOVED "ServiceRemoved"
64 #define CONTEXT_ADDED "ContextAdded"
65 #define CONTEXT_REMOVED "ContextRemoved"
66 #define PROPERTY_CHANGED "PropertyChanged"
70 #define STRING2BOOL(a) ((g_str_equal(a, "TRUE")) ? (TRUE):(FALSE))
72 static DBusConnection *connection;
73 static GHashTable *modem_hash;
74 static GHashTable *service_hash;
75 static GHashTable *network_hash;
77 struct telephony_service {
82 gboolean roaming; /* global roaming state */
83 gboolean ps_attached; /* packet service is available */
86 struct telephony_modem {
93 gboolean data_allowed;
94 gboolean roaming_allowed;
96 struct connman_device *device;
97 struct telephony_service *s_service;
100 struct telephony_network {
102 struct connman_network *network;
104 enum connman_ipconfig_method ipv4_method;
105 struct connman_ipaddress *ipv4_address;
107 enum connman_ipconfig_method ipv6_method;
108 struct connman_ipaddress *ipv6_address;
111 /* function prototype */
112 static void telephony_connect(DBusConnection *connection, void *user_data);
113 static void telephony_disconnect(DBusConnection *connection, void *user_data);
114 static void __remove_modem(gpointer data);
115 static void __remove_service(gpointer data);
116 static void __remove_network(gpointer data);
118 static int __modem_probe(struct connman_device *device);
119 static void __modem_remove(struct connman_device *device);
120 static int __modem_enable(struct connman_device *device);
121 static int __modem_disable(struct connman_device *device);
123 static int __network_probe(struct connman_network *network);
124 static void __network_remove(struct connman_network *network);
125 static int __network_connect(struct connman_network *network);
126 static int __network_disconnect(struct connman_network *network);
129 /* dbus request and reply */
130 static int __dbus_request(const char *path, const char *interface,
132 DBusPendingCallNotifyFunction notify, void *user_data,
133 DBusFreeFunction free_function, int type, ...);
135 static int __request_get_modems(void);
136 static void __response_get_modems(DBusPendingCall *call, void *user_data);
137 static int __request_get_services(const char *path);
138 static void __response_get_services(DBusPendingCall *call, void *user_data);
139 static int __request_get_contexts(struct telephony_modem *modem);
140 static void __response_get_contexts(DBusPendingCall *call, void *user_data);
141 static int __request_network_activate(struct connman_network *network);
142 static void __response_network_activate(DBusPendingCall *call, void *user_data);
143 static int __request_network_deactivate(struct connman_network *network);
145 /* telephony internal function */
146 static void __add_modem(const char *path, DBusMessageIter *prop);
147 static void __add_service(struct telephony_modem *modem,
148 const char *service_path, DBusMessageIter *prop);
149 static void __add_connman_device(const char *modem_path, const char *operator);
150 static void __remove_connman_device(struct telephony_modem *modem);
151 static void __remove_connman_networks(struct connman_device *device);
152 static void __set_device_powered(struct telephony_modem *modem,
154 static int __check_device_powered(const char *path, gboolean online);
155 static gboolean __check_network_available(struct connman_network *network);
156 static void __create_service(struct connman_network *network);
157 static int __add_context(struct connman_device *device, const char *path,
158 DBusMessageIter *prop);
159 static gboolean __set_network_ipconfig(struct telephony_network *network,
160 DBusMessageIter *dict);
161 static void __set_network_connected(struct telephony_network *network,
163 static char *__get_ident(const char *path);
166 static gboolean __changed_modem(DBusConnection *connection,
167 DBusMessage *message, void *user_data);
168 static gboolean __added_modem(DBusConnection *connection,
169 DBusMessage *message, void *user_data);
170 static gboolean __removed_modem(DBusConnection *connection,
171 DBusMessage *message, void *user_data);
172 static gboolean __changed_service(DBusConnection *connection,
173 DBusMessage *message, void *user_data);
174 static gboolean __added_service(DBusConnection *connection,
175 DBusMessage *message, void *user_data);
176 static gboolean __removed_service(DBusConnection *connection,
177 DBusMessage *message, void *user_data);
178 static gboolean __changed_context(DBusConnection *connection,
179 DBusMessage *message, void *user_data);
180 static gboolean __added_context(DBusConnection *connection,
181 DBusMessage *message, void *user_data);
182 static gboolean __removed_context(DBusConnection *connection,
183 DBusMessage *message, void *user_data);
186 static struct connman_device_driver modem_driver = {
188 .type = CONNMAN_DEVICE_TYPE_CELLULAR,
189 .probe = __modem_probe,
190 .remove = __modem_remove,
191 .enable = __modem_enable,
192 .disable = __modem_disable,
196 static struct connman_network_driver network_driver = {
198 .type = CONNMAN_NETWORK_TYPE_CELLULAR,
199 .probe = __network_probe,
200 .remove = __network_remove,
201 .connect = __network_connect,
202 .disconnect = __network_disconnect,
205 static int tech_probe(struct connman_technology *technology)
210 static void tech_remove(struct connman_technology *technology)
214 static struct connman_technology_driver tech_driver = {
216 .type = CONNMAN_SERVICE_TYPE_CELLULAR,
218 .remove = tech_remove,
222 static void telephony_connect(DBusConnection *connection, void *user_data)
224 DBG("connection %p", connection);
225 modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
226 g_free, __remove_modem);
227 service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
228 g_free, __remove_service);
229 network_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
230 g_free, __remove_network);
231 __request_get_modems();
235 static void telephony_disconnect(DBusConnection *connection, void *user_data)
237 DBG("connection %p", connection);
239 if (modem_hash != NULL) {
240 g_hash_table_destroy(modem_hash);
244 if (network_hash != NULL) {
245 g_hash_table_destroy(network_hash);
252 static void __remove_modem(gpointer data)
254 struct telephony_modem *modem = data;
256 __remove_connman_device(modem);
259 g_free(modem->operator);
263 static void __remove_service(gpointer data)
265 struct telephony_service *service = data;
267 g_free(service->path);
268 g_free(service->act);
272 static void __remove_network(gpointer data)
274 struct telephony_network *info = data;
275 struct connman_device *device;
277 device = connman_network_get_device(info->network);
279 connman_device_remove_network(device, info->network);
281 connman_network_unref(info->network);
284 connman_ipaddress_free(info->ipv4_address);
285 connman_ipaddress_free(info->ipv6_address);
289 static int __modem_probe(struct connman_device *device)
291 DBG("device %p", device);
295 static void __modem_remove(struct connman_device *device)
297 DBG("device %p", device);
300 static int __modem_enable(struct connman_device *device)
302 const char *path = connman_device_get_string(device, "Path");
303 DBG("device %p, path, %s", device, path);
305 return __check_device_powered(path, TRUE);
308 static int __modem_disable(struct connman_device *device)
310 const char *path = connman_device_get_string(device, "Path");
311 DBG("device %p, path, %s", device, path);
313 return __check_device_powered(path, FALSE);
316 static int __network_probe(struct connman_network *network)
318 DBG("network_prove network(%p)", network);
322 static int __network_connect(struct connman_network *network)
324 struct connman_device *device;
325 struct telephony_modem *modem;
326 struct telephony_service *service;
328 DBG("network %p", network);
330 device = connman_network_get_device(network);
334 modem = connman_device_get_data(device);
338 service = modem->s_service;
342 if (modem->powered == FALSE)
345 if (modem->data_allowed == FALSE || service->ps_attached == FALSE)
348 return __request_network_activate(network);
351 static int __network_disconnect(struct connman_network *network)
353 DBG("network %p", network);
355 if (connman_network_get_index(network) < 0)
358 connman_network_set_associating(network, FALSE);
360 return __request_network_deactivate(network);
363 static void __network_remove(struct connman_network *network)
365 char const *path = connman_network_get_string(network, "Path");
366 DBG("network %p path %s", network, path);
368 g_hash_table_remove(network_hash, path);
372 static int __dbus_request(const char *path, const char *interface,
374 DBusPendingCallNotifyFunction notify, void *user_data,
375 DBusFreeFunction free_function, int type, ...)
377 DBusMessage *message;
378 DBusPendingCall *call;
382 DBG("Telephony request path %s %s.%s", path, interface, method);
387 message = dbus_message_new_method_call(PS_DBUS_SERVICE, path,
392 dbus_message_set_auto_start(message, FALSE);
395 ok = dbus_message_append_args_valist(message, type, va);
401 if (dbus_connection_send_with_reply(connection, message,
402 &call, TIMEOUT) == FALSE) {
403 connman_error("Failed to call %s.%s", interface, method);
404 dbus_message_unref(message);
409 connman_error("D-Bus connection not available");
410 dbus_message_unref(message);
414 dbus_pending_call_set_notify(call, notify, user_data, free_function);
416 dbus_message_unref(message);
421 static int __request_get_modems(void)
423 DBG("request get modem");
424 /* call connect master */
425 return __dbus_request("/", PS_MASTER_INTERFACE, GET_MODEMS,
426 __response_get_modems, NULL, NULL, DBUS_TYPE_INVALID);
429 static void __response_get_modems(DBusPendingCall *call, void *user_data)
433 DBusMessageIter args, dict;
437 reply = dbus_pending_call_steal_reply(call);
439 dbus_error_init(&error);
441 if (dbus_set_error_from_message(&error, reply)) {
442 connman_error("GetModems() %s %s", error.name, error.message);
443 dbus_error_free(&error);
447 DBG("message signature (%s)", dbus_message_get_signature(reply));
449 if (dbus_message_iter_init(reply, &args) == FALSE)
452 dbus_message_iter_recurse(&args, &dict);
454 while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
455 DBusMessageIter entry, property;
456 const char *modem_path;
458 dbus_message_iter_recurse(&dict, &entry);
459 dbus_message_iter_get_basic(&entry, &modem_path);
460 DBG("modem path (%s)", modem_path);
462 dbus_message_iter_next(&entry);
463 dbus_message_iter_recurse(&entry, &property);
465 __add_modem(modem_path, &property);
467 dbus_message_iter_next(&dict);
471 dbus_message_unref(reply);
472 dbus_pending_call_unref(call);
476 static int __request_get_services(const char *path)
478 DBG("request get service");
479 return __dbus_request(path, PS_MODEM_INTERFACE, GET_SERVICES,
480 __response_get_services, g_strdup(path),
481 g_free, DBUS_TYPE_INVALID);
484 static void __response_get_services(DBusPendingCall *call, void *user_data)
488 DBusMessageIter args, dict;
490 const char *path = user_data;
491 struct telephony_modem *modem;
493 modem = g_hash_table_lookup(modem_hash, path);
496 if (modem->device == NULL)
501 reply = dbus_pending_call_steal_reply(call);
503 dbus_error_init(&error);
505 if (dbus_set_error_from_message(&error, reply)) {
506 connman_error("GetServices() %s %s", error.name, error.message);
507 dbus_error_free(&error);
511 DBG("message signature (%s)", dbus_message_get_signature(reply));
513 if (dbus_message_iter_init(reply, &args) == FALSE)
516 dbus_message_iter_recurse(&args, &dict);
518 while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
519 DBusMessageIter entry, property;
520 const char *service_path;
522 dbus_message_iter_recurse(&dict, &entry);
523 dbus_message_iter_get_basic(&entry, &service_path);
524 DBG("service path (%s)", service_path);
526 dbus_message_iter_next(&entry);
527 dbus_message_iter_recurse(&entry, &property);
529 __add_service(modem, service_path, &property);
531 dbus_message_iter_next(&dict);
535 dbus_message_unref(reply);
536 dbus_pending_call_unref(call);
540 static int __request_get_contexts(struct telephony_modem *modem)
542 DBG("request get contexts");
543 return __dbus_request(modem->s_service->path,
544 PS_SERVICE_INTERFACE, GET_CONTEXTS,
545 __response_get_contexts, g_strdup(modem->path),
546 g_free, DBUS_TYPE_INVALID);
549 static void __response_get_contexts(DBusPendingCall *call, void *user_data)
553 DBusMessageIter args, dict;
555 const char *path = user_data;
556 struct telephony_modem *modem;
560 modem = g_hash_table_lookup(modem_hash, path);
563 if (modem->s_service == NULL)
565 if (modem->device == NULL)
568 reply = dbus_pending_call_steal_reply(call);
570 dbus_error_init(&error);
572 if (dbus_set_error_from_message(&error, reply)) {
573 connman_error("GetContexts() %s %s", error.name, error.message);
574 dbus_error_free(&error);
578 DBG("message signature (%s)", dbus_message_get_signature(reply));
580 if (dbus_message_iter_init(reply, &args) == FALSE)
583 dbus_message_iter_recurse(&args, &dict);
585 while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
586 DBusMessageIter entry, property;
587 const char *context_path;
589 dbus_message_iter_recurse(&dict, &entry);
590 dbus_message_iter_get_basic(&entry, &context_path);
591 DBG("context path (%s)", context_path);
593 dbus_message_iter_next(&entry);
594 dbus_message_iter_recurse(&entry, &property);
596 __add_context(modem->device, context_path, &property);
598 dbus_message_iter_next(&dict);
602 dbus_message_unref(reply);
603 dbus_pending_call_unref(call);
607 static int __request_network_activate(struct connman_network *network)
609 DBG("request network activate");
611 const char *path = connman_network_get_string(network, "Path");
612 DBG("network %p, path %s", network, path);
614 return __dbus_request(path, PS_CONTEXT_INTERFACE, ACTIVATE_CONTEXT,
615 __response_network_activate,
616 g_strdup(path), NULL, DBUS_TYPE_INVALID);
619 static void __response_network_activate(DBusPendingCall *call, void *user_data)
621 DBG("network activation response");
626 struct telephony_network *info;
627 const char *path = user_data;
629 info = g_hash_table_lookup(network_hash, path);
630 reply = dbus_pending_call_steal_reply(call);
635 if (!__check_network_available(info->network)) {
636 g_hash_table_remove(network_hash, path);
640 dbus_error_init(&error);
641 if (dbus_set_error_from_message(&error, reply)) {
642 connman_error("connection activate() %s %s",
643 error.name, error.message);
645 if (connman_network_get_index(info->network) < 0)
646 connman_network_set_error(info->network,
647 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
649 dbus_error_free(&error);
654 dbus_message_unref(reply);
655 dbus_pending_call_unref(call);
659 static int __request_network_deactivate(struct connman_network *network)
661 DBG("request network deactivate");
663 const char *path = connman_network_get_string(network, "Path");
664 DBG("network %p, path %s", network, path);
666 return __dbus_request(path, PS_CONTEXT_INTERFACE, DEACTIVATE_CONTEXT,
667 NULL, NULL, NULL, DBUS_TYPE_INVALID);
670 static void __add_modem(const char *path, DBusMessageIter *prop)
672 struct telephony_modem *modem;
674 modem = g_hash_table_lookup(modem_hash, path);
678 modem = (struct telephony_modem *)malloc(
679 sizeof(struct telephony_modem));
680 memset(modem, 0, sizeof(struct telephony_modem));
682 modem->path = g_strdup(path);
683 modem->device = NULL;
684 modem->s_service = NULL;
686 g_hash_table_insert(modem_hash, g_strdup(path), modem);
688 while (dbus_message_iter_get_arg_type(prop) != DBUS_TYPE_INVALID) {
689 DBusMessageIter entry;
690 const char *key, *tmp;
692 dbus_message_iter_recurse(prop, &entry);
693 dbus_message_iter_get_basic(&entry, &key);
695 dbus_message_iter_next(&entry);
696 dbus_message_iter_get_basic(&entry, &tmp);
698 DBG("key (%s) value(%s)", key, tmp);
700 if (g_str_equal(key, "powered") == TRUE) {
701 modem->powered = STRING2BOOL(tmp);
702 } else if (g_str_equal(key, "operator") == TRUE) {
703 modem->operator = g_strdup(tmp);
704 } else if (g_str_equal(key, "sim_init") == TRUE) {
705 modem->sim_init = STRING2BOOL(tmp);
706 } else if (g_str_equal(key, "flight_mode") == TRUE) {
707 modem->flight_mode = STRING2BOOL(tmp);
708 } else if (g_str_equal(key, "roaming_allowed") == TRUE) {
709 modem->roaming_allowed = STRING2BOOL(tmp);
710 } else if (g_str_equal(key, "data_allowed") == TRUE) {
711 modem->data_allowed = STRING2BOOL(tmp);
713 dbus_message_iter_next(prop);
716 __add_connman_device(path, modem->operator);
717 __set_device_powered(modem, modem->powered);
719 if (modem->powered != TRUE) {
720 DBG("modem is not powered");
724 __request_get_services(modem->path);
729 static void __add_service(struct telephony_modem *modem,
730 const char *service_path, DBusMessageIter *prop)
732 struct telephony_service *service;
734 if (modem->s_service != NULL)
737 service = (struct telephony_service *)g_try_malloc(
738 sizeof(struct telephony_service));
742 memset(service, 0, sizeof(struct telephony_service));
744 service->path = g_strdup(service_path);
745 service->p_modem = modem;
746 g_hash_table_insert(service_hash, g_strdup(service_path), service);
748 while (dbus_message_iter_get_arg_type(prop) != DBUS_TYPE_INVALID) {
749 DBusMessageIter entry;
750 const char *key, *tmp;
752 dbus_message_iter_recurse(prop, &entry);
753 dbus_message_iter_get_basic(&entry, &key);
755 dbus_message_iter_next(&entry);
756 dbus_message_iter_get_basic(&entry, &tmp);
758 DBG("key (%s) value(%s)", key, tmp);
760 if (g_str_equal(key, "roaming") == TRUE) {
761 service->roaming = STRING2BOOL(tmp);
762 } else if (g_str_equal(key, "act") == TRUE) {
763 service->act = g_strdup(tmp);
764 } else if (g_str_equal(key, "ps_attached") == TRUE) {
765 service->ps_attached = STRING2BOOL(tmp);
768 dbus_message_iter_next(prop);
771 modem->s_service = service;
772 __request_get_contexts(modem);
777 static void __add_connman_device(const char *modem_path, const char *operator)
779 struct telephony_modem *modem;
780 struct connman_device *device;
782 DBG("path %s operator %s", modem_path, operator);
784 if (modem_path == NULL)
787 if (operator == NULL)
790 modem = g_hash_table_lookup(modem_hash, modem_path);
795 if (!g_strcmp0(operator,
796 connman_device_get_ident(modem->device)))
799 __remove_connman_device(modem);
802 if (strlen(operator) == 0)
805 device = connman_device_create(operator, CONNMAN_DEVICE_TYPE_CELLULAR);
809 connman_device_set_ident(device, operator);
810 connman_device_set_string(device, "Path", modem_path);
811 connman_device_set_data(device, modem);
813 if (connman_device_register(device) < 0) {
814 connman_error("Failed to register cellular device");
815 connman_device_unref(device);
819 modem->device = device;
824 static void __remove_connman_device(struct telephony_modem *modem)
826 DBG("modem %p path %s device %p", modem, modem->path, modem->device);
828 if (modem->device == NULL)
831 __remove_connman_networks(modem->device);
833 connman_device_unregister(modem->device);
834 connman_device_unref(modem->device);
836 modem->device = NULL;
841 static void __remove_connman_networks(struct connman_device *device)
845 GSList *info_list = NULL;
848 if (network_hash == NULL)
851 g_hash_table_iter_init(&iter, network_hash);
853 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
854 struct telephony_network *info = value;
856 if (connman_network_get_device(info->network) != device)
859 info_list = g_slist_append(info_list, info);
862 for (list = info_list; list != NULL; list = list->next) {
863 struct telephony_network *info = list->data;
864 connman_device_remove_network(device, info->network);
867 g_slist_free(info_list);
870 static void __set_device_powered(struct telephony_modem *modem,
873 DBG("set modem(%s) powered(%d)", modem->path, powered);
876 connman_device_set_powered(modem->device, powered);
881 static int __check_device_powered(const char *path, gboolean powered)
883 struct telephony_modem *modem = g_hash_table_lookup(modem_hash, path);
888 DBG("check modem (%s) powered (%d)", modem->path, modem->powered);
890 if (modem->powered == powered)
896 static gboolean __check_network_available(struct connman_network *network)
898 if (network == NULL || connman_network_get_device(network) == NULL) {
899 DBG("Modem or network was removed");
906 static int __add_context(struct connman_device *device, const char *path,
907 DBusMessageIter *prop)
910 gboolean active = FALSE;
912 struct telephony_modem *modem = connman_device_get_data(device);
913 struct connman_network *network;
914 struct telephony_network *info;
916 DBG("modem %p device %p path %s", modem, device, path);
918 ident = __get_ident(path);
920 network = connman_device_get_network(device, ident);
924 info = g_hash_table_lookup(network_hash, path);
926 DBG("path %p already exists with device %p", path,
927 connman_network_get_device(info->network));
929 if (connman_network_get_device(info->network))
932 g_hash_table_remove(network_hash, path);
935 network = connman_network_create(ident, CONNMAN_NETWORK_TYPE_CELLULAR);
939 info = (struct telephony_network *)g_try_malloc(
940 sizeof(struct telephony_network));
942 connman_network_unref(network);
946 memset(info, 0, sizeof(struct telephony_network));
948 info->path = g_strdup(path);
950 connman_ipaddress_clear(info->ipv4_address);
951 connman_ipaddress_clear(info->ipv6_address);
952 info->network = network;
954 connman_network_set_string(network, "Path", path);
955 connman_network_set_name(network, path);
957 __create_service(network);
959 g_hash_table_insert(network_hash, g_strdup(path), info);
961 connman_network_set_available(network, TRUE);
962 connman_network_set_index(network, -1);
963 connman_network_set_bool(network, "Roaming", modem->s_service->roaming);
965 if (connman_device_add_network(device, network) != 0) {
966 g_hash_table_remove(network_hash, path);
970 active = __set_network_ipconfig(info, prop);
972 if (active && (connman_network_get_connecting(network) ||
973 connman_network_get_associating(network)))
974 __set_network_connected(info, active);
979 static void __create_service(struct connman_network *network)
986 path = connman_network_get_string(network, "Path");
988 group = __get_ident(path);
990 connman_network_set_group(network, group);
993 static gboolean __set_network_ipconfig(struct telephony_network *network,
994 DBusMessageIter *dict)
996 DBG("set network info");
998 gboolean active = FALSE;
999 char *dev_name = NULL, *proxy_addr = NULL;
1000 char *ipv4_addr = NULL, *ipv4_gw = NULL, *ipv4_netmask = NULL,
1001 *ipv4_dns1 = NULL, *ipv4_dns2 = NULL;
1002 char *ipv6_addr = NULL, *ipv6_gw = NULL, *ipv6_netmask = NULL,
1003 *ipv6_dns1 = NULL, *ipv6_dns2 = NULL;
1007 while (dbus_message_iter_get_arg_type(dict) != DBUS_TYPE_INVALID) {
1008 DBusMessageIter entry;
1009 const char *key, *tmp;
1011 dbus_message_iter_recurse(dict, &entry);
1012 dbus_message_iter_get_basic(&entry, &key);
1014 dbus_message_iter_next(&entry);
1016 DBG("key (%s)", key);
1018 if (g_str_equal(key, "dev_name") == TRUE) {
1019 dbus_message_iter_get_basic(&entry, &dev_name);
1020 DBG("dev_name (%s)", dev_name);
1021 } else if (g_str_equal(key, "proxy") == TRUE) {
1022 dbus_message_iter_get_basic(&entry, &proxy_addr);
1023 } else if (g_str_equal(key, "ipv4_address") == TRUE) {
1024 dbus_message_iter_get_basic(&entry, &ipv4_addr);
1025 DBG("ipv4 address (%s)", ipv4_addr);
1026 } else if (g_str_equal(key, "ipv4_gateway") == TRUE) {
1027 dbus_message_iter_get_basic(&entry, &ipv4_gw);
1028 } else if (g_str_equal(key, "ipv4_netmask") == TRUE) {
1029 dbus_message_iter_get_basic(&entry, &ipv4_netmask);
1030 } else if (g_str_equal(key, "ipv4_dns1") == TRUE) {
1031 dbus_message_iter_get_basic(&entry, &ipv4_dns1);
1032 } else if (g_str_equal(key, "ipv4_dns2") == TRUE) {
1033 dbus_message_iter_get_basic(&entry, &ipv4_dns2);
1034 } else if (g_str_equal(key, "ipv6_address") == TRUE) {
1035 dbus_message_iter_get_basic(&entry, &ipv6_addr);
1036 DBG("ipv6 address (%s)", ipv6_addr);
1037 } else if (g_str_equal(key, "ipv6_gateway") == TRUE) {
1038 dbus_message_iter_get_basic(&entry, &ipv6_gw);
1039 } else if (g_str_equal(key, "ipv6_netmask") == TRUE) {
1040 dbus_message_iter_get_basic(&entry, &ipv6_netmask);
1041 } else if (g_str_equal(key, "ipv6_dns1") == TRUE) {
1042 dbus_message_iter_get_basic(&entry, &ipv6_dns1);
1043 } else if (g_str_equal(key, "ipv6_dns2") == TRUE) {
1044 dbus_message_iter_get_basic(&entry, &ipv6_dns2);
1045 } else if (g_str_equal(key, "active") == TRUE) {
1046 dbus_message_iter_get_basic(&entry, &tmp);
1047 DBG("active (%s)", tmp);
1048 active = STRING2BOOL(tmp);
1051 dbus_message_iter_next(dict);
1054 /* interface index set */
1055 if (dev_name == NULL)
1058 if (!g_str_equal(dev_name, "")) {
1059 index = connman_inet_ifindex(dev_name);
1060 DBG("interface %s, index %d", dev_name, index);
1061 connman_network_set_index(network->network, index);
1065 if (proxy_addr == NULL)
1068 DBG("proxy (%s) is set", proxy_addr);
1069 connman_network_set_proxy(network->network, proxy_addr);
1072 if (ipv4_addr == NULL)
1073 ipv4_addr = "0.0.0.0";
1075 if (g_str_equal(ipv4_addr, "0.0.0.0")) {
1076 network->ipv4_method = CONNMAN_IPCONFIG_METHOD_OFF;
1078 network->ipv4_method = CONNMAN_IPCONFIG_METHOD_FIXED;
1079 network->ipv4_address =
1080 connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4);
1081 if (network->ipv4_address == NULL)
1084 connman_ipaddress_set_ipv4(network->ipv4_address, ipv4_addr,
1085 ipv4_netmask, ipv4_gw);
1087 if (ipv4_dns1 == NULL)
1088 ipv4_dns1 = "0.0.0.0";
1089 if (ipv4_dns2 == NULL)
1090 ipv4_dns2 = "0.0.0.0";
1092 if (g_str_equal(ipv4_dns1, "0.0.0.0"))
1095 if (g_str_equal(ipv4_dns2, "0.0.0.0"))
1098 gchar *nameservers = NULL;
1102 nameservers = g_strdup_printf("%s %s", ipv4_dns1,
1106 nameservers = g_strdup_printf("%s", ipv4_dns2);
1109 nameservers = g_strdup_printf("%s", ipv4_dns1);
1112 connman_network_set_nameservers(network->network, nameservers);
1113 g_free(nameservers);
1117 if (ipv6_addr == NULL)
1120 if (g_str_equal(ipv6_addr, "::")) {
1121 network->ipv6_method = CONNMAN_IPCONFIG_METHOD_OFF;
1123 network->ipv6_method = CONNMAN_IPCONFIG_METHOD_FIXED;
1124 unsigned char prefix_length = 64;
1125 network->ipv6_address =
1126 connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6);
1127 if (network->ipv6_address == NULL)
1130 connman_ipaddress_set_ipv6(network->ipv6_address, ipv6_addr,
1131 prefix_length, ipv6_gw);
1135 if (ipv6_dns1 == NULL)
1137 if (ipv6_dns2 == NULL)
1140 if (g_str_equal(ipv6_dns1, "::"))
1143 if (g_str_equal(ipv6_dns2, "::"))
1146 gchar *nameservers = NULL;
1150 nameservers = g_strdup_printf("%s %s", ipv6_dns1,
1154 nameservers = g_strdup_printf("%s", ipv6_dns2);
1157 nameservers = g_strdup_printf("%s", ipv6_dns1);
1160 connman_network_set_nameservers(network->network, nameservers);
1161 g_free(nameservers);
1165 connman_network_set_associating(network->network, TRUE);
1170 static void __set_network_connected(struct telephony_network *network,
1173 gboolean setip = FALSE;
1175 DBG("network %p connected %d", network, connected);
1177 switch (network->ipv4_method) {
1178 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1179 case CONNMAN_IPCONFIG_METHOD_OFF:
1180 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1181 case CONNMAN_IPCONFIG_METHOD_AUTO:
1185 case CONNMAN_IPCONFIG_METHOD_FIXED:
1186 connman_network_set_ipv4_method(network->network,
1187 network->ipv4_method);
1188 connman_network_set_ipaddress(network->network,
1189 network->ipv4_address);
1193 case CONNMAN_IPCONFIG_METHOD_DHCP:
1194 connman_network_set_ipv4_method(network->network,
1195 network->ipv4_method);
1200 switch (network->ipv6_method) {
1201 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1202 case CONNMAN_IPCONFIG_METHOD_OFF:
1203 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1204 case CONNMAN_IPCONFIG_METHOD_DHCP:
1206 case CONNMAN_IPCONFIG_METHOD_AUTO:
1207 connman_network_set_ipv6_method(network->network,
1208 network->ipv6_method);
1212 case CONNMAN_IPCONFIG_METHOD_FIXED:
1213 connman_network_set_ipv6_method(network->network,
1214 network->ipv6_method);
1215 connman_network_set_ipaddress(network->network,
1216 network->ipv6_address);
1222 connman_network_set_connected(network->network, connected);
1227 static char *__get_ident(const char *path)
1234 pos = strrchr(path, '/');
1241 static gboolean __changed_modem(DBusConnection *connection,
1242 DBusMessage *message, void *user_data)
1244 DBG("modem changed signal");
1246 DBusMessageIter args, dict;
1247 const char *path = dbus_message_get_path(message);
1248 struct telephony_modem *modem;
1250 DBG("modem path %s", path);
1252 modem = g_hash_table_lookup(modem_hash, path);
1253 if (modem == NULL) {
1254 DBG("modem object does not exists");
1258 DBG("message signature (%s)", dbus_message_get_signature(message));
1260 if (dbus_message_iter_init(message, &args) == FALSE) {
1261 DBG("error to read message");
1265 dbus_message_iter_recurse(&args, &dict);
1267 while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
1268 DBusMessageIter entry;
1269 const char *key, *tmp;
1271 dbus_message_iter_recurse(&dict, &entry);
1272 dbus_message_iter_get_basic(&entry, &key);
1274 dbus_message_iter_next(&entry);
1275 dbus_message_iter_get_basic(&entry, &tmp);
1277 DBG("key(%s), value(%s)", key, tmp);
1279 if (g_str_equal(key, "powered") == TRUE) {
1280 modem->powered = STRING2BOOL(tmp);
1281 } else if (g_str_equal(key, "operator") == TRUE) {
1282 modem->operator = g_strdup(tmp);
1283 } else if (g_str_equal(key, "sim_init") == TRUE) {
1284 modem->sim_init = STRING2BOOL(tmp);
1285 } else if (g_str_equal(key, "flight_mode") == TRUE) {
1286 modem->flight_mode = STRING2BOOL(tmp);
1287 } else if (g_str_equal(key, "roaming_allowed") == TRUE) {
1288 modem->roaming_allowed = STRING2BOOL(tmp);
1289 } else if (g_str_equal(key, "data_allowed") == TRUE) {
1290 modem->data_allowed = STRING2BOOL(tmp);
1293 dbus_message_iter_next(&dict);
1296 if (modem->device == NULL)
1297 __add_connman_device(path, modem->operator);
1299 __set_device_powered(modem, modem->powered);
1301 if (modem->powered != TRUE) {
1302 DBG("modem is not powered");
1306 if (!modem->s_service) {
1307 __request_get_services(modem->path);
1311 if (modem->flight_mode || !modem->data_allowed) {
1312 DBG("modem(%s) flight mode(%d) data allowed(%d)",
1313 modem->path, modem->flight_mode, modem->data_allowed);
1320 static gboolean __added_modem(DBusConnection *connection,
1321 DBusMessage *message, void *user_data)
1323 DBG("modem added signal");
1325 const char *modem_path = NULL;
1326 DBusMessageIter args, dict, tmp;
1328 DBG("message signature (%s)", dbus_message_get_signature(message));
1329 if (dbus_message_iter_init(message, &args) == FALSE) {
1330 DBG("error to read message");
1334 dbus_message_iter_recurse(&args, &dict);
1335 memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
1337 while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
1338 DBusMessageIter entry;
1339 const char *key, *value;
1341 dbus_message_iter_recurse(&tmp, &entry);
1342 dbus_message_iter_get_basic(&entry, &key);
1344 dbus_message_iter_next(&entry);
1345 dbus_message_iter_get_basic(&entry, &value);
1347 DBG("key (%s) value(%s)", key, value);
1349 if (g_str_equal(key, "path") == TRUE)
1350 modem_path = g_strdup(value);
1352 dbus_message_iter_next(&tmp);
1355 if (modem_path != NULL)
1356 __add_modem(modem_path, &dict);
1361 static gboolean __removed_modem(DBusConnection *connection,
1362 DBusMessage *message, void *user_data)
1364 DBG("modem removed signal");
1366 DBusMessageIter iter;
1367 const char *modem_path;
1369 if (dbus_message_iter_init(message, &iter) == FALSE) {
1370 DBG("error to read message");
1374 dbus_message_iter_get_basic(&iter, &modem_path);
1375 g_hash_table_remove(modem_hash, modem_path);
1380 static gboolean __changed_service(DBusConnection *connection,
1381 DBusMessage *message, void *user_data)
1383 DBG("service changed signal");
1385 DBusMessageIter args, dict;
1386 const char *service_path = dbus_message_get_path(message);
1387 struct telephony_modem *modem;
1388 struct telephony_service *s_service;
1389 gboolean roaming_option = TRUE;
1391 DBG("service path %s", service_path);
1393 s_service = g_hash_table_lookup(service_hash, service_path);
1394 if (s_service == NULL) {
1395 DBG("service object does not exists");
1399 modem = s_service->p_modem;
1400 if (modem == NULL) {
1401 DBG("modem object does not exists");
1405 DBG("message signature (%s)", dbus_message_get_signature(message));
1407 if (dbus_message_iter_init(message, &args) == FALSE) {
1408 DBG("error to read message");
1412 dbus_message_iter_recurse(&args, &dict);
1414 while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
1415 DBusMessageIter entry;
1416 const char *key, *tmp;
1418 dbus_message_iter_recurse(&dict, &entry);
1419 dbus_message_iter_get_basic(&entry, &key);
1421 dbus_message_iter_next(&entry);
1422 dbus_message_iter_get_basic(&entry, &tmp);
1424 DBG("key(%s), value(%s)", key, tmp);
1426 if (g_str_equal(key, "roaming") == TRUE) {
1427 s_service->roaming = STRING2BOOL(tmp);
1428 } else if (g_str_equal(key, "act") == TRUE) {
1429 s_service->act = g_strdup(tmp);
1430 } else if (g_str_equal(key, "ps_attached") == TRUE) {
1431 s_service->ps_attached = STRING2BOOL(tmp);
1434 dbus_message_iter_next(&dict);
1437 roaming_option &= (!s_service->roaming && !modem->roaming_allowed)
1438 || modem->roaming_allowed;
1444 static gboolean __added_service(DBusConnection *connection,
1445 DBusMessage *message, void *user_data)
1447 DBG("service added signal");
1449 const char *path = dbus_message_get_path(message);
1450 const char *service_path = NULL;
1451 DBusMessageIter args, dict, tmp;
1452 struct telephony_modem *modem;
1454 modem = g_hash_table_lookup(modem_hash, path);
1455 if (modem == NULL || modem->device == NULL)
1458 DBG("message signature (%s)", dbus_message_get_signature(message));
1459 if (dbus_message_iter_init(message, &args) == FALSE) {
1460 DBG("error to read message");
1464 dbus_message_iter_recurse(&args, &dict);
1465 memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
1467 while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
1468 DBusMessageIter entry;
1469 const char *key, *value;
1471 dbus_message_iter_recurse(&tmp, &entry);
1472 dbus_message_iter_get_basic(&entry, &key);
1474 dbus_message_iter_next(&entry);
1475 dbus_message_iter_get_basic(&entry, &value);
1477 DBG("key (%s) value(%s)", key, value);
1479 if (g_str_equal(key, "path") == TRUE) {
1480 service_path = g_strdup(value);
1483 dbus_message_iter_next(&tmp);
1486 if (service_path != NULL)
1487 __add_service(modem, service_path, &dict);
1492 static gboolean __removed_service(DBusConnection *connection,
1493 DBusMessage *message, void *user_data)
1495 DBG("service removed signal");
1497 DBusMessageIter iter;
1498 const char *service_path;
1500 if (dbus_message_iter_init(message, &iter) == FALSE) {
1501 DBG("error to read message");
1505 dbus_message_iter_get_basic(&iter, &service_path);
1506 g_hash_table_remove(service_hash, service_path);
1511 static gboolean __changed_context(DBusConnection *connection,
1512 DBusMessage *message, void *user_data)
1514 DBG("network changed signal");
1516 gboolean active = FALSE;
1517 const char *path = dbus_message_get_path(message);
1518 struct telephony_network *info;
1519 DBusMessageIter args, dict;
1521 DBG("path %s", path);
1522 info = g_hash_table_lookup(network_hash, path);
1526 if (!__check_network_available(info->network)) {
1527 g_hash_table_remove(network_hash, path);
1531 if (dbus_message_iter_init(message, &args) == FALSE) {
1532 DBG("error to read message");
1536 dbus_message_iter_recurse(&args, &dict);
1538 active = __set_network_ipconfig(info, &dict);
1540 if (active == FALSE)
1541 __set_network_connected(info, active);
1542 else if ((connman_network_get_connecting(info->network) ||
1543 connman_network_get_associating(info->network)))
1544 __set_network_connected(info, active);
1549 static gboolean __added_context(DBusConnection *connection,
1550 DBusMessage *message, void *user_data)
1552 DBG("network added signal");
1554 DBusMessageIter args, dict, tmp;
1555 const char *path = dbus_message_get_path(message);
1556 const char *network_path = NULL;
1557 struct telephony_service *service = NULL;
1558 struct telephony_modem *modem = NULL;
1560 service = g_hash_table_lookup(service_hash, path);
1561 if (service == NULL || service->p_modem == NULL)
1564 modem = service->p_modem;
1565 if (modem == NULL || modem->device == NULL)
1568 DBG("message signature (%s)", dbus_message_get_signature(message));
1569 if (dbus_message_iter_init(message, &args) == FALSE) {
1570 DBG("error to read message");
1574 dbus_message_iter_recurse(&args, &dict);
1575 memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
1577 while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
1578 DBusMessageIter entry;
1579 const char *key, *value;
1581 dbus_message_iter_recurse(&tmp, &entry);
1582 dbus_message_iter_get_basic(&entry, &key);
1584 dbus_message_iter_next(&entry);
1585 dbus_message_iter_get_basic(&entry, &value);
1587 DBG("key (%s) value(%s)", key, value);
1589 if (g_str_equal(key, "path") == TRUE)
1590 network_path = g_strdup(value);
1592 dbus_message_iter_next(&tmp);
1595 if (network_path != NULL)
1596 __add_context(modem->device, network_path, &dict);
1601 static gboolean __removed_context(DBusConnection *connection,
1602 DBusMessage *message, void *user_data)
1604 DBG("network removed signal");
1606 DBusMessageIter iter;
1607 const char *path = dbus_message_get_path(message);
1608 const char *network_path = NULL;
1609 struct telephony_service *service = NULL;
1611 service = g_hash_table_lookup(service_hash, path);
1612 if (service == NULL || service->p_modem == NULL)
1615 if (dbus_message_iter_init(message, &iter) == FALSE) {
1616 DBG("error to read message");
1620 dbus_message_iter_get_basic(&iter, &network_path);
1621 g_hash_table_remove(network_hash, network_path);
1626 /* telephony initialization */
1628 static guint modem_watch;
1629 static guint modem_added_watch;
1630 static guint modem_removed_watch;
1631 static guint service_watch;
1632 static guint service_added_watch;
1633 static guint service_removed_watch;
1634 static guint context_watch;
1635 static guint context_added_watch;
1636 static guint context_removed_watch;
1638 static int telephony_init(void)
1640 DBG("telephony plugin");
1643 connection = connman_dbus_get_connection();
1644 if (connection == NULL)
1647 /* telephony watch */
1648 watch = g_dbus_add_service_watch(connection, PS_DBUS_SERVICE,
1649 telephony_connect, telephony_disconnect,
1652 modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1655 __changed_modem, NULL, NULL);
1657 modem_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1658 PS_MASTER_INTERFACE,
1659 MODEM_ADDED, __added_modem,
1662 modem_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1663 PS_MASTER_INTERFACE,
1664 MODEM_REMOVED, __removed_modem,
1667 service_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1668 PS_SERVICE_INTERFACE,
1673 service_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1675 SERVICE_ADDED, __added_service,
1678 service_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1684 context_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1685 PS_CONTEXT_INTERFACE,
1690 context_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1691 PS_SERVICE_INTERFACE,
1692 CONTEXT_ADDED, __added_context,
1695 context_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1696 PS_SERVICE_INTERFACE,
1701 if (watch == 0 || modem_watch == 0 || modem_added_watch == 0
1702 || modem_removed_watch == 0 || service_watch == 0
1703 || service_added_watch == 0 || context_watch == 0
1704 || service_removed_watch == 0
1705 || context_added_watch == 0
1706 || context_removed_watch == 0) {
1711 err = connman_network_driver_register(&network_driver);
1715 err = connman_device_driver_register(&modem_driver);
1717 connman_network_driver_unregister(&network_driver);
1721 err = connman_technology_driver_register(&tech_driver);
1723 connman_device_driver_unregister(&modem_driver);
1724 connman_network_driver_unregister(&network_driver);
1731 g_dbus_remove_watch(connection, watch);
1732 g_dbus_remove_watch(connection, modem_watch);
1733 g_dbus_remove_watch(connection, modem_added_watch);
1734 g_dbus_remove_watch(connection, modem_removed_watch);
1735 g_dbus_remove_watch(connection, service_watch);
1736 g_dbus_remove_watch(connection, service_added_watch);
1737 g_dbus_remove_watch(connection, service_removed_watch);
1738 g_dbus_remove_watch(connection, context_watch);
1739 g_dbus_remove_watch(connection, context_added_watch);
1740 g_dbus_remove_watch(connection, context_removed_watch);
1742 dbus_connection_unref(connection);
1746 static void telephony_exit(void)
1748 g_dbus_remove_watch(connection, watch);
1749 g_dbus_remove_watch(connection, modem_watch);
1750 g_dbus_remove_watch(connection, modem_added_watch);
1751 g_dbus_remove_watch(connection, modem_removed_watch);
1752 g_dbus_remove_watch(connection, service_watch);
1753 g_dbus_remove_watch(connection, service_added_watch);
1754 g_dbus_remove_watch(connection, service_removed_watch);
1755 g_dbus_remove_watch(connection, context_watch);
1756 g_dbus_remove_watch(connection, context_added_watch);
1757 g_dbus_remove_watch(connection, context_removed_watch);
1759 telephony_disconnect(connection, NULL);
1761 connman_device_driver_unregister(&modem_driver);
1762 connman_network_driver_unregister(&network_driver);
1764 dbus_connection_unref(connection);
1767 CONNMAN_PLUGIN_DEFINE(telephony, "Samsung Telephony Framework plug-in", VERSION,
1768 CONNMAN_PLUGIN_PRIORITY_DEFAULT, telephony_init, telephony_exit)