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;
130 /* CDMA ConnectionManager Interface */
131 connman_bool_t cdma_cm_powered;
133 /* ConnectionManager Interface */
134 connman_bool_t attached;
135 connman_bool_t cm_powered;
137 connman_bool_t set_cm_powered;
139 /* ConnectionContext Interface */
140 connman_bool_t active;
141 connman_bool_t set_active;
143 /* SimManager Interface */
146 /* Netreg Interface */
149 uint8_t data_strength; /* 1xEVDO signal strength */
150 connman_bool_t roaming;
153 DBusPendingCall *call_set_property;
154 DBusPendingCall *call_get_properties;
155 DBusPendingCall *call_get_contexts;
158 static char *get_ident(const char *path)
165 pos = strrchr(path, '/');
172 static struct network_context *network_context_alloc(const char *path)
174 struct network_context *context;
176 context = g_try_new0(struct network_context, 1);
180 context->path = g_strdup(path);
183 context->ipv4_method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
184 context->ipv4_address = NULL;
185 context->ipv4_nameservers = NULL;
187 context->ipv6_method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
188 context->ipv6_address = NULL;
189 context->ipv6_nameservers = NULL;
194 static void network_context_free(struct network_context *context)
196 g_free(context->path);
198 connman_ipaddress_free(context->ipv4_address);
199 g_free(context->ipv4_nameservers);
201 connman_ipaddress_free(context->ipv6_address);
202 g_free(context->ipv6_nameservers);
207 static void set_connected(struct modem_data *modem)
209 connman_bool_t setip = FALSE;
211 DBG("%s", modem->path);
213 connman_network_set_index(modem->network, modem->context->index);
215 switch (modem->context->ipv4_method) {
216 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
217 case CONNMAN_IPCONFIG_METHOD_OFF:
218 case CONNMAN_IPCONFIG_METHOD_MANUAL:
219 case CONNMAN_IPCONFIG_METHOD_AUTO:
222 case CONNMAN_IPCONFIG_METHOD_FIXED:
223 connman_network_set_ipv4_method(modem->network,
224 modem->context->ipv4_method);
225 connman_network_set_ipaddress(modem->network,
226 modem->context->ipv4_address);
227 connman_network_set_nameservers(modem->network,
228 modem->context->ipv4_nameservers);
232 case CONNMAN_IPCONFIG_METHOD_DHCP:
233 connman_network_set_ipv4_method(modem->network,
234 modem->context->ipv4_method);
239 switch (modem->context->ipv6_method) {
240 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
241 case CONNMAN_IPCONFIG_METHOD_OFF:
242 case CONNMAN_IPCONFIG_METHOD_MANUAL:
243 case CONNMAN_IPCONFIG_METHOD_DHCP:
244 case CONNMAN_IPCONFIG_METHOD_AUTO:
247 case CONNMAN_IPCONFIG_METHOD_FIXED:
248 connman_network_set_ipv6_method(modem->network,
249 modem->context->ipv6_method);
250 connman_network_set_ipaddress(modem->network,
251 modem->context->ipv6_address);
257 connman_network_set_connected(modem->network, TRUE);
260 static void set_disconnected(struct modem_data *modem)
262 DBG("%s", modem->path);
264 connman_network_set_connected(modem->network, FALSE);
267 typedef void (*set_property_cb)(struct modem_data *data,
268 connman_bool_t success);
269 typedef void (*get_properties_cb)(struct modem_data *data,
270 DBusMessageIter *dict);
272 struct property_info {
273 struct modem_data *modem;
275 const char *interface;
276 const char *property;
277 set_property_cb set_property_cb;
278 get_properties_cb get_properties_cb;
281 static void set_property_reply(DBusPendingCall *call, void *user_data)
283 struct property_info *info = user_data;
286 connman_bool_t success = TRUE;
288 DBG("%s path %s %s.%s", info->modem->path,
289 info->path, info->interface, info->property);
291 info->modem->call_set_property = NULL;
293 dbus_error_init(&error);
295 reply = dbus_pending_call_steal_reply(call);
297 if (dbus_set_error_from_message(&error, reply)) {
298 connman_error("Failed to change property: %s %s.%s: %s %s",
299 info->path, info->interface, info->property,
300 error.name, error.message);
301 dbus_error_free(&error);
305 if (info->set_property_cb != NULL)
306 (*info->set_property_cb)(info->modem, success);
308 dbus_message_unref(reply);
310 dbus_pending_call_unref(call);
313 static int set_property(struct modem_data *modem,
314 const char *path, const char *interface,
315 const char *property, int type, void *value,
316 set_property_cb notify)
318 DBusMessage *message;
319 DBusMessageIter iter;
320 struct property_info *info;
322 DBG("%s path %s %s.%s", modem->path, path, interface, property);
324 if (modem->call_set_property != NULL) {
325 connman_error("Pending SetProperty");
329 message = dbus_message_new_method_call(OFONO_SERVICE, path,
330 interface, SET_PROPERTY);
334 dbus_message_iter_init_append(message, &iter);
335 connman_dbus_property_append_basic(&iter, property, type, value);
337 if (dbus_connection_send_with_reply(connection, message,
338 &modem->call_set_property, TIMEOUT) == FALSE) {
339 connman_error("Failed to change property: %s %s.%s",
340 path, interface, property);
341 dbus_message_unref(message);
345 if (modem->call_set_property == NULL) {
346 connman_error("D-Bus connection not available");
347 dbus_message_unref(message);
351 info = g_try_new0(struct property_info, 1);
353 dbus_message_unref(message);
359 info->interface = interface;
360 info->property = property;
361 info->set_property_cb = notify;
363 dbus_pending_call_set_notify(modem->call_set_property,
364 set_property_reply, info, g_free);
366 dbus_message_unref(message);
371 static void get_properties_reply(DBusPendingCall *call, void *user_data)
373 struct property_info *info = user_data;
374 DBusMessageIter array, dict;
378 DBG("%s path %s %s", info->modem->path, info->path, info->interface);
380 info->modem->call_get_properties = NULL;
382 dbus_error_init(&error);
384 reply = dbus_pending_call_steal_reply(call);
386 if (dbus_set_error_from_message(&error, reply)) {
387 connman_error("Failed to get properties: %s %s: %s %s",
388 info->path, info->interface,
389 error.name, error.message);
390 dbus_error_free(&error);
395 if (dbus_message_iter_init(reply, &array) == FALSE)
398 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
401 dbus_message_iter_recurse(&array, &dict);
403 if (info->get_properties_cb != NULL)
404 (*info->get_properties_cb)(info->modem, &dict);
408 dbus_message_unref(reply);
410 dbus_pending_call_unref(call);
413 static int get_properties(const char *path, const char *interface,
414 get_properties_cb notify,
415 struct modem_data *modem)
417 DBusMessage *message;
418 struct property_info *info;
420 DBG("%s path %s %s", modem->path, path, interface);
422 if (modem->call_get_properties != NULL) {
423 connman_error("Pending GetProperties");
427 message = dbus_message_new_method_call(OFONO_SERVICE, path,
428 interface, GET_PROPERTIES);
432 if (dbus_connection_send_with_reply(connection, message,
433 &modem->call_get_properties, TIMEOUT) == FALSE) {
434 connman_error("Failed to call %s.GetProperties()", interface);
435 dbus_message_unref(message);
439 if (modem->call_get_properties == NULL) {
440 connman_error("D-Bus connection not available");
441 dbus_message_unref(message);
445 info = g_try_new0(struct property_info, 1);
447 dbus_message_unref(message);
453 info->interface = interface;
454 info->get_properties_cb = notify;
456 dbus_pending_call_set_notify(modem->call_get_properties,
457 get_properties_reply, info, g_free);
459 dbus_message_unref(message);
464 static void context_set_active_reply(struct modem_data *modem,
465 connman_bool_t success)
467 DBG("%s", modem->path);
469 if (success == TRUE) {
471 * Don't handle do anything on success here. oFono will send
472 * the change via PropertyChanged singal.
478 * Active = True might fail due a timeout. That means oFono
479 * still tries to go online. If we retry to set Active = True,
480 * we just get a InProgress error message. Should we power
481 * cycle the modem in such cases?
484 if (modem->network == NULL) {
486 * In the case where we power down the device
487 * we don't wait for the reply, therefore the network
488 * might already be gone.
493 connman_network_set_error(modem->network,
494 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
497 static int context_set_active(struct modem_data *modem,
498 connman_bool_t active)
502 DBG("%s active %d", modem->path, active);
504 err = set_property(modem, modem->context->path,
505 OFONO_CONTEXT_INTERFACE,
506 "Active", DBUS_TYPE_BOOLEAN,
508 context_set_active_reply);
510 if (active == FALSE && err == -EINPROGRESS)
516 static void cdma_cm_set_powered_reply(struct modem_data *modem,
517 connman_bool_t success)
519 DBG("%s", modem->path);
521 if (success == TRUE) {
523 * Don't handle do anything on success here. oFono will send
524 * the change via PropertyChanged singal.
530 * Powered = True might fail due a timeout. That means oFono
531 * still tries to go online. If we retry to set Powered = True,
532 * we just get a InProgress error message. Should we power
533 * cycle the modem in such cases?
536 if (modem->network == NULL) {
538 * In the case where we power down the device
539 * we don't wait for the reply, therefore the network
540 * might already be gone.
545 connman_network_set_error(modem->network,
546 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
549 static int cdma_cm_set_powered(struct modem_data *modem, connman_bool_t powered)
553 DBG("%s powered %d", modem->path, powered);
555 err = set_property(modem, modem->path, OFONO_CDMA_CM_INTERFACE,
556 "Powered", DBUS_TYPE_BOOLEAN,
558 cdma_cm_set_powered_reply);
560 if (powered == FALSE && err == -EINPROGRESS)
566 static int modem_set_online(struct modem_data *modem, connman_bool_t online)
568 DBG("%s online %d", modem->path, online);
570 return set_property(modem, modem->path,
571 OFONO_MODEM_INTERFACE,
572 "Online", DBUS_TYPE_BOOLEAN,
577 static void cm_set_powered_reply(struct modem_data *modem,
578 connman_bool_t success)
580 DBG("%s", modem->path);
582 if (success == TRUE) {
584 * Don't handle do anything on success here. oFono will send
585 * the change via PropertyChanged singal.
590 modem->set_cm_powered = FALSE;
593 static int cm_set_powered(struct modem_data *modem)
595 DBG("%s", modem->path);
597 modem->set_cm_powered = TRUE;
599 return set_property(modem, modem->path,
601 "Powered", DBUS_TYPE_BOOLEAN,
602 &modem->set_cm_powered,
603 cm_set_powered_reply);
606 static int modem_set_powered(struct modem_data *modem)
608 DBG("%s", modem->path);
610 modem->set_powered = TRUE;
612 return set_property(modem, modem->path,
613 OFONO_MODEM_INTERFACE,
614 "Powered", DBUS_TYPE_BOOLEAN,
619 static int modem_set_unpowered(struct modem_data *modem)
621 DBG("%s", modem->path);
623 modem->set_powered = FALSE;
625 return set_property(modem, modem->path,
626 OFONO_MODEM_INTERFACE,
627 "Powered", DBUS_TYPE_BOOLEAN,
632 static connman_bool_t has_interface(uint8_t interfaces,
635 if ((interfaces & api) == api)
641 static uint8_t extract_interfaces(DBusMessageIter *array)
643 DBusMessageIter entry;
644 uint8_t interfaces = 0;
646 dbus_message_iter_recurse(array, &entry);
648 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
651 dbus_message_iter_get_basic(&entry, &name);
653 if (g_str_equal(name, OFONO_SIM_INTERFACE) == TRUE)
654 interfaces |= OFONO_API_SIM;
655 else if (g_str_equal(name, OFONO_NETREG_INTERFACE) == TRUE)
656 interfaces |= OFONO_API_NETREG;
657 else if (g_str_equal(name, OFONO_CM_INTERFACE) == TRUE)
658 interfaces |= OFONO_API_CM;
659 else if (g_str_equal(name, OFONO_CDMA_CM_INTERFACE) == TRUE)
660 interfaces |= OFONO_API_CDMA_CM;
661 else if (g_str_equal(name, OFONO_CDMA_NETREG_INTERFACE) == TRUE)
662 interfaces |= OFONO_API_CDMA_NETREG;
664 dbus_message_iter_next(&entry);
670 static char *extract_nameservers(DBusMessageIter *array)
672 DBusMessageIter entry;
673 char *nameservers = NULL;
676 dbus_message_iter_recurse(array, &entry);
678 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
679 const char *nameserver;
681 dbus_message_iter_get_basic(&entry, &nameserver);
683 if (nameservers == NULL) {
684 nameservers = g_strdup(nameserver);
687 nameservers = g_strdup_printf("%s %s", tmp, nameserver);
691 dbus_message_iter_next(&entry);
697 static void extract_ipv4_settings(DBusMessageIter *array,
698 struct network_context *context)
700 DBusMessageIter dict;
701 char *address = NULL, *netmask = NULL, *gateway = NULL;
702 char *nameservers = NULL;
703 const char *interface = NULL;
706 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
709 dbus_message_iter_recurse(array, &dict);
711 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
712 DBusMessageIter entry, value;
713 const char *key, *val;
715 dbus_message_iter_recurse(&dict, &entry);
716 dbus_message_iter_get_basic(&entry, &key);
718 dbus_message_iter_next(&entry);
719 dbus_message_iter_recurse(&entry, &value);
721 if (g_str_equal(key, "Interface") == TRUE) {
722 dbus_message_iter_get_basic(&value, &interface);
724 DBG("Interface %s", interface);
726 index = connman_inet_ifindex(interface);
728 DBG("index %d", index);
729 } else if (g_str_equal(key, "Method") == TRUE) {
730 dbus_message_iter_get_basic(&value, &val);
732 DBG("Method %s", val);
734 if (g_strcmp0(val, "static") == 0) {
735 context->ipv4_method = CONNMAN_IPCONFIG_METHOD_FIXED;
736 } else if (g_strcmp0(val, "dhcp") == 0) {
737 context->ipv4_method = CONNMAN_IPCONFIG_METHOD_DHCP;
740 } else if (g_str_equal(key, "Address") == TRUE) {
741 dbus_message_iter_get_basic(&value, &val);
743 address = g_strdup(val);
745 DBG("Address %s", address);
746 } else if (g_str_equal(key, "Netmask") == TRUE) {
747 dbus_message_iter_get_basic(&value, &val);
749 netmask = g_strdup(val);
751 DBG("Netmask %s", netmask);
752 } else if (g_str_equal(key, "DomainNameServers") == TRUE) {
753 nameservers = extract_nameservers(&value);
755 DBG("Nameservers %s", nameservers);
756 } else if (g_str_equal(key, "Gateway") == TRUE) {
757 dbus_message_iter_get_basic(&value, &val);
759 gateway = g_strdup(val);
761 DBG("Gateway %s", gateway);
764 dbus_message_iter_next(&dict);
770 if (context->ipv4_method != CONNMAN_IPCONFIG_METHOD_FIXED)
773 context->ipv4_address = connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4);
774 if (context->ipv4_address == NULL)
777 context->index = index;
778 connman_ipaddress_set_ipv4(context->ipv4_address, address,
781 context->ipv4_nameservers = nameservers;
784 if (context->ipv4_nameservers != nameservers)
792 static void extract_ipv6_settings(DBusMessageIter *array,
793 struct network_context *context)
795 DBusMessageIter dict;
796 char *address = NULL, *gateway = NULL;
797 unsigned char prefix_length;
798 char *nameservers = NULL;
799 const char *interface = NULL;
802 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
805 dbus_message_iter_recurse(array, &dict);
807 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
808 DBusMessageIter entry, value;
809 const char *key, *val;
811 dbus_message_iter_recurse(&dict, &entry);
812 dbus_message_iter_get_basic(&entry, &key);
814 dbus_message_iter_next(&entry);
815 dbus_message_iter_recurse(&entry, &value);
817 if (g_str_equal(key, "Interface") == TRUE) {
818 dbus_message_iter_get_basic(&value, &interface);
820 DBG("Interface %s", interface);
822 index = connman_inet_ifindex(interface);
824 DBG("index %d", index);
825 } else if (g_str_equal(key, "Address") == TRUE) {
826 dbus_message_iter_get_basic(&value, &val);
828 address = g_strdup(val);
830 DBG("Address %s", address);
831 } else if (g_str_equal(key, "PrefixLength") == TRUE) {
832 dbus_message_iter_get_basic(&value, &prefix_length);
834 DBG("prefix length %d", prefix_length);
835 } else if (g_str_equal(key, "DomainNameServers") == TRUE) {
836 nameservers = extract_nameservers(&value);
838 DBG("Nameservers %s", nameservers);
839 } else if (g_str_equal(key, "Gateway") == TRUE) {
840 dbus_message_iter_get_basic(&value, &val);
842 gateway = g_strdup(val);
844 DBG("Gateway %s", gateway);
847 dbus_message_iter_next(&dict);
853 context->ipv6_method = CONNMAN_IPCONFIG_METHOD_FIXED;
855 context->ipv6_address =
856 connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6);
857 if (context->ipv6_address == NULL)
860 context->index = index;
861 connman_ipaddress_set_ipv6(context->ipv6_address, address,
862 prefix_length, gateway);
864 context->ipv6_nameservers = nameservers;
867 if (context->ipv6_nameservers != nameservers)
874 static connman_bool_t ready_to_create_device(struct modem_data *modem)
877 * There are three different modem types which behave slightly
879 * - GSM modems will expose the SIM interface then the
881 * - DUN modems will expose first a unique serial number (BDADDR)
882 * and then the CM interface.
883 * - CDMA modems will expose CM first and sometime later
884 * a unique serial number.
886 * This functions tests if we have the necessary information gathered
887 * before we are able to create a device.
890 if (modem->device != NULL)
893 if (modem->imsi != NULL || modem->serial != NULL)
899 static void create_device(struct modem_data *modem)
901 struct connman_device *device;
902 char *uninitialized_var(ident);
904 DBG("%s", modem->path);
906 if (modem->imsi != NULL)
908 else if (modem->serial != NULL)
909 ident = modem->serial;
911 if (connman_dbus_validate_ident(ident) == FALSE)
912 ident = connman_dbus_encode_string(ident);
914 ident = g_strdup(ident);
916 device = connman_device_create(ident, CONNMAN_DEVICE_TYPE_CELLULAR);
920 DBG("device %p", device);
922 connman_device_set_ident(device, ident);
924 connman_device_set_string(device, "Path", modem->path);
926 connman_device_set_data(device, modem);
928 if (connman_device_register(device) < 0) {
929 connman_error("Failed to register cellular device");
930 connman_device_unref(device);
934 modem->device = device;
940 static void destroy_device(struct modem_data *modem)
942 DBG("%s", modem->path);
944 connman_device_set_powered(modem->device, FALSE);
946 if (modem->network != NULL) {
947 connman_device_remove_network(modem->device, modem->network);
948 connman_network_unref(modem->network);
949 modem->network = NULL;
952 connman_device_unregister(modem->device);
953 connman_device_unref(modem->device);
955 modem->device = NULL;
958 static void add_network(struct modem_data *modem)
962 DBG("%s", modem->path);
964 if (modem->network != NULL)
967 modem->network = connman_network_create(modem->context->path,
968 CONNMAN_NETWORK_TYPE_CELLULAR);
969 if (modem->network == NULL)
972 DBG("network %p", modem->network);
974 connman_network_set_data(modem->network, modem);
976 connman_network_set_string(modem->network, "Path",
977 modem->context->path);
979 connman_network_set_index(modem->network, modem->context->index);
981 if (modem->name != NULL)
982 connman_network_set_name(modem->network, modem->name);
984 connman_network_set_name(modem->network, "");
986 connman_network_set_strength(modem->network, modem->strength);
988 group = get_ident(modem->context->path);
989 connman_network_set_group(modem->network, group);
991 connman_network_set_available(modem->network, TRUE);
993 connman_network_set_bool(modem->network, "Roaming",
996 if (connman_device_add_network(modem->device, modem->network) < 0) {
997 connman_network_unref(modem->network);
998 modem->network = NULL;
1003 static int add_cm_context(struct modem_data *modem, const char *context_path,
1004 DBusMessageIter *dict)
1006 const char *context_type;
1007 struct network_context *context = NULL;
1008 connman_bool_t active = FALSE;
1010 DBG("%s context path %s", modem->path, context_path);
1012 if (modem->context != NULL) {
1014 * We have already assigned a context to this modem
1015 * and we do only support one Internet context.
1020 context = network_context_alloc(context_path);
1021 if (context == NULL)
1024 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1025 DBusMessageIter entry, value;
1028 dbus_message_iter_recurse(dict, &entry);
1029 dbus_message_iter_get_basic(&entry, &key);
1031 dbus_message_iter_next(&entry);
1032 dbus_message_iter_recurse(&entry, &value);
1034 if (g_str_equal(key, "Type") == TRUE) {
1035 dbus_message_iter_get_basic(&value, &context_type);
1037 DBG("%s context %s type %s", modem->path,
1038 context_path, context_type);
1039 } else if (g_str_equal(key, "Settings") == TRUE) {
1040 DBG("%s Settings", modem->path);
1042 extract_ipv4_settings(&value, context);
1043 } else if (g_str_equal(key, "IPv6.Settings") == TRUE) {
1044 DBG("%s IPv6.Settings", modem->path);
1046 extract_ipv6_settings(&value, context);
1047 } else if (g_str_equal(key, "Active") == TRUE) {
1048 dbus_message_iter_get_basic(&value, &active);
1050 DBG("%s Active %d", modem->path, active);
1053 dbus_message_iter_next(dict);
1056 if (g_strcmp0(context_type, "internet") != 0) {
1057 network_context_free(context);
1061 modem->context = context;
1062 modem->active = active;
1064 g_hash_table_replace(context_hash, g_strdup(context_path), modem);
1069 static void remove_cm_context(struct modem_data *modem,
1070 const char *context_path)
1072 if (modem->context == NULL)
1075 g_hash_table_remove(context_hash, context_path);
1077 network_context_free(modem->context);
1078 modem->context = NULL;
1081 static gboolean context_changed(DBusConnection *connection,
1082 DBusMessage *message,
1085 const char *context_path = dbus_message_get_path(message);
1086 struct modem_data *modem = NULL;
1087 DBusMessageIter iter, value;
1090 DBG("context_path %s", context_path);
1092 modem = g_hash_table_lookup(context_hash, context_path);
1096 if (dbus_message_iter_init(message, &iter) == FALSE)
1099 dbus_message_iter_get_basic(&iter, &key);
1101 dbus_message_iter_next(&iter);
1102 dbus_message_iter_recurse(&iter, &value);
1105 * oFono guarantees the ordering of Settings and
1106 * Active. Settings will always be send before Active = True.
1107 * That means we don't have to order here.
1109 if (g_str_equal(key, "Settings") == TRUE) {
1110 DBG("%s Settings", modem->path);
1112 extract_ipv4_settings(&value, modem->context);
1113 } else if (g_str_equal(key, "IPv6.Settings") == TRUE) {
1114 DBG("%s IPv6.Settings", modem->path);
1116 extract_ipv6_settings(&value, modem->context);
1117 } else if (g_str_equal(key, "Active") == TRUE) {
1118 dbus_message_iter_get_basic(&value, &modem->active);
1120 DBG("%s Active %d", modem->path, modem->active);
1122 if (modem->active == TRUE)
1123 set_connected(modem);
1125 set_disconnected(modem);
1131 static void cm_get_contexts_reply(DBusPendingCall *call, void *user_data)
1133 struct modem_data *modem = user_data;
1134 DBusMessageIter array, dict, entry, value;
1138 DBG("%s", modem->path);
1140 modem->call_get_contexts = NULL;
1142 reply = dbus_pending_call_steal_reply(call);
1144 dbus_error_init(&error);
1146 if (dbus_set_error_from_message(&error, reply) == TRUE) {
1147 connman_error("%s", error.message);
1148 dbus_error_free(&error);
1152 if (dbus_message_iter_init(reply, &array) == FALSE)
1155 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
1158 dbus_message_iter_recurse(&array, &dict);
1160 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT) {
1161 const char *context_path;
1163 dbus_message_iter_recurse(&dict, &entry);
1164 dbus_message_iter_get_basic(&entry, &context_path);
1166 dbus_message_iter_next(&entry);
1167 dbus_message_iter_recurse(&entry, &value);
1169 if (add_cm_context(modem, context_path, &value) == 0)
1172 dbus_message_iter_next(&dict);
1176 dbus_message_unref(reply);
1178 dbus_pending_call_unref(call);
1181 static int cm_get_contexts(struct modem_data *modem)
1183 DBusMessage *message;
1185 DBG("%s", modem->path);
1187 if (modem->call_get_contexts != NULL)
1190 message = dbus_message_new_method_call(OFONO_SERVICE, modem->path,
1191 OFONO_CM_INTERFACE, GET_CONTEXTS);
1192 if (message == NULL)
1195 if (dbus_connection_send_with_reply(connection, message,
1196 &modem->call_get_contexts, TIMEOUT) == FALSE) {
1197 connman_error("Failed to call GetContexts()");
1198 dbus_message_unref(message);
1202 if (modem->call_get_contexts == NULL) {
1203 connman_error("D-Bus connection not available");
1204 dbus_message_unref(message);
1208 dbus_pending_call_set_notify(modem->call_get_contexts,
1209 cm_get_contexts_reply,
1212 dbus_message_unref(message);
1214 return -EINPROGRESS;
1217 static gboolean cm_context_added(DBusConnection *connection,
1218 DBusMessage *message,
1221 const char *path = dbus_message_get_path(message);
1223 struct modem_data *modem;
1224 DBusMessageIter iter, properties;
1228 modem = g_hash_table_lookup(modem_hash, context_path);
1232 if (dbus_message_iter_init(message, &iter) == FALSE)
1235 dbus_message_iter_get_basic(&iter, &context_path);
1237 dbus_message_iter_next(&iter);
1238 dbus_message_iter_recurse(&iter, &properties);
1240 if (add_cm_context(modem, context_path, &properties) != 0)
1246 static gboolean cm_context_removed(DBusConnection *connection,
1247 DBusMessage *message,
1250 const char *path = dbus_message_get_path(message);
1251 const char *context_path;
1252 struct modem_data *modem;
1253 DBusMessageIter iter;
1255 DBG("context path %s", path);
1257 if (dbus_message_iter_init(message, &iter) == FALSE)
1260 dbus_message_iter_get_basic(&iter, &context_path);
1262 modem = g_hash_table_lookup(context_hash, context_path);
1266 remove_cm_context(modem, context_path);
1271 static void netreg_update_name(struct modem_data *modem,
1272 DBusMessageIter* value)
1276 dbus_message_iter_get_basic(value, &name);
1278 DBG("%s Name %s", modem->path, name);
1280 g_free(modem->name);
1281 modem->name = g_strdup(name);
1283 if (modem->network == NULL)
1286 connman_network_set_name(modem->network, modem->name);
1287 connman_network_update(modem->network);
1290 static void netreg_update_strength(struct modem_data *modem,
1291 DBusMessageIter *value)
1293 dbus_message_iter_get_basic(value, &modem->strength);
1295 DBG("%s Strength %d", modem->path, modem->strength);
1297 if (modem->network == NULL)
1302 * We don't have 2 signal notifications we always report the strength
1303 * signal. data_strength is always equal to 0.
1306 * In the case we have a data_strength signal (from 1xEVDO network)
1307 * we don't need to update the value with strength signal (from 1xCDMA)
1308 * because the modem is registered to 1xEVDO network for data call.
1309 * In case we have no data_strength signal (not registered to 1xEVDO
1310 * network), we must report the strength signal (registered to 1xCDMA
1311 * network e.g slow mode).
1313 if (modem->data_strength != 0)
1316 connman_network_set_strength(modem->network, modem->strength);
1317 connman_network_update(modem->network);
1320 /* Retrieve 1xEVDO Data Strength signal */
1321 static void netreg_update_datastrength(struct modem_data *modem,
1322 DBusMessageIter *value)
1324 dbus_message_iter_get_basic(value, &modem->data_strength);
1326 DBG("%s Data Strength %d", modem->path, modem->data_strength);
1328 if (modem->network == NULL)
1332 * CDMA modem is not registered to 1xEVDO network, let
1333 * update_signal_strength() reporting the value on the Strength signal
1336 if (modem->data_strength == 0)
1339 connman_network_set_strength(modem->network, modem->data_strength);
1340 connman_network_update(modem->network);
1343 static void netreg_update_roaming(struct modem_data *modem,
1344 DBusMessageIter *value)
1347 connman_bool_t roaming;
1349 dbus_message_iter_get_basic(value, &status);
1351 if (g_str_equal(status, "roaming") == TRUE)
1356 if (roaming == modem->roaming)
1359 modem->roaming = roaming;
1361 if (modem->network == NULL)
1364 connman_network_set_bool(modem->network,
1365 "Roaming", modem->roaming);
1366 connman_network_update(modem->network);
1369 static void netreg_update_regdom(struct modem_data *modem,
1370 DBusMessageIter *value)
1372 char *mobile_country_code;
1376 dbus_message_iter_get_basic(value, &mobile_country_code);
1378 DBG("%s MobileContryCode %s", modem->path, mobile_country_code);
1381 mcc = atoi(mobile_country_code);
1385 alpha2 = mcc_country_codes[mcc - 200];
1386 connman_technology_set_regdom(alpha2);
1389 static gboolean netreg_changed(DBusConnection *connection, DBusMessage *message,
1392 const char *path = dbus_message_get_path(message);
1393 struct modem_data *modem;
1394 DBusMessageIter iter, value;
1397 modem = g_hash_table_lookup(modem_hash, path);
1401 if (modem->ignore == TRUE)
1404 if (dbus_message_iter_init(message, &iter) == FALSE)
1407 dbus_message_iter_get_basic(&iter, &key);
1409 dbus_message_iter_next(&iter);
1410 dbus_message_iter_recurse(&iter, &value);
1412 if (g_str_equal(key, "Name") == TRUE)
1413 netreg_update_name(modem, &value);
1414 else if (g_str_equal(key, "Strength") == TRUE)
1415 netreg_update_strength(modem, &value);
1416 else if (g_str_equal(key, "Status") == TRUE)
1417 netreg_update_roaming(modem, &value);
1418 else if (g_str_equal(key, "MobileCountryCode") == TRUE)
1419 netreg_update_regdom(modem, &value);
1424 static void netreg_properties_reply(struct modem_data *modem,
1425 DBusMessageIter *dict)
1427 DBG("%s", modem->path);
1429 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1430 DBusMessageIter entry, value;
1433 dbus_message_iter_recurse(dict, &entry);
1434 dbus_message_iter_get_basic(&entry, &key);
1436 dbus_message_iter_next(&entry);
1437 dbus_message_iter_recurse(&entry, &value);
1439 if (g_str_equal(key, "Name") == TRUE)
1440 netreg_update_name(modem, &value);
1441 else if (g_str_equal(key, "Strength") == TRUE)
1442 netreg_update_strength(modem, &value);
1443 else if (g_str_equal(key, "Status") == TRUE)
1444 netreg_update_roaming(modem, &value);
1445 else if (g_str_equal(key, "MobileCountryCode") == TRUE)
1446 netreg_update_regdom(modem, &value);
1448 dbus_message_iter_next(dict);
1451 if (modem->context == NULL) {
1453 * netgreg_get_properties() was issued after we got
1454 * cm_get_contexts_reply() where we create the
1455 * context. Though before we got the
1456 * netreg_properties_reply the context was removed
1457 * again. Therefore we have to skip the network
1465 if (modem->active == TRUE)
1466 set_connected(modem);
1469 static int netreg_get_properties(struct modem_data *modem)
1471 return get_properties(modem->path, OFONO_NETREG_INTERFACE,
1472 netreg_properties_reply, modem);
1475 static void add_cdma_network(struct modem_data *modem)
1477 /* Be sure that device is created before adding CDMA network */
1478 if (modem->device == NULL)
1482 * CDMA modems don't need contexts for data call, however the current
1483 * add_network() logic needs one, so we create one to proceed.
1485 if (modem->context == NULL)
1486 modem->context = network_context_alloc(modem->path);
1490 if (modem->cdma_cm_powered == TRUE)
1491 set_connected(modem);
1494 static gboolean cdma_netreg_changed(DBusConnection *connection,
1495 DBusMessage *message,
1498 const char *path = dbus_message_get_path(message);
1499 struct modem_data *modem;
1500 DBusMessageIter iter, value;
1505 modem = g_hash_table_lookup(modem_hash, path);
1509 if (modem->ignore == TRUE)
1512 if (dbus_message_iter_init(message, &iter) == FALSE)
1515 dbus_message_iter_get_basic(&iter, &key);
1517 dbus_message_iter_next(&iter);
1518 dbus_message_iter_recurse(&iter, &value);
1520 if (g_str_equal(key, "Name") == TRUE)
1521 netreg_update_name(modem, &value);
1522 else if (g_str_equal(key, "Strength") == TRUE)
1523 netreg_update_strength(modem, &value);
1524 else if (g_str_equal(key, "DataStrength") == TRUE)
1525 netreg_update_datastrength(modem, &value);
1526 else if (g_str_equal(key, "Status") == TRUE)
1527 netreg_update_roaming(modem, &value);
1529 add_cdma_network(modem);
1534 static void cdma_netreg_properties_reply(struct modem_data *modem,
1535 DBusMessageIter *dict)
1537 DBG("%s", modem->path);
1539 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1540 DBusMessageIter entry, value;
1543 dbus_message_iter_recurse(dict, &entry);
1544 dbus_message_iter_get_basic(&entry, &key);
1546 dbus_message_iter_next(&entry);
1547 dbus_message_iter_recurse(&entry, &value);
1549 if (g_str_equal(key, "Name") == TRUE)
1550 netreg_update_name(modem, &value);
1551 else if (g_str_equal(key, "Strength") == TRUE)
1552 netreg_update_strength(modem, &value);
1553 else if (g_str_equal(key, "DataStrength") == TRUE)
1554 netreg_update_datastrength(modem, &value);
1555 else if (g_str_equal(key, "Status") == TRUE)
1556 netreg_update_roaming(modem, &value);
1558 dbus_message_iter_next(dict);
1561 add_cdma_network(modem);
1564 static int cdma_netreg_get_properties(struct modem_data *modem)
1566 return get_properties(modem->path, OFONO_CDMA_NETREG_INTERFACE,
1567 cdma_netreg_properties_reply, modem);
1570 static void cm_update_attached(struct modem_data *modem,
1571 DBusMessageIter *value)
1573 dbus_message_iter_get_basic(value, &modem->attached);
1575 DBG("%s Attached %d", modem->path, modem->attached);
1577 if (modem->attached == FALSE)
1580 if (has_interface(modem->interfaces,
1581 OFONO_API_NETREG) == FALSE) {
1585 netreg_get_properties(modem);
1588 static void cm_update_powered(struct modem_data *modem,
1589 DBusMessageIter *value)
1591 dbus_message_iter_get_basic(value, &modem->cm_powered);
1593 DBG("%s ConnnectionManager Powered %d", modem->path,
1596 if (modem->cm_powered == TRUE)
1599 cm_set_powered(modem);
1602 static gboolean cm_changed(DBusConnection *connection, DBusMessage *message,
1605 const char *path = dbus_message_get_path(message);
1606 struct modem_data *modem;
1607 DBusMessageIter iter, value;
1610 modem = g_hash_table_lookup(modem_hash, path);
1614 if (modem->ignore == TRUE)
1617 if (dbus_message_iter_init(message, &iter) == FALSE)
1620 dbus_message_iter_get_basic(&iter, &key);
1622 dbus_message_iter_next(&iter);
1623 dbus_message_iter_recurse(&iter, &value);
1625 if (g_str_equal(key, "Attached") == TRUE)
1626 cm_update_attached(modem, &value);
1627 else if (g_str_equal(key, "Powered") == TRUE)
1628 cm_update_powered(modem, &value);
1633 static void cdma_cm_update_powered(struct modem_data *modem,
1634 DBusMessageIter *value)
1636 dbus_message_iter_get_basic(value, &modem->cdma_cm_powered);
1638 DBG("%s CDMA cm Powered %d", modem->path, modem->cdma_cm_powered);
1640 if (modem->network == NULL)
1643 if (modem->cdma_cm_powered == TRUE)
1644 set_connected(modem);
1646 set_disconnected(modem);
1649 static void cdma_cm_update_settings(struct modem_data *modem,
1650 DBusMessageIter *value)
1652 DBG("%s Settings", modem->path);
1654 if (modem->context != NULL)
1657 extract_ipv4_settings(value, modem->context);
1660 static gboolean cdma_cm_changed(DBusConnection *connection,
1661 DBusMessage *message, void *user_data)
1663 const char *path = dbus_message_get_path(message);
1664 struct modem_data *modem;
1665 DBusMessageIter iter, value;
1668 modem = g_hash_table_lookup(modem_hash, path);
1672 if (modem->online == TRUE && modem->network == NULL)
1673 cdma_netreg_get_properties(modem);
1675 if (dbus_message_iter_init(message, &iter) == FALSE)
1678 dbus_message_iter_get_basic(&iter, &key);
1680 dbus_message_iter_next(&iter);
1681 dbus_message_iter_recurse(&iter, &value);
1683 if (g_str_equal(key, "Powered") == TRUE)
1684 cdma_cm_update_powered(modem, &value);
1685 if (g_str_equal(key, "Settings") == TRUE)
1686 cdma_cm_update_settings(modem, &value);
1691 static void cm_properties_reply(struct modem_data *modem, DBusMessageIter *dict)
1693 DBG("%s", modem->path);
1695 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1696 DBusMessageIter entry, value;
1699 dbus_message_iter_recurse(dict, &entry);
1700 dbus_message_iter_get_basic(&entry, &key);
1702 dbus_message_iter_next(&entry);
1703 dbus_message_iter_recurse(&entry, &value);
1705 if (g_str_equal(key, "Attached") == TRUE)
1706 cm_update_attached(modem, &value);
1707 else if (g_str_equal(key, "Powered") == TRUE)
1708 cm_update_powered(modem, &value);
1710 dbus_message_iter_next(dict);
1714 static int cm_get_properties(struct modem_data *modem)
1716 return get_properties(modem->path, OFONO_CM_INTERFACE,
1717 cm_properties_reply, modem);
1720 static void cdma_cm_properties_reply(struct modem_data *modem,
1721 DBusMessageIter *dict)
1723 DBG("%s", modem->path);
1725 if (modem->online == TRUE)
1726 cdma_netreg_get_properties(modem);
1728 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1729 DBusMessageIter entry, value;
1732 dbus_message_iter_recurse(dict, &entry);
1733 dbus_message_iter_get_basic(&entry, &key);
1735 dbus_message_iter_next(&entry);
1736 dbus_message_iter_recurse(&entry, &value);
1738 if (g_str_equal(key, "Powered") == TRUE)
1739 cdma_cm_update_powered(modem, &value);
1740 if (g_str_equal(key, "Settings") == TRUE)
1741 cdma_cm_update_settings(modem, &value);
1743 dbus_message_iter_next(dict);
1747 static int cdma_cm_get_properties(struct modem_data *modem)
1749 return get_properties(modem->path, OFONO_CDMA_CM_INTERFACE,
1750 cdma_cm_properties_reply, modem);
1753 static connman_bool_t connection_manager_init(struct modem_data *modem)
1755 if (has_interface(modem->interfaces, OFONO_API_CM) == TRUE) {
1756 if (ready_to_create_device(modem) == TRUE)
1757 create_device(modem);
1759 if (modem->device != NULL) {
1760 cm_get_properties(modem);
1761 cm_get_contexts(modem);
1767 if (has_interface(modem->interfaces, OFONO_API_CDMA_CM) == TRUE) {
1768 if (ready_to_create_device(modem) == TRUE)
1769 create_device(modem);
1771 if (modem->device != NULL)
1772 cdma_cm_get_properties(modem);
1780 static void sim_update_imsi(struct modem_data *modem,
1781 DBusMessageIter* value)
1785 dbus_message_iter_get_basic(value, &imsi);
1787 DBG("%s imsi %s", modem->path, imsi);
1789 g_free(modem->imsi);
1790 modem->imsi = g_strdup(imsi);
1793 static gboolean sim_changed(DBusConnection *connection, DBusMessage *message,
1796 const char *path = dbus_message_get_path(message);
1797 struct modem_data *modem;
1798 DBusMessageIter iter, value;
1801 modem = g_hash_table_lookup(modem_hash, path);
1805 if (modem->ignore == TRUE)
1808 if (dbus_message_iter_init(message, &iter) == FALSE)
1811 dbus_message_iter_get_basic(&iter, &key);
1813 dbus_message_iter_next(&iter);
1814 dbus_message_iter_recurse(&iter, &value);
1816 if (g_str_equal(key, "SubscriberIdentity") == TRUE) {
1817 sim_update_imsi(modem, &value);
1819 if (modem->online == FALSE) {
1820 modem_set_online(modem, TRUE);
1821 } else if (has_interface(modem->interfaces,
1822 OFONO_API_CM) == TRUE) {
1823 if (ready_to_create_device(modem) == TRUE)
1824 create_device(modem);
1825 } else if (has_interface(modem->interfaces,
1826 OFONO_API_CDMA_CM) == TRUE) {
1827 if (ready_to_create_device(modem) == TRUE)
1828 create_device(modem);
1835 static void sim_properties_reply(struct modem_data *modem,
1836 DBusMessageIter *dict)
1838 DBG("%s", modem->path);
1840 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1841 DBusMessageIter entry, value;
1844 dbus_message_iter_recurse(dict, &entry);
1845 dbus_message_iter_get_basic(&entry, &key);
1847 dbus_message_iter_next(&entry);
1848 dbus_message_iter_recurse(&entry, &value);
1850 if (g_str_equal(key, "SubscriberIdentity") == TRUE) {
1851 sim_update_imsi(modem, &value);
1853 if (modem->online == FALSE) {
1854 modem_set_online(modem, TRUE);
1858 connection_manager_init(modem);
1863 dbus_message_iter_next(dict);
1867 static int sim_get_properties(struct modem_data *modem)
1869 return get_properties(modem->path, OFONO_SIM_INTERFACE,
1870 sim_properties_reply, modem);
1873 static gboolean modem_changed(DBusConnection *connection, DBusMessage *message,
1876 const char *path = dbus_message_get_path(message);
1877 struct modem_data *modem;
1878 DBusMessageIter iter, value;
1881 modem = g_hash_table_lookup(modem_hash, path);
1885 if (modem->ignore == TRUE)
1888 if (dbus_message_iter_init(message, &iter) == FALSE)
1891 dbus_message_iter_get_basic(&iter, &key);
1893 dbus_message_iter_next(&iter);
1894 dbus_message_iter_recurse(&iter, &value);
1896 if (g_str_equal(key, "Powered") == TRUE) {
1897 dbus_message_iter_get_basic(&value, &modem->powered);
1899 DBG("%s Powered %d", modem->path, modem->powered);
1901 if (modem->powered == FALSE)
1902 modem_set_powered(modem);
1903 } else if (g_str_equal(key, "Online") == TRUE) {
1904 dbus_message_iter_get_basic(&value, &modem->online);
1906 DBG("%s Online %d", modem->path, modem->online);
1908 if (modem->online == FALSE)
1911 connection_manager_init(modem);
1912 } else if (g_str_equal(key, "Interfaces") == TRUE) {
1913 modem->interfaces = extract_interfaces(&value);
1915 DBG("%s Interfaces 0x%02x", modem->path,
1918 if (has_interface(modem->interfaces, OFONO_API_SIM) == TRUE) {
1919 if (modem->imsi == NULL &&
1920 modem->set_powered == FALSE) {
1922 * Only use do GetProperties() when
1923 * device has not been powered up.
1925 sim_get_properties(modem);
1930 if (connection_manager_init(modem) == FALSE) {
1931 if (modem->context != NULL) {
1932 remove_cm_context(modem,
1933 modem->context->path);
1936 if (modem->device != NULL)
1937 destroy_device(modem);
1942 if (has_interface(modem->interfaces, OFONO_API_NETREG) == TRUE) {
1943 if (modem->attached == TRUE)
1944 netreg_get_properties(modem);
1945 } else if (has_interface(modem->interfaces,
1946 OFONO_API_CDMA_NETREG) == TRUE)
1947 cdma_netreg_get_properties(modem);
1948 } else if (g_str_equal(key, "Serial") == TRUE) {
1951 dbus_message_iter_get_basic(&value, &serial);
1953 g_free(modem->serial);
1954 modem->serial = g_strdup(serial);
1956 DBG("%s Serial %s", modem->path, modem->serial);
1958 connection_manager_init(modem);
1964 static void add_modem(const char *path, DBusMessageIter *prop)
1966 struct modem_data *modem;
1970 modem = g_hash_table_lookup(modem_hash, path);
1971 if (modem != NULL) {
1973 * When oFono powers up we ask for the modems and oFono is
1974 * reporting with modem_added signal the modems. Only
1980 modem = g_try_new0(struct modem_data, 1);
1984 modem->path = g_strdup(path);
1986 g_hash_table_insert(modem_hash, g_strdup(path), modem);
1988 while (dbus_message_iter_get_arg_type(prop) == DBUS_TYPE_DICT_ENTRY) {
1989 DBusMessageIter entry, value;
1992 dbus_message_iter_recurse(prop, &entry);
1993 dbus_message_iter_get_basic(&entry, &key);
1995 dbus_message_iter_next(&entry);
1996 dbus_message_iter_recurse(&entry, &value);
1998 if (g_str_equal(key, "Powered") == TRUE) {
1999 dbus_message_iter_get_basic(&value, &modem->powered);
2001 DBG("%s Powered %d", modem->path, modem->powered);
2002 } else if (g_str_equal(key, "Online") == TRUE) {
2003 dbus_message_iter_get_basic(&value, &modem->online);
2005 DBG("%s Online %d", modem->path, modem->online);
2006 } else if (g_str_equal(key, "Interfaces") == TRUE) {
2007 modem->interfaces = extract_interfaces(&value);
2009 DBG("%s Interfaces 0x%02x", modem->path,
2011 } else if (g_str_equal(key, "Serial") == TRUE) {
2014 dbus_message_iter_get_basic(&value, &serial);
2015 modem->serial = g_strdup(serial);
2017 DBG("%s Serial %s", modem->path, modem->serial);
2018 } else if (g_str_equal(key, "Type") == TRUE) {
2021 dbus_message_iter_get_basic(&value, &type);
2023 DBG("%s Type %s", modem->path, type);
2024 if (g_strcmp0(type, "hardware") != 0) {
2025 DBG("%s Ignore this modem", modem->path);
2026 modem->ignore = TRUE;
2030 dbus_message_iter_next(prop);
2033 if (modem->ignore == TRUE)
2036 if (modem->powered == FALSE)
2037 modem_set_powered(modem);
2038 else if (has_interface(modem->interfaces, OFONO_API_SIM) == TRUE)
2039 sim_get_properties(modem);
2041 connection_manager_init(modem);
2044 static void modem_power_down(gpointer key, gpointer value, gpointer user_data)
2046 struct modem_data *modem = value;
2048 DBG("%s", modem->path);
2050 if (modem->ignore == TRUE)
2053 modem_set_unpowered(modem);
2056 static void remove_modem(gpointer data)
2058 struct modem_data *modem = data;
2060 DBG("%s", modem->path);
2062 if (modem->call_set_property != NULL)
2063 dbus_pending_call_cancel(modem->call_set_property);
2065 if (modem->call_get_properties != NULL)
2066 dbus_pending_call_cancel(modem->call_get_properties);
2068 if (modem->call_get_contexts != NULL)
2069 dbus_pending_call_cancel(modem->call_get_contexts);
2071 if (modem->device != NULL)
2072 destroy_device(modem);
2074 if (modem->context != NULL)
2075 remove_cm_context(modem, modem->context->path);
2077 g_free(modem->serial);
2078 g_free(modem->name);
2079 g_free(modem->imsi);
2080 g_free(modem->path);
2085 static gboolean modem_added(DBusConnection *connection,
2086 DBusMessage *message, void *user_data)
2088 DBusMessageIter iter, properties;
2093 if (dbus_message_iter_init(message, &iter) == FALSE)
2096 dbus_message_iter_get_basic(&iter, &path);
2098 dbus_message_iter_next(&iter);
2099 dbus_message_iter_recurse(&iter, &properties);
2101 add_modem(path, &properties);
2106 static gboolean modem_removed(DBusConnection *connection,
2107 DBusMessage *message, void *user_data)
2109 DBusMessageIter iter;
2114 if (dbus_message_iter_init(message, &iter) == FALSE)
2117 dbus_message_iter_get_basic(&iter, &path);
2119 g_hash_table_remove(modem_hash, path);
2124 static void manager_get_modems_reply(DBusPendingCall *call, void *user_data)
2128 DBusMessageIter array, dict;
2132 reply = dbus_pending_call_steal_reply(call);
2134 dbus_error_init(&error);
2136 if (dbus_set_error_from_message(&error, reply) == TRUE) {
2137 connman_error("%s", error.message);
2138 dbus_error_free(&error);
2142 if (dbus_message_iter_init(reply, &array) == FALSE)
2145 dbus_message_iter_recurse(&array, &dict);
2147 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT) {
2148 DBusMessageIter value, properties;
2151 dbus_message_iter_recurse(&dict, &value);
2152 dbus_message_iter_get_basic(&value, &path);
2154 dbus_message_iter_next(&value);
2155 dbus_message_iter_recurse(&value, &properties);
2157 add_modem(path, &properties);
2159 dbus_message_iter_next(&dict);
2163 dbus_message_unref(reply);
2165 dbus_pending_call_unref(call);
2168 static int manager_get_modems(void)
2170 DBusMessage *message;
2171 DBusPendingCall *call;
2175 message = dbus_message_new_method_call(OFONO_SERVICE, "/",
2176 OFONO_MANAGER_INTERFACE, GET_MODEMS);
2177 if (message == NULL)
2180 if (dbus_connection_send_with_reply(connection, message,
2181 &call, TIMEOUT) == FALSE) {
2182 connman_error("Failed to call GetModems()");
2183 dbus_message_unref(message);
2188 connman_error("D-Bus connection not available");
2189 dbus_message_unref(message);
2193 dbus_pending_call_set_notify(call, manager_get_modems_reply,
2196 dbus_message_unref(message);
2198 return -EINPROGRESS;
2201 static void ofono_connect(DBusConnection *conn, void *user_data)
2205 modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2206 g_free, remove_modem);
2207 if (modem_hash == NULL)
2210 context_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2212 if (context_hash == NULL) {
2213 g_hash_table_destroy(modem_hash);
2217 manager_get_modems();
2220 static void ofono_disconnect(DBusConnection *conn, void *user_data)
2224 if (modem_hash == NULL || context_hash == NULL)
2227 g_hash_table_destroy(modem_hash);
2230 g_hash_table_destroy(context_hash);
2231 context_hash = NULL;
2234 static int network_probe(struct connman_network *network)
2236 struct modem_data *modem = connman_network_get_data(network);
2238 DBG("%s network %p", modem->path, network);
2243 static void network_remove(struct connman_network *network)
2245 struct modem_data *modem = connman_network_get_data(network);
2247 DBG("%s network %p", modem->path, network);
2250 static int network_connect(struct connman_network *network)
2252 struct modem_data *modem = connman_network_get_data(network);
2254 DBG("%s network %p", modem->path, network);
2256 if (has_interface(modem->interfaces, OFONO_API_CM) == TRUE)
2257 return context_set_active(modem, TRUE);
2258 else if (has_interface(modem->interfaces, OFONO_API_CDMA_CM) == TRUE)
2259 return cdma_cm_set_powered(modem, TRUE);
2261 connman_error("Connection manager interface not available");
2266 static int network_disconnect(struct connman_network *network)
2268 struct modem_data *modem = connman_network_get_data(network);
2270 DBG("%s network %p", modem->path, network);
2272 if (has_interface(modem->interfaces, OFONO_API_CM) == TRUE)
2273 return context_set_active(modem, FALSE);
2274 else if (has_interface(modem->interfaces, OFONO_API_CDMA_CM) == TRUE)
2275 return cdma_cm_set_powered(modem, FALSE);
2277 connman_error("Connection manager interface not available");
2282 static struct connman_network_driver network_driver = {
2284 .type = CONNMAN_NETWORK_TYPE_CELLULAR,
2285 .probe = network_probe,
2286 .remove = network_remove,
2287 .connect = network_connect,
2288 .disconnect = network_disconnect,
2291 static int modem_probe(struct connman_device *device)
2293 struct modem_data *modem = connman_device_get_data(device);
2295 DBG("%s device %p", modem->path, device);
2300 static void modem_remove(struct connman_device *device)
2302 struct modem_data *modem = connman_device_get_data(device);
2304 DBG("%s device %p", modem->path, device);
2307 static int modem_enable(struct connman_device *device)
2309 struct modem_data *modem = connman_device_get_data(device);
2311 DBG("%s device %p", modem->path, device);
2316 static int modem_disable(struct connman_device *device)
2318 struct modem_data *modem = connman_device_get_data(device);
2320 DBG("%s device %p", modem->path, device);
2325 static struct connman_device_driver modem_driver = {
2327 .type = CONNMAN_DEVICE_TYPE_CELLULAR,
2328 .probe = modem_probe,
2329 .remove = modem_remove,
2330 .enable = modem_enable,
2331 .disable = modem_disable,
2335 static guint modem_added_watch;
2336 static guint modem_removed_watch;
2337 static guint modem_watch;
2338 static guint cm_watch;
2339 static guint sim_watch;
2340 static guint context_added_watch;
2341 static guint context_removed_watch;
2342 static guint netreg_watch;
2343 static guint context_watch;
2344 static guint cdma_cm_watch;
2345 static guint cdma_netreg_watch;
2347 static int ofono_init(void)
2353 connection = connman_dbus_get_connection();
2354 if (connection == NULL)
2357 watch = g_dbus_add_service_watch(connection,
2358 OFONO_SERVICE, ofono_connect,
2359 ofono_disconnect, NULL, NULL);
2361 modem_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2362 OFONO_MANAGER_INTERFACE,
2367 modem_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2368 OFONO_MANAGER_INTERFACE,
2373 modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2374 OFONO_MODEM_INTERFACE,
2379 cm_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2385 sim_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2386 OFONO_SIM_INTERFACE,
2391 context_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2397 context_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2403 context_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2404 OFONO_CONTEXT_INTERFACE,
2409 netreg_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2410 OFONO_NETREG_INTERFACE,
2415 cdma_cm_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2416 OFONO_CDMA_CM_INTERFACE,
2421 cdma_netreg_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2422 OFONO_CDMA_NETREG_INTERFACE,
2424 cdma_netreg_changed,
2428 if (watch == 0 || modem_added_watch == 0 || modem_removed_watch == 0 ||
2429 modem_watch == 0 || cm_watch == 0 || sim_watch == 0 ||
2430 context_added_watch == 0 ||
2431 context_removed_watch == 0 ||
2432 context_watch == 0 || netreg_watch == 0 ||
2433 cdma_cm_watch == 0 || cdma_netreg_watch == 0) {
2438 err = connman_network_driver_register(&network_driver);
2442 err = connman_device_driver_register(&modem_driver);
2444 connman_network_driver_unregister(&network_driver);
2451 g_dbus_remove_watch(connection, cdma_netreg_watch);
2452 g_dbus_remove_watch(connection, cdma_cm_watch);
2453 g_dbus_remove_watch(connection, netreg_watch);
2454 g_dbus_remove_watch(connection, context_watch);
2455 g_dbus_remove_watch(connection, context_removed_watch);
2456 g_dbus_remove_watch(connection, context_added_watch);
2457 g_dbus_remove_watch(connection, sim_watch);
2458 g_dbus_remove_watch(connection, cm_watch);
2459 g_dbus_remove_watch(connection, modem_watch);
2460 g_dbus_remove_watch(connection, modem_removed_watch);
2461 g_dbus_remove_watch(connection, modem_added_watch);
2462 g_dbus_remove_watch(connection, watch);
2463 dbus_connection_unref(connection);
2468 static void ofono_exit(void)
2472 if (modem_hash != NULL) {
2474 * We should propably wait for the SetProperty() reply
2475 * message, because ...
2477 g_hash_table_foreach(modem_hash, modem_power_down, NULL);
2480 * ... here we will cancel the call.
2482 g_hash_table_destroy(modem_hash);
2486 if (context_hash != NULL) {
2487 g_hash_table_destroy(context_hash);
2488 context_hash = NULL;
2491 connman_device_driver_unregister(&modem_driver);
2492 connman_network_driver_unregister(&network_driver);
2494 g_dbus_remove_watch(connection, cdma_netreg_watch);
2495 g_dbus_remove_watch(connection, cdma_cm_watch);
2496 g_dbus_remove_watch(connection, netreg_watch);
2497 g_dbus_remove_watch(connection, context_watch);
2498 g_dbus_remove_watch(connection, context_removed_watch);
2499 g_dbus_remove_watch(connection, context_added_watch);
2500 g_dbus_remove_watch(connection, sim_watch);
2501 g_dbus_remove_watch(connection, cm_watch);
2502 g_dbus_remove_watch(connection, modem_watch);
2503 g_dbus_remove_watch(connection, modem_added_watch);
2504 g_dbus_remove_watch(connection, modem_removed_watch);
2505 g_dbus_remove_watch(connection, watch);
2507 dbus_connection_unref(connection);
2510 CONNMAN_PLUGIN_DEFINE(ofono, "oFono telephony plugin", VERSION,
2511 CONNMAN_PLUGIN_PRIORITY_DEFAULT, ofono_init, ofono_exit)