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;
327 DBG("network %p", network);
329 device = connman_network_get_device(network);
333 modem = connman_device_get_data(device);
337 if (modem->powered == FALSE)
340 return __request_network_activate(network);
343 static int __network_disconnect(struct connman_network *network)
345 DBG("network %p", network);
347 if (connman_network_get_index(network) < 0)
350 connman_network_set_associating(network, FALSE);
352 return __request_network_deactivate(network);
355 static void __network_remove(struct connman_network *network)
357 char const *path = connman_network_get_string(network, "Path");
358 DBG("network %p path %s", network, path);
360 g_hash_table_remove(network_hash, path);
364 static int __dbus_request(const char *path, const char *interface,
366 DBusPendingCallNotifyFunction notify, void *user_data,
367 DBusFreeFunction free_function, int type, ...)
369 DBusMessage *message;
370 DBusPendingCall *call;
374 DBG("Telephony request path %s %s.%s", path, interface, method);
379 message = dbus_message_new_method_call(PS_DBUS_SERVICE, path,
384 dbus_message_set_auto_start(message, FALSE);
387 ok = dbus_message_append_args_valist(message, type, va);
393 if (dbus_connection_send_with_reply(connection, message,
394 &call, TIMEOUT) == FALSE) {
395 connman_error("Failed to call %s.%s", interface, method);
396 dbus_message_unref(message);
401 connman_error("D-Bus connection not available");
402 dbus_message_unref(message);
406 dbus_pending_call_set_notify(call, notify, user_data, free_function);
408 dbus_message_unref(message);
413 static int __request_get_modems(void)
415 DBG("request get modem");
416 /* call connect master */
417 return __dbus_request("/", PS_MASTER_INTERFACE, GET_MODEMS,
418 __response_get_modems, NULL, NULL, DBUS_TYPE_INVALID);
421 static void __response_get_modems(DBusPendingCall *call, void *user_data)
425 DBusMessageIter args, dict;
429 reply = dbus_pending_call_steal_reply(call);
431 dbus_error_init(&error);
433 if (dbus_set_error_from_message(&error, reply)) {
434 connman_error("GetModems() %s %s", error.name, error.message);
435 dbus_error_free(&error);
439 DBG("message signature (%s)", dbus_message_get_signature(reply));
441 if (dbus_message_iter_init(reply, &args) == FALSE)
444 dbus_message_iter_recurse(&args, &dict);
446 while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
447 DBusMessageIter entry, property;
448 const char *modem_path;
450 dbus_message_iter_recurse(&dict, &entry);
451 dbus_message_iter_get_basic(&entry, &modem_path);
452 DBG("modem path (%s)", modem_path);
454 dbus_message_iter_next(&entry);
455 dbus_message_iter_recurse(&entry, &property);
457 __add_modem(modem_path, &property);
459 dbus_message_iter_next(&dict);
463 dbus_message_unref(reply);
464 dbus_pending_call_unref(call);
468 static int __request_get_services(const char *path)
470 DBG("request get service");
471 return __dbus_request(path, PS_MODEM_INTERFACE, GET_SERVICES,
472 __response_get_services, g_strdup(path),
473 g_free, DBUS_TYPE_INVALID);
476 static void __response_get_services(DBusPendingCall *call, void *user_data)
480 DBusMessageIter args, dict;
482 const char *path = user_data;
483 struct telephony_modem *modem;
485 modem = g_hash_table_lookup(modem_hash, path);
488 if (modem->device == NULL)
493 reply = dbus_pending_call_steal_reply(call);
495 dbus_error_init(&error);
497 if (dbus_set_error_from_message(&error, reply)) {
498 connman_error("GetServices() %s %s", error.name, error.message);
499 dbus_error_free(&error);
503 DBG("message signature (%s)", dbus_message_get_signature(reply));
505 if (dbus_message_iter_init(reply, &args) == FALSE)
508 dbus_message_iter_recurse(&args, &dict);
510 while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
511 DBusMessageIter entry, property;
512 const char *service_path;
514 dbus_message_iter_recurse(&dict, &entry);
515 dbus_message_iter_get_basic(&entry, &service_path);
516 DBG("service path (%s)", service_path);
518 dbus_message_iter_next(&entry);
519 dbus_message_iter_recurse(&entry, &property);
521 __add_service(modem, service_path, &property);
523 dbus_message_iter_next(&dict);
527 dbus_message_unref(reply);
528 dbus_pending_call_unref(call);
532 static int __request_get_contexts(struct telephony_modem *modem)
534 DBG("request get contexts");
535 return __dbus_request(modem->s_service->path,
536 PS_SERVICE_INTERFACE, GET_CONTEXTS,
537 __response_get_contexts, g_strdup(modem->path),
538 g_free, DBUS_TYPE_INVALID);
541 static void __response_get_contexts(DBusPendingCall *call, void *user_data)
545 DBusMessageIter args, dict;
547 const char *path = user_data;
548 struct telephony_modem *modem;
552 modem = g_hash_table_lookup(modem_hash, path);
555 if (modem->s_service == NULL)
557 if (modem->device == NULL)
560 reply = dbus_pending_call_steal_reply(call);
562 dbus_error_init(&error);
564 if (dbus_set_error_from_message(&error, reply)) {
565 connman_error("GetContexts() %s %s", error.name, error.message);
566 dbus_error_free(&error);
570 DBG("message signature (%s)", dbus_message_get_signature(reply));
572 if (dbus_message_iter_init(reply, &args) == FALSE)
575 dbus_message_iter_recurse(&args, &dict);
577 while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
578 DBusMessageIter entry, property;
579 const char *context_path;
581 dbus_message_iter_recurse(&dict, &entry);
582 dbus_message_iter_get_basic(&entry, &context_path);
583 DBG("context path (%s)", context_path);
585 dbus_message_iter_next(&entry);
586 dbus_message_iter_recurse(&entry, &property);
588 __add_context(modem->device, context_path, &property);
590 dbus_message_iter_next(&dict);
594 dbus_message_unref(reply);
595 dbus_pending_call_unref(call);
599 static int __request_network_activate(struct connman_network *network)
601 DBG("request network activate");
603 const char *path = connman_network_get_string(network, "Path");
604 DBG("network %p, path %s", network, path);
606 return __dbus_request(path, PS_CONTEXT_INTERFACE, ACTIVATE_CONTEXT,
607 __response_network_activate,
608 g_strdup(path), NULL, DBUS_TYPE_INVALID);
611 static void __response_network_activate(DBusPendingCall *call, void *user_data)
613 DBG("network activation response");
618 struct telephony_network *info;
619 const char *path = user_data;
621 info = g_hash_table_lookup(network_hash, path);
622 reply = dbus_pending_call_steal_reply(call);
627 if (!__check_network_available(info->network)) {
628 g_hash_table_remove(network_hash, path);
632 dbus_error_init(&error);
633 if (dbus_set_error_from_message(&error, reply)) {
634 connman_error("connection activate() %s %s",
635 error.name, error.message);
637 if (connman_network_get_index(info->network) < 0)
638 connman_network_set_error(info->network,
639 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
641 dbus_error_free(&error);
646 dbus_message_unref(reply);
647 dbus_pending_call_unref(call);
651 static int __request_network_deactivate(struct connman_network *network)
653 DBG("request network deactivate");
655 const char *path = connman_network_get_string(network, "Path");
656 DBG("network %p, path %s", network, path);
658 return __dbus_request(path, PS_CONTEXT_INTERFACE, DEACTIVATE_CONTEXT,
659 NULL, NULL, NULL, DBUS_TYPE_INVALID);
662 static void __add_modem(const char *path, DBusMessageIter *prop)
664 struct telephony_modem *modem;
666 modem = g_hash_table_lookup(modem_hash, path);
670 modem = (struct telephony_modem *)malloc(
671 sizeof(struct telephony_modem));
672 memset(modem, 0, sizeof(struct telephony_modem));
674 modem->path = g_strdup(path);
675 modem->device = NULL;
676 modem->s_service = NULL;
678 g_hash_table_insert(modem_hash, g_strdup(path), modem);
680 while (dbus_message_iter_get_arg_type(prop) != DBUS_TYPE_INVALID) {
681 DBusMessageIter entry;
682 const char *key, *tmp;
684 dbus_message_iter_recurse(prop, &entry);
685 dbus_message_iter_get_basic(&entry, &key);
687 dbus_message_iter_next(&entry);
688 dbus_message_iter_get_basic(&entry, &tmp);
690 DBG("key (%s) value(%s)", key, tmp);
692 if (g_str_equal(key, "powered") == TRUE) {
693 modem->powered = STRING2BOOL(tmp);
694 } else if (g_str_equal(key, "operator") == TRUE) {
695 modem->operator = g_strdup(tmp);
696 } else if (g_str_equal(key, "sim_init") == TRUE) {
697 modem->sim_init = STRING2BOOL(tmp);
698 } else if (g_str_equal(key, "flight_mode") == TRUE) {
699 modem->flight_mode = STRING2BOOL(tmp);
700 } else if (g_str_equal(key, "roaming_allowed") == TRUE) {
701 modem->roaming_allowed = STRING2BOOL(tmp);
702 } else if (g_str_equal(key, "data_allowed") == TRUE) {
703 modem->data_allowed = STRING2BOOL(tmp);
705 dbus_message_iter_next(prop);
708 __add_connman_device(path, modem->operator);
709 __set_device_powered(modem, modem->powered);
711 if (modem->powered != TRUE) {
712 DBG("modem is not powered");
716 __request_get_services(modem->path);
721 static void __add_service(struct telephony_modem *modem,
722 const char *service_path, DBusMessageIter *prop)
724 struct telephony_service *service;
726 if (modem->s_service != NULL)
729 service = (struct telephony_service *)g_try_malloc(
730 sizeof(struct telephony_service));
734 memset(service, 0, sizeof(struct telephony_service));
736 service->path = g_strdup(service_path);
737 service->p_modem = modem;
738 g_hash_table_insert(service_hash, g_strdup(service_path), service);
740 while (dbus_message_iter_get_arg_type(prop) != DBUS_TYPE_INVALID) {
741 DBusMessageIter entry;
742 const char *key, *tmp;
744 dbus_message_iter_recurse(prop, &entry);
745 dbus_message_iter_get_basic(&entry, &key);
747 dbus_message_iter_next(&entry);
748 dbus_message_iter_get_basic(&entry, &tmp);
750 DBG("key (%s) value(%s)", key, tmp);
752 if (g_str_equal(key, "roaming") == TRUE) {
753 service->roaming = STRING2BOOL(tmp);
754 } else if (g_str_equal(key, "act") == TRUE) {
755 service->act = g_strdup(tmp);
756 } else if (g_str_equal(key, "ps_attached") == TRUE) {
757 service->ps_attached = STRING2BOOL(tmp);
760 dbus_message_iter_next(prop);
763 modem->s_service = service;
764 __request_get_contexts(modem);
769 static void __add_connman_device(const char *modem_path, const char *operator)
771 struct telephony_modem *modem;
772 struct connman_device *device;
774 DBG("path %s operator %s", modem_path, operator);
776 if (modem_path == NULL)
779 if (operator == NULL)
782 modem = g_hash_table_lookup(modem_hash, modem_path);
787 if (!g_strcmp0(operator,
788 connman_device_get_ident(modem->device)))
791 __remove_connman_device(modem);
794 if (strlen(operator) == 0)
797 device = connman_device_create(operator, CONNMAN_DEVICE_TYPE_CELLULAR);
801 connman_device_set_ident(device, operator);
802 connman_device_set_string(device, "Path", modem_path);
803 connman_device_set_data(device, modem);
805 if (connman_device_register(device) < 0) {
806 connman_error("Failed to register cellular device");
807 connman_device_unref(device);
811 modem->device = device;
816 static void __remove_connman_device(struct telephony_modem *modem)
818 DBG("modem %p path %s device %p", modem, modem->path, modem->device);
820 if (modem->device == NULL)
823 __remove_connman_networks(modem->device);
825 connman_device_unregister(modem->device);
826 connman_device_unref(modem->device);
828 modem->device = NULL;
833 static void __remove_connman_networks(struct connman_device *device)
837 GSList *info_list = NULL;
840 if (network_hash == NULL)
843 g_hash_table_iter_init(&iter, network_hash);
845 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
846 struct telephony_network *info = value;
848 if (connman_network_get_device(info->network) != device)
851 info_list = g_slist_append(info_list, info);
854 for (list = info_list; list != NULL; list = list->next) {
855 struct telephony_network *info = list->data;
856 connman_device_remove_network(device, info->network);
859 g_slist_free(info_list);
862 static void __set_device_powered(struct telephony_modem *modem,
865 DBG("set modem(%s) powered(%d)", modem->path, powered);
868 connman_device_set_powered(modem->device, powered);
873 static int __check_device_powered(const char *path, gboolean powered)
875 struct telephony_modem *modem = g_hash_table_lookup(modem_hash, path);
880 DBG("check modem (%s) powered (%d)", modem->path, modem->powered);
882 if (modem->powered == powered)
888 static gboolean __check_network_available(struct connman_network *network)
890 if (network == NULL || connman_network_get_device(network) == NULL) {
891 DBG("Modem or network was removed");
898 static int __add_context(struct connman_device *device, const char *path,
899 DBusMessageIter *prop)
902 gboolean active = FALSE;
904 struct telephony_modem *modem = connman_device_get_data(device);
905 struct connman_network *network;
906 struct telephony_network *info;
908 DBG("modem %p device %p path %s", modem, device, path);
910 ident = __get_ident(path);
912 network = connman_device_get_network(device, ident);
916 info = g_hash_table_lookup(network_hash, path);
918 DBG("path %p already exists with device %p", path,
919 connman_network_get_device(info->network));
921 if (connman_network_get_device(info->network))
924 g_hash_table_remove(network_hash, path);
927 network = connman_network_create(ident, CONNMAN_NETWORK_TYPE_CELLULAR);
931 info = (struct telephony_network *)g_try_malloc(
932 sizeof(struct telephony_network));
934 connman_network_unref(network);
938 memset(info, 0, sizeof(struct telephony_network));
940 info->path = g_strdup(path);
942 connman_ipaddress_clear(info->ipv4_address);
943 connman_ipaddress_clear(info->ipv6_address);
944 info->network = network;
946 connman_network_set_string(network, "Path", path);
947 connman_network_set_name(network, path);
949 __create_service(network);
951 g_hash_table_insert(network_hash, g_strdup(path), info);
953 connman_network_set_available(network, TRUE);
954 connman_network_set_index(network, -1);
955 connman_network_set_bool(network, "Roaming", modem->s_service->roaming);
957 if (connman_device_add_network(device, network) != 0) {
958 g_hash_table_remove(network_hash, path);
962 active = __set_network_ipconfig(info, prop);
964 if (active && (connman_network_get_connecting(network) ||
965 connman_network_get_associating(network)))
966 __set_network_connected(info, active);
971 static void __create_service(struct connman_network *network)
978 path = connman_network_get_string(network, "Path");
980 group = __get_ident(path);
982 connman_network_set_group(network, group);
985 static gboolean __set_network_ipconfig(struct telephony_network *network,
986 DBusMessageIter *dict)
988 DBG("set network info");
990 gboolean active = FALSE;
991 char *dev_name = NULL, *proxy_addr = NULL;
992 char *ipv4_addr = NULL, *ipv4_gw = NULL, *ipv4_netmask = NULL,
993 *ipv4_dns1 = NULL, *ipv4_dns2 = NULL;
994 char *ipv6_addr = NULL, *ipv6_gw = NULL, *ipv6_netmask = NULL,
995 *ipv6_dns1 = NULL, *ipv6_dns2 = NULL;
999 while (dbus_message_iter_get_arg_type(dict) != DBUS_TYPE_INVALID) {
1000 DBusMessageIter entry;
1001 const char *key, *tmp;
1003 dbus_message_iter_recurse(dict, &entry);
1004 dbus_message_iter_get_basic(&entry, &key);
1006 dbus_message_iter_next(&entry);
1008 DBG("key (%s)", key);
1010 if (g_str_equal(key, "dev_name") == TRUE) {
1011 dbus_message_iter_get_basic(&entry, &dev_name);
1012 DBG("dev_name (%s)", dev_name);
1013 } else if (g_str_equal(key, "proxy") == TRUE) {
1014 dbus_message_iter_get_basic(&entry, &proxy_addr);
1015 } else if (g_str_equal(key, "ipv4_address") == TRUE) {
1016 dbus_message_iter_get_basic(&entry, &ipv4_addr);
1017 DBG("ipv4 address (%s)", ipv4_addr);
1018 } else if (g_str_equal(key, "ipv4_gateway") == TRUE) {
1019 dbus_message_iter_get_basic(&entry, &ipv4_gw);
1020 } else if (g_str_equal(key, "ipv4_netmask") == TRUE) {
1021 dbus_message_iter_get_basic(&entry, &ipv4_netmask);
1022 } else if (g_str_equal(key, "ipv4_dns1") == TRUE) {
1023 dbus_message_iter_get_basic(&entry, &ipv4_dns1);
1024 } else if (g_str_equal(key, "ipv4_dns2") == TRUE) {
1025 dbus_message_iter_get_basic(&entry, &ipv4_dns2);
1026 } else if (g_str_equal(key, "ipv6_address") == TRUE) {
1027 dbus_message_iter_get_basic(&entry, &ipv6_addr);
1028 DBG("ipv6 address (%s)", ipv6_addr);
1029 } else if (g_str_equal(key, "ipv6_gateway") == TRUE) {
1030 dbus_message_iter_get_basic(&entry, &ipv6_gw);
1031 } else if (g_str_equal(key, "ipv6_netmask") == TRUE) {
1032 dbus_message_iter_get_basic(&entry, &ipv6_netmask);
1033 } else if (g_str_equal(key, "ipv6_dns1") == TRUE) {
1034 dbus_message_iter_get_basic(&entry, &ipv6_dns1);
1035 } else if (g_str_equal(key, "ipv6_dns2") == TRUE) {
1036 dbus_message_iter_get_basic(&entry, &ipv6_dns2);
1037 } else if (g_str_equal(key, "active") == TRUE) {
1038 dbus_message_iter_get_basic(&entry, &tmp);
1039 DBG("active (%s)", tmp);
1040 active = STRING2BOOL(tmp);
1043 dbus_message_iter_next(dict);
1046 /* interface index set */
1047 if (dev_name == NULL)
1050 if (!g_str_equal(dev_name, "")) {
1051 index = connman_inet_ifindex(dev_name);
1052 DBG("interface %s, index %d", dev_name, index);
1053 connman_network_set_index(network->network, index);
1057 if (proxy_addr == NULL)
1060 DBG("proxy (%s) is set", proxy_addr);
1061 connman_network_set_proxy(network->network, proxy_addr);
1064 if (ipv4_addr == NULL)
1065 ipv4_addr = "0.0.0.0";
1067 if (g_str_equal(ipv4_addr, "0.0.0.0")) {
1068 network->ipv4_method = CONNMAN_IPCONFIG_METHOD_OFF;
1070 network->ipv4_method = CONNMAN_IPCONFIG_METHOD_FIXED;
1071 network->ipv4_address =
1072 connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4);
1073 if (network->ipv4_address == NULL)
1076 connman_ipaddress_set_ipv4(network->ipv4_address, ipv4_addr,
1077 ipv4_netmask, ipv4_gw);
1079 if (ipv4_dns1 == NULL)
1080 ipv4_dns1 = "0.0.0.0";
1081 if (ipv4_dns2 == NULL)
1082 ipv4_dns2 = "0.0.0.0";
1084 if (g_str_equal(ipv4_dns1, "0.0.0.0"))
1087 if (g_str_equal(ipv4_dns2, "0.0.0.0"))
1090 gchar *nameservers = NULL;
1094 nameservers = g_strdup_printf("%s %s", ipv4_dns1,
1098 nameservers = g_strdup_printf("%s", ipv4_dns2);
1101 nameservers = g_strdup_printf("%s", ipv4_dns1);
1104 connman_network_set_nameservers(network->network, nameservers);
1105 g_free(nameservers);
1109 if (ipv6_addr == NULL)
1112 if (g_str_equal(ipv6_addr, "::")) {
1113 network->ipv6_method = CONNMAN_IPCONFIG_METHOD_OFF;
1115 network->ipv6_method = CONNMAN_IPCONFIG_METHOD_FIXED;
1116 unsigned char prefix_length = 64;
1117 network->ipv6_address =
1118 connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6);
1119 if (network->ipv6_address == NULL)
1122 connman_ipaddress_set_ipv6(network->ipv6_address, ipv6_addr,
1123 prefix_length, ipv6_gw);
1127 if (ipv6_dns1 == NULL)
1129 if (ipv6_dns2 == NULL)
1132 if (g_str_equal(ipv6_dns1, "::"))
1135 if (g_str_equal(ipv6_dns2, "::"))
1138 gchar *nameservers = NULL;
1142 nameservers = g_strdup_printf("%s %s", ipv6_dns1,
1146 nameservers = g_strdup_printf("%s", ipv6_dns2);
1149 nameservers = g_strdup_printf("%s", ipv6_dns1);
1152 connman_network_set_nameservers(network->network, nameservers);
1153 g_free(nameservers);
1157 connman_network_set_associating(network->network, TRUE);
1162 static void __set_network_connected(struct telephony_network *network,
1165 gboolean setip = FALSE;
1167 DBG("network %p connected %d", network, connected);
1169 switch (network->ipv4_method) {
1170 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1171 case CONNMAN_IPCONFIG_METHOD_OFF:
1172 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1173 case CONNMAN_IPCONFIG_METHOD_AUTO:
1177 case CONNMAN_IPCONFIG_METHOD_FIXED:
1178 connman_network_set_ipv4_method(network->network,
1179 network->ipv4_method);
1180 connman_network_set_ipaddress(network->network,
1181 network->ipv4_address);
1185 case CONNMAN_IPCONFIG_METHOD_DHCP:
1186 connman_network_set_ipv4_method(network->network,
1187 network->ipv4_method);
1192 switch (network->ipv6_method) {
1193 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1194 case CONNMAN_IPCONFIG_METHOD_OFF:
1195 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1196 case CONNMAN_IPCONFIG_METHOD_DHCP:
1197 case CONNMAN_IPCONFIG_METHOD_AUTO:
1198 DBG("ipv6 not supported");
1201 case CONNMAN_IPCONFIG_METHOD_FIXED:
1202 connman_network_set_ipv6_method(network->network,
1203 network->ipv6_method);
1204 connman_network_set_ipaddress(network->network,
1205 network->ipv6_address);
1211 connman_network_set_connected(network->network, connected);
1216 static char *__get_ident(const char *path)
1223 pos = strrchr(path, '/');
1230 static gboolean __changed_modem(DBusConnection *connection,
1231 DBusMessage *message, void *user_data)
1233 DBG("modem changed signal");
1235 DBusMessageIter args, dict;
1236 const char *path = dbus_message_get_path(message);
1237 struct telephony_modem *modem;
1239 DBG("modem path %s", path);
1241 modem = g_hash_table_lookup(modem_hash, path);
1242 if (modem == NULL) {
1243 DBG("modem object does not exists");
1247 DBG("message signature (%s)", dbus_message_get_signature(message));
1249 if (dbus_message_iter_init(message, &args) == FALSE) {
1250 DBG("error to read message");
1254 dbus_message_iter_recurse(&args, &dict);
1256 while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
1257 DBusMessageIter entry;
1258 const char *key, *tmp;
1260 dbus_message_iter_recurse(&dict, &entry);
1261 dbus_message_iter_get_basic(&entry, &key);
1263 dbus_message_iter_next(&entry);
1264 dbus_message_iter_get_basic(&entry, &tmp);
1266 DBG("key(%s), value(%s)", key, tmp);
1268 if (g_str_equal(key, "powered") == TRUE) {
1269 modem->powered = STRING2BOOL(tmp);
1270 } else if (g_str_equal(key, "operator") == TRUE) {
1271 modem->operator = g_strdup(tmp);
1272 } else if (g_str_equal(key, "sim_init") == TRUE) {
1273 modem->sim_init = STRING2BOOL(tmp);
1274 } else if (g_str_equal(key, "flight_mode") == TRUE) {
1275 modem->flight_mode = STRING2BOOL(tmp);
1276 } else if (g_str_equal(key, "roaming_allowed") == TRUE) {
1277 modem->roaming_allowed = STRING2BOOL(tmp);
1278 } else if (g_str_equal(key, "data_allowed") == TRUE) {
1279 modem->data_allowed = STRING2BOOL(tmp);
1282 dbus_message_iter_next(&dict);
1285 if (modem->device == NULL)
1286 __add_connman_device(path, modem->operator);
1288 __set_device_powered(modem, modem->powered);
1290 if (modem->powered != TRUE) {
1291 DBG("modem is not powered");
1295 if (!modem->s_service) {
1296 __request_get_services(modem->path);
1300 if (modem->flight_mode || !modem->data_allowed) {
1301 DBG("modem(%s) flight mode(%d) data allowed(%d)",
1302 modem->path, modem->flight_mode, modem->data_allowed);
1309 static gboolean __added_modem(DBusConnection *connection,
1310 DBusMessage *message, void *user_data)
1312 DBG("modem added signal");
1314 const char *modem_path = NULL;
1315 DBusMessageIter args, dict, tmp;
1317 DBG("message signature (%s)", dbus_message_get_signature(message));
1318 if (dbus_message_iter_init(message, &args) == FALSE) {
1319 DBG("error to read message");
1323 dbus_message_iter_recurse(&args, &dict);
1324 memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
1326 while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
1327 DBusMessageIter entry;
1328 const char *key, *value;
1330 dbus_message_iter_recurse(&tmp, &entry);
1331 dbus_message_iter_get_basic(&entry, &key);
1333 dbus_message_iter_next(&entry);
1334 dbus_message_iter_get_basic(&entry, &value);
1336 DBG("key (%s) value(%s)", key, value);
1338 if (g_str_equal(key, "path") == TRUE)
1339 modem_path = g_strdup(value);
1341 dbus_message_iter_next(&tmp);
1344 if (modem_path != NULL)
1345 __add_modem(modem_path, &dict);
1350 static gboolean __removed_modem(DBusConnection *connection,
1351 DBusMessage *message, void *user_data)
1353 DBG("modem removed signal");
1355 DBusMessageIter iter;
1356 const char *modem_path;
1358 if (dbus_message_iter_init(message, &iter) == FALSE) {
1359 DBG("error to read message");
1363 dbus_message_iter_get_basic(&iter, &modem_path);
1364 g_hash_table_remove(modem_hash, modem_path);
1369 static gboolean __changed_service(DBusConnection *connection,
1370 DBusMessage *message, void *user_data)
1372 DBG("service changed signal");
1374 DBusMessageIter args, dict;
1375 const char *service_path = dbus_message_get_path(message);
1376 struct telephony_modem *modem;
1377 struct telephony_service *s_service;
1378 gboolean roaming_option = TRUE;
1380 DBG("service path %s", service_path);
1382 s_service = g_hash_table_lookup(service_hash, service_path);
1383 if (s_service == NULL) {
1384 DBG("service object does not exists");
1388 modem = s_service->p_modem;
1389 if (modem == NULL) {
1390 DBG("modem object does not exists");
1394 DBG("message signature (%s)", dbus_message_get_signature(message));
1396 if (dbus_message_iter_init(message, &args) == FALSE) {
1397 DBG("error to read message");
1401 dbus_message_iter_recurse(&args, &dict);
1403 while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
1404 DBusMessageIter entry;
1405 const char *key, *tmp;
1407 dbus_message_iter_recurse(&dict, &entry);
1408 dbus_message_iter_get_basic(&entry, &key);
1410 dbus_message_iter_next(&entry);
1411 dbus_message_iter_get_basic(&entry, &tmp);
1413 DBG("key(%s), value(%s)", key, tmp);
1415 if (g_str_equal(key, "roaming") == TRUE) {
1416 s_service->roaming = STRING2BOOL(tmp);
1417 } else if (g_str_equal(key, "act") == TRUE) {
1418 s_service->act = g_strdup(tmp);
1419 } else if (g_str_equal(key, "ps_attached") == TRUE) {
1420 s_service->ps_attached = STRING2BOOL(tmp);
1423 dbus_message_iter_next(&dict);
1426 roaming_option &= (!s_service->roaming && !modem->roaming_allowed)
1427 || modem->roaming_allowed;
1433 static gboolean __added_service(DBusConnection *connection,
1434 DBusMessage *message, void *user_data)
1436 DBG("service added signal");
1438 const char *path = dbus_message_get_path(message);
1439 const char *service_path = NULL;
1440 DBusMessageIter args, dict, tmp;
1441 struct telephony_modem *modem;
1443 modem = g_hash_table_lookup(modem_hash, path);
1444 if (modem == NULL || modem->device == NULL)
1447 DBG("message signature (%s)", dbus_message_get_signature(message));
1448 if (dbus_message_iter_init(message, &args) == FALSE) {
1449 DBG("error to read message");
1453 dbus_message_iter_recurse(&args, &dict);
1454 memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
1456 while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
1457 DBusMessageIter entry;
1458 const char *key, *value;
1460 dbus_message_iter_recurse(&tmp, &entry);
1461 dbus_message_iter_get_basic(&entry, &key);
1463 dbus_message_iter_next(&entry);
1464 dbus_message_iter_get_basic(&entry, &value);
1466 DBG("key (%s) value(%s)", key, value);
1468 if (g_str_equal(key, "path") == TRUE) {
1469 service_path = g_strdup(value);
1472 dbus_message_iter_next(&tmp);
1475 if (service_path != NULL)
1476 __add_service(modem, service_path, &dict);
1481 static gboolean __removed_service(DBusConnection *connection,
1482 DBusMessage *message, void *user_data)
1484 DBG("service removed signal");
1486 DBusMessageIter iter;
1487 const char *service_path;
1489 if (dbus_message_iter_init(message, &iter) == FALSE) {
1490 DBG("error to read message");
1494 dbus_message_iter_get_basic(&iter, &service_path);
1495 g_hash_table_remove(service_hash, service_path);
1500 static gboolean __changed_context(DBusConnection *connection,
1501 DBusMessage *message, void *user_data)
1503 DBG("network changed signal");
1505 gboolean active = FALSE;
1506 const char *path = dbus_message_get_path(message);
1507 struct telephony_network *info;
1508 DBusMessageIter args, dict;
1510 DBG("path %s", path);
1511 info = g_hash_table_lookup(network_hash, path);
1515 if (!__check_network_available(info->network)) {
1516 g_hash_table_remove(network_hash, path);
1520 if (dbus_message_iter_init(message, &args) == FALSE) {
1521 DBG("error to read message");
1525 dbus_message_iter_recurse(&args, &dict);
1527 active = __set_network_ipconfig(info, &dict);
1529 if (active == FALSE)
1530 __set_network_connected(info, active);
1531 else if ((connman_network_get_connecting(info->network) ||
1532 connman_network_get_associating(info->network)))
1533 __set_network_connected(info, active);
1538 static gboolean __added_context(DBusConnection *connection,
1539 DBusMessage *message, void *user_data)
1541 DBG("network added signal");
1543 DBusMessageIter args, dict, tmp;
1544 const char *path = dbus_message_get_path(message);
1545 const char *network_path = NULL;
1546 struct telephony_service *service = NULL;
1547 struct telephony_modem *modem = NULL;
1549 service = g_hash_table_lookup(service_hash, path);
1550 if (service == NULL || service->p_modem == NULL)
1553 modem = service->p_modem;
1554 if (modem == NULL || modem->device == NULL)
1557 DBG("message signature (%s)", dbus_message_get_signature(message));
1558 if (dbus_message_iter_init(message, &args) == FALSE) {
1559 DBG("error to read message");
1563 dbus_message_iter_recurse(&args, &dict);
1564 memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
1566 while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
1567 DBusMessageIter entry;
1568 const char *key, *value;
1570 dbus_message_iter_recurse(&tmp, &entry);
1571 dbus_message_iter_get_basic(&entry, &key);
1573 dbus_message_iter_next(&entry);
1574 dbus_message_iter_get_basic(&entry, &value);
1576 DBG("key (%s) value(%s)", key, value);
1578 if (g_str_equal(key, "path") == TRUE)
1579 network_path = g_strdup(value);
1581 dbus_message_iter_next(&tmp);
1584 if (network_path != NULL)
1585 __add_context(modem->device, network_path, &dict);
1590 static gboolean __removed_context(DBusConnection *connection,
1591 DBusMessage *message, void *user_data)
1593 DBG("network removed signal");
1595 DBusMessageIter iter;
1596 const char *path = dbus_message_get_path(message);
1597 const char *network_path = NULL;
1598 struct telephony_service *service = NULL;
1600 service = g_hash_table_lookup(service_hash, path);
1601 if (service == NULL || service->p_modem == NULL)
1604 if (dbus_message_iter_init(message, &iter) == FALSE) {
1605 DBG("error to read message");
1609 dbus_message_iter_get_basic(&iter, &network_path);
1610 g_hash_table_remove(network_hash, network_path);
1615 /* telephony initialization */
1617 static guint modem_watch;
1618 static guint modem_added_watch;
1619 static guint modem_removed_watch;
1620 static guint service_watch;
1621 static guint service_added_watch;
1622 static guint service_removed_watch;
1623 static guint context_watch;
1624 static guint context_added_watch;
1625 static guint context_removed_watch;
1627 static int telephony_init(void)
1629 DBG("telephony plugin");
1632 connection = connman_dbus_get_connection();
1633 if (connection == NULL)
1636 /* telephony watch */
1637 watch = g_dbus_add_service_watch(connection, PS_DBUS_SERVICE,
1638 telephony_connect, telephony_disconnect,
1641 modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1644 __changed_modem, NULL, NULL);
1646 modem_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1647 PS_MASTER_INTERFACE,
1648 MODEM_ADDED, __added_modem,
1651 modem_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1652 PS_MASTER_INTERFACE,
1653 MODEM_REMOVED, __removed_modem,
1656 service_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1657 PS_SERVICE_INTERFACE,
1662 service_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1664 SERVICE_ADDED, __added_service,
1667 service_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1673 context_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1674 PS_CONTEXT_INTERFACE,
1679 context_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1680 PS_SERVICE_INTERFACE,
1681 CONTEXT_ADDED, __added_context,
1684 context_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
1685 PS_SERVICE_INTERFACE,
1690 if (watch == 0 || modem_watch == 0 || modem_added_watch == 0
1691 || modem_removed_watch == 0 || service_watch == 0
1692 || service_added_watch == 0 || context_watch == 0
1693 || service_removed_watch == 0
1694 || context_added_watch == 0
1695 || context_removed_watch == 0) {
1700 err = connman_network_driver_register(&network_driver);
1704 err = connman_device_driver_register(&modem_driver);
1706 connman_network_driver_unregister(&network_driver);
1710 err = connman_technology_driver_register(&tech_driver);
1712 connman_device_driver_unregister(&modem_driver);
1713 connman_network_driver_unregister(&network_driver);
1720 g_dbus_remove_watch(connection, watch);
1721 g_dbus_remove_watch(connection, modem_watch);
1722 g_dbus_remove_watch(connection, modem_added_watch);
1723 g_dbus_remove_watch(connection, modem_removed_watch);
1724 g_dbus_remove_watch(connection, service_watch);
1725 g_dbus_remove_watch(connection, service_added_watch);
1726 g_dbus_remove_watch(connection, service_removed_watch);
1727 g_dbus_remove_watch(connection, context_watch);
1728 g_dbus_remove_watch(connection, context_added_watch);
1729 g_dbus_remove_watch(connection, context_removed_watch);
1731 dbus_connection_unref(connection);
1735 static void telephony_exit(void)
1737 g_dbus_remove_watch(connection, watch);
1738 g_dbus_remove_watch(connection, modem_watch);
1739 g_dbus_remove_watch(connection, modem_added_watch);
1740 g_dbus_remove_watch(connection, modem_removed_watch);
1741 g_dbus_remove_watch(connection, service_watch);
1742 g_dbus_remove_watch(connection, service_added_watch);
1743 g_dbus_remove_watch(connection, service_removed_watch);
1744 g_dbus_remove_watch(connection, context_watch);
1745 g_dbus_remove_watch(connection, context_added_watch);
1746 g_dbus_remove_watch(connection, context_removed_watch);
1748 telephony_disconnect(connection, NULL);
1750 connman_device_driver_unregister(&modem_driver);
1751 connman_network_driver_unregister(&network_driver);
1753 dbus_connection_unref(connection);
1756 CONNMAN_PLUGIN_DEFINE(telephony, "Samsung Telephony Framework plug-in", VERSION,
1757 CONNMAN_PLUGIN_PRIORITY_DEFAULT, telephony_init, telephony_exit)