5 * Copyright (C) 2007-2010 Intel Corporation. All rights reserved.
6 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
7 * Copyright (C) 2011 BWM Car IT GmbH. All rights reserved.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35 #define CONNMAN_API_SUBJECT_TO_CHANGE
36 #include <connman/plugin.h>
37 #include <connman/device.h>
38 #include <connman/network.h>
39 #include <connman/inet.h>
40 #include <connman/dbus.h>
41 #include <connman/log.h>
42 #include <connman/technology.h>
46 #define uninitialized_var(x) x = x
48 #define OFONO_SERVICE "org.ofono"
50 #define OFONO_MANAGER_INTERFACE OFONO_SERVICE ".Manager"
51 #define OFONO_MODEM_INTERFACE OFONO_SERVICE ".Modem"
52 #define OFONO_SIM_INTERFACE OFONO_SERVICE ".SimManager"
53 #define OFONO_NETREG_INTERFACE OFONO_SERVICE ".NetworkRegistration"
54 #define OFONO_CM_INTERFACE OFONO_SERVICE ".ConnectionManager"
55 #define OFONO_CONTEXT_INTERFACE OFONO_SERVICE ".ConnectionContext"
56 #define OFONO_CDMA_CM_INTERFACE OFONO_SERVICE ".cdma.ConnectionManager"
57 #define OFONO_CDMA_NETREG_INTERFACE OFONO_SERVICE ".cdma.NetworkRegistration"
59 #define MODEM_ADDED "ModemAdded"
60 #define MODEM_REMOVED "ModemRemoved"
61 #define PROPERTY_CHANGED "PropertyChanged"
62 #define CONTEXT_ADDED "ContextAdded"
63 #define CONTEXT_REMOVED "ContextRemoved"
65 #define GET_PROPERTIES "GetProperties"
66 #define SET_PROPERTY "SetProperty"
67 #define GET_MODEMS "GetModems"
68 #define GET_CONTEXTS "GetContexts"
74 OFONO_API_NETREG = 0x2,
76 OFONO_API_CDMA_NETREG = 0x8,
77 OFONO_API_CDMA_CM = 0x10,
81 * The way this plugin works is following:
83 * powered -> SubscriberIdentity or Online = True -> gprs, context ->
84 * attached -> netreg -> ready
86 * Enabling and disabling modems are steered through the rfkill
87 * interface. That means when ConnMan toggles the rfkill bit oFono
88 * will add or remove the modems.
90 * ConnMan will always power up (set Powered and Online) the
91 * modems. No need to power them down because this will be done
92 * through the rfkill inteface.
95 static DBusConnection *connection;
97 static GHashTable *modem_hash;
98 static GHashTable *context_hash;
100 struct network_context {
104 enum connman_ipconfig_method ipv4_method;
105 struct connman_ipaddress *ipv4_address;
106 char *ipv4_nameservers;
108 enum connman_ipconfig_method ipv6_method;
109 struct connman_ipaddress *ipv6_address;
110 char *ipv6_nameservers;
116 struct connman_device *device;
117 struct connman_network *network;
119 struct network_context *context;
121 /* Modem Interface */
123 connman_bool_t powered;
124 connman_bool_t online;
126 connman_bool_t ignore;
128 connman_bool_t set_powered;
129 connman_bool_t set_online;
131 /* CDMA ConnectionManager Interface */
132 connman_bool_t cdma_cm_powered;
134 /* ConnectionManager Interface */
135 connman_bool_t attached;
136 connman_bool_t cm_powered;
138 connman_bool_t set_cm_powered;
140 /* ConnectionContext Interface */
141 connman_bool_t active;
142 connman_bool_t set_active;
144 /* SimManager Interface */
147 /* Netreg Interface */
150 uint8_t data_strength; /* 1xEVDO signal strength */
151 connman_bool_t roaming;
154 DBusPendingCall *call_set_property;
155 DBusPendingCall *call_get_properties;
156 DBusPendingCall *call_get_contexts;
159 static char *get_ident(const char *path)
166 pos = strrchr(path, '/');
173 static struct network_context *network_context_alloc(const char *path)
175 struct network_context *context;
177 context = g_try_new0(struct network_context, 1);
181 context->path = g_strdup(path);
184 context->ipv4_method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
185 context->ipv4_address = NULL;
186 context->ipv4_nameservers = NULL;
188 context->ipv6_method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
189 context->ipv6_address = NULL;
190 context->ipv6_nameservers = NULL;
195 static void network_context_free(struct network_context *context)
197 g_free(context->path);
199 connman_ipaddress_free(context->ipv4_address);
200 g_free(context->ipv4_nameservers);
202 connman_ipaddress_free(context->ipv6_address);
203 g_free(context->ipv6_nameservers);
208 static void set_connected(struct modem_data *modem)
210 connman_bool_t setip = FALSE;
212 DBG("%s", modem->path);
214 connman_network_set_index(modem->network, modem->context->index);
216 switch (modem->context->ipv4_method) {
217 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
218 case CONNMAN_IPCONFIG_METHOD_OFF:
219 case CONNMAN_IPCONFIG_METHOD_MANUAL:
220 case CONNMAN_IPCONFIG_METHOD_AUTO:
223 case CONNMAN_IPCONFIG_METHOD_FIXED:
224 connman_network_set_ipv4_method(modem->network,
225 modem->context->ipv4_method);
226 connman_network_set_ipaddress(modem->network,
227 modem->context->ipv4_address);
228 connman_network_set_nameservers(modem->network,
229 modem->context->ipv4_nameservers);
233 case CONNMAN_IPCONFIG_METHOD_DHCP:
234 connman_network_set_ipv4_method(modem->network,
235 modem->context->ipv4_method);
240 switch (modem->context->ipv6_method) {
241 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
242 case CONNMAN_IPCONFIG_METHOD_OFF:
243 case CONNMAN_IPCONFIG_METHOD_MANUAL:
244 case CONNMAN_IPCONFIG_METHOD_DHCP:
245 case CONNMAN_IPCONFIG_METHOD_AUTO:
248 case CONNMAN_IPCONFIG_METHOD_FIXED:
249 connman_network_set_ipv6_method(modem->network,
250 modem->context->ipv6_method);
251 connman_network_set_ipaddress(modem->network,
252 modem->context->ipv6_address);
258 connman_network_set_connected(modem->network, TRUE);
261 static void set_disconnected(struct modem_data *modem)
263 DBG("%s", modem->path);
265 connman_network_set_connected(modem->network, FALSE);
268 typedef void (*set_property_cb)(struct modem_data *data,
269 connman_bool_t success);
270 typedef void (*get_properties_cb)(struct modem_data *data,
271 DBusMessageIter *dict);
273 struct property_info {
274 struct modem_data *modem;
276 const char *interface;
277 const char *property;
278 set_property_cb set_property_cb;
279 get_properties_cb get_properties_cb;
282 static void set_property_reply(DBusPendingCall *call, void *user_data)
284 struct property_info *info = user_data;
287 connman_bool_t success = TRUE;
289 DBG("%s path %s %s.%s", info->modem->path,
290 info->path, info->interface, info->property);
292 info->modem->call_set_property = NULL;
294 dbus_error_init(&error);
296 reply = dbus_pending_call_steal_reply(call);
298 if (dbus_set_error_from_message(&error, reply)) {
299 connman_error("Failed to change property: %s %s.%s: %s %s",
300 info->path, info->interface, info->property,
301 error.name, error.message);
302 dbus_error_free(&error);
306 if (info->set_property_cb != NULL)
307 (*info->set_property_cb)(info->modem, success);
309 dbus_message_unref(reply);
311 dbus_pending_call_unref(call);
314 static int set_property(struct modem_data *modem,
315 const char *path, const char *interface,
316 const char *property, int type, void *value,
317 set_property_cb notify)
319 DBusMessage *message;
320 DBusMessageIter iter;
321 struct property_info *info;
323 DBG("%s path %s %s.%s", modem->path, path, interface, property);
325 if (modem->call_set_property != NULL) {
326 connman_error("Pending SetProperty");
330 message = dbus_message_new_method_call(OFONO_SERVICE, path,
331 interface, SET_PROPERTY);
335 dbus_message_iter_init_append(message, &iter);
336 connman_dbus_property_append_basic(&iter, property, type, value);
338 if (dbus_connection_send_with_reply(connection, message,
339 &modem->call_set_property, TIMEOUT) == FALSE) {
340 connman_error("Failed to change property: %s %s.%s",
341 path, interface, property);
342 dbus_message_unref(message);
346 if (modem->call_set_property == NULL) {
347 connman_error("D-Bus connection not available");
348 dbus_message_unref(message);
352 info = g_try_new0(struct property_info, 1);
354 dbus_message_unref(message);
360 info->interface = interface;
361 info->property = property;
362 info->set_property_cb = notify;
364 dbus_pending_call_set_notify(modem->call_set_property,
365 set_property_reply, info, g_free);
367 dbus_message_unref(message);
372 static void get_properties_reply(DBusPendingCall *call, void *user_data)
374 struct property_info *info = user_data;
375 DBusMessageIter array, dict;
379 DBG("%s path %s %s", info->modem->path, info->path, info->interface);
381 info->modem->call_get_properties = NULL;
383 dbus_error_init(&error);
385 reply = dbus_pending_call_steal_reply(call);
387 if (dbus_set_error_from_message(&error, reply)) {
388 connman_error("Failed to get properties: %s %s: %s %s",
389 info->path, info->interface,
390 error.name, error.message);
391 dbus_error_free(&error);
396 if (dbus_message_iter_init(reply, &array) == FALSE)
399 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
402 dbus_message_iter_recurse(&array, &dict);
404 if (info->get_properties_cb != NULL)
405 (*info->get_properties_cb)(info->modem, &dict);
409 dbus_message_unref(reply);
411 dbus_pending_call_unref(call);
414 static int get_properties(const char *path, const char *interface,
415 get_properties_cb notify,
416 struct modem_data *modem)
418 DBusMessage *message;
419 struct property_info *info;
421 DBG("%s path %s %s", modem->path, path, interface);
423 if (modem->call_get_properties != NULL) {
424 connman_error("Pending GetProperties");
428 message = dbus_message_new_method_call(OFONO_SERVICE, path,
429 interface, GET_PROPERTIES);
433 if (dbus_connection_send_with_reply(connection, message,
434 &modem->call_get_properties, TIMEOUT) == FALSE) {
435 connman_error("Failed to call %s.GetProperties()", interface);
436 dbus_message_unref(message);
440 if (modem->call_get_properties == NULL) {
441 connman_error("D-Bus connection not available");
442 dbus_message_unref(message);
446 info = g_try_new0(struct property_info, 1);
448 dbus_message_unref(message);
454 info->interface = interface;
455 info->get_properties_cb = notify;
457 dbus_pending_call_set_notify(modem->call_get_properties,
458 get_properties_reply, info, g_free);
460 dbus_message_unref(message);
465 static void context_set_active_reply(struct modem_data *modem,
466 connman_bool_t success)
468 DBG("%s", modem->path);
470 if (success == TRUE) {
472 * Don't handle do anything on success here. oFono will send
473 * the change via PropertyChanged singal.
479 * Active = True might fail due a timeout. That means oFono
480 * still tries to go online. If we retry to set Active = True,
481 * we just get a InProgress error message. Should we power
482 * cycle the modem in such cases?
485 if (modem->network == NULL) {
487 * In the case where we power down the device
488 * we don't wait for the reply, therefore the network
489 * might already be gone.
494 connman_network_set_error(modem->network,
495 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
498 static int context_set_active(struct modem_data *modem,
499 connman_bool_t active)
503 DBG("%s active %d", modem->path, active);
505 err = set_property(modem, modem->context->path,
506 OFONO_CONTEXT_INTERFACE,
507 "Active", DBUS_TYPE_BOOLEAN,
509 context_set_active_reply);
511 if (active == FALSE && err == -EINPROGRESS)
517 static void cdma_cm_set_powered_reply(struct modem_data *modem,
518 connman_bool_t success)
520 DBG("%s", modem->path);
522 if (success == TRUE) {
524 * Don't handle do anything on success here. oFono will send
525 * the change via PropertyChanged singal.
531 * Powered = True might fail due a timeout. That means oFono
532 * still tries to go online. If we retry to set Powered = True,
533 * we just get a InProgress error message. Should we power
534 * cycle the modem in such cases?
537 if (modem->network == NULL) {
539 * In the case where we power down the device
540 * we don't wait for the reply, therefore the network
541 * might already be gone.
546 connman_network_set_error(modem->network,
547 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
550 static int cdma_cm_set_powered(struct modem_data *modem, connman_bool_t powered)
554 DBG("%s powered %d", modem->path, powered);
556 err = set_property(modem, modem->path, OFONO_CDMA_CM_INTERFACE,
557 "Powered", DBUS_TYPE_BOOLEAN,
559 cdma_cm_set_powered_reply);
561 if (powered == FALSE && err == -EINPROGRESS)
567 static void modem_set_online_reply(struct modem_data *modem,
568 connman_bool_t success)
570 DBG("%s", modem->path);
572 if (success == TRUE) {
574 * Don't handle do anything on success here. oFono will send
575 * the change via PropertyChanged singal.
580 modem->set_online = FALSE;
583 static int modem_set_online(struct modem_data *modem)
585 DBG("%s", modem->path);
587 modem->set_online = TRUE;
589 return set_property(modem, modem->path,
590 OFONO_MODEM_INTERFACE,
591 "Online", DBUS_TYPE_BOOLEAN,
593 modem_set_online_reply);
596 static void cm_set_powered_reply(struct modem_data *modem,
597 connman_bool_t success)
599 DBG("%s", modem->path);
601 if (success == TRUE) {
603 * Don't handle do anything on success here. oFono will send
604 * the change via PropertyChanged singal.
609 modem->set_cm_powered = FALSE;
612 static int cm_set_powered(struct modem_data *modem)
614 DBG("%s", modem->path);
616 modem->set_cm_powered = TRUE;
618 return set_property(modem, modem->path,
620 "Powered", DBUS_TYPE_BOOLEAN,
621 &modem->set_cm_powered,
622 cm_set_powered_reply);
625 static int modem_set_powered(struct modem_data *modem)
627 DBG("%s", modem->path);
629 modem->set_powered = TRUE;
631 return set_property(modem, modem->path,
632 OFONO_MODEM_INTERFACE,
633 "Powered", DBUS_TYPE_BOOLEAN,
638 static int modem_set_unpowered(struct modem_data *modem)
640 DBG("%s", modem->path);
642 modem->set_powered = FALSE;
644 return set_property(modem, modem->path,
645 OFONO_MODEM_INTERFACE,
646 "Powered", DBUS_TYPE_BOOLEAN,
651 static connman_bool_t has_interface(uint8_t interfaces,
654 if ((interfaces & api) == api)
660 static uint8_t extract_interfaces(DBusMessageIter *array)
662 DBusMessageIter entry;
663 uint8_t interfaces = 0;
665 dbus_message_iter_recurse(array, &entry);
667 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
670 dbus_message_iter_get_basic(&entry, &name);
672 if (g_str_equal(name, OFONO_SIM_INTERFACE) == TRUE)
673 interfaces |= OFONO_API_SIM;
674 else if (g_str_equal(name, OFONO_NETREG_INTERFACE) == TRUE)
675 interfaces |= OFONO_API_NETREG;
676 else if (g_str_equal(name, OFONO_CM_INTERFACE) == TRUE)
677 interfaces |= OFONO_API_CM;
678 else if (g_str_equal(name, OFONO_CDMA_CM_INTERFACE) == TRUE)
679 interfaces |= OFONO_API_CDMA_CM;
680 else if (g_str_equal(name, OFONO_CDMA_NETREG_INTERFACE) == TRUE)
681 interfaces |= OFONO_API_CDMA_NETREG;
683 dbus_message_iter_next(&entry);
689 static char *extract_nameservers(DBusMessageIter *array)
691 DBusMessageIter entry;
692 char *nameservers = NULL;
695 dbus_message_iter_recurse(array, &entry);
697 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
698 const char *nameserver;
700 dbus_message_iter_get_basic(&entry, &nameserver);
702 if (nameservers == NULL) {
703 nameservers = g_strdup(nameserver);
706 nameservers = g_strdup_printf("%s %s", tmp, nameserver);
710 dbus_message_iter_next(&entry);
716 static void extract_ipv4_settings(DBusMessageIter *array,
717 struct network_context *context)
719 DBusMessageIter dict;
720 char *address = NULL, *netmask = NULL, *gateway = NULL;
721 char *nameservers = NULL;
722 const char *interface = NULL;
725 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
728 dbus_message_iter_recurse(array, &dict);
730 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
731 DBusMessageIter entry, value;
732 const char *key, *val;
734 dbus_message_iter_recurse(&dict, &entry);
735 dbus_message_iter_get_basic(&entry, &key);
737 dbus_message_iter_next(&entry);
738 dbus_message_iter_recurse(&entry, &value);
740 if (g_str_equal(key, "Interface") == TRUE) {
741 dbus_message_iter_get_basic(&value, &interface);
743 DBG("Interface %s", interface);
745 index = connman_inet_ifindex(interface);
747 DBG("index %d", index);
748 } else if (g_str_equal(key, "Method") == TRUE) {
749 dbus_message_iter_get_basic(&value, &val);
751 DBG("Method %s", val);
753 if (g_strcmp0(val, "static") == 0) {
754 context->ipv4_method = CONNMAN_IPCONFIG_METHOD_FIXED;
755 } else if (g_strcmp0(val, "dhcp") == 0) {
756 context->ipv4_method = CONNMAN_IPCONFIG_METHOD_DHCP;
759 } else if (g_str_equal(key, "Address") == TRUE) {
760 dbus_message_iter_get_basic(&value, &val);
762 address = g_strdup(val);
764 DBG("Address %s", address);
765 } else if (g_str_equal(key, "Netmask") == TRUE) {
766 dbus_message_iter_get_basic(&value, &val);
768 netmask = g_strdup(val);
770 DBG("Netmask %s", netmask);
771 } else if (g_str_equal(key, "DomainNameServers") == TRUE) {
772 nameservers = extract_nameservers(&value);
774 DBG("Nameservers %s", nameservers);
775 } else if (g_str_equal(key, "Gateway") == TRUE) {
776 dbus_message_iter_get_basic(&value, &val);
778 gateway = g_strdup(val);
780 DBG("Gateway %s", gateway);
783 dbus_message_iter_next(&dict);
789 if (context->ipv4_method != CONNMAN_IPCONFIG_METHOD_FIXED)
792 context->ipv4_address = connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4);
793 if (context->ipv4_address == NULL)
796 context->index = index;
797 connman_ipaddress_set_ipv4(context->ipv4_address, address,
800 context->ipv4_nameservers = nameservers;
803 if (context->ipv4_nameservers != nameservers)
811 static void extract_ipv6_settings(DBusMessageIter *array,
812 struct network_context *context)
814 DBusMessageIter dict;
815 char *address = NULL, *gateway = NULL;
816 unsigned char prefix_length;
817 char *nameservers = NULL;
818 const char *interface = NULL;
821 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
824 dbus_message_iter_recurse(array, &dict);
826 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
827 DBusMessageIter entry, value;
828 const char *key, *val;
830 dbus_message_iter_recurse(&dict, &entry);
831 dbus_message_iter_get_basic(&entry, &key);
833 dbus_message_iter_next(&entry);
834 dbus_message_iter_recurse(&entry, &value);
836 if (g_str_equal(key, "Interface") == TRUE) {
837 dbus_message_iter_get_basic(&value, &interface);
839 DBG("Interface %s", interface);
841 index = connman_inet_ifindex(interface);
843 DBG("index %d", index);
844 } else if (g_str_equal(key, "Address") == TRUE) {
845 dbus_message_iter_get_basic(&value, &val);
847 address = g_strdup(val);
849 DBG("Address %s", address);
850 } else if (g_str_equal(key, "PrefixLength") == TRUE) {
851 dbus_message_iter_get_basic(&value, &prefix_length);
853 DBG("prefix length %d", prefix_length);
854 } else if (g_str_equal(key, "DomainNameServers") == TRUE) {
855 nameservers = extract_nameservers(&value);
857 DBG("Nameservers %s", nameservers);
858 } else if (g_str_equal(key, "Gateway") == TRUE) {
859 dbus_message_iter_get_basic(&value, &val);
861 gateway = g_strdup(val);
863 DBG("Gateway %s", gateway);
866 dbus_message_iter_next(&dict);
872 context->ipv6_method = CONNMAN_IPCONFIG_METHOD_FIXED;
874 context->ipv6_address =
875 connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6);
876 if (context->ipv6_address == NULL)
879 context->index = index;
880 connman_ipaddress_set_ipv6(context->ipv6_address, address,
881 prefix_length, gateway);
883 context->ipv6_nameservers = nameservers;
886 if (context->ipv6_nameservers != nameservers)
893 static connman_bool_t ready_to_create_device(struct modem_data *modem)
896 * There are three different modem types which behave slightly
898 * - GSM modems will expose the SIM interface then the
900 * - DUN modems will expose first a unique serial number (BDADDR)
901 * and then the CM interface.
902 * - CDMA modems will expose CM first and sometime later
903 * a unique serial number.
905 * This functions tests if we have the necessary information gathered
906 * before we are able to create a device.
909 if (modem->device != NULL)
912 if (modem->imsi != NULL || modem->serial != NULL)
918 static void create_device(struct modem_data *modem)
920 struct connman_device *device;
921 char *uninitialized_var(ident);
923 DBG("%s", modem->path);
925 if (modem->imsi != NULL)
927 else if (modem->serial != NULL)
928 ident = modem->serial;
930 if (connman_dbus_validate_ident(ident) == FALSE)
931 ident = connman_dbus_encode_string(ident);
933 ident = g_strdup(ident);
935 device = connman_device_create(ident, CONNMAN_DEVICE_TYPE_CELLULAR);
939 DBG("device %p", device);
941 connman_device_set_ident(device, ident);
943 connman_device_set_string(device, "Path", modem->path);
945 connman_device_set_data(device, modem);
947 if (connman_device_register(device) < 0) {
948 connman_error("Failed to register cellular device");
949 connman_device_unref(device);
953 modem->device = device;
959 static void destroy_device(struct modem_data *modem)
961 DBG("%s", modem->path);
963 connman_device_set_powered(modem->device, FALSE);
965 if (modem->network != NULL) {
966 connman_device_remove_network(modem->device, modem->network);
967 connman_network_unref(modem->network);
968 modem->network = NULL;
971 connman_device_unregister(modem->device);
972 connman_device_unref(modem->device);
974 modem->device = NULL;
977 static void add_network(struct modem_data *modem)
981 DBG("%s", modem->path);
983 if (modem->network != NULL)
986 modem->network = connman_network_create(modem->context->path,
987 CONNMAN_NETWORK_TYPE_CELLULAR);
988 if (modem->network == NULL)
991 DBG("network %p", modem->network);
993 connman_network_set_data(modem->network, modem);
995 connman_network_set_string(modem->network, "Path",
996 modem->context->path);
998 connman_network_set_index(modem->network, modem->context->index);
1000 if (modem->name != NULL)
1001 connman_network_set_name(modem->network, modem->name);
1003 connman_network_set_name(modem->network, "");
1005 connman_network_set_strength(modem->network, modem->strength);
1007 group = get_ident(modem->context->path);
1008 connman_network_set_group(modem->network, group);
1010 connman_network_set_available(modem->network, TRUE);
1012 connman_network_set_bool(modem->network, "Roaming",
1015 if (connman_device_add_network(modem->device, modem->network) < 0) {
1016 connman_network_unref(modem->network);
1017 modem->network = NULL;
1022 static int add_cm_context(struct modem_data *modem, const char *context_path,
1023 DBusMessageIter *dict)
1025 const char *context_type;
1026 struct network_context *context = NULL;
1027 connman_bool_t active = FALSE;
1029 DBG("%s context path %s", modem->path, context_path);
1031 if (modem->context != NULL) {
1033 * We have already assigned a context to this modem
1034 * and we do only support one Internet context.
1039 context = network_context_alloc(context_path);
1040 if (context == NULL)
1043 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1044 DBusMessageIter entry, value;
1047 dbus_message_iter_recurse(dict, &entry);
1048 dbus_message_iter_get_basic(&entry, &key);
1050 dbus_message_iter_next(&entry);
1051 dbus_message_iter_recurse(&entry, &value);
1053 if (g_str_equal(key, "Type") == TRUE) {
1054 dbus_message_iter_get_basic(&value, &context_type);
1056 DBG("%s context %s type %s", modem->path,
1057 context_path, context_type);
1058 } else if (g_str_equal(key, "Settings") == TRUE) {
1059 DBG("%s Settings", modem->path);
1061 extract_ipv4_settings(&value, context);
1062 } else if (g_str_equal(key, "IPv6.Settings") == TRUE) {
1063 DBG("%s IPv6.Settings", modem->path);
1065 extract_ipv6_settings(&value, context);
1066 } else if (g_str_equal(key, "Active") == TRUE) {
1067 dbus_message_iter_get_basic(&value, &active);
1069 DBG("%s Active %d", modem->path, active);
1072 dbus_message_iter_next(dict);
1075 if (g_strcmp0(context_type, "internet") != 0) {
1076 network_context_free(context);
1080 modem->context = context;
1081 modem->active = active;
1083 g_hash_table_replace(context_hash, g_strdup(context_path), modem);
1088 static void remove_cm_context(struct modem_data *modem,
1089 const char *context_path)
1091 if (modem->context == NULL)
1094 g_hash_table_remove(context_hash, context_path);
1096 network_context_free(modem->context);
1097 modem->context = NULL;
1100 static gboolean context_changed(DBusConnection *connection,
1101 DBusMessage *message,
1104 const char *context_path = dbus_message_get_path(message);
1105 struct modem_data *modem = NULL;
1106 DBusMessageIter iter, value;
1109 DBG("context_path %s", context_path);
1111 modem = g_hash_table_lookup(context_hash, context_path);
1115 if (dbus_message_iter_init(message, &iter) == FALSE)
1118 dbus_message_iter_get_basic(&iter, &key);
1120 dbus_message_iter_next(&iter);
1121 dbus_message_iter_recurse(&iter, &value);
1124 * oFono guarantees the ordering of Settings and
1125 * Active. Settings will always be send before Active = True.
1126 * That means we don't have to order here.
1128 if (g_str_equal(key, "Settings") == TRUE) {
1129 DBG("%s Settings", modem->path);
1131 extract_ipv4_settings(&value, modem->context);
1132 } else if (g_str_equal(key, "IPv6.Settings") == TRUE) {
1133 DBG("%s IPv6.Settings", modem->path);
1135 extract_ipv6_settings(&value, modem->context);
1136 } else if (g_str_equal(key, "Active") == TRUE) {
1137 dbus_message_iter_get_basic(&value, &modem->active);
1139 DBG("%s Active %d", modem->path, modem->active);
1141 if (modem->active == TRUE)
1142 set_connected(modem);
1144 set_disconnected(modem);
1150 static void cm_get_contexts_reply(DBusPendingCall *call, void *user_data)
1152 struct modem_data *modem = user_data;
1153 DBusMessageIter array, dict, entry, value;
1157 DBG("%s", modem->path);
1159 modem->call_get_contexts = NULL;
1161 reply = dbus_pending_call_steal_reply(call);
1163 dbus_error_init(&error);
1165 if (dbus_set_error_from_message(&error, reply) == TRUE) {
1166 connman_error("%s", error.message);
1167 dbus_error_free(&error);
1171 if (dbus_message_iter_init(reply, &array) == FALSE)
1174 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
1177 dbus_message_iter_recurse(&array, &dict);
1179 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT) {
1180 const char *context_path;
1182 dbus_message_iter_recurse(&dict, &entry);
1183 dbus_message_iter_get_basic(&entry, &context_path);
1185 dbus_message_iter_next(&entry);
1186 dbus_message_iter_recurse(&entry, &value);
1188 if (add_cm_context(modem, context_path, &value) == 0)
1191 dbus_message_iter_next(&dict);
1195 dbus_message_unref(reply);
1197 dbus_pending_call_unref(call);
1200 static int cm_get_contexts(struct modem_data *modem)
1202 DBusMessage *message;
1204 DBG("%s", modem->path);
1206 if (modem->call_get_contexts != NULL)
1209 message = dbus_message_new_method_call(OFONO_SERVICE, modem->path,
1210 OFONO_CM_INTERFACE, GET_CONTEXTS);
1211 if (message == NULL)
1214 if (dbus_connection_send_with_reply(connection, message,
1215 &modem->call_get_contexts, TIMEOUT) == FALSE) {
1216 connman_error("Failed to call GetContexts()");
1217 dbus_message_unref(message);
1221 if (modem->call_get_contexts == NULL) {
1222 connman_error("D-Bus connection not available");
1223 dbus_message_unref(message);
1227 dbus_pending_call_set_notify(modem->call_get_contexts,
1228 cm_get_contexts_reply,
1231 dbus_message_unref(message);
1233 return -EINPROGRESS;
1236 static gboolean cm_context_added(DBusConnection *connection,
1237 DBusMessage *message,
1240 const char *path = dbus_message_get_path(message);
1242 struct modem_data *modem;
1243 DBusMessageIter iter, properties;
1247 modem = g_hash_table_lookup(modem_hash, context_path);
1251 if (dbus_message_iter_init(message, &iter) == FALSE)
1254 dbus_message_iter_get_basic(&iter, &context_path);
1256 dbus_message_iter_next(&iter);
1257 dbus_message_iter_recurse(&iter, &properties);
1259 if (add_cm_context(modem, context_path, &properties) != 0)
1265 static gboolean cm_context_removed(DBusConnection *connection,
1266 DBusMessage *message,
1269 const char *path = dbus_message_get_path(message);
1270 const char *context_path;
1271 struct modem_data *modem;
1272 DBusMessageIter iter;
1274 DBG("context path %s", path);
1276 if (dbus_message_iter_init(message, &iter) == FALSE)
1279 dbus_message_iter_get_basic(&iter, &context_path);
1281 modem = g_hash_table_lookup(context_hash, context_path);
1285 remove_cm_context(modem, context_path);
1290 static void netreg_update_name(struct modem_data *modem,
1291 DBusMessageIter* value)
1295 dbus_message_iter_get_basic(value, &name);
1297 DBG("%s Name %s", modem->path, name);
1299 g_free(modem->name);
1300 modem->name = g_strdup(name);
1302 if (modem->network == NULL)
1305 connman_network_set_name(modem->network, modem->name);
1306 connman_network_update(modem->network);
1309 static void netreg_update_strength(struct modem_data *modem,
1310 DBusMessageIter *value)
1312 dbus_message_iter_get_basic(value, &modem->strength);
1314 DBG("%s Strength %d", modem->path, modem->strength);
1316 if (modem->network == NULL)
1321 * We don't have 2 signal notifications we always report the strength
1322 * signal. data_strength is always equal to 0.
1325 * In the case we have a data_strength signal (from 1xEVDO network)
1326 * we don't need to update the value with strength signal (from 1xCDMA)
1327 * because the modem is registered to 1xEVDO network for data call.
1328 * In case we have no data_strength signal (not registered to 1xEVDO
1329 * network), we must report the strength signal (registered to 1xCDMA
1330 * network e.g slow mode).
1332 if (modem->data_strength != 0)
1335 connman_network_set_strength(modem->network, modem->strength);
1336 connman_network_update(modem->network);
1339 /* Retrieve 1xEVDO Data Strength signal */
1340 static void netreg_update_datastrength(struct modem_data *modem,
1341 DBusMessageIter *value)
1343 dbus_message_iter_get_basic(value, &modem->data_strength);
1345 DBG("%s Data Strength %d", modem->path, modem->data_strength);
1347 if (modem->network == NULL)
1351 * CDMA modem is not registered to 1xEVDO network, let
1352 * update_signal_strength() reporting the value on the Strength signal
1355 if (modem->data_strength == 0)
1358 connman_network_set_strength(modem->network, modem->data_strength);
1359 connman_network_update(modem->network);
1362 static void netreg_update_roaming(struct modem_data *modem,
1363 DBusMessageIter *value)
1366 connman_bool_t roaming;
1368 dbus_message_iter_get_basic(value, &status);
1370 if (g_str_equal(status, "roaming") == TRUE)
1375 if (roaming == modem->roaming)
1378 modem->roaming = roaming;
1380 if (modem->network == NULL)
1383 connman_network_set_bool(modem->network,
1384 "Roaming", modem->roaming);
1385 connman_network_update(modem->network);
1388 static void netreg_update_regdom(struct modem_data *modem,
1389 DBusMessageIter *value)
1391 char *mobile_country_code;
1395 dbus_message_iter_get_basic(value, &mobile_country_code);
1397 DBG("%s MobileContryCode %s", modem->path, mobile_country_code);
1400 mcc = atoi(mobile_country_code);
1404 alpha2 = mcc_country_codes[mcc - 200];
1405 connman_technology_set_regdom(alpha2);
1408 static gboolean netreg_changed(DBusConnection *connection, DBusMessage *message,
1411 const char *path = dbus_message_get_path(message);
1412 struct modem_data *modem;
1413 DBusMessageIter iter, value;
1416 modem = g_hash_table_lookup(modem_hash, path);
1420 if (modem->ignore == TRUE)
1423 if (dbus_message_iter_init(message, &iter) == FALSE)
1426 dbus_message_iter_get_basic(&iter, &key);
1428 dbus_message_iter_next(&iter);
1429 dbus_message_iter_recurse(&iter, &value);
1431 if (g_str_equal(key, "Name") == TRUE)
1432 netreg_update_name(modem, &value);
1433 else if (g_str_equal(key, "Strength") == TRUE)
1434 netreg_update_strength(modem, &value);
1435 else if (g_str_equal(key, "Status") == TRUE)
1436 netreg_update_roaming(modem, &value);
1437 else if (g_str_equal(key, "MobileCountryCode") == TRUE)
1438 netreg_update_regdom(modem, &value);
1443 static void netreg_properties_reply(struct modem_data *modem,
1444 DBusMessageIter *dict)
1446 DBG("%s", modem->path);
1448 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1449 DBusMessageIter entry, value;
1452 dbus_message_iter_recurse(dict, &entry);
1453 dbus_message_iter_get_basic(&entry, &key);
1455 dbus_message_iter_next(&entry);
1456 dbus_message_iter_recurse(&entry, &value);
1458 if (g_str_equal(key, "Name") == TRUE)
1459 netreg_update_name(modem, &value);
1460 else if (g_str_equal(key, "Strength") == TRUE)
1461 netreg_update_strength(modem, &value);
1462 else if (g_str_equal(key, "Status") == TRUE)
1463 netreg_update_roaming(modem, &value);
1464 else if (g_str_equal(key, "MobileCountryCode") == TRUE)
1465 netreg_update_regdom(modem, &value);
1467 dbus_message_iter_next(dict);
1470 if (modem->context == NULL) {
1472 * netgreg_get_properties() was issued after we got
1473 * cm_get_contexts_reply() where we create the
1474 * context. Though before we got the
1475 * netreg_properties_reply the context was removed
1476 * again. Therefore we have to skip the network
1484 if (modem->active == TRUE)
1485 set_connected(modem);
1488 static int netreg_get_properties(struct modem_data *modem)
1490 return get_properties(modem->path, OFONO_NETREG_INTERFACE,
1491 netreg_properties_reply, modem);
1494 static void add_cdma_network(struct modem_data *modem)
1496 /* Be sure that device is created before adding CDMA network */
1497 if (modem->device == NULL)
1501 * CDMA modems don't need contexts for data call, however the current
1502 * add_network() logic needs one, so we create one to proceed.
1504 if (modem->context == NULL)
1505 modem->context = network_context_alloc(modem->path);
1509 if (modem->cdma_cm_powered == TRUE)
1510 set_connected(modem);
1513 static gboolean cdma_netreg_changed(DBusConnection *connection,
1514 DBusMessage *message,
1517 const char *path = dbus_message_get_path(message);
1518 struct modem_data *modem;
1519 DBusMessageIter iter, value;
1524 modem = g_hash_table_lookup(modem_hash, path);
1528 if (modem->ignore == TRUE)
1531 if (dbus_message_iter_init(message, &iter) == FALSE)
1534 dbus_message_iter_get_basic(&iter, &key);
1536 dbus_message_iter_next(&iter);
1537 dbus_message_iter_recurse(&iter, &value);
1539 if (g_str_equal(key, "Name") == TRUE)
1540 netreg_update_name(modem, &value);
1541 else if (g_str_equal(key, "Strength") == TRUE)
1542 netreg_update_strength(modem, &value);
1543 else if (g_str_equal(key, "DataStrength") == TRUE)
1544 netreg_update_datastrength(modem, &value);
1545 else if (g_str_equal(key, "Status") == TRUE)
1546 netreg_update_roaming(modem, &value);
1548 add_cdma_network(modem);
1553 static void cdma_netreg_properties_reply(struct modem_data *modem,
1554 DBusMessageIter *dict)
1556 DBG("%s", modem->path);
1558 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1559 DBusMessageIter entry, value;
1562 dbus_message_iter_recurse(dict, &entry);
1563 dbus_message_iter_get_basic(&entry, &key);
1565 dbus_message_iter_next(&entry);
1566 dbus_message_iter_recurse(&entry, &value);
1568 if (g_str_equal(key, "Name") == TRUE)
1569 netreg_update_name(modem, &value);
1570 else if (g_str_equal(key, "Strength") == TRUE)
1571 netreg_update_strength(modem, &value);
1572 else if (g_str_equal(key, "DataStrength") == TRUE)
1573 netreg_update_datastrength(modem, &value);
1574 else if (g_str_equal(key, "Status") == TRUE)
1575 netreg_update_roaming(modem, &value);
1577 dbus_message_iter_next(dict);
1580 add_cdma_network(modem);
1583 static int cdma_netreg_get_properties(struct modem_data *modem)
1585 return get_properties(modem->path, OFONO_CDMA_NETREG_INTERFACE,
1586 cdma_netreg_properties_reply, modem);
1589 static void cm_update_attached(struct modem_data *modem,
1590 DBusMessageIter *value)
1592 dbus_message_iter_get_basic(value, &modem->attached);
1594 DBG("%s Attached %d", modem->path, modem->attached);
1596 if (modem->attached == FALSE)
1599 if (has_interface(modem->interfaces,
1600 OFONO_API_NETREG) == FALSE) {
1604 netreg_get_properties(modem);
1607 static void cm_update_powered(struct modem_data *modem,
1608 DBusMessageIter *value)
1610 dbus_message_iter_get_basic(value, &modem->cm_powered);
1612 DBG("%s ConnnectionManager Powered %d", modem->path,
1615 if (modem->cm_powered == TRUE)
1618 cm_set_powered(modem);
1621 static gboolean cm_changed(DBusConnection *connection, DBusMessage *message,
1624 const char *path = dbus_message_get_path(message);
1625 struct modem_data *modem;
1626 DBusMessageIter iter, value;
1629 modem = g_hash_table_lookup(modem_hash, path);
1633 if (modem->ignore == TRUE)
1636 if (dbus_message_iter_init(message, &iter) == FALSE)
1639 dbus_message_iter_get_basic(&iter, &key);
1641 dbus_message_iter_next(&iter);
1642 dbus_message_iter_recurse(&iter, &value);
1644 if (g_str_equal(key, "Attached") == TRUE)
1645 cm_update_attached(modem, &value);
1646 else if (g_str_equal(key, "Powered") == TRUE)
1647 cm_update_powered(modem, &value);
1652 static void cdma_cm_update_powered(struct modem_data *modem,
1653 DBusMessageIter *value)
1655 dbus_message_iter_get_basic(value, &modem->cdma_cm_powered);
1657 DBG("%s CDMA cm Powered %d", modem->path, modem->cdma_cm_powered);
1659 if (modem->network == NULL)
1662 if (modem->cdma_cm_powered == TRUE)
1663 set_connected(modem);
1665 set_disconnected(modem);
1668 static void cdma_cm_update_settings(struct modem_data *modem,
1669 DBusMessageIter *value)
1671 DBG("%s Settings", modem->path);
1673 if (modem->context != NULL)
1676 extract_ipv4_settings(value, modem->context);
1679 static gboolean cdma_cm_changed(DBusConnection *connection,
1680 DBusMessage *message, void *user_data)
1682 const char *path = dbus_message_get_path(message);
1683 struct modem_data *modem;
1684 DBusMessageIter iter, value;
1687 modem = g_hash_table_lookup(modem_hash, path);
1691 if (modem->online == TRUE && modem->network == NULL)
1692 cdma_netreg_get_properties(modem);
1694 if (dbus_message_iter_init(message, &iter) == FALSE)
1697 dbus_message_iter_get_basic(&iter, &key);
1699 dbus_message_iter_next(&iter);
1700 dbus_message_iter_recurse(&iter, &value);
1702 if (g_str_equal(key, "Powered") == TRUE)
1703 cdma_cm_update_powered(modem, &value);
1704 if (g_str_equal(key, "Settings") == TRUE)
1705 cdma_cm_update_settings(modem, &value);
1710 static void cm_properties_reply(struct modem_data *modem, DBusMessageIter *dict)
1712 DBG("%s", modem->path);
1714 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1715 DBusMessageIter entry, value;
1718 dbus_message_iter_recurse(dict, &entry);
1719 dbus_message_iter_get_basic(&entry, &key);
1721 dbus_message_iter_next(&entry);
1722 dbus_message_iter_recurse(&entry, &value);
1724 if (g_str_equal(key, "Attached") == TRUE)
1725 cm_update_attached(modem, &value);
1726 else if (g_str_equal(key, "Powered") == TRUE)
1727 cm_update_powered(modem, &value);
1729 dbus_message_iter_next(dict);
1733 static int cm_get_properties(struct modem_data *modem)
1735 return get_properties(modem->path, OFONO_CM_INTERFACE,
1736 cm_properties_reply, modem);
1739 static void cdma_cm_properties_reply(struct modem_data *modem,
1740 DBusMessageIter *dict)
1742 DBG("%s", modem->path);
1744 if (modem->online == TRUE)
1745 cdma_netreg_get_properties(modem);
1747 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1748 DBusMessageIter entry, value;
1751 dbus_message_iter_recurse(dict, &entry);
1752 dbus_message_iter_get_basic(&entry, &key);
1754 dbus_message_iter_next(&entry);
1755 dbus_message_iter_recurse(&entry, &value);
1757 if (g_str_equal(key, "Powered") == TRUE)
1758 cdma_cm_update_powered(modem, &value);
1759 if (g_str_equal(key, "Settings") == TRUE)
1760 cdma_cm_update_settings(modem, &value);
1762 dbus_message_iter_next(dict);
1766 static int cdma_cm_get_properties(struct modem_data *modem)
1768 return get_properties(modem->path, OFONO_CDMA_CM_INTERFACE,
1769 cdma_cm_properties_reply, modem);
1772 static connman_bool_t connection_manager_init(struct modem_data *modem)
1774 if (has_interface(modem->interfaces, OFONO_API_CM) == TRUE) {
1775 if (ready_to_create_device(modem) == TRUE)
1776 create_device(modem);
1778 if (modem->device != NULL) {
1779 cm_get_properties(modem);
1780 cm_get_contexts(modem);
1786 if (has_interface(modem->interfaces, OFONO_API_CDMA_CM) == TRUE) {
1787 if (ready_to_create_device(modem) == TRUE)
1788 create_device(modem);
1790 if (modem->device != NULL)
1791 cdma_cm_get_properties(modem);
1799 static void sim_update_imsi(struct modem_data *modem,
1800 DBusMessageIter* value)
1804 dbus_message_iter_get_basic(value, &imsi);
1806 DBG("%s imsi %s", modem->path, imsi);
1808 g_free(modem->imsi);
1809 modem->imsi = g_strdup(imsi);
1812 static gboolean sim_changed(DBusConnection *connection, DBusMessage *message,
1815 const char *path = dbus_message_get_path(message);
1816 struct modem_data *modem;
1817 DBusMessageIter iter, value;
1820 modem = g_hash_table_lookup(modem_hash, path);
1824 if (modem->ignore == TRUE)
1827 if (dbus_message_iter_init(message, &iter) == FALSE)
1830 dbus_message_iter_get_basic(&iter, &key);
1832 dbus_message_iter_next(&iter);
1833 dbus_message_iter_recurse(&iter, &value);
1835 if (g_str_equal(key, "SubscriberIdentity") == TRUE) {
1836 sim_update_imsi(modem, &value);
1838 if (modem->online == FALSE) {
1839 modem_set_online(modem);
1840 } else if (has_interface(modem->interfaces,
1841 OFONO_API_CM) == TRUE) {
1842 if (ready_to_create_device(modem) == TRUE)
1843 create_device(modem);
1844 } else if (has_interface(modem->interfaces,
1845 OFONO_API_CDMA_CM) == TRUE) {
1846 if (ready_to_create_device(modem) == TRUE)
1847 create_device(modem);
1854 static void sim_properties_reply(struct modem_data *modem,
1855 DBusMessageIter *dict)
1857 DBG("%s", modem->path);
1859 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1860 DBusMessageIter entry, value;
1863 dbus_message_iter_recurse(dict, &entry);
1864 dbus_message_iter_get_basic(&entry, &key);
1866 dbus_message_iter_next(&entry);
1867 dbus_message_iter_recurse(&entry, &value);
1869 if (g_str_equal(key, "SubscriberIdentity") == TRUE) {
1870 sim_update_imsi(modem, &value);
1872 if (modem->online == FALSE) {
1873 modem_set_online(modem);
1877 connection_manager_init(modem);
1882 dbus_message_iter_next(dict);
1886 static int sim_get_properties(struct modem_data *modem)
1888 return get_properties(modem->path, OFONO_SIM_INTERFACE,
1889 sim_properties_reply, modem);
1892 static gboolean modem_changed(DBusConnection *connection, DBusMessage *message,
1895 const char *path = dbus_message_get_path(message);
1896 struct modem_data *modem;
1897 DBusMessageIter iter, value;
1900 modem = g_hash_table_lookup(modem_hash, path);
1904 if (modem->ignore == TRUE)
1907 if (dbus_message_iter_init(message, &iter) == FALSE)
1910 dbus_message_iter_get_basic(&iter, &key);
1912 dbus_message_iter_next(&iter);
1913 dbus_message_iter_recurse(&iter, &value);
1915 if (g_str_equal(key, "Powered") == TRUE) {
1916 dbus_message_iter_get_basic(&value, &modem->powered);
1918 DBG("%s Powered %d", modem->path, modem->powered);
1920 if (modem->powered == FALSE)
1921 modem_set_powered(modem);
1922 } else if (g_str_equal(key, "Online") == TRUE) {
1923 dbus_message_iter_get_basic(&value, &modem->online);
1925 DBG("%s Online %d", modem->path, modem->online);
1927 if (modem->online == FALSE)
1930 connection_manager_init(modem);
1931 } else if (g_str_equal(key, "Interfaces") == TRUE) {
1932 modem->interfaces = extract_interfaces(&value);
1934 DBG("%s Interfaces 0x%02x", modem->path,
1937 if (has_interface(modem->interfaces, OFONO_API_SIM) == TRUE) {
1938 if (modem->imsi == NULL &&
1939 modem->set_powered == FALSE) {
1941 * Only use do GetProperties() when
1942 * device has not been powered up.
1944 sim_get_properties(modem);
1949 if (connection_manager_init(modem) == FALSE) {
1950 if (modem->context != NULL) {
1951 remove_cm_context(modem,
1952 modem->context->path);
1955 if (modem->device != NULL)
1956 destroy_device(modem);
1961 if (has_interface(modem->interfaces, OFONO_API_NETREG) == TRUE) {
1962 if (modem->attached == TRUE)
1963 netreg_get_properties(modem);
1964 } else if (has_interface(modem->interfaces,
1965 OFONO_API_CDMA_NETREG) == TRUE)
1966 cdma_netreg_get_properties(modem);
1967 } else if (g_str_equal(key, "Serial") == TRUE) {
1970 dbus_message_iter_get_basic(&value, &serial);
1972 g_free(modem->serial);
1973 modem->serial = g_strdup(serial);
1975 DBG("%s Serial %s", modem->path, modem->serial);
1977 connection_manager_init(modem);
1983 static void add_modem(const char *path, DBusMessageIter *prop)
1985 struct modem_data *modem;
1989 modem = g_hash_table_lookup(modem_hash, path);
1990 if (modem != NULL) {
1992 * When oFono powers up we ask for the modems and oFono is
1993 * reporting with modem_added signal the modems. Only
1999 modem = g_try_new0(struct modem_data, 1);
2003 modem->path = g_strdup(path);
2005 g_hash_table_insert(modem_hash, g_strdup(path), modem);
2007 while (dbus_message_iter_get_arg_type(prop) == DBUS_TYPE_DICT_ENTRY) {
2008 DBusMessageIter entry, value;
2011 dbus_message_iter_recurse(prop, &entry);
2012 dbus_message_iter_get_basic(&entry, &key);
2014 dbus_message_iter_next(&entry);
2015 dbus_message_iter_recurse(&entry, &value);
2017 if (g_str_equal(key, "Powered") == TRUE) {
2018 dbus_message_iter_get_basic(&value, &modem->powered);
2020 DBG("%s Powered %d", modem->path, modem->powered);
2021 } else if (g_str_equal(key, "Online") == TRUE) {
2022 dbus_message_iter_get_basic(&value, &modem->online);
2024 DBG("%s Online %d", modem->path, modem->online);
2025 } else if (g_str_equal(key, "Interfaces") == TRUE) {
2026 modem->interfaces = extract_interfaces(&value);
2028 DBG("%s Interfaces 0x%02x", modem->path,
2030 } else if (g_str_equal(key, "Serial") == TRUE) {
2033 dbus_message_iter_get_basic(&value, &serial);
2034 modem->serial = g_strdup(serial);
2036 DBG("%s Serial %s", modem->path, modem->serial);
2037 } else if (g_str_equal(key, "Type") == TRUE) {
2040 dbus_message_iter_get_basic(&value, &type);
2042 DBG("%s Type %s", modem->path, type);
2043 if (g_strcmp0(type, "hardware") != 0) {
2044 DBG("%s Ignore this modem", modem->path);
2045 modem->ignore = TRUE;
2049 dbus_message_iter_next(prop);
2052 if (modem->ignore == TRUE)
2055 if (modem->powered == FALSE)
2056 modem_set_powered(modem);
2057 else if (has_interface(modem->interfaces, OFONO_API_SIM) == TRUE)
2058 sim_get_properties(modem);
2060 connection_manager_init(modem);
2063 static void modem_power_down(gpointer key, gpointer value, gpointer user_data)
2065 struct modem_data *modem = value;
2067 DBG("%s", modem->path);
2069 if (modem->ignore == TRUE)
2072 modem_set_unpowered(modem);
2075 static void remove_modem(gpointer data)
2077 struct modem_data *modem = data;
2079 DBG("%s", modem->path);
2081 if (modem->call_set_property != NULL)
2082 dbus_pending_call_cancel(modem->call_set_property);
2084 if (modem->call_get_properties != NULL)
2085 dbus_pending_call_cancel(modem->call_get_properties);
2087 if (modem->call_get_contexts != NULL)
2088 dbus_pending_call_cancel(modem->call_get_contexts);
2090 if (modem->device != NULL)
2091 destroy_device(modem);
2093 if (modem->context != NULL)
2094 remove_cm_context(modem, modem->context->path);
2096 g_free(modem->serial);
2097 g_free(modem->name);
2098 g_free(modem->imsi);
2099 g_free(modem->path);
2104 static gboolean modem_added(DBusConnection *connection,
2105 DBusMessage *message, void *user_data)
2107 DBusMessageIter iter, properties;
2112 if (dbus_message_iter_init(message, &iter) == FALSE)
2115 dbus_message_iter_get_basic(&iter, &path);
2117 dbus_message_iter_next(&iter);
2118 dbus_message_iter_recurse(&iter, &properties);
2120 add_modem(path, &properties);
2125 static gboolean modem_removed(DBusConnection *connection,
2126 DBusMessage *message, void *user_data)
2128 DBusMessageIter iter;
2133 if (dbus_message_iter_init(message, &iter) == FALSE)
2136 dbus_message_iter_get_basic(&iter, &path);
2138 g_hash_table_remove(modem_hash, path);
2143 static void manager_get_modems_reply(DBusPendingCall *call, void *user_data)
2147 DBusMessageIter array, dict;
2151 reply = dbus_pending_call_steal_reply(call);
2153 dbus_error_init(&error);
2155 if (dbus_set_error_from_message(&error, reply) == TRUE) {
2156 connman_error("%s", error.message);
2157 dbus_error_free(&error);
2161 if (dbus_message_iter_init(reply, &array) == FALSE)
2164 dbus_message_iter_recurse(&array, &dict);
2166 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT) {
2167 DBusMessageIter value, properties;
2170 dbus_message_iter_recurse(&dict, &value);
2171 dbus_message_iter_get_basic(&value, &path);
2173 dbus_message_iter_next(&value);
2174 dbus_message_iter_recurse(&value, &properties);
2176 add_modem(path, &properties);
2178 dbus_message_iter_next(&dict);
2182 dbus_message_unref(reply);
2184 dbus_pending_call_unref(call);
2187 static int manager_get_modems(void)
2189 DBusMessage *message;
2190 DBusPendingCall *call;
2194 message = dbus_message_new_method_call(OFONO_SERVICE, "/",
2195 OFONO_MANAGER_INTERFACE, GET_MODEMS);
2196 if (message == NULL)
2199 if (dbus_connection_send_with_reply(connection, message,
2200 &call, TIMEOUT) == FALSE) {
2201 connman_error("Failed to call GetModems()");
2202 dbus_message_unref(message);
2207 connman_error("D-Bus connection not available");
2208 dbus_message_unref(message);
2212 dbus_pending_call_set_notify(call, manager_get_modems_reply,
2215 dbus_message_unref(message);
2217 return -EINPROGRESS;
2220 static void ofono_connect(DBusConnection *conn, void *user_data)
2224 modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2225 g_free, remove_modem);
2226 if (modem_hash == NULL)
2229 context_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2231 if (context_hash == NULL) {
2232 g_hash_table_destroy(modem_hash);
2236 manager_get_modems();
2239 static void ofono_disconnect(DBusConnection *conn, void *user_data)
2243 if (modem_hash == NULL || context_hash == NULL)
2246 g_hash_table_destroy(modem_hash);
2249 g_hash_table_destroy(context_hash);
2250 context_hash = NULL;
2253 static int network_probe(struct connman_network *network)
2255 struct modem_data *modem = connman_network_get_data(network);
2257 DBG("%s network %p", modem->path, network);
2262 static void network_remove(struct connman_network *network)
2264 struct modem_data *modem = connman_network_get_data(network);
2266 DBG("%s network %p", modem->path, network);
2269 static int network_connect(struct connman_network *network)
2271 struct modem_data *modem = connman_network_get_data(network);
2273 DBG("%s network %p", modem->path, network);
2275 if (has_interface(modem->interfaces, OFONO_API_CM) == TRUE)
2276 return context_set_active(modem, TRUE);
2277 else if (has_interface(modem->interfaces, OFONO_API_CDMA_CM) == TRUE)
2278 return cdma_cm_set_powered(modem, TRUE);
2280 connman_error("Connection manager interface not available");
2285 static int network_disconnect(struct connman_network *network)
2287 struct modem_data *modem = connman_network_get_data(network);
2289 DBG("%s network %p", modem->path, network);
2291 if (has_interface(modem->interfaces, OFONO_API_CM) == TRUE)
2292 return context_set_active(modem, FALSE);
2293 else if (has_interface(modem->interfaces, OFONO_API_CDMA_CM) == TRUE)
2294 return cdma_cm_set_powered(modem, FALSE);
2296 connman_error("Connection manager interface not available");
2301 static struct connman_network_driver network_driver = {
2303 .type = CONNMAN_NETWORK_TYPE_CELLULAR,
2304 .probe = network_probe,
2305 .remove = network_remove,
2306 .connect = network_connect,
2307 .disconnect = network_disconnect,
2310 static int modem_probe(struct connman_device *device)
2312 struct modem_data *modem = connman_device_get_data(device);
2314 DBG("%s device %p", modem->path, device);
2319 static void modem_remove(struct connman_device *device)
2321 struct modem_data *modem = connman_device_get_data(device);
2323 DBG("%s device %p", modem->path, device);
2326 static int modem_enable(struct connman_device *device)
2328 struct modem_data *modem = connman_device_get_data(device);
2330 DBG("%s device %p", modem->path, device);
2335 static int modem_disable(struct connman_device *device)
2337 struct modem_data *modem = connman_device_get_data(device);
2339 DBG("%s device %p", modem->path, device);
2344 static struct connman_device_driver modem_driver = {
2346 .type = CONNMAN_DEVICE_TYPE_CELLULAR,
2347 .probe = modem_probe,
2348 .remove = modem_remove,
2349 .enable = modem_enable,
2350 .disable = modem_disable,
2354 static guint modem_added_watch;
2355 static guint modem_removed_watch;
2356 static guint modem_watch;
2357 static guint cm_watch;
2358 static guint sim_watch;
2359 static guint context_added_watch;
2360 static guint context_removed_watch;
2361 static guint netreg_watch;
2362 static guint context_watch;
2363 static guint cdma_cm_watch;
2364 static guint cdma_netreg_watch;
2366 static int ofono_init(void)
2372 connection = connman_dbus_get_connection();
2373 if (connection == NULL)
2376 watch = g_dbus_add_service_watch(connection,
2377 OFONO_SERVICE, ofono_connect,
2378 ofono_disconnect, NULL, NULL);
2380 modem_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2381 OFONO_MANAGER_INTERFACE,
2386 modem_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2387 OFONO_MANAGER_INTERFACE,
2392 modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2393 OFONO_MODEM_INTERFACE,
2398 cm_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2404 sim_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2405 OFONO_SIM_INTERFACE,
2410 context_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2416 context_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2422 context_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2423 OFONO_CONTEXT_INTERFACE,
2428 netreg_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2429 OFONO_NETREG_INTERFACE,
2434 cdma_cm_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2435 OFONO_CDMA_CM_INTERFACE,
2440 cdma_netreg_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2441 OFONO_CDMA_NETREG_INTERFACE,
2443 cdma_netreg_changed,
2447 if (watch == 0 || modem_added_watch == 0 || modem_removed_watch == 0 ||
2448 modem_watch == 0 || cm_watch == 0 || sim_watch == 0 ||
2449 context_added_watch == 0 ||
2450 context_removed_watch == 0 ||
2451 context_watch == 0 || netreg_watch == 0 ||
2452 cdma_cm_watch == 0 || cdma_netreg_watch == 0) {
2457 err = connman_network_driver_register(&network_driver);
2461 err = connman_device_driver_register(&modem_driver);
2463 connman_network_driver_unregister(&network_driver);
2470 g_dbus_remove_watch(connection, cdma_netreg_watch);
2471 g_dbus_remove_watch(connection, cdma_cm_watch);
2472 g_dbus_remove_watch(connection, netreg_watch);
2473 g_dbus_remove_watch(connection, context_watch);
2474 g_dbus_remove_watch(connection, context_removed_watch);
2475 g_dbus_remove_watch(connection, context_added_watch);
2476 g_dbus_remove_watch(connection, sim_watch);
2477 g_dbus_remove_watch(connection, cm_watch);
2478 g_dbus_remove_watch(connection, modem_watch);
2479 g_dbus_remove_watch(connection, modem_removed_watch);
2480 g_dbus_remove_watch(connection, modem_added_watch);
2481 g_dbus_remove_watch(connection, watch);
2482 dbus_connection_unref(connection);
2487 static void ofono_exit(void)
2491 if (modem_hash != NULL) {
2493 * We should propably wait for the SetProperty() reply
2494 * message, because ...
2496 g_hash_table_foreach(modem_hash, modem_power_down, NULL);
2499 * ... here we will cancel the call.
2501 g_hash_table_destroy(modem_hash);
2505 if (context_hash != NULL) {
2506 g_hash_table_destroy(context_hash);
2507 context_hash = NULL;
2510 connman_device_driver_unregister(&modem_driver);
2511 connman_network_driver_unregister(&network_driver);
2513 g_dbus_remove_watch(connection, cdma_netreg_watch);
2514 g_dbus_remove_watch(connection, cdma_cm_watch);
2515 g_dbus_remove_watch(connection, netreg_watch);
2516 g_dbus_remove_watch(connection, context_watch);
2517 g_dbus_remove_watch(connection, context_removed_watch);
2518 g_dbus_remove_watch(connection, context_added_watch);
2519 g_dbus_remove_watch(connection, sim_watch);
2520 g_dbus_remove_watch(connection, cm_watch);
2521 g_dbus_remove_watch(connection, modem_watch);
2522 g_dbus_remove_watch(connection, modem_added_watch);
2523 g_dbus_remove_watch(connection, modem_removed_watch);
2524 g_dbus_remove_watch(connection, watch);
2526 dbus_connection_unref(connection);
2529 CONNMAN_PLUGIN_DEFINE(ofono, "oFono telephony plugin", VERSION,
2530 CONNMAN_PLUGIN_PRIORITY_DEFAULT, ofono_init, ofono_exit)