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 /* ConnectionContext Interface */
138 connman_bool_t active;
139 connman_bool_t set_active;
141 /* SimManager Interface */
144 /* Netreg Interface */
147 uint8_t data_strength; /* 1xEVDO signal strength */
148 connman_bool_t roaming;
151 DBusPendingCall *call_set_property;
152 DBusPendingCall *call_get_properties;
153 DBusPendingCall *call_get_contexts;
156 static char *get_ident(const char *path)
163 pos = strrchr(path, '/');
170 static struct network_context *network_context_alloc(const char *path)
172 struct network_context *context;
174 context = g_try_new0(struct network_context, 1);
178 context->path = g_strdup(path);
181 context->ipv4_method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
182 context->ipv4_address = NULL;
183 context->ipv4_nameservers = NULL;
185 context->ipv6_method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
186 context->ipv6_address = NULL;
187 context->ipv6_nameservers = NULL;
192 static void network_context_free(struct network_context *context)
194 g_free(context->path);
196 connman_ipaddress_free(context->ipv4_address);
197 g_free(context->ipv4_nameservers);
199 connman_ipaddress_free(context->ipv6_address);
200 g_free(context->ipv6_nameservers);
205 static void set_connected(struct modem_data *modem)
207 connman_bool_t setip = FALSE;
209 DBG("%s", modem->path);
211 connman_network_set_index(modem->network, modem->context->index);
213 switch (modem->context->ipv4_method) {
214 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
215 case CONNMAN_IPCONFIG_METHOD_OFF:
216 case CONNMAN_IPCONFIG_METHOD_MANUAL:
217 case CONNMAN_IPCONFIG_METHOD_AUTO:
220 case CONNMAN_IPCONFIG_METHOD_FIXED:
221 connman_network_set_ipv4_method(modem->network,
222 modem->context->ipv4_method);
223 connman_network_set_ipaddress(modem->network,
224 modem->context->ipv4_address);
225 connman_network_set_nameservers(modem->network,
226 modem->context->ipv4_nameservers);
230 case CONNMAN_IPCONFIG_METHOD_DHCP:
231 connman_network_set_ipv4_method(modem->network,
232 modem->context->ipv4_method);
237 switch (modem->context->ipv6_method) {
238 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
239 case CONNMAN_IPCONFIG_METHOD_OFF:
240 case CONNMAN_IPCONFIG_METHOD_MANUAL:
241 case CONNMAN_IPCONFIG_METHOD_DHCP:
242 case CONNMAN_IPCONFIG_METHOD_AUTO:
245 case CONNMAN_IPCONFIG_METHOD_FIXED:
246 connman_network_set_ipv6_method(modem->network,
247 modem->context->ipv6_method);
248 connman_network_set_ipaddress(modem->network,
249 modem->context->ipv6_address);
255 connman_network_set_connected(modem->network, TRUE);
258 static void set_disconnected(struct modem_data *modem)
260 DBG("%s", modem->path);
262 connman_network_set_connected(modem->network, FALSE);
265 typedef void (*set_property_cb)(struct modem_data *data,
266 connman_bool_t success);
267 typedef void (*get_properties_cb)(struct modem_data *data,
268 DBusMessageIter *dict);
270 struct property_info {
271 struct modem_data *modem;
273 const char *interface;
274 const char *property;
275 set_property_cb set_property_cb;
276 get_properties_cb get_properties_cb;
279 static void set_property_reply(DBusPendingCall *call, void *user_data)
281 struct property_info *info = user_data;
284 connman_bool_t success = TRUE;
286 DBG("%s path %s %s.%s", info->modem->path,
287 info->path, info->interface, info->property);
289 info->modem->call_set_property = NULL;
291 dbus_error_init(&error);
293 reply = dbus_pending_call_steal_reply(call);
295 if (dbus_set_error_from_message(&error, reply)) {
296 connman_error("Failed to change property: %s %s.%s: %s %s",
297 info->path, info->interface, info->property,
298 error.name, error.message);
299 dbus_error_free(&error);
303 if (info->set_property_cb != NULL)
304 (*info->set_property_cb)(info->modem, success);
306 dbus_message_unref(reply);
308 dbus_pending_call_unref(call);
311 static int set_property(struct modem_data *modem,
312 const char *path, const char *interface,
313 const char *property, int type, void *value,
314 set_property_cb notify)
316 DBusMessage *message;
317 DBusMessageIter iter;
318 struct property_info *info;
320 DBG("%s path %s %s.%s", modem->path, path, interface, property);
322 if (modem->call_set_property != NULL) {
323 connman_error("Pending SetProperty");
327 message = dbus_message_new_method_call(OFONO_SERVICE, path,
328 interface, SET_PROPERTY);
332 dbus_message_iter_init_append(message, &iter);
333 connman_dbus_property_append_basic(&iter, property, type, value);
335 if (dbus_connection_send_with_reply(connection, message,
336 &modem->call_set_property, TIMEOUT) == FALSE) {
337 connman_error("Failed to change property: %s %s.%s",
338 path, interface, property);
339 dbus_message_unref(message);
343 if (modem->call_set_property == NULL) {
344 connman_error("D-Bus connection not available");
345 dbus_message_unref(message);
349 info = g_try_new0(struct property_info, 1);
351 dbus_message_unref(message);
357 info->interface = interface;
358 info->property = property;
359 info->set_property_cb = notify;
361 dbus_pending_call_set_notify(modem->call_set_property,
362 set_property_reply, info, g_free);
364 dbus_message_unref(message);
369 static void get_properties_reply(DBusPendingCall *call, void *user_data)
371 struct property_info *info = user_data;
372 DBusMessageIter array, dict;
376 DBG("%s path %s %s", info->modem->path, info->path, info->interface);
378 info->modem->call_get_properties = NULL;
380 dbus_error_init(&error);
382 reply = dbus_pending_call_steal_reply(call);
384 if (dbus_set_error_from_message(&error, reply)) {
385 connman_error("Failed to get properties: %s %s: %s %s",
386 info->path, info->interface,
387 error.name, error.message);
388 dbus_error_free(&error);
393 if (dbus_message_iter_init(reply, &array) == FALSE)
396 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
399 dbus_message_iter_recurse(&array, &dict);
401 if (info->get_properties_cb != NULL)
402 (*info->get_properties_cb)(info->modem, &dict);
406 dbus_message_unref(reply);
408 dbus_pending_call_unref(call);
411 static int get_properties(const char *path, const char *interface,
412 get_properties_cb notify,
413 struct modem_data *modem)
415 DBusMessage *message;
416 struct property_info *info;
418 DBG("%s path %s %s", modem->path, path, interface);
420 if (modem->call_get_properties != NULL) {
421 connman_error("Pending GetProperties");
425 message = dbus_message_new_method_call(OFONO_SERVICE, path,
426 interface, GET_PROPERTIES);
430 if (dbus_connection_send_with_reply(connection, message,
431 &modem->call_get_properties, TIMEOUT) == FALSE) {
432 connman_error("Failed to call %s.GetProperties()", interface);
433 dbus_message_unref(message);
437 if (modem->call_get_properties == NULL) {
438 connman_error("D-Bus connection not available");
439 dbus_message_unref(message);
443 info = g_try_new0(struct property_info, 1);
445 dbus_message_unref(message);
451 info->interface = interface;
452 info->get_properties_cb = notify;
454 dbus_pending_call_set_notify(modem->call_get_properties,
455 get_properties_reply, info, g_free);
457 dbus_message_unref(message);
462 static void context_set_active_reply(struct modem_data *modem,
463 connman_bool_t success)
465 DBG("%s", modem->path);
467 if (success == TRUE) {
469 * Don't handle do anything on success here. oFono will send
470 * the change via PropertyChanged singal.
476 * Active = True might fail due a timeout. That means oFono
477 * still tries to go online. If we retry to set Active = True,
478 * we just get a InProgress error message. Should we power
479 * cycle the modem in such cases?
482 if (modem->network == NULL) {
484 * In the case where we power down the device
485 * we don't wait for the reply, therefore the network
486 * might already be gone.
491 connman_network_set_error(modem->network,
492 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
495 static int context_set_active(struct modem_data *modem,
496 connman_bool_t active)
500 DBG("%s active %d", modem->path, active);
502 err = set_property(modem, modem->context->path,
503 OFONO_CONTEXT_INTERFACE,
504 "Active", DBUS_TYPE_BOOLEAN,
506 context_set_active_reply);
508 if (active == FALSE && err == -EINPROGRESS)
514 static void cdma_cm_set_powered_reply(struct modem_data *modem,
515 connman_bool_t success)
517 DBG("%s", modem->path);
519 if (success == TRUE) {
521 * Don't handle do anything on success here. oFono will send
522 * the change via PropertyChanged singal.
528 * Powered = True might fail due a timeout. That means oFono
529 * still tries to go online. If we retry to set Powered = True,
530 * we just get a InProgress error message. Should we power
531 * cycle the modem in such cases?
534 if (modem->network == NULL) {
536 * In the case where we power down the device
537 * we don't wait for the reply, therefore the network
538 * might already be gone.
543 connman_network_set_error(modem->network,
544 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
547 static int cdma_cm_set_powered(struct modem_data *modem, connman_bool_t powered)
551 DBG("%s powered %d", modem->path, powered);
553 err = set_property(modem, modem->path, OFONO_CDMA_CM_INTERFACE,
554 "Powered", DBUS_TYPE_BOOLEAN,
556 cdma_cm_set_powered_reply);
558 if (powered == FALSE && err == -EINPROGRESS)
564 static int modem_set_online(struct modem_data *modem, connman_bool_t online)
566 DBG("%s online %d", modem->path, online);
568 return set_property(modem, modem->path,
569 OFONO_MODEM_INTERFACE,
570 "Online", DBUS_TYPE_BOOLEAN,
575 static int cm_set_powered(struct modem_data *modem, connman_bool_t powered)
579 DBG("%s powered %d", modem->path, powered);
581 err = set_property(modem, modem->path,
583 "Powered", DBUS_TYPE_BOOLEAN,
587 if (powered == FALSE && err == -EINPROGRESS)
593 static int modem_set_powered(struct modem_data *modem, connman_bool_t powered)
597 DBG("%s powered %d", modem->path, powered);
599 modem->set_powered = powered;
601 err = set_property(modem, modem->path,
602 OFONO_MODEM_INTERFACE,
603 "Powered", DBUS_TYPE_BOOLEAN,
607 if (powered == FALSE && err == -EINPROGRESS)
613 static connman_bool_t has_interface(uint8_t interfaces,
616 if ((interfaces & api) == api)
622 static uint8_t extract_interfaces(DBusMessageIter *array)
624 DBusMessageIter entry;
625 uint8_t interfaces = 0;
627 dbus_message_iter_recurse(array, &entry);
629 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
632 dbus_message_iter_get_basic(&entry, &name);
634 if (g_str_equal(name, OFONO_SIM_INTERFACE) == TRUE)
635 interfaces |= OFONO_API_SIM;
636 else if (g_str_equal(name, OFONO_NETREG_INTERFACE) == TRUE)
637 interfaces |= OFONO_API_NETREG;
638 else if (g_str_equal(name, OFONO_CM_INTERFACE) == TRUE)
639 interfaces |= OFONO_API_CM;
640 else if (g_str_equal(name, OFONO_CDMA_CM_INTERFACE) == TRUE)
641 interfaces |= OFONO_API_CDMA_CM;
642 else if (g_str_equal(name, OFONO_CDMA_NETREG_INTERFACE) == TRUE)
643 interfaces |= OFONO_API_CDMA_NETREG;
645 dbus_message_iter_next(&entry);
651 static char *extract_nameservers(DBusMessageIter *array)
653 DBusMessageIter entry;
654 char *nameservers = NULL;
657 dbus_message_iter_recurse(array, &entry);
659 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
660 const char *nameserver;
662 dbus_message_iter_get_basic(&entry, &nameserver);
664 if (nameservers == NULL) {
665 nameservers = g_strdup(nameserver);
668 nameservers = g_strdup_printf("%s %s", tmp, nameserver);
672 dbus_message_iter_next(&entry);
678 static void extract_ipv4_settings(DBusMessageIter *array,
679 struct network_context *context)
681 DBusMessageIter dict;
682 char *address = NULL, *netmask = NULL, *gateway = NULL;
683 char *nameservers = NULL;
684 const char *interface = NULL;
687 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
690 dbus_message_iter_recurse(array, &dict);
692 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
693 DBusMessageIter entry, value;
694 const char *key, *val;
696 dbus_message_iter_recurse(&dict, &entry);
697 dbus_message_iter_get_basic(&entry, &key);
699 dbus_message_iter_next(&entry);
700 dbus_message_iter_recurse(&entry, &value);
702 if (g_str_equal(key, "Interface") == TRUE) {
703 dbus_message_iter_get_basic(&value, &interface);
705 DBG("Interface %s", interface);
707 index = connman_inet_ifindex(interface);
709 DBG("index %d", index);
710 } else if (g_str_equal(key, "Method") == TRUE) {
711 dbus_message_iter_get_basic(&value, &val);
713 DBG("Method %s", val);
715 if (g_strcmp0(val, "static") == 0) {
716 context->ipv4_method = CONNMAN_IPCONFIG_METHOD_FIXED;
717 } else if (g_strcmp0(val, "dhcp") == 0) {
718 context->ipv4_method = CONNMAN_IPCONFIG_METHOD_DHCP;
721 } else if (g_str_equal(key, "Address") == TRUE) {
722 dbus_message_iter_get_basic(&value, &val);
724 address = g_strdup(val);
726 DBG("Address %s", address);
727 } else if (g_str_equal(key, "Netmask") == TRUE) {
728 dbus_message_iter_get_basic(&value, &val);
730 netmask = g_strdup(val);
732 DBG("Netmask %s", netmask);
733 } else if (g_str_equal(key, "DomainNameServers") == TRUE) {
734 nameservers = extract_nameservers(&value);
736 DBG("Nameservers %s", nameservers);
737 } else if (g_str_equal(key, "Gateway") == TRUE) {
738 dbus_message_iter_get_basic(&value, &val);
740 gateway = g_strdup(val);
742 DBG("Gateway %s", gateway);
745 dbus_message_iter_next(&dict);
751 if (context->ipv4_method != CONNMAN_IPCONFIG_METHOD_FIXED)
754 context->ipv4_address = connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4);
755 if (context->ipv4_address == NULL)
758 context->index = index;
759 connman_ipaddress_set_ipv4(context->ipv4_address, address,
762 context->ipv4_nameservers = nameservers;
765 if (context->ipv4_nameservers != nameservers)
773 static void extract_ipv6_settings(DBusMessageIter *array,
774 struct network_context *context)
776 DBusMessageIter dict;
777 char *address = NULL, *gateway = NULL;
778 unsigned char prefix_length;
779 char *nameservers = NULL;
780 const char *interface = NULL;
783 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
786 dbus_message_iter_recurse(array, &dict);
788 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
789 DBusMessageIter entry, value;
790 const char *key, *val;
792 dbus_message_iter_recurse(&dict, &entry);
793 dbus_message_iter_get_basic(&entry, &key);
795 dbus_message_iter_next(&entry);
796 dbus_message_iter_recurse(&entry, &value);
798 if (g_str_equal(key, "Interface") == TRUE) {
799 dbus_message_iter_get_basic(&value, &interface);
801 DBG("Interface %s", interface);
803 index = connman_inet_ifindex(interface);
805 DBG("index %d", index);
806 } else if (g_str_equal(key, "Address") == TRUE) {
807 dbus_message_iter_get_basic(&value, &val);
809 address = g_strdup(val);
811 DBG("Address %s", address);
812 } else if (g_str_equal(key, "PrefixLength") == TRUE) {
813 dbus_message_iter_get_basic(&value, &prefix_length);
815 DBG("prefix length %d", prefix_length);
816 } else if (g_str_equal(key, "DomainNameServers") == TRUE) {
817 nameservers = extract_nameservers(&value);
819 DBG("Nameservers %s", nameservers);
820 } else if (g_str_equal(key, "Gateway") == TRUE) {
821 dbus_message_iter_get_basic(&value, &val);
823 gateway = g_strdup(val);
825 DBG("Gateway %s", gateway);
828 dbus_message_iter_next(&dict);
834 context->ipv6_method = CONNMAN_IPCONFIG_METHOD_FIXED;
836 context->ipv6_address =
837 connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6);
838 if (context->ipv6_address == NULL)
841 context->index = index;
842 connman_ipaddress_set_ipv6(context->ipv6_address, address,
843 prefix_length, gateway);
845 context->ipv6_nameservers = nameservers;
848 if (context->ipv6_nameservers != nameservers)
855 static connman_bool_t ready_to_create_device(struct modem_data *modem)
858 * There are three different modem types which behave slightly
860 * - GSM modems will expose the SIM interface then the
862 * - DUN modems will expose first a unique serial number (BDADDR)
863 * and then the CM interface.
864 * - CDMA modems will expose CM first and sometime later
865 * a unique serial number.
867 * This functions tests if we have the necessary information gathered
868 * before we are able to create a device.
871 if (modem->device != NULL)
874 if (modem->imsi != NULL || modem->serial != NULL)
880 static void create_device(struct modem_data *modem)
882 struct connman_device *device;
883 char *uninitialized_var(ident);
885 DBG("%s", modem->path);
887 if (modem->imsi != NULL)
889 else if (modem->serial != NULL)
890 ident = modem->serial;
892 if (connman_dbus_validate_ident(ident) == FALSE)
893 ident = connman_dbus_encode_string(ident);
895 ident = g_strdup(ident);
897 device = connman_device_create(ident, CONNMAN_DEVICE_TYPE_CELLULAR);
901 DBG("device %p", device);
903 connman_device_set_ident(device, ident);
905 connman_device_set_string(device, "Path", modem->path);
907 connman_device_set_data(device, modem);
909 if (connman_device_register(device) < 0) {
910 connman_error("Failed to register cellular device");
911 connman_device_unref(device);
915 modem->device = device;
921 static void destroy_device(struct modem_data *modem)
923 DBG("%s", modem->path);
925 connman_device_set_powered(modem->device, FALSE);
927 if (modem->network != NULL) {
928 connman_device_remove_network(modem->device, modem->network);
929 connman_network_unref(modem->network);
930 modem->network = NULL;
933 connman_device_unregister(modem->device);
934 connman_device_unref(modem->device);
936 modem->device = NULL;
939 static void add_network(struct modem_data *modem)
943 DBG("%s", modem->path);
945 if (modem->network != NULL)
948 modem->network = connman_network_create(modem->context->path,
949 CONNMAN_NETWORK_TYPE_CELLULAR);
950 if (modem->network == NULL)
953 DBG("network %p", modem->network);
955 connman_network_set_data(modem->network, modem);
957 connman_network_set_string(modem->network, "Path",
958 modem->context->path);
960 connman_network_set_index(modem->network, modem->context->index);
962 if (modem->name != NULL)
963 connman_network_set_name(modem->network, modem->name);
965 connman_network_set_name(modem->network, "");
967 connman_network_set_strength(modem->network, modem->strength);
969 group = get_ident(modem->context->path);
970 connman_network_set_group(modem->network, group);
972 connman_network_set_available(modem->network, TRUE);
974 connman_network_set_bool(modem->network, "Roaming",
977 if (connman_device_add_network(modem->device, modem->network) < 0) {
978 connman_network_unref(modem->network);
979 modem->network = NULL;
984 static int add_cm_context(struct modem_data *modem, const char *context_path,
985 DBusMessageIter *dict)
987 const char *context_type;
988 struct network_context *context = NULL;
989 connman_bool_t active = FALSE;
991 DBG("%s context path %s", modem->path, context_path);
993 if (modem->context != NULL) {
995 * We have already assigned a context to this modem
996 * and we do only support one Internet context.
1001 context = network_context_alloc(context_path);
1002 if (context == NULL)
1005 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1006 DBusMessageIter entry, value;
1009 dbus_message_iter_recurse(dict, &entry);
1010 dbus_message_iter_get_basic(&entry, &key);
1012 dbus_message_iter_next(&entry);
1013 dbus_message_iter_recurse(&entry, &value);
1015 if (g_str_equal(key, "Type") == TRUE) {
1016 dbus_message_iter_get_basic(&value, &context_type);
1018 DBG("%s context %s type %s", modem->path,
1019 context_path, context_type);
1020 } else if (g_str_equal(key, "Settings") == TRUE) {
1021 DBG("%s Settings", modem->path);
1023 extract_ipv4_settings(&value, context);
1024 } else if (g_str_equal(key, "IPv6.Settings") == TRUE) {
1025 DBG("%s IPv6.Settings", modem->path);
1027 extract_ipv6_settings(&value, context);
1028 } else if (g_str_equal(key, "Active") == TRUE) {
1029 dbus_message_iter_get_basic(&value, &active);
1031 DBG("%s Active %d", modem->path, active);
1034 dbus_message_iter_next(dict);
1037 if (g_strcmp0(context_type, "internet") != 0) {
1038 network_context_free(context);
1042 modem->context = context;
1043 modem->active = active;
1045 g_hash_table_replace(context_hash, g_strdup(context_path), modem);
1050 static void remove_cm_context(struct modem_data *modem,
1051 const char *context_path)
1053 if (modem->context == NULL)
1056 g_hash_table_remove(context_hash, context_path);
1058 network_context_free(modem->context);
1059 modem->context = NULL;
1062 static gboolean context_changed(DBusConnection *connection,
1063 DBusMessage *message,
1066 const char *context_path = dbus_message_get_path(message);
1067 struct modem_data *modem = NULL;
1068 DBusMessageIter iter, value;
1071 DBG("context_path %s", context_path);
1073 modem = g_hash_table_lookup(context_hash, context_path);
1077 if (dbus_message_iter_init(message, &iter) == FALSE)
1080 dbus_message_iter_get_basic(&iter, &key);
1082 dbus_message_iter_next(&iter);
1083 dbus_message_iter_recurse(&iter, &value);
1086 * oFono guarantees the ordering of Settings and
1087 * Active. Settings will always be send before Active = True.
1088 * That means we don't have to order here.
1090 if (g_str_equal(key, "Settings") == TRUE) {
1091 DBG("%s Settings", modem->path);
1093 extract_ipv4_settings(&value, modem->context);
1094 } else if (g_str_equal(key, "IPv6.Settings") == TRUE) {
1095 DBG("%s IPv6.Settings", modem->path);
1097 extract_ipv6_settings(&value, modem->context);
1098 } else if (g_str_equal(key, "Active") == TRUE) {
1099 dbus_message_iter_get_basic(&value, &modem->active);
1101 DBG("%s Active %d", modem->path, modem->active);
1103 if (modem->active == TRUE)
1104 set_connected(modem);
1106 set_disconnected(modem);
1112 static void cm_get_contexts_reply(DBusPendingCall *call, void *user_data)
1114 struct modem_data *modem = user_data;
1115 DBusMessageIter array, dict, entry, value;
1119 DBG("%s", modem->path);
1121 modem->call_get_contexts = NULL;
1123 reply = dbus_pending_call_steal_reply(call);
1125 dbus_error_init(&error);
1127 if (dbus_set_error_from_message(&error, reply) == TRUE) {
1128 connman_error("%s", error.message);
1129 dbus_error_free(&error);
1133 if (dbus_message_iter_init(reply, &array) == FALSE)
1136 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
1139 dbus_message_iter_recurse(&array, &dict);
1141 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT) {
1142 const char *context_path;
1144 dbus_message_iter_recurse(&dict, &entry);
1145 dbus_message_iter_get_basic(&entry, &context_path);
1147 dbus_message_iter_next(&entry);
1148 dbus_message_iter_recurse(&entry, &value);
1150 if (add_cm_context(modem, context_path, &value) == 0)
1153 dbus_message_iter_next(&dict);
1157 dbus_message_unref(reply);
1159 dbus_pending_call_unref(call);
1162 static int cm_get_contexts(struct modem_data *modem)
1164 DBusMessage *message;
1166 DBG("%s", modem->path);
1168 if (modem->call_get_contexts != NULL)
1171 message = dbus_message_new_method_call(OFONO_SERVICE, modem->path,
1172 OFONO_CM_INTERFACE, GET_CONTEXTS);
1173 if (message == NULL)
1176 if (dbus_connection_send_with_reply(connection, message,
1177 &modem->call_get_contexts, TIMEOUT) == FALSE) {
1178 connman_error("Failed to call GetContexts()");
1179 dbus_message_unref(message);
1183 if (modem->call_get_contexts == NULL) {
1184 connman_error("D-Bus connection not available");
1185 dbus_message_unref(message);
1189 dbus_pending_call_set_notify(modem->call_get_contexts,
1190 cm_get_contexts_reply,
1193 dbus_message_unref(message);
1195 return -EINPROGRESS;
1198 static gboolean cm_context_added(DBusConnection *connection,
1199 DBusMessage *message,
1202 const char *path = dbus_message_get_path(message);
1204 struct modem_data *modem;
1205 DBusMessageIter iter, properties;
1209 modem = g_hash_table_lookup(modem_hash, context_path);
1213 if (dbus_message_iter_init(message, &iter) == FALSE)
1216 dbus_message_iter_get_basic(&iter, &context_path);
1218 dbus_message_iter_next(&iter);
1219 dbus_message_iter_recurse(&iter, &properties);
1221 if (add_cm_context(modem, context_path, &properties) != 0)
1227 static gboolean cm_context_removed(DBusConnection *connection,
1228 DBusMessage *message,
1231 const char *path = dbus_message_get_path(message);
1232 const char *context_path;
1233 struct modem_data *modem;
1234 DBusMessageIter iter;
1236 DBG("context path %s", path);
1238 if (dbus_message_iter_init(message, &iter) == FALSE)
1241 dbus_message_iter_get_basic(&iter, &context_path);
1243 modem = g_hash_table_lookup(context_hash, context_path);
1247 remove_cm_context(modem, context_path);
1252 static void netreg_update_name(struct modem_data *modem,
1253 DBusMessageIter* value)
1257 dbus_message_iter_get_basic(value, &name);
1259 DBG("%s Name %s", modem->path, name);
1261 g_free(modem->name);
1262 modem->name = g_strdup(name);
1264 if (modem->network == NULL)
1267 connman_network_set_name(modem->network, modem->name);
1268 connman_network_update(modem->network);
1271 static void netreg_update_strength(struct modem_data *modem,
1272 DBusMessageIter *value)
1274 dbus_message_iter_get_basic(value, &modem->strength);
1276 DBG("%s Strength %d", modem->path, modem->strength);
1278 if (modem->network == NULL)
1283 * We don't have 2 signal notifications we always report the strength
1284 * signal. data_strength is always equal to 0.
1287 * In the case we have a data_strength signal (from 1xEVDO network)
1288 * we don't need to update the value with strength signal (from 1xCDMA)
1289 * because the modem is registered to 1xEVDO network for data call.
1290 * In case we have no data_strength signal (not registered to 1xEVDO
1291 * network), we must report the strength signal (registered to 1xCDMA
1292 * network e.g slow mode).
1294 if (modem->data_strength != 0)
1297 connman_network_set_strength(modem->network, modem->strength);
1298 connman_network_update(modem->network);
1301 /* Retrieve 1xEVDO Data Strength signal */
1302 static void netreg_update_datastrength(struct modem_data *modem,
1303 DBusMessageIter *value)
1305 dbus_message_iter_get_basic(value, &modem->data_strength);
1307 DBG("%s Data Strength %d", modem->path, modem->data_strength);
1309 if (modem->network == NULL)
1313 * CDMA modem is not registered to 1xEVDO network, let
1314 * update_signal_strength() reporting the value on the Strength signal
1317 if (modem->data_strength == 0)
1320 connman_network_set_strength(modem->network, modem->data_strength);
1321 connman_network_update(modem->network);
1324 static void netreg_update_roaming(struct modem_data *modem,
1325 DBusMessageIter *value)
1328 connman_bool_t roaming;
1330 dbus_message_iter_get_basic(value, &status);
1332 if (g_str_equal(status, "roaming") == TRUE)
1337 if (roaming == modem->roaming)
1340 modem->roaming = roaming;
1342 if (modem->network == NULL)
1345 connman_network_set_bool(modem->network,
1346 "Roaming", modem->roaming);
1347 connman_network_update(modem->network);
1350 static void netreg_update_regdom(struct modem_data *modem,
1351 DBusMessageIter *value)
1353 char *mobile_country_code;
1357 dbus_message_iter_get_basic(value, &mobile_country_code);
1359 DBG("%s MobileContryCode %s", modem->path, mobile_country_code);
1362 mcc = atoi(mobile_country_code);
1366 alpha2 = mcc_country_codes[mcc - 200];
1367 connman_technology_set_regdom(alpha2);
1370 static gboolean netreg_changed(DBusConnection *connection, DBusMessage *message,
1373 const char *path = dbus_message_get_path(message);
1374 struct modem_data *modem;
1375 DBusMessageIter iter, value;
1378 modem = g_hash_table_lookup(modem_hash, path);
1382 if (modem->ignore == TRUE)
1385 if (dbus_message_iter_init(message, &iter) == FALSE)
1388 dbus_message_iter_get_basic(&iter, &key);
1390 dbus_message_iter_next(&iter);
1391 dbus_message_iter_recurse(&iter, &value);
1393 if (g_str_equal(key, "Name") == TRUE)
1394 netreg_update_name(modem, &value);
1395 else if (g_str_equal(key, "Strength") == TRUE)
1396 netreg_update_strength(modem, &value);
1397 else if (g_str_equal(key, "Status") == TRUE)
1398 netreg_update_roaming(modem, &value);
1399 else if (g_str_equal(key, "MobileCountryCode") == TRUE)
1400 netreg_update_regdom(modem, &value);
1405 static void netreg_properties_reply(struct modem_data *modem,
1406 DBusMessageIter *dict)
1408 DBG("%s", modem->path);
1410 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1411 DBusMessageIter entry, value;
1414 dbus_message_iter_recurse(dict, &entry);
1415 dbus_message_iter_get_basic(&entry, &key);
1417 dbus_message_iter_next(&entry);
1418 dbus_message_iter_recurse(&entry, &value);
1420 if (g_str_equal(key, "Name") == TRUE)
1421 netreg_update_name(modem, &value);
1422 else if (g_str_equal(key, "Strength") == TRUE)
1423 netreg_update_strength(modem, &value);
1424 else if (g_str_equal(key, "Status") == TRUE)
1425 netreg_update_roaming(modem, &value);
1426 else if (g_str_equal(key, "MobileCountryCode") == TRUE)
1427 netreg_update_regdom(modem, &value);
1429 dbus_message_iter_next(dict);
1432 if (modem->context == NULL) {
1434 * netgreg_get_properties() was issued after we got
1435 * cm_get_contexts_reply() where we create the
1436 * context. Though before we got the
1437 * netreg_properties_reply the context was removed
1438 * again. Therefore we have to skip the network
1446 if (modem->active == TRUE)
1447 set_connected(modem);
1450 static int netreg_get_properties(struct modem_data *modem)
1452 return get_properties(modem->path, OFONO_NETREG_INTERFACE,
1453 netreg_properties_reply, modem);
1456 static void add_cdma_network(struct modem_data *modem)
1458 /* Be sure that device is created before adding CDMA network */
1459 if (modem->device == NULL)
1463 * CDMA modems don't need contexts for data call, however the current
1464 * add_network() logic needs one, so we create one to proceed.
1466 if (modem->context == NULL)
1467 modem->context = network_context_alloc(modem->path);
1471 if (modem->cdma_cm_powered == TRUE)
1472 set_connected(modem);
1475 static gboolean cdma_netreg_changed(DBusConnection *connection,
1476 DBusMessage *message,
1479 const char *path = dbus_message_get_path(message);
1480 struct modem_data *modem;
1481 DBusMessageIter iter, value;
1486 modem = g_hash_table_lookup(modem_hash, path);
1490 if (modem->ignore == TRUE)
1493 if (dbus_message_iter_init(message, &iter) == FALSE)
1496 dbus_message_iter_get_basic(&iter, &key);
1498 dbus_message_iter_next(&iter);
1499 dbus_message_iter_recurse(&iter, &value);
1501 if (g_str_equal(key, "Name") == TRUE)
1502 netreg_update_name(modem, &value);
1503 else if (g_str_equal(key, "Strength") == TRUE)
1504 netreg_update_strength(modem, &value);
1505 else if (g_str_equal(key, "DataStrength") == TRUE)
1506 netreg_update_datastrength(modem, &value);
1507 else if (g_str_equal(key, "Status") == TRUE)
1508 netreg_update_roaming(modem, &value);
1510 add_cdma_network(modem);
1515 static void cdma_netreg_properties_reply(struct modem_data *modem,
1516 DBusMessageIter *dict)
1518 DBG("%s", modem->path);
1520 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1521 DBusMessageIter entry, value;
1524 dbus_message_iter_recurse(dict, &entry);
1525 dbus_message_iter_get_basic(&entry, &key);
1527 dbus_message_iter_next(&entry);
1528 dbus_message_iter_recurse(&entry, &value);
1530 if (g_str_equal(key, "Name") == TRUE)
1531 netreg_update_name(modem, &value);
1532 else if (g_str_equal(key, "Strength") == TRUE)
1533 netreg_update_strength(modem, &value);
1534 else if (g_str_equal(key, "DataStrength") == TRUE)
1535 netreg_update_datastrength(modem, &value);
1536 else if (g_str_equal(key, "Status") == TRUE)
1537 netreg_update_roaming(modem, &value);
1539 dbus_message_iter_next(dict);
1542 add_cdma_network(modem);
1545 static int cdma_netreg_get_properties(struct modem_data *modem)
1547 return get_properties(modem->path, OFONO_CDMA_NETREG_INTERFACE,
1548 cdma_netreg_properties_reply, modem);
1551 static void cm_update_attached(struct modem_data *modem,
1552 DBusMessageIter *value)
1554 dbus_message_iter_get_basic(value, &modem->attached);
1556 DBG("%s Attached %d", modem->path, modem->attached);
1558 if (modem->attached == FALSE)
1561 if (has_interface(modem->interfaces,
1562 OFONO_API_NETREG) == FALSE) {
1566 netreg_get_properties(modem);
1569 static void cm_update_powered(struct modem_data *modem,
1570 DBusMessageIter *value)
1572 dbus_message_iter_get_basic(value, &modem->cm_powered);
1574 DBG("%s ConnnectionManager Powered %d", modem->path,
1577 if (modem->cm_powered == TRUE)
1580 cm_set_powered(modem, TRUE);
1583 static gboolean cm_changed(DBusConnection *connection, DBusMessage *message,
1586 const char *path = dbus_message_get_path(message);
1587 struct modem_data *modem;
1588 DBusMessageIter iter, value;
1591 modem = g_hash_table_lookup(modem_hash, path);
1595 if (modem->ignore == TRUE)
1598 if (dbus_message_iter_init(message, &iter) == FALSE)
1601 dbus_message_iter_get_basic(&iter, &key);
1603 dbus_message_iter_next(&iter);
1604 dbus_message_iter_recurse(&iter, &value);
1606 if (g_str_equal(key, "Attached") == TRUE)
1607 cm_update_attached(modem, &value);
1608 else if (g_str_equal(key, "Powered") == TRUE)
1609 cm_update_powered(modem, &value);
1614 static void cdma_cm_update_powered(struct modem_data *modem,
1615 DBusMessageIter *value)
1617 dbus_message_iter_get_basic(value, &modem->cdma_cm_powered);
1619 DBG("%s CDMA cm Powered %d", modem->path, modem->cdma_cm_powered);
1621 if (modem->network == NULL)
1624 if (modem->cdma_cm_powered == TRUE)
1625 set_connected(modem);
1627 set_disconnected(modem);
1630 static void cdma_cm_update_settings(struct modem_data *modem,
1631 DBusMessageIter *value)
1633 DBG("%s Settings", modem->path);
1635 if (modem->context != NULL)
1638 extract_ipv4_settings(value, modem->context);
1641 static gboolean cdma_cm_changed(DBusConnection *connection,
1642 DBusMessage *message, void *user_data)
1644 const char *path = dbus_message_get_path(message);
1645 struct modem_data *modem;
1646 DBusMessageIter iter, value;
1649 modem = g_hash_table_lookup(modem_hash, path);
1653 if (modem->online == TRUE && modem->network == NULL)
1654 cdma_netreg_get_properties(modem);
1656 if (dbus_message_iter_init(message, &iter) == FALSE)
1659 dbus_message_iter_get_basic(&iter, &key);
1661 dbus_message_iter_next(&iter);
1662 dbus_message_iter_recurse(&iter, &value);
1664 if (g_str_equal(key, "Powered") == TRUE)
1665 cdma_cm_update_powered(modem, &value);
1666 if (g_str_equal(key, "Settings") == TRUE)
1667 cdma_cm_update_settings(modem, &value);
1672 static void cm_properties_reply(struct modem_data *modem, DBusMessageIter *dict)
1674 DBG("%s", modem->path);
1676 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1677 DBusMessageIter entry, value;
1680 dbus_message_iter_recurse(dict, &entry);
1681 dbus_message_iter_get_basic(&entry, &key);
1683 dbus_message_iter_next(&entry);
1684 dbus_message_iter_recurse(&entry, &value);
1686 if (g_str_equal(key, "Attached") == TRUE)
1687 cm_update_attached(modem, &value);
1688 else if (g_str_equal(key, "Powered") == TRUE)
1689 cm_update_powered(modem, &value);
1691 dbus_message_iter_next(dict);
1695 static int cm_get_properties(struct modem_data *modem)
1697 return get_properties(modem->path, OFONO_CM_INTERFACE,
1698 cm_properties_reply, modem);
1701 static void cdma_cm_properties_reply(struct modem_data *modem,
1702 DBusMessageIter *dict)
1704 DBG("%s", modem->path);
1706 if (modem->online == TRUE)
1707 cdma_netreg_get_properties(modem);
1709 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1710 DBusMessageIter entry, value;
1713 dbus_message_iter_recurse(dict, &entry);
1714 dbus_message_iter_get_basic(&entry, &key);
1716 dbus_message_iter_next(&entry);
1717 dbus_message_iter_recurse(&entry, &value);
1719 if (g_str_equal(key, "Powered") == TRUE)
1720 cdma_cm_update_powered(modem, &value);
1721 if (g_str_equal(key, "Settings") == TRUE)
1722 cdma_cm_update_settings(modem, &value);
1724 dbus_message_iter_next(dict);
1728 static int cdma_cm_get_properties(struct modem_data *modem)
1730 return get_properties(modem->path, OFONO_CDMA_CM_INTERFACE,
1731 cdma_cm_properties_reply, modem);
1734 static connman_bool_t connection_manager_init(struct modem_data *modem)
1736 if (has_interface(modem->interfaces, OFONO_API_CM) == TRUE) {
1737 if (ready_to_create_device(modem) == TRUE)
1738 create_device(modem);
1740 if (modem->device != NULL) {
1741 cm_get_properties(modem);
1742 cm_get_contexts(modem);
1748 if (has_interface(modem->interfaces, OFONO_API_CDMA_CM) == TRUE) {
1749 if (ready_to_create_device(modem) == TRUE)
1750 create_device(modem);
1752 if (modem->device != NULL)
1753 cdma_cm_get_properties(modem);
1761 static void sim_update_imsi(struct modem_data *modem,
1762 DBusMessageIter* value)
1766 dbus_message_iter_get_basic(value, &imsi);
1768 DBG("%s imsi %s", modem->path, imsi);
1770 g_free(modem->imsi);
1771 modem->imsi = g_strdup(imsi);
1774 static gboolean sim_changed(DBusConnection *connection, DBusMessage *message,
1777 const char *path = dbus_message_get_path(message);
1778 struct modem_data *modem;
1779 DBusMessageIter iter, value;
1782 modem = g_hash_table_lookup(modem_hash, path);
1786 if (modem->ignore == TRUE)
1789 if (dbus_message_iter_init(message, &iter) == FALSE)
1792 dbus_message_iter_get_basic(&iter, &key);
1794 dbus_message_iter_next(&iter);
1795 dbus_message_iter_recurse(&iter, &value);
1797 if (g_str_equal(key, "SubscriberIdentity") == TRUE) {
1798 sim_update_imsi(modem, &value);
1800 if (modem->online == FALSE) {
1801 modem_set_online(modem, TRUE);
1802 } else if (has_interface(modem->interfaces,
1803 OFONO_API_CM) == TRUE) {
1804 if (ready_to_create_device(modem) == TRUE)
1805 create_device(modem);
1806 } else if (has_interface(modem->interfaces,
1807 OFONO_API_CDMA_CM) == TRUE) {
1808 if (ready_to_create_device(modem) == TRUE)
1809 create_device(modem);
1816 static void sim_properties_reply(struct modem_data *modem,
1817 DBusMessageIter *dict)
1819 DBG("%s", modem->path);
1821 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1822 DBusMessageIter entry, value;
1825 dbus_message_iter_recurse(dict, &entry);
1826 dbus_message_iter_get_basic(&entry, &key);
1828 dbus_message_iter_next(&entry);
1829 dbus_message_iter_recurse(&entry, &value);
1831 if (g_str_equal(key, "SubscriberIdentity") == TRUE) {
1832 sim_update_imsi(modem, &value);
1834 if (modem->online == FALSE) {
1835 modem_set_online(modem, TRUE);
1839 connection_manager_init(modem);
1844 dbus_message_iter_next(dict);
1848 static int sim_get_properties(struct modem_data *modem)
1850 return get_properties(modem->path, OFONO_SIM_INTERFACE,
1851 sim_properties_reply, modem);
1854 static gboolean modem_changed(DBusConnection *connection, DBusMessage *message,
1857 const char *path = dbus_message_get_path(message);
1858 struct modem_data *modem;
1859 DBusMessageIter iter, value;
1862 modem = g_hash_table_lookup(modem_hash, path);
1866 if (modem->ignore == TRUE)
1869 if (dbus_message_iter_init(message, &iter) == FALSE)
1872 dbus_message_iter_get_basic(&iter, &key);
1874 dbus_message_iter_next(&iter);
1875 dbus_message_iter_recurse(&iter, &value);
1877 if (g_str_equal(key, "Powered") == TRUE) {
1878 dbus_message_iter_get_basic(&value, &modem->powered);
1880 DBG("%s Powered %d", modem->path, modem->powered);
1882 if (modem->powered == FALSE)
1883 modem_set_powered(modem, TRUE);
1884 } else if (g_str_equal(key, "Online") == TRUE) {
1885 dbus_message_iter_get_basic(&value, &modem->online);
1887 DBG("%s Online %d", modem->path, modem->online);
1889 if (modem->online == FALSE)
1892 connection_manager_init(modem);
1893 } else if (g_str_equal(key, "Interfaces") == TRUE) {
1894 modem->interfaces = extract_interfaces(&value);
1896 DBG("%s Interfaces 0x%02x", modem->path,
1899 if (has_interface(modem->interfaces, OFONO_API_SIM) == TRUE) {
1900 if (modem->imsi == NULL &&
1901 modem->set_powered == FALSE) {
1903 * Only use do GetProperties() when
1904 * device has not been powered up.
1906 sim_get_properties(modem);
1911 if (connection_manager_init(modem) == FALSE) {
1912 if (modem->context != NULL) {
1913 remove_cm_context(modem,
1914 modem->context->path);
1917 if (modem->device != NULL)
1918 destroy_device(modem);
1923 if (has_interface(modem->interfaces, OFONO_API_NETREG) == TRUE) {
1924 if (modem->attached == TRUE)
1925 netreg_get_properties(modem);
1926 } else if (has_interface(modem->interfaces,
1927 OFONO_API_CDMA_NETREG) == TRUE)
1928 cdma_netreg_get_properties(modem);
1929 } else if (g_str_equal(key, "Serial") == TRUE) {
1932 dbus_message_iter_get_basic(&value, &serial);
1934 g_free(modem->serial);
1935 modem->serial = g_strdup(serial);
1937 DBG("%s Serial %s", modem->path, modem->serial);
1939 connection_manager_init(modem);
1945 static void add_modem(const char *path, DBusMessageIter *prop)
1947 struct modem_data *modem;
1951 modem = g_hash_table_lookup(modem_hash, path);
1952 if (modem != NULL) {
1954 * When oFono powers up we ask for the modems and oFono is
1955 * reporting with modem_added signal the modems. Only
1961 modem = g_try_new0(struct modem_data, 1);
1965 modem->path = g_strdup(path);
1967 g_hash_table_insert(modem_hash, g_strdup(path), modem);
1969 while (dbus_message_iter_get_arg_type(prop) == DBUS_TYPE_DICT_ENTRY) {
1970 DBusMessageIter entry, value;
1973 dbus_message_iter_recurse(prop, &entry);
1974 dbus_message_iter_get_basic(&entry, &key);
1976 dbus_message_iter_next(&entry);
1977 dbus_message_iter_recurse(&entry, &value);
1979 if (g_str_equal(key, "Powered") == TRUE) {
1980 dbus_message_iter_get_basic(&value, &modem->powered);
1982 DBG("%s Powered %d", modem->path, modem->powered);
1983 } else if (g_str_equal(key, "Online") == TRUE) {
1984 dbus_message_iter_get_basic(&value, &modem->online);
1986 DBG("%s Online %d", modem->path, modem->online);
1987 } else if (g_str_equal(key, "Interfaces") == TRUE) {
1988 modem->interfaces = extract_interfaces(&value);
1990 DBG("%s Interfaces 0x%02x", modem->path,
1992 } else if (g_str_equal(key, "Serial") == TRUE) {
1995 dbus_message_iter_get_basic(&value, &serial);
1996 modem->serial = g_strdup(serial);
1998 DBG("%s Serial %s", modem->path, modem->serial);
1999 } else if (g_str_equal(key, "Type") == TRUE) {
2002 dbus_message_iter_get_basic(&value, &type);
2004 DBG("%s Type %s", modem->path, type);
2005 if (g_strcmp0(type, "hardware") != 0) {
2006 DBG("%s Ignore this modem", modem->path);
2007 modem->ignore = TRUE;
2011 dbus_message_iter_next(prop);
2014 if (modem->ignore == TRUE)
2017 if (modem->powered == FALSE)
2018 modem_set_powered(modem, TRUE);
2019 else if (has_interface(modem->interfaces, OFONO_API_SIM) == TRUE)
2020 sim_get_properties(modem);
2022 connection_manager_init(modem);
2025 static void modem_power_down(gpointer key, gpointer value, gpointer user_data)
2027 struct modem_data *modem = value;
2029 DBG("%s", modem->path);
2031 if (modem->ignore == TRUE)
2034 modem_set_powered(modem, FALSE);
2037 static void remove_modem(gpointer data)
2039 struct modem_data *modem = data;
2041 DBG("%s", modem->path);
2043 if (modem->call_set_property != NULL)
2044 dbus_pending_call_cancel(modem->call_set_property);
2046 if (modem->call_get_properties != NULL)
2047 dbus_pending_call_cancel(modem->call_get_properties);
2049 if (modem->call_get_contexts != NULL)
2050 dbus_pending_call_cancel(modem->call_get_contexts);
2052 if (modem->device != NULL)
2053 destroy_device(modem);
2055 if (modem->context != NULL)
2056 remove_cm_context(modem, modem->context->path);
2058 g_free(modem->serial);
2059 g_free(modem->name);
2060 g_free(modem->imsi);
2061 g_free(modem->path);
2066 static gboolean modem_added(DBusConnection *connection,
2067 DBusMessage *message, void *user_data)
2069 DBusMessageIter iter, properties;
2074 if (dbus_message_iter_init(message, &iter) == FALSE)
2077 dbus_message_iter_get_basic(&iter, &path);
2079 dbus_message_iter_next(&iter);
2080 dbus_message_iter_recurse(&iter, &properties);
2082 add_modem(path, &properties);
2087 static gboolean modem_removed(DBusConnection *connection,
2088 DBusMessage *message, void *user_data)
2090 DBusMessageIter iter;
2095 if (dbus_message_iter_init(message, &iter) == FALSE)
2098 dbus_message_iter_get_basic(&iter, &path);
2100 g_hash_table_remove(modem_hash, path);
2105 static void manager_get_modems_reply(DBusPendingCall *call, void *user_data)
2109 DBusMessageIter array, dict;
2113 reply = dbus_pending_call_steal_reply(call);
2115 dbus_error_init(&error);
2117 if (dbus_set_error_from_message(&error, reply) == TRUE) {
2118 connman_error("%s", error.message);
2119 dbus_error_free(&error);
2123 if (dbus_message_iter_init(reply, &array) == FALSE)
2126 dbus_message_iter_recurse(&array, &dict);
2128 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT) {
2129 DBusMessageIter value, properties;
2132 dbus_message_iter_recurse(&dict, &value);
2133 dbus_message_iter_get_basic(&value, &path);
2135 dbus_message_iter_next(&value);
2136 dbus_message_iter_recurse(&value, &properties);
2138 add_modem(path, &properties);
2140 dbus_message_iter_next(&dict);
2144 dbus_message_unref(reply);
2146 dbus_pending_call_unref(call);
2149 static int manager_get_modems(void)
2151 DBusMessage *message;
2152 DBusPendingCall *call;
2156 message = dbus_message_new_method_call(OFONO_SERVICE, "/",
2157 OFONO_MANAGER_INTERFACE, GET_MODEMS);
2158 if (message == NULL)
2161 if (dbus_connection_send_with_reply(connection, message,
2162 &call, TIMEOUT) == FALSE) {
2163 connman_error("Failed to call GetModems()");
2164 dbus_message_unref(message);
2169 connman_error("D-Bus connection not available");
2170 dbus_message_unref(message);
2174 dbus_pending_call_set_notify(call, manager_get_modems_reply,
2177 dbus_message_unref(message);
2179 return -EINPROGRESS;
2182 static void ofono_connect(DBusConnection *conn, void *user_data)
2186 modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2187 g_free, remove_modem);
2188 if (modem_hash == NULL)
2191 context_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2193 if (context_hash == NULL) {
2194 g_hash_table_destroy(modem_hash);
2198 manager_get_modems();
2201 static void ofono_disconnect(DBusConnection *conn, void *user_data)
2205 if (modem_hash == NULL || context_hash == NULL)
2208 g_hash_table_destroy(modem_hash);
2211 g_hash_table_destroy(context_hash);
2212 context_hash = NULL;
2215 static int network_probe(struct connman_network *network)
2217 struct modem_data *modem = connman_network_get_data(network);
2219 DBG("%s network %p", modem->path, network);
2224 static void network_remove(struct connman_network *network)
2226 struct modem_data *modem = connman_network_get_data(network);
2228 DBG("%s network %p", modem->path, network);
2231 static int network_connect(struct connman_network *network)
2233 struct modem_data *modem = connman_network_get_data(network);
2235 DBG("%s network %p", modem->path, network);
2237 if (has_interface(modem->interfaces, OFONO_API_CM) == TRUE)
2238 return context_set_active(modem, TRUE);
2239 else if (has_interface(modem->interfaces, OFONO_API_CDMA_CM) == TRUE)
2240 return cdma_cm_set_powered(modem, TRUE);
2242 connman_error("Connection manager interface not available");
2247 static int network_disconnect(struct connman_network *network)
2249 struct modem_data *modem = connman_network_get_data(network);
2251 DBG("%s network %p", modem->path, network);
2253 if (has_interface(modem->interfaces, OFONO_API_CM) == TRUE)
2254 return context_set_active(modem, FALSE);
2255 else if (has_interface(modem->interfaces, OFONO_API_CDMA_CM) == TRUE)
2256 return cdma_cm_set_powered(modem, FALSE);
2258 connman_error("Connection manager interface not available");
2263 static struct connman_network_driver network_driver = {
2265 .type = CONNMAN_NETWORK_TYPE_CELLULAR,
2266 .probe = network_probe,
2267 .remove = network_remove,
2268 .connect = network_connect,
2269 .disconnect = network_disconnect,
2272 static int modem_probe(struct connman_device *device)
2274 struct modem_data *modem = connman_device_get_data(device);
2276 DBG("%s device %p", modem->path, device);
2281 static void modem_remove(struct connman_device *device)
2283 struct modem_data *modem = connman_device_get_data(device);
2285 DBG("%s device %p", modem->path, device);
2288 static int modem_enable(struct connman_device *device)
2290 struct modem_data *modem = connman_device_get_data(device);
2292 DBG("%s device %p", modem->path, device);
2297 static int modem_disable(struct connman_device *device)
2299 struct modem_data *modem = connman_device_get_data(device);
2301 DBG("%s device %p", modem->path, device);
2306 static struct connman_device_driver modem_driver = {
2308 .type = CONNMAN_DEVICE_TYPE_CELLULAR,
2309 .probe = modem_probe,
2310 .remove = modem_remove,
2311 .enable = modem_enable,
2312 .disable = modem_disable,
2316 static guint modem_added_watch;
2317 static guint modem_removed_watch;
2318 static guint modem_watch;
2319 static guint cm_watch;
2320 static guint sim_watch;
2321 static guint context_added_watch;
2322 static guint context_removed_watch;
2323 static guint netreg_watch;
2324 static guint context_watch;
2325 static guint cdma_cm_watch;
2326 static guint cdma_netreg_watch;
2328 static int ofono_init(void)
2334 connection = connman_dbus_get_connection();
2335 if (connection == NULL)
2338 watch = g_dbus_add_service_watch(connection,
2339 OFONO_SERVICE, ofono_connect,
2340 ofono_disconnect, NULL, NULL);
2342 modem_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2343 OFONO_MANAGER_INTERFACE,
2348 modem_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2349 OFONO_MANAGER_INTERFACE,
2354 modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2355 OFONO_MODEM_INTERFACE,
2360 cm_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2366 sim_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2367 OFONO_SIM_INTERFACE,
2372 context_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2378 context_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2384 context_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2385 OFONO_CONTEXT_INTERFACE,
2390 netreg_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2391 OFONO_NETREG_INTERFACE,
2396 cdma_cm_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2397 OFONO_CDMA_CM_INTERFACE,
2402 cdma_netreg_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2403 OFONO_CDMA_NETREG_INTERFACE,
2405 cdma_netreg_changed,
2409 if (watch == 0 || modem_added_watch == 0 || modem_removed_watch == 0 ||
2410 modem_watch == 0 || cm_watch == 0 || sim_watch == 0 ||
2411 context_added_watch == 0 ||
2412 context_removed_watch == 0 ||
2413 context_watch == 0 || netreg_watch == 0 ||
2414 cdma_cm_watch == 0 || cdma_netreg_watch == 0) {
2419 err = connman_network_driver_register(&network_driver);
2423 err = connman_device_driver_register(&modem_driver);
2425 connman_network_driver_unregister(&network_driver);
2432 g_dbus_remove_watch(connection, cdma_netreg_watch);
2433 g_dbus_remove_watch(connection, cdma_cm_watch);
2434 g_dbus_remove_watch(connection, netreg_watch);
2435 g_dbus_remove_watch(connection, context_watch);
2436 g_dbus_remove_watch(connection, context_removed_watch);
2437 g_dbus_remove_watch(connection, context_added_watch);
2438 g_dbus_remove_watch(connection, sim_watch);
2439 g_dbus_remove_watch(connection, cm_watch);
2440 g_dbus_remove_watch(connection, modem_watch);
2441 g_dbus_remove_watch(connection, modem_removed_watch);
2442 g_dbus_remove_watch(connection, modem_added_watch);
2443 g_dbus_remove_watch(connection, watch);
2444 dbus_connection_unref(connection);
2449 static void ofono_exit(void)
2453 if (modem_hash != NULL) {
2455 * We should propably wait for the SetProperty() reply
2456 * message, because ...
2458 g_hash_table_foreach(modem_hash, modem_power_down, NULL);
2461 * ... here we will cancel the call.
2463 g_hash_table_destroy(modem_hash);
2467 if (context_hash != NULL) {
2468 g_hash_table_destroy(context_hash);
2469 context_hash = NULL;
2472 connman_device_driver_unregister(&modem_driver);
2473 connman_network_driver_unregister(&network_driver);
2475 g_dbus_remove_watch(connection, cdma_netreg_watch);
2476 g_dbus_remove_watch(connection, cdma_cm_watch);
2477 g_dbus_remove_watch(connection, netreg_watch);
2478 g_dbus_remove_watch(connection, context_watch);
2479 g_dbus_remove_watch(connection, context_removed_watch);
2480 g_dbus_remove_watch(connection, context_added_watch);
2481 g_dbus_remove_watch(connection, sim_watch);
2482 g_dbus_remove_watch(connection, cm_watch);
2483 g_dbus_remove_watch(connection, modem_watch);
2484 g_dbus_remove_watch(connection, modem_added_watch);
2485 g_dbus_remove_watch(connection, modem_removed_watch);
2486 g_dbus_remove_watch(connection, watch);
2488 dbus_connection_unref(connection);
2491 CONNMAN_PLUGIN_DEFINE(ofono, "oFono telephony plugin", VERSION,
2492 CONNMAN_PLUGIN_PRIORITY_DEFAULT, ofono_init, ofono_exit)