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 * Depending on the modem type, this plugin will behave differently.
90 * When a new modem appears, the plugin always powers it up. This
91 * allows the plugin to create a connman_device. The core will call
92 * modem_enable() if the technology is enabled. modem_enable() will
93 * then set the modem online. If the technology is disabled then
94 * modem_disable() will just set the modem offline. The modem is
95 * always kept powered all the time.
97 * After setting the modem online the plugin waits for the
98 * ConnectionManager and ConnectionContext to appear. When the context
99 * signals that it is attached and the NetworkRegistration interface
100 * appears, a new Service will be created and registered at the core.
102 * When asked to connect to the network (network_connect()) the plugin
103 * will set the Active property on the context. If this operation is
104 * successful the modem is connected to the network. oFono will inform
105 * the plugin about IP configuration through the updating the context's
110 * When a new modem appears, the plugin always powers it up. This
111 * allows the plugin to create connman_device either using IMSI either
112 * using modem Serial if the modem got a SIM interface or not.
114 * As for GSM, the core will call modem_enable() if the technology
115 * is enabled. modem_enable() will then set the modem online.
116 * If the technology is disabled then modem_disable() will just set the
117 * modem offline. The modem is always kept powered all the time.
119 * After setting the modem online the plugin waits for CdmaConnectionManager
120 * interface to appear. Then, once CdmaNetworkRegistration appears, a new
121 * Service will be created and registered at the core.
123 * When asked to connect to the network (network_connect()) the plugin
124 * will power up the CdmaConnectionManager interface.
125 * If the operation is successful the modem is connected to the network.
126 * oFono will inform the plugin about IP configuration through the
127 * updating CdmaConnectionManager settings properties.
130 static DBusConnection *connection;
132 static GHashTable *modem_hash;
133 static GHashTable *context_hash;
135 struct network_context {
139 enum connman_ipconfig_method ipv4_method;
140 struct connman_ipaddress *ipv4_address;
141 char *ipv4_nameservers;
143 enum connman_ipconfig_method ipv6_method;
144 struct connman_ipaddress *ipv6_address;
145 char *ipv6_nameservers;
151 struct connman_device *device;
152 struct connman_network *network;
154 struct network_context *context;
156 /* Modem Interface */
158 connman_bool_t powered;
159 connman_bool_t online;
161 connman_bool_t ignore;
163 connman_bool_t set_powered;
165 /* CDMA ConnectionManager Interface */
166 connman_bool_t cdma_cm_powered;
168 /* ConnectionManager Interface */
169 connman_bool_t attached;
170 connman_bool_t cm_powered;
172 /* ConnectionContext Interface */
173 connman_bool_t active;
174 connman_bool_t set_active;
176 /* SimManager Interface */
179 /* Netreg Interface */
182 uint8_t data_strength; /* 1xEVDO signal strength */
183 connman_bool_t roaming;
186 DBusPendingCall *call_set_property;
187 DBusPendingCall *call_get_properties;
188 DBusPendingCall *call_get_contexts;
191 static const char *api2string(enum ofono_api api)
196 case OFONO_API_NETREG:
200 case OFONO_API_CDMA_NETREG:
201 return "cdma-netreg";
202 case OFONO_API_CDMA_CM:
209 static char *get_ident(const char *path)
216 pos = strrchr(path, '/');
223 static struct network_context *network_context_alloc(const char *path)
225 struct network_context *context;
227 context = g_try_new0(struct network_context, 1);
231 context->path = g_strdup(path);
234 context->ipv4_method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
235 context->ipv4_address = NULL;
236 context->ipv4_nameservers = NULL;
238 context->ipv6_method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
239 context->ipv6_address = NULL;
240 context->ipv6_nameservers = NULL;
245 static void network_context_free(struct network_context *context)
247 g_free(context->path);
249 connman_ipaddress_free(context->ipv4_address);
250 g_free(context->ipv4_nameservers);
252 connman_ipaddress_free(context->ipv6_address);
253 g_free(context->ipv6_nameservers);
258 static void set_connected(struct modem_data *modem)
260 connman_bool_t setip = FALSE;
262 DBG("%s", modem->path);
264 connman_network_set_index(modem->network, modem->context->index);
266 switch (modem->context->ipv4_method) {
267 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
268 case CONNMAN_IPCONFIG_METHOD_OFF:
269 case CONNMAN_IPCONFIG_METHOD_MANUAL:
270 case CONNMAN_IPCONFIG_METHOD_AUTO:
273 case CONNMAN_IPCONFIG_METHOD_FIXED:
274 connman_network_set_ipv4_method(modem->network,
275 modem->context->ipv4_method);
276 connman_network_set_ipaddress(modem->network,
277 modem->context->ipv4_address);
278 connman_network_set_nameservers(modem->network,
279 modem->context->ipv4_nameservers);
283 case CONNMAN_IPCONFIG_METHOD_DHCP:
284 connman_network_set_ipv4_method(modem->network,
285 modem->context->ipv4_method);
290 switch (modem->context->ipv6_method) {
291 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
292 case CONNMAN_IPCONFIG_METHOD_OFF:
293 case CONNMAN_IPCONFIG_METHOD_MANUAL:
294 case CONNMAN_IPCONFIG_METHOD_DHCP:
295 case CONNMAN_IPCONFIG_METHOD_AUTO:
298 case CONNMAN_IPCONFIG_METHOD_FIXED:
299 connman_network_set_ipv6_method(modem->network,
300 modem->context->ipv6_method);
301 connman_network_set_ipaddress(modem->network,
302 modem->context->ipv6_address);
308 connman_network_set_connected(modem->network, TRUE);
311 static void set_disconnected(struct modem_data *modem)
313 DBG("%s", modem->path);
315 if (modem->network == NULL)
318 connman_network_set_connected(modem->network, FALSE);
321 typedef void (*set_property_cb)(struct modem_data *data,
322 connman_bool_t success);
323 typedef void (*get_properties_cb)(struct modem_data *data,
324 DBusMessageIter *dict);
326 struct property_info {
327 struct modem_data *modem;
329 const char *interface;
330 const char *property;
331 set_property_cb set_property_cb;
332 get_properties_cb get_properties_cb;
335 static void set_property_reply(DBusPendingCall *call, void *user_data)
337 struct property_info *info = user_data;
340 connman_bool_t success = TRUE;
342 DBG("%s path %s %s.%s", info->modem->path,
343 info->path, info->interface, info->property);
345 info->modem->call_set_property = NULL;
347 dbus_error_init(&error);
349 reply = dbus_pending_call_steal_reply(call);
351 if (dbus_set_error_from_message(&error, reply)) {
352 connman_error("Failed to change property: %s %s.%s: %s %s",
353 info->path, info->interface, info->property,
354 error.name, error.message);
355 dbus_error_free(&error);
359 if (info->set_property_cb != NULL)
360 (*info->set_property_cb)(info->modem, success);
362 dbus_message_unref(reply);
364 dbus_pending_call_unref(call);
367 static int set_property(struct modem_data *modem,
368 const char *path, const char *interface,
369 const char *property, int type, void *value,
370 set_property_cb notify)
372 DBusMessage *message;
373 DBusMessageIter iter;
374 struct property_info *info;
376 DBG("%s path %s %s.%s", modem->path, path, interface, property);
378 if (modem->call_set_property != NULL) {
379 DBG("Cancel pending SetProperty");
381 dbus_pending_call_cancel(modem->call_set_property);
382 modem->call_set_property = NULL;
385 message = dbus_message_new_method_call(OFONO_SERVICE, path,
386 interface, SET_PROPERTY);
390 dbus_message_iter_init_append(message, &iter);
391 connman_dbus_property_append_basic(&iter, property, type, value);
393 if (dbus_connection_send_with_reply(connection, message,
394 &modem->call_set_property, TIMEOUT) == FALSE) {
395 connman_error("Failed to change property: %s %s.%s",
396 path, interface, property);
397 dbus_message_unref(message);
401 if (modem->call_set_property == NULL) {
402 connman_error("D-Bus connection not available");
403 dbus_message_unref(message);
407 info = g_try_new0(struct property_info, 1);
409 dbus_message_unref(message);
415 info->interface = interface;
416 info->property = property;
417 info->set_property_cb = notify;
419 dbus_pending_call_set_notify(modem->call_set_property,
420 set_property_reply, info, g_free);
422 dbus_message_unref(message);
427 static void get_properties_reply(DBusPendingCall *call, void *user_data)
429 struct property_info *info = user_data;
430 DBusMessageIter array, dict;
434 DBG("%s path %s %s", info->modem->path, info->path, info->interface);
436 info->modem->call_get_properties = NULL;
438 dbus_error_init(&error);
440 reply = dbus_pending_call_steal_reply(call);
442 if (dbus_set_error_from_message(&error, reply)) {
443 connman_error("Failed to get properties: %s %s: %s %s",
444 info->path, info->interface,
445 error.name, error.message);
446 dbus_error_free(&error);
451 if (dbus_message_iter_init(reply, &array) == FALSE)
454 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
457 dbus_message_iter_recurse(&array, &dict);
459 if (info->get_properties_cb != NULL)
460 (*info->get_properties_cb)(info->modem, &dict);
464 dbus_message_unref(reply);
466 dbus_pending_call_unref(call);
469 static int get_properties(const char *path, const char *interface,
470 get_properties_cb notify,
471 struct modem_data *modem)
473 DBusMessage *message;
474 struct property_info *info;
476 DBG("%s path %s %s", modem->path, path, interface);
478 if (modem->call_get_properties != NULL) {
479 connman_error("Pending GetProperties");
483 message = dbus_message_new_method_call(OFONO_SERVICE, path,
484 interface, GET_PROPERTIES);
488 if (dbus_connection_send_with_reply(connection, message,
489 &modem->call_get_properties, TIMEOUT) == FALSE) {
490 connman_error("Failed to call %s.GetProperties()", interface);
491 dbus_message_unref(message);
495 if (modem->call_get_properties == NULL) {
496 connman_error("D-Bus connection not available");
497 dbus_message_unref(message);
501 info = g_try_new0(struct property_info, 1);
503 dbus_message_unref(message);
509 info->interface = interface;
510 info->get_properties_cb = notify;
512 dbus_pending_call_set_notify(modem->call_get_properties,
513 get_properties_reply, info, g_free);
515 dbus_message_unref(message);
520 static void context_set_active_reply(struct modem_data *modem,
521 connman_bool_t success)
523 DBG("%s", modem->path);
525 if (success == TRUE) {
527 * Don't handle do anything on success here. oFono will send
528 * the change via PropertyChanged singal.
534 * Active = True might fail due a timeout. That means oFono
535 * still tries to go online. If we retry to set Active = True,
536 * we just get a InProgress error message. Should we power
537 * cycle the modem in such cases?
540 if (modem->network == NULL) {
542 * In the case where we power down the device
543 * we don't wait for the reply, therefore the network
544 * might already be gone.
549 connman_network_set_error(modem->network,
550 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
553 static int context_set_active(struct modem_data *modem,
554 connman_bool_t active)
558 DBG("%s active %d", modem->path, active);
560 err = set_property(modem, modem->context->path,
561 OFONO_CONTEXT_INTERFACE,
562 "Active", DBUS_TYPE_BOOLEAN,
564 context_set_active_reply);
566 if (active == FALSE && err == -EINPROGRESS)
572 static void cdma_cm_set_powered_reply(struct modem_data *modem,
573 connman_bool_t success)
575 DBG("%s", modem->path);
577 if (success == TRUE) {
579 * Don't handle do anything on success here. oFono will send
580 * the change via PropertyChanged singal.
586 * Powered = True might fail due a timeout. That means oFono
587 * still tries to go online. If we retry to set Powered = True,
588 * we just get a InProgress error message. Should we power
589 * cycle the modem in such cases?
592 if (modem->network == NULL) {
594 * In the case where we power down the device
595 * we don't wait for the reply, therefore the network
596 * might already be gone.
601 connman_network_set_error(modem->network,
602 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
605 static int cdma_cm_set_powered(struct modem_data *modem, connman_bool_t powered)
609 DBG("%s powered %d", modem->path, powered);
611 err = set_property(modem, modem->path, OFONO_CDMA_CM_INTERFACE,
612 "Powered", DBUS_TYPE_BOOLEAN,
614 cdma_cm_set_powered_reply);
616 if (powered == FALSE && err == -EINPROGRESS)
622 static int modem_set_online(struct modem_data *modem, connman_bool_t online)
624 DBG("%s online %d", modem->path, online);
626 return set_property(modem, modem->path,
627 OFONO_MODEM_INTERFACE,
628 "Online", DBUS_TYPE_BOOLEAN,
633 static int cm_set_powered(struct modem_data *modem, connman_bool_t powered)
637 DBG("%s powered %d", modem->path, powered);
639 err = set_property(modem, modem->path,
641 "Powered", DBUS_TYPE_BOOLEAN,
645 if (powered == FALSE && err == -EINPROGRESS)
651 static int modem_set_powered(struct modem_data *modem, connman_bool_t powered)
655 DBG("%s powered %d", modem->path, powered);
657 modem->set_powered = powered;
659 err = set_property(modem, modem->path,
660 OFONO_MODEM_INTERFACE,
661 "Powered", DBUS_TYPE_BOOLEAN,
665 if (powered == FALSE && err == -EINPROGRESS)
671 static connman_bool_t has_interface(uint8_t interfaces,
674 if ((interfaces & api) == api)
680 static uint8_t extract_interfaces(DBusMessageIter *array)
682 DBusMessageIter entry;
683 uint8_t interfaces = 0;
685 dbus_message_iter_recurse(array, &entry);
687 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
690 dbus_message_iter_get_basic(&entry, &name);
692 if (g_str_equal(name, OFONO_SIM_INTERFACE) == TRUE)
693 interfaces |= OFONO_API_SIM;
694 else if (g_str_equal(name, OFONO_NETREG_INTERFACE) == TRUE)
695 interfaces |= OFONO_API_NETREG;
696 else if (g_str_equal(name, OFONO_CM_INTERFACE) == TRUE)
697 interfaces |= OFONO_API_CM;
698 else if (g_str_equal(name, OFONO_CDMA_CM_INTERFACE) == TRUE)
699 interfaces |= OFONO_API_CDMA_CM;
700 else if (g_str_equal(name, OFONO_CDMA_NETREG_INTERFACE) == TRUE)
701 interfaces |= OFONO_API_CDMA_NETREG;
703 dbus_message_iter_next(&entry);
709 static char *extract_nameservers(DBusMessageIter *array)
711 DBusMessageIter entry;
712 char *nameservers = NULL;
715 dbus_message_iter_recurse(array, &entry);
717 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
718 const char *nameserver;
720 dbus_message_iter_get_basic(&entry, &nameserver);
722 if (nameservers == NULL) {
723 nameservers = g_strdup(nameserver);
726 nameservers = g_strdup_printf("%s %s", tmp, nameserver);
730 dbus_message_iter_next(&entry);
736 static void extract_ipv4_settings(DBusMessageIter *array,
737 struct network_context *context)
739 DBusMessageIter dict;
740 char *address = NULL, *netmask = NULL, *gateway = NULL;
741 char *nameservers = NULL;
742 const char *interface = NULL;
745 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
748 dbus_message_iter_recurse(array, &dict);
750 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
751 DBusMessageIter entry, value;
752 const char *key, *val;
754 dbus_message_iter_recurse(&dict, &entry);
755 dbus_message_iter_get_basic(&entry, &key);
757 dbus_message_iter_next(&entry);
758 dbus_message_iter_recurse(&entry, &value);
760 if (g_str_equal(key, "Interface") == TRUE) {
761 dbus_message_iter_get_basic(&value, &interface);
763 DBG("Interface %s", interface);
765 index = connman_inet_ifindex(interface);
767 DBG("index %d", index);
768 } else if (g_str_equal(key, "Method") == TRUE) {
769 dbus_message_iter_get_basic(&value, &val);
771 DBG("Method %s", val);
773 if (g_strcmp0(val, "static") == 0) {
774 context->ipv4_method = CONNMAN_IPCONFIG_METHOD_FIXED;
775 } else if (g_strcmp0(val, "dhcp") == 0) {
776 context->ipv4_method = CONNMAN_IPCONFIG_METHOD_DHCP;
779 } else if (g_str_equal(key, "Address") == TRUE) {
780 dbus_message_iter_get_basic(&value, &val);
782 address = g_strdup(val);
784 DBG("Address %s", address);
785 } else if (g_str_equal(key, "Netmask") == TRUE) {
786 dbus_message_iter_get_basic(&value, &val);
788 netmask = g_strdup(val);
790 DBG("Netmask %s", netmask);
791 } else if (g_str_equal(key, "DomainNameServers") == TRUE) {
792 nameservers = extract_nameservers(&value);
794 DBG("Nameservers %s", nameservers);
795 } else if (g_str_equal(key, "Gateway") == TRUE) {
796 dbus_message_iter_get_basic(&value, &val);
798 gateway = g_strdup(val);
800 DBG("Gateway %s", gateway);
803 dbus_message_iter_next(&dict);
809 if (context->ipv4_method != CONNMAN_IPCONFIG_METHOD_FIXED)
812 context->ipv4_address = connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4);
813 if (context->ipv4_address == NULL)
816 context->index = index;
817 connman_ipaddress_set_ipv4(context->ipv4_address, address,
820 context->ipv4_nameservers = nameservers;
823 if (context->ipv4_nameservers != nameservers)
831 static void extract_ipv6_settings(DBusMessageIter *array,
832 struct network_context *context)
834 DBusMessageIter dict;
835 char *address = NULL, *gateway = NULL;
836 unsigned char prefix_length;
837 char *nameservers = NULL;
838 const char *interface = NULL;
841 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
844 dbus_message_iter_recurse(array, &dict);
846 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
847 DBusMessageIter entry, value;
848 const char *key, *val;
850 dbus_message_iter_recurse(&dict, &entry);
851 dbus_message_iter_get_basic(&entry, &key);
853 dbus_message_iter_next(&entry);
854 dbus_message_iter_recurse(&entry, &value);
856 if (g_str_equal(key, "Interface") == TRUE) {
857 dbus_message_iter_get_basic(&value, &interface);
859 DBG("Interface %s", interface);
861 index = connman_inet_ifindex(interface);
863 DBG("index %d", index);
864 } else if (g_str_equal(key, "Address") == TRUE) {
865 dbus_message_iter_get_basic(&value, &val);
867 address = g_strdup(val);
869 DBG("Address %s", address);
870 } else if (g_str_equal(key, "PrefixLength") == TRUE) {
871 dbus_message_iter_get_basic(&value, &prefix_length);
873 DBG("prefix length %d", prefix_length);
874 } else if (g_str_equal(key, "DomainNameServers") == TRUE) {
875 nameservers = extract_nameservers(&value);
877 DBG("Nameservers %s", nameservers);
878 } else if (g_str_equal(key, "Gateway") == TRUE) {
879 dbus_message_iter_get_basic(&value, &val);
881 gateway = g_strdup(val);
883 DBG("Gateway %s", gateway);
886 dbus_message_iter_next(&dict);
892 context->ipv6_method = CONNMAN_IPCONFIG_METHOD_FIXED;
894 context->ipv6_address =
895 connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6);
896 if (context->ipv6_address == NULL)
899 context->index = index;
900 connman_ipaddress_set_ipv6(context->ipv6_address, address,
901 prefix_length, gateway);
903 context->ipv6_nameservers = nameservers;
906 if (context->ipv6_nameservers != nameservers)
913 static connman_bool_t ready_to_create_device(struct modem_data *modem)
916 * There are three different modem types which behave slightly
918 * - GSM modems will expose the SIM interface then the
920 * - CDMA modems will expose CM first and sometime later
921 * a unique serial number.
923 * This functions tests if we have the necessary information gathered
924 * before we are able to create a device.
927 if (modem->device != NULL)
930 if (modem->imsi != NULL || modem->serial != NULL)
936 static void create_device(struct modem_data *modem)
938 struct connman_device *device;
939 char *uninitialized_var(ident);
941 DBG("%s", modem->path);
943 if (modem->imsi != NULL)
945 else if (modem->serial != NULL)
946 ident = modem->serial;
948 if (connman_dbus_validate_ident(ident) == FALSE)
949 ident = connman_dbus_encode_string(ident);
951 ident = g_strdup(ident);
953 device = connman_device_create(ident, CONNMAN_DEVICE_TYPE_CELLULAR);
957 DBG("device %p", device);
959 connman_device_set_ident(device, ident);
961 connman_device_set_string(device, "Path", modem->path);
963 connman_device_set_data(device, modem);
965 if (connman_device_register(device) < 0) {
966 connman_error("Failed to register cellular device");
967 connman_device_unref(device);
971 modem->device = device;
973 connman_device_set_powered(modem->device, modem->online);
978 static void destroy_device(struct modem_data *modem)
980 DBG("%s", modem->path);
982 connman_device_set_powered(modem->device, FALSE);
984 if (modem->network != NULL) {
985 connman_device_remove_network(modem->device, modem->network);
986 connman_network_unref(modem->network);
987 modem->network = NULL;
990 connman_device_unregister(modem->device);
991 connman_device_unref(modem->device);
993 modem->device = NULL;
996 static void add_network(struct modem_data *modem)
1000 DBG("%s", modem->path);
1002 if (modem->network != NULL)
1005 modem->network = connman_network_create(modem->context->path,
1006 CONNMAN_NETWORK_TYPE_CELLULAR);
1007 if (modem->network == NULL)
1010 DBG("network %p", modem->network);
1012 connman_network_set_data(modem->network, modem);
1014 connman_network_set_string(modem->network, "Path",
1015 modem->context->path);
1017 connman_network_set_index(modem->network, modem->context->index);
1019 if (modem->name != NULL)
1020 connman_network_set_name(modem->network, modem->name);
1022 connman_network_set_name(modem->network, "");
1024 connman_network_set_strength(modem->network, modem->strength);
1026 group = get_ident(modem->context->path);
1027 connman_network_set_group(modem->network, group);
1029 connman_network_set_available(modem->network, TRUE);
1031 connman_network_set_bool(modem->network, "Roaming",
1034 if (connman_device_add_network(modem->device, modem->network) < 0) {
1035 connman_network_unref(modem->network);
1036 modem->network = NULL;
1041 * Create the ipconfig layer before trying to connect. Withouth
1042 * the ipconfig layer the core is not ready to process errors.
1044 connman_network_set_index(modem->network, -1);
1047 static void remove_network(struct modem_data *modem)
1049 DBG("%s", modem->path);
1051 if (modem->network == NULL)
1054 DBG("network %p", modem->network);
1056 connman_device_remove_network(modem->device, modem->network);
1057 connman_network_unref(modem->network);
1058 modem->network = NULL;
1061 static int add_cm_context(struct modem_data *modem, const char *context_path,
1062 DBusMessageIter *dict)
1064 const char *context_type;
1065 struct network_context *context = NULL;
1066 connman_bool_t active = FALSE;
1068 DBG("%s context path %s", modem->path, context_path);
1070 if (modem->context != NULL) {
1072 * We have already assigned a context to this modem
1073 * and we do only support one Internet context.
1078 context = network_context_alloc(context_path);
1079 if (context == NULL)
1082 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1083 DBusMessageIter entry, value;
1086 dbus_message_iter_recurse(dict, &entry);
1087 dbus_message_iter_get_basic(&entry, &key);
1089 dbus_message_iter_next(&entry);
1090 dbus_message_iter_recurse(&entry, &value);
1092 if (g_str_equal(key, "Type") == TRUE) {
1093 dbus_message_iter_get_basic(&value, &context_type);
1095 DBG("%s context %s type %s", modem->path,
1096 context_path, context_type);
1097 } else if (g_str_equal(key, "Settings") == TRUE) {
1098 DBG("%s Settings", modem->path);
1100 extract_ipv4_settings(&value, context);
1101 } else if (g_str_equal(key, "IPv6.Settings") == TRUE) {
1102 DBG("%s IPv6.Settings", modem->path);
1104 extract_ipv6_settings(&value, context);
1105 } else if (g_str_equal(key, "Active") == TRUE) {
1106 dbus_message_iter_get_basic(&value, &active);
1108 DBG("%s Active %d", modem->path, active);
1111 dbus_message_iter_next(dict);
1114 if (g_strcmp0(context_type, "internet") != 0) {
1115 network_context_free(context);
1119 modem->context = context;
1120 modem->active = active;
1122 g_hash_table_replace(context_hash, g_strdup(context_path), modem);
1127 static void remove_cm_context(struct modem_data *modem,
1128 const char *context_path)
1130 if (modem->context == NULL)
1133 if (modem->network != NULL)
1134 remove_network(modem);
1136 g_hash_table_remove(context_hash, context_path);
1138 network_context_free(modem->context);
1139 modem->context = NULL;
1142 static gboolean context_changed(DBusConnection *connection,
1143 DBusMessage *message,
1146 const char *context_path = dbus_message_get_path(message);
1147 struct modem_data *modem = NULL;
1148 DBusMessageIter iter, value;
1151 DBG("context_path %s", context_path);
1153 modem = g_hash_table_lookup(context_hash, context_path);
1157 if (dbus_message_iter_init(message, &iter) == FALSE)
1160 dbus_message_iter_get_basic(&iter, &key);
1162 dbus_message_iter_next(&iter);
1163 dbus_message_iter_recurse(&iter, &value);
1166 * oFono guarantees the ordering of Settings and
1167 * Active. Settings will always be send before Active = True.
1168 * That means we don't have to order here.
1170 if (g_str_equal(key, "Settings") == TRUE) {
1171 DBG("%s Settings", modem->path);
1173 extract_ipv4_settings(&value, modem->context);
1174 } else if (g_str_equal(key, "IPv6.Settings") == TRUE) {
1175 DBG("%s IPv6.Settings", modem->path);
1177 extract_ipv6_settings(&value, modem->context);
1178 } else if (g_str_equal(key, "Active") == TRUE) {
1179 dbus_message_iter_get_basic(&value, &modem->active);
1181 DBG("%s Active %d", modem->path, modem->active);
1183 if (modem->active == TRUE)
1184 set_connected(modem);
1186 set_disconnected(modem);
1192 static void cm_get_contexts_reply(DBusPendingCall *call, void *user_data)
1194 struct modem_data *modem = user_data;
1195 DBusMessageIter array, dict, entry, value;
1199 DBG("%s", modem->path);
1201 modem->call_get_contexts = NULL;
1203 reply = dbus_pending_call_steal_reply(call);
1205 dbus_error_init(&error);
1207 if (dbus_set_error_from_message(&error, reply) == TRUE) {
1208 connman_error("%s", error.message);
1209 dbus_error_free(&error);
1213 if (dbus_message_iter_init(reply, &array) == FALSE)
1216 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
1219 dbus_message_iter_recurse(&array, &dict);
1221 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT) {
1222 const char *context_path;
1224 dbus_message_iter_recurse(&dict, &entry);
1225 dbus_message_iter_get_basic(&entry, &context_path);
1227 dbus_message_iter_next(&entry);
1228 dbus_message_iter_recurse(&entry, &value);
1230 if (add_cm_context(modem, context_path, &value) == 0)
1233 dbus_message_iter_next(&dict);
1237 dbus_message_unref(reply);
1239 dbus_pending_call_unref(call);
1242 static int cm_get_contexts(struct modem_data *modem)
1244 DBusMessage *message;
1246 DBG("%s", modem->path);
1248 if (modem->call_get_contexts != NULL)
1251 message = dbus_message_new_method_call(OFONO_SERVICE, modem->path,
1252 OFONO_CM_INTERFACE, GET_CONTEXTS);
1253 if (message == NULL)
1256 if (dbus_connection_send_with_reply(connection, message,
1257 &modem->call_get_contexts, TIMEOUT) == FALSE) {
1258 connman_error("Failed to call GetContexts()");
1259 dbus_message_unref(message);
1263 if (modem->call_get_contexts == NULL) {
1264 connman_error("D-Bus connection not available");
1265 dbus_message_unref(message);
1269 dbus_pending_call_set_notify(modem->call_get_contexts,
1270 cm_get_contexts_reply,
1273 dbus_message_unref(message);
1275 return -EINPROGRESS;
1278 static gboolean cm_context_added(DBusConnection *connection,
1279 DBusMessage *message,
1282 const char *path = dbus_message_get_path(message);
1284 struct modem_data *modem;
1285 DBusMessageIter iter, properties;
1289 modem = g_hash_table_lookup(modem_hash, path);
1293 if (dbus_message_iter_init(message, &iter) == FALSE)
1296 dbus_message_iter_get_basic(&iter, &context_path);
1298 dbus_message_iter_next(&iter);
1299 dbus_message_iter_recurse(&iter, &properties);
1301 if (add_cm_context(modem, context_path, &properties) != 0)
1307 static gboolean cm_context_removed(DBusConnection *connection,
1308 DBusMessage *message,
1311 const char *path = dbus_message_get_path(message);
1312 const char *context_path;
1313 struct modem_data *modem;
1314 DBusMessageIter iter;
1316 DBG("context path %s", path);
1318 if (dbus_message_iter_init(message, &iter) == FALSE)
1321 dbus_message_iter_get_basic(&iter, &context_path);
1323 modem = g_hash_table_lookup(context_hash, context_path);
1327 remove_cm_context(modem, context_path);
1332 static void netreg_update_name(struct modem_data *modem,
1333 DBusMessageIter* value)
1337 dbus_message_iter_get_basic(value, &name);
1339 DBG("%s Name %s", modem->path, name);
1341 g_free(modem->name);
1342 modem->name = g_strdup(name);
1344 if (modem->network == NULL)
1347 connman_network_set_name(modem->network, modem->name);
1348 connman_network_update(modem->network);
1351 static void netreg_update_strength(struct modem_data *modem,
1352 DBusMessageIter *value)
1354 dbus_message_iter_get_basic(value, &modem->strength);
1356 DBG("%s Strength %d", modem->path, modem->strength);
1358 if (modem->network == NULL)
1363 * We don't have 2 signal notifications we always report the strength
1364 * signal. data_strength is always equal to 0.
1367 * In the case we have a data_strength signal (from 1xEVDO network)
1368 * we don't need to update the value with strength signal (from 1xCDMA)
1369 * because the modem is registered to 1xEVDO network for data call.
1370 * In case we have no data_strength signal (not registered to 1xEVDO
1371 * network), we must report the strength signal (registered to 1xCDMA
1372 * network e.g slow mode).
1374 if (modem->data_strength != 0)
1377 connman_network_set_strength(modem->network, modem->strength);
1378 connman_network_update(modem->network);
1381 /* Retrieve 1xEVDO Data Strength signal */
1382 static void netreg_update_datastrength(struct modem_data *modem,
1383 DBusMessageIter *value)
1385 dbus_message_iter_get_basic(value, &modem->data_strength);
1387 DBG("%s Data Strength %d", modem->path, modem->data_strength);
1389 if (modem->network == NULL)
1393 * CDMA modem is not registered to 1xEVDO network, let
1394 * update_signal_strength() reporting the value on the Strength signal
1397 if (modem->data_strength == 0)
1400 connman_network_set_strength(modem->network, modem->data_strength);
1401 connman_network_update(modem->network);
1404 static void netreg_update_roaming(struct modem_data *modem,
1405 DBusMessageIter *value)
1408 connman_bool_t roaming;
1410 dbus_message_iter_get_basic(value, &status);
1412 if (g_str_equal(status, "roaming") == TRUE)
1417 if (roaming == modem->roaming)
1420 modem->roaming = roaming;
1422 if (modem->network == NULL)
1425 connman_network_set_bool(modem->network,
1426 "Roaming", modem->roaming);
1427 connman_network_update(modem->network);
1430 static void netreg_update_regdom(struct modem_data *modem,
1431 DBusMessageIter *value)
1433 char *mobile_country_code;
1437 dbus_message_iter_get_basic(value, &mobile_country_code);
1439 DBG("%s MobileContryCode %s", modem->path, mobile_country_code);
1442 mcc = atoi(mobile_country_code);
1443 if (mcc > 799 || mcc < 200)
1446 alpha2 = mcc_country_codes[mcc - 200];
1448 connman_technology_set_regdom(alpha2);
1451 static gboolean netreg_changed(DBusConnection *connection, DBusMessage *message,
1454 const char *path = dbus_message_get_path(message);
1455 struct modem_data *modem;
1456 DBusMessageIter iter, value;
1459 modem = g_hash_table_lookup(modem_hash, path);
1463 if (modem->ignore == TRUE)
1466 if (dbus_message_iter_init(message, &iter) == FALSE)
1469 dbus_message_iter_get_basic(&iter, &key);
1471 dbus_message_iter_next(&iter);
1472 dbus_message_iter_recurse(&iter, &value);
1474 if (g_str_equal(key, "Name") == TRUE)
1475 netreg_update_name(modem, &value);
1476 else if (g_str_equal(key, "Strength") == TRUE)
1477 netreg_update_strength(modem, &value);
1478 else if (g_str_equal(key, "Status") == TRUE)
1479 netreg_update_roaming(modem, &value);
1480 else if (g_str_equal(key, "MobileCountryCode") == TRUE)
1481 netreg_update_regdom(modem, &value);
1486 static void netreg_properties_reply(struct modem_data *modem,
1487 DBusMessageIter *dict)
1489 DBG("%s", modem->path);
1491 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1492 DBusMessageIter entry, value;
1495 dbus_message_iter_recurse(dict, &entry);
1496 dbus_message_iter_get_basic(&entry, &key);
1498 dbus_message_iter_next(&entry);
1499 dbus_message_iter_recurse(&entry, &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, "Status") == TRUE)
1506 netreg_update_roaming(modem, &value);
1507 else if (g_str_equal(key, "MobileCountryCode") == TRUE)
1508 netreg_update_regdom(modem, &value);
1510 dbus_message_iter_next(dict);
1513 if (modem->context == NULL) {
1515 * netgreg_get_properties() was issued after we got
1516 * cm_get_contexts_reply() where we create the
1517 * context. Though before we got the
1518 * netreg_properties_reply the context was removed
1519 * again. Therefore we have to skip the network
1527 if (modem->active == TRUE)
1528 set_connected(modem);
1531 static int netreg_get_properties(struct modem_data *modem)
1533 return get_properties(modem->path, OFONO_NETREG_INTERFACE,
1534 netreg_properties_reply, modem);
1537 static void add_cdma_network(struct modem_data *modem)
1539 /* Be sure that device is created before adding CDMA network */
1540 if (modem->device == NULL)
1544 * CDMA modems don't need contexts for data call, however the current
1545 * add_network() logic needs one, so we create one to proceed.
1547 if (modem->context == NULL)
1548 modem->context = network_context_alloc(modem->path);
1550 if (modem->name == NULL)
1551 modem->name = g_strdup("CDMA Network");
1555 if (modem->cdma_cm_powered == TRUE)
1556 set_connected(modem);
1559 static gboolean cdma_netreg_changed(DBusConnection *connection,
1560 DBusMessage *message,
1563 const char *path = dbus_message_get_path(message);
1564 struct modem_data *modem;
1565 DBusMessageIter iter, value;
1570 modem = g_hash_table_lookup(modem_hash, path);
1574 if (modem->ignore == TRUE)
1577 if (dbus_message_iter_init(message, &iter) == FALSE)
1580 dbus_message_iter_get_basic(&iter, &key);
1582 dbus_message_iter_next(&iter);
1583 dbus_message_iter_recurse(&iter, &value);
1585 if (g_str_equal(key, "Name") == TRUE)
1586 netreg_update_name(modem, &value);
1587 else if (g_str_equal(key, "Strength") == TRUE)
1588 netreg_update_strength(modem, &value);
1589 else if (g_str_equal(key, "DataStrength") == TRUE)
1590 netreg_update_datastrength(modem, &value);
1591 else if (g_str_equal(key, "Status") == TRUE)
1592 netreg_update_roaming(modem, &value);
1594 add_cdma_network(modem);
1599 static void cdma_netreg_properties_reply(struct modem_data *modem,
1600 DBusMessageIter *dict)
1602 DBG("%s", modem->path);
1604 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1605 DBusMessageIter entry, value;
1608 dbus_message_iter_recurse(dict, &entry);
1609 dbus_message_iter_get_basic(&entry, &key);
1611 dbus_message_iter_next(&entry);
1612 dbus_message_iter_recurse(&entry, &value);
1614 if (g_str_equal(key, "Name") == TRUE)
1615 netreg_update_name(modem, &value);
1616 else if (g_str_equal(key, "Strength") == TRUE)
1617 netreg_update_strength(modem, &value);
1618 else if (g_str_equal(key, "DataStrength") == TRUE)
1619 netreg_update_datastrength(modem, &value);
1620 else if (g_str_equal(key, "Status") == TRUE)
1621 netreg_update_roaming(modem, &value);
1623 dbus_message_iter_next(dict);
1626 add_cdma_network(modem);
1629 static int cdma_netreg_get_properties(struct modem_data *modem)
1631 return get_properties(modem->path, OFONO_CDMA_NETREG_INTERFACE,
1632 cdma_netreg_properties_reply, modem);
1635 static void cm_update_attached(struct modem_data *modem,
1636 DBusMessageIter *value)
1638 dbus_message_iter_get_basic(value, &modem->attached);
1640 DBG("%s Attached %d", modem->path, modem->attached);
1642 if (modem->attached == FALSE)
1645 if (has_interface(modem->interfaces,
1646 OFONO_API_NETREG) == FALSE) {
1650 netreg_get_properties(modem);
1653 static void cm_update_powered(struct modem_data *modem,
1654 DBusMessageIter *value)
1656 dbus_message_iter_get_basic(value, &modem->cm_powered);
1658 DBG("%s ConnnectionManager Powered %d", modem->path,
1661 if (modem->cm_powered == TRUE)
1664 cm_set_powered(modem, TRUE);
1667 static gboolean cm_changed(DBusConnection *connection, DBusMessage *message,
1670 const char *path = dbus_message_get_path(message);
1671 struct modem_data *modem;
1672 DBusMessageIter iter, value;
1675 modem = g_hash_table_lookup(modem_hash, path);
1679 if (modem->ignore == TRUE)
1682 if (dbus_message_iter_init(message, &iter) == FALSE)
1685 dbus_message_iter_get_basic(&iter, &key);
1687 dbus_message_iter_next(&iter);
1688 dbus_message_iter_recurse(&iter, &value);
1690 if (g_str_equal(key, "Attached") == TRUE)
1691 cm_update_attached(modem, &value);
1692 else if (g_str_equal(key, "Powered") == TRUE)
1693 cm_update_powered(modem, &value);
1698 static void cdma_cm_update_powered(struct modem_data *modem,
1699 DBusMessageIter *value)
1701 dbus_message_iter_get_basic(value, &modem->cdma_cm_powered);
1703 DBG("%s CDMA cm Powered %d", modem->path, modem->cdma_cm_powered);
1705 if (modem->network == NULL)
1708 if (modem->cdma_cm_powered == TRUE)
1709 set_connected(modem);
1711 set_disconnected(modem);
1714 static void cdma_cm_update_settings(struct modem_data *modem,
1715 DBusMessageIter *value)
1717 DBG("%s Settings", modem->path);
1719 extract_ipv4_settings(value, modem->context);
1722 static gboolean cdma_cm_changed(DBusConnection *connection,
1723 DBusMessage *message, void *user_data)
1725 const char *path = dbus_message_get_path(message);
1726 struct modem_data *modem;
1727 DBusMessageIter iter, value;
1730 modem = g_hash_table_lookup(modem_hash, path);
1734 if (modem->online == TRUE && modem->network == NULL)
1735 cdma_netreg_get_properties(modem);
1737 if (dbus_message_iter_init(message, &iter) == FALSE)
1740 dbus_message_iter_get_basic(&iter, &key);
1742 dbus_message_iter_next(&iter);
1743 dbus_message_iter_recurse(&iter, &value);
1745 if (g_str_equal(key, "Powered") == TRUE)
1746 cdma_cm_update_powered(modem, &value);
1747 if (g_str_equal(key, "Settings") == TRUE)
1748 cdma_cm_update_settings(modem, &value);
1753 static void cm_properties_reply(struct modem_data *modem, DBusMessageIter *dict)
1755 DBG("%s", modem->path);
1757 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1758 DBusMessageIter entry, value;
1761 dbus_message_iter_recurse(dict, &entry);
1762 dbus_message_iter_get_basic(&entry, &key);
1764 dbus_message_iter_next(&entry);
1765 dbus_message_iter_recurse(&entry, &value);
1767 if (g_str_equal(key, "Attached") == TRUE)
1768 cm_update_attached(modem, &value);
1769 else if (g_str_equal(key, "Powered") == TRUE)
1770 cm_update_powered(modem, &value);
1772 dbus_message_iter_next(dict);
1776 static int cm_get_properties(struct modem_data *modem)
1778 return get_properties(modem->path, OFONO_CM_INTERFACE,
1779 cm_properties_reply, modem);
1782 static void cdma_cm_properties_reply(struct modem_data *modem,
1783 DBusMessageIter *dict)
1785 DBG("%s", modem->path);
1787 if (modem->online == TRUE)
1788 cdma_netreg_get_properties(modem);
1790 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1791 DBusMessageIter entry, value;
1794 dbus_message_iter_recurse(dict, &entry);
1795 dbus_message_iter_get_basic(&entry, &key);
1797 dbus_message_iter_next(&entry);
1798 dbus_message_iter_recurse(&entry, &value);
1800 if (g_str_equal(key, "Powered") == TRUE)
1801 cdma_cm_update_powered(modem, &value);
1802 if (g_str_equal(key, "Settings") == TRUE)
1803 cdma_cm_update_settings(modem, &value);
1805 dbus_message_iter_next(dict);
1809 static int cdma_cm_get_properties(struct modem_data *modem)
1811 return get_properties(modem->path, OFONO_CDMA_CM_INTERFACE,
1812 cdma_cm_properties_reply, modem);
1815 static void sim_update_imsi(struct modem_data *modem,
1816 DBusMessageIter* value)
1820 dbus_message_iter_get_basic(value, &imsi);
1822 DBG("%s imsi %s", modem->path, imsi);
1824 g_free(modem->imsi);
1825 modem->imsi = g_strdup(imsi);
1828 static gboolean sim_changed(DBusConnection *connection, DBusMessage *message,
1831 const char *path = dbus_message_get_path(message);
1832 struct modem_data *modem;
1833 DBusMessageIter iter, value;
1836 modem = g_hash_table_lookup(modem_hash, path);
1840 if (modem->ignore == TRUE)
1843 if (dbus_message_iter_init(message, &iter) == FALSE)
1846 dbus_message_iter_get_basic(&iter, &key);
1848 dbus_message_iter_next(&iter);
1849 dbus_message_iter_recurse(&iter, &value);
1851 if (g_str_equal(key, "SubscriberIdentity") == TRUE) {
1852 sim_update_imsi(modem, &value);
1854 if (ready_to_create_device(modem) == FALSE)
1858 * This is a GSM modem. Create the device and
1859 * register it at the core. Enabling (setting
1860 * it online is done through the
1861 * modem_enable() callback.
1863 create_device(modem);
1869 static void sim_properties_reply(struct modem_data *modem,
1870 DBusMessageIter *dict)
1872 DBG("%s", modem->path);
1874 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1875 DBusMessageIter entry, value;
1878 dbus_message_iter_recurse(dict, &entry);
1879 dbus_message_iter_get_basic(&entry, &key);
1881 dbus_message_iter_next(&entry);
1882 dbus_message_iter_recurse(&entry, &value);
1884 if (g_str_equal(key, "SubscriberIdentity") == TRUE) {
1885 sim_update_imsi(modem, &value);
1887 if (ready_to_create_device(modem) == FALSE)
1891 * This is a GSM modem. Create the device and
1892 * register it at the core. Enabling (setting
1893 * it online is done through the
1894 * modem_enable() callback.
1896 create_device(modem);
1898 if (modem->online == FALSE)
1902 * The modem is already online and we have the CM interface.
1903 * There will be no interface update and therefore our
1904 * state machine will not go to next step. We have to
1905 * trigger it from here.
1907 if (has_interface(modem->interfaces, OFONO_API_CM) == TRUE) {
1908 cm_get_properties(modem);
1909 cm_get_contexts(modem);
1914 dbus_message_iter_next(dict);
1918 static int sim_get_properties(struct modem_data *modem)
1920 return get_properties(modem->path, OFONO_SIM_INTERFACE,
1921 sim_properties_reply, modem);
1924 static connman_bool_t api_added(uint8_t old_iface, uint8_t new_iface,
1927 if (has_interface(old_iface, api) == FALSE &&
1928 has_interface(new_iface, api) == TRUE) {
1929 DBG("%s added", api2string(api));
1936 static connman_bool_t api_removed(uint8_t old_iface, uint8_t new_iface,
1939 if (has_interface(old_iface, api) == TRUE &&
1940 has_interface(new_iface, api) == FALSE) {
1941 DBG("%s removed", api2string(api));
1948 static void modem_update_interfaces(struct modem_data *modem,
1952 DBG("%s", modem->path);
1954 if (api_added(old_ifaces, new_ifaces, OFONO_API_SIM) == TRUE) {
1955 if (modem->imsi == NULL &&
1956 modem->set_powered == FALSE) {
1958 * Only use do GetProperties() when
1959 * device has not been powered up.
1961 sim_get_properties(modem);
1965 if (api_added(old_ifaces, new_ifaces, OFONO_API_CM) == TRUE) {
1966 if (modem->device != NULL) {
1967 cm_get_properties(modem);
1968 cm_get_contexts(modem);
1972 if (api_added(old_ifaces, new_ifaces, OFONO_API_CDMA_CM) == TRUE) {
1973 if (ready_to_create_device(modem) == TRUE)
1974 create_device(modem);
1976 if (modem->device != NULL)
1977 cdma_cm_get_properties(modem);
1980 if (api_added(old_ifaces, new_ifaces, OFONO_API_NETREG) == TRUE) {
1981 if (modem->attached == TRUE)
1982 netreg_get_properties(modem);
1985 if (api_added(old_ifaces, new_ifaces, OFONO_API_CDMA_NETREG) == TRUE) {
1986 cdma_netreg_get_properties(modem);
1989 if (api_removed(old_ifaces, new_ifaces, OFONO_API_CM) == TRUE) {
1990 remove_cm_context(modem, modem->context->path);
1993 if (api_removed(old_ifaces, new_ifaces, OFONO_API_CDMA_CM) == TRUE) {
1994 remove_cm_context(modem, modem->context->path);
1997 if (api_removed(old_ifaces, new_ifaces, OFONO_API_NETREG) == TRUE) {
1998 remove_network(modem);
2001 if (api_removed(old_ifaces, new_ifaces, OFONO_API_CDMA_NETREG == TRUE)) {
2002 remove_network(modem);
2006 static gboolean modem_changed(DBusConnection *connection, DBusMessage *message,
2009 const char *path = dbus_message_get_path(message);
2010 struct modem_data *modem;
2011 DBusMessageIter iter, value;
2014 modem = g_hash_table_lookup(modem_hash, path);
2018 if (modem->ignore == TRUE)
2021 if (dbus_message_iter_init(message, &iter) == FALSE)
2024 dbus_message_iter_get_basic(&iter, &key);
2026 dbus_message_iter_next(&iter);
2027 dbus_message_iter_recurse(&iter, &value);
2029 if (g_str_equal(key, "Powered") == TRUE) {
2030 dbus_message_iter_get_basic(&value, &modem->powered);
2032 DBG("%s Powered %d", modem->path, modem->powered);
2034 if (modem->powered == FALSE)
2035 modem_set_powered(modem, TRUE);
2036 } else if (g_str_equal(key, "Online") == TRUE) {
2037 dbus_message_iter_get_basic(&value, &modem->online);
2039 DBG("%s Online %d", modem->path, modem->online);
2041 if (modem->device == NULL)
2044 connman_device_set_powered(modem->device, modem->online);
2045 } else if (g_str_equal(key, "Interfaces") == TRUE) {
2048 interfaces = extract_interfaces(&value);
2050 if (interfaces == modem->interfaces)
2053 DBG("%s Interfaces 0x%02x", modem->path, interfaces);
2055 modem_update_interfaces(modem, modem->interfaces, interfaces);
2057 modem->interfaces = interfaces;
2058 } else if (g_str_equal(key, "Serial") == TRUE) {
2061 dbus_message_iter_get_basic(&value, &serial);
2063 g_free(modem->serial);
2064 modem->serial = g_strdup(serial);
2066 DBG("%s Serial %s", modem->path, modem->serial);
2068 if (has_interface(modem->interfaces,
2069 OFONO_API_CDMA_CM) == TRUE) {
2070 if (ready_to_create_device(modem) == TRUE)
2071 create_device(modem);
2078 static void add_modem(const char *path, DBusMessageIter *prop)
2080 struct modem_data *modem;
2084 modem = g_hash_table_lookup(modem_hash, path);
2085 if (modem != NULL) {
2087 * When oFono powers up we ask for the modems and oFono is
2088 * reporting with modem_added signal the modems. Only
2094 modem = g_try_new0(struct modem_data, 1);
2098 modem->path = g_strdup(path);
2100 g_hash_table_insert(modem_hash, g_strdup(path), modem);
2102 while (dbus_message_iter_get_arg_type(prop) == DBUS_TYPE_DICT_ENTRY) {
2103 DBusMessageIter entry, value;
2106 dbus_message_iter_recurse(prop, &entry);
2107 dbus_message_iter_get_basic(&entry, &key);
2109 dbus_message_iter_next(&entry);
2110 dbus_message_iter_recurse(&entry, &value);
2112 if (g_str_equal(key, "Powered") == TRUE) {
2113 dbus_message_iter_get_basic(&value, &modem->powered);
2115 DBG("%s Powered %d", modem->path, modem->powered);
2116 } else if (g_str_equal(key, "Online") == TRUE) {
2117 dbus_message_iter_get_basic(&value, &modem->online);
2119 DBG("%s Online %d", modem->path, modem->online);
2120 } else if (g_str_equal(key, "Interfaces") == TRUE) {
2121 modem->interfaces = extract_interfaces(&value);
2123 DBG("%s Interfaces 0x%02x", modem->path,
2125 } else if (g_str_equal(key, "Serial") == TRUE) {
2128 dbus_message_iter_get_basic(&value, &serial);
2129 modem->serial = g_strdup(serial);
2131 DBG("%s Serial %s", modem->path, modem->serial);
2132 } else if (g_str_equal(key, "Type") == TRUE) {
2135 dbus_message_iter_get_basic(&value, &type);
2137 DBG("%s Type %s", modem->path, type);
2138 if (g_strcmp0(type, "hardware") != 0) {
2139 DBG("%s Ignore this modem", modem->path);
2140 modem->ignore = TRUE;
2144 dbus_message_iter_next(prop);
2147 if (modem->ignore == TRUE)
2150 if (modem->powered == FALSE) {
2151 modem_set_powered(modem, TRUE);
2155 modem_update_interfaces(modem, 0, modem->interfaces);
2158 static void modem_power_down(gpointer key, gpointer value, gpointer user_data)
2160 struct modem_data *modem = value;
2162 DBG("%s", modem->path);
2164 if (modem->ignore == TRUE)
2167 modem_set_powered(modem, FALSE);
2170 static void remove_modem(gpointer data)
2172 struct modem_data *modem = data;
2174 DBG("%s", modem->path);
2176 if (modem->call_set_property != NULL)
2177 dbus_pending_call_cancel(modem->call_set_property);
2179 if (modem->call_get_properties != NULL)
2180 dbus_pending_call_cancel(modem->call_get_properties);
2182 if (modem->call_get_contexts != NULL)
2183 dbus_pending_call_cancel(modem->call_get_contexts);
2185 if (modem->device != NULL)
2186 destroy_device(modem);
2188 if (modem->context != NULL)
2189 remove_cm_context(modem, modem->context->path);
2191 g_free(modem->serial);
2192 g_free(modem->name);
2193 g_free(modem->imsi);
2194 g_free(modem->path);
2199 static gboolean modem_added(DBusConnection *connection,
2200 DBusMessage *message, void *user_data)
2202 DBusMessageIter iter, properties;
2207 if (dbus_message_iter_init(message, &iter) == FALSE)
2210 dbus_message_iter_get_basic(&iter, &path);
2212 dbus_message_iter_next(&iter);
2213 dbus_message_iter_recurse(&iter, &properties);
2215 add_modem(path, &properties);
2220 static gboolean modem_removed(DBusConnection *connection,
2221 DBusMessage *message, void *user_data)
2223 DBusMessageIter iter;
2228 if (dbus_message_iter_init(message, &iter) == FALSE)
2231 dbus_message_iter_get_basic(&iter, &path);
2233 g_hash_table_remove(modem_hash, path);
2238 static void manager_get_modems_reply(DBusPendingCall *call, void *user_data)
2242 DBusMessageIter array, dict;
2246 reply = dbus_pending_call_steal_reply(call);
2248 dbus_error_init(&error);
2250 if (dbus_set_error_from_message(&error, reply) == TRUE) {
2251 connman_error("%s", error.message);
2252 dbus_error_free(&error);
2256 if (dbus_message_iter_init(reply, &array) == FALSE)
2259 dbus_message_iter_recurse(&array, &dict);
2261 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT) {
2262 DBusMessageIter value, properties;
2265 dbus_message_iter_recurse(&dict, &value);
2266 dbus_message_iter_get_basic(&value, &path);
2268 dbus_message_iter_next(&value);
2269 dbus_message_iter_recurse(&value, &properties);
2271 add_modem(path, &properties);
2273 dbus_message_iter_next(&dict);
2277 dbus_message_unref(reply);
2279 dbus_pending_call_unref(call);
2282 static int manager_get_modems(void)
2284 DBusMessage *message;
2285 DBusPendingCall *call;
2289 message = dbus_message_new_method_call(OFONO_SERVICE, "/",
2290 OFONO_MANAGER_INTERFACE, GET_MODEMS);
2291 if (message == NULL)
2294 if (dbus_connection_send_with_reply(connection, message,
2295 &call, TIMEOUT) == FALSE) {
2296 connman_error("Failed to call GetModems()");
2297 dbus_message_unref(message);
2302 connman_error("D-Bus connection not available");
2303 dbus_message_unref(message);
2307 dbus_pending_call_set_notify(call, manager_get_modems_reply,
2310 dbus_message_unref(message);
2312 return -EINPROGRESS;
2315 static void ofono_connect(DBusConnection *conn, void *user_data)
2319 modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2320 g_free, remove_modem);
2321 if (modem_hash == NULL)
2324 context_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2326 if (context_hash == NULL) {
2327 g_hash_table_destroy(modem_hash);
2331 manager_get_modems();
2334 static void ofono_disconnect(DBusConnection *conn, void *user_data)
2338 if (modem_hash == NULL || context_hash == NULL)
2341 g_hash_table_destroy(modem_hash);
2344 g_hash_table_destroy(context_hash);
2345 context_hash = NULL;
2348 static int network_probe(struct connman_network *network)
2350 struct modem_data *modem = connman_network_get_data(network);
2352 DBG("%s network %p", modem->path, network);
2357 static void network_remove(struct connman_network *network)
2359 struct modem_data *modem = connman_network_get_data(network);
2361 DBG("%s network %p", modem->path, network);
2364 static int network_connect(struct connman_network *network)
2366 struct modem_data *modem = connman_network_get_data(network);
2368 DBG("%s network %p", modem->path, network);
2370 if (has_interface(modem->interfaces, OFONO_API_CM) == TRUE)
2371 return context_set_active(modem, TRUE);
2372 else if (has_interface(modem->interfaces, OFONO_API_CDMA_CM) == TRUE)
2373 return cdma_cm_set_powered(modem, TRUE);
2375 connman_error("Connection manager interface not available");
2380 static int network_disconnect(struct connman_network *network)
2382 struct modem_data *modem = connman_network_get_data(network);
2384 DBG("%s network %p", modem->path, network);
2386 if (has_interface(modem->interfaces, OFONO_API_CM) == TRUE)
2387 return context_set_active(modem, FALSE);
2388 else if (has_interface(modem->interfaces, OFONO_API_CDMA_CM) == TRUE)
2389 return cdma_cm_set_powered(modem, FALSE);
2391 connman_error("Connection manager interface not available");
2396 static struct connman_network_driver network_driver = {
2398 .type = CONNMAN_NETWORK_TYPE_CELLULAR,
2399 .probe = network_probe,
2400 .remove = network_remove,
2401 .connect = network_connect,
2402 .disconnect = network_disconnect,
2405 static int modem_probe(struct connman_device *device)
2407 struct modem_data *modem = connman_device_get_data(device);
2409 DBG("%s device %p", modem->path, device);
2414 static void modem_remove(struct connman_device *device)
2416 struct modem_data *modem = connman_device_get_data(device);
2418 DBG("%s device %p", modem->path, device);
2421 static int modem_enable(struct connman_device *device)
2423 struct modem_data *modem = connman_device_get_data(device);
2425 DBG("%s device %p", modem->path, device);
2427 if (modem->online == TRUE)
2430 return modem_set_online(modem, TRUE);
2433 static int modem_disable(struct connman_device *device)
2435 struct modem_data *modem = connman_device_get_data(device);
2437 DBG("%s device %p", modem->path, device);
2439 if (modem->online == FALSE)
2442 return modem_set_online(modem, FALSE);
2445 static struct connman_device_driver modem_driver = {
2447 .type = CONNMAN_DEVICE_TYPE_CELLULAR,
2448 .probe = modem_probe,
2449 .remove = modem_remove,
2450 .enable = modem_enable,
2451 .disable = modem_disable,
2454 static int tech_probe(struct connman_technology *technology)
2459 static void tech_remove(struct connman_technology *technology)
2463 static struct connman_technology_driver tech_driver = {
2465 .type = CONNMAN_SERVICE_TYPE_CELLULAR,
2466 .probe = tech_probe,
2467 .remove = tech_remove,
2471 static guint modem_added_watch;
2472 static guint modem_removed_watch;
2473 static guint modem_watch;
2474 static guint cm_watch;
2475 static guint sim_watch;
2476 static guint context_added_watch;
2477 static guint context_removed_watch;
2478 static guint netreg_watch;
2479 static guint context_watch;
2480 static guint cdma_cm_watch;
2481 static guint cdma_netreg_watch;
2483 static int ofono_init(void)
2489 connection = connman_dbus_get_connection();
2490 if (connection == NULL)
2493 watch = g_dbus_add_service_watch(connection,
2494 OFONO_SERVICE, ofono_connect,
2495 ofono_disconnect, NULL, NULL);
2497 modem_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2498 OFONO_MANAGER_INTERFACE,
2503 modem_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2504 OFONO_MANAGER_INTERFACE,
2509 modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2510 OFONO_MODEM_INTERFACE,
2515 cm_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2521 sim_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2522 OFONO_SIM_INTERFACE,
2527 context_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2533 context_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2539 context_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2540 OFONO_CONTEXT_INTERFACE,
2545 netreg_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2546 OFONO_NETREG_INTERFACE,
2551 cdma_cm_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2552 OFONO_CDMA_CM_INTERFACE,
2557 cdma_netreg_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
2558 OFONO_CDMA_NETREG_INTERFACE,
2560 cdma_netreg_changed,
2564 if (watch == 0 || modem_added_watch == 0 || modem_removed_watch == 0 ||
2565 modem_watch == 0 || cm_watch == 0 || sim_watch == 0 ||
2566 context_added_watch == 0 ||
2567 context_removed_watch == 0 ||
2568 context_watch == 0 || netreg_watch == 0 ||
2569 cdma_cm_watch == 0 || cdma_netreg_watch == 0) {
2574 err = connman_network_driver_register(&network_driver);
2578 err = connman_device_driver_register(&modem_driver);
2580 connman_network_driver_unregister(&network_driver);
2584 err = connman_technology_driver_register(&tech_driver);
2586 connman_device_driver_unregister(&modem_driver);
2587 connman_network_driver_unregister(&network_driver);
2594 g_dbus_remove_watch(connection, cdma_netreg_watch);
2595 g_dbus_remove_watch(connection, cdma_cm_watch);
2596 g_dbus_remove_watch(connection, netreg_watch);
2597 g_dbus_remove_watch(connection, context_watch);
2598 g_dbus_remove_watch(connection, context_removed_watch);
2599 g_dbus_remove_watch(connection, context_added_watch);
2600 g_dbus_remove_watch(connection, sim_watch);
2601 g_dbus_remove_watch(connection, cm_watch);
2602 g_dbus_remove_watch(connection, modem_watch);
2603 g_dbus_remove_watch(connection, modem_removed_watch);
2604 g_dbus_remove_watch(connection, modem_added_watch);
2605 g_dbus_remove_watch(connection, watch);
2606 dbus_connection_unref(connection);
2611 static void ofono_exit(void)
2615 if (modem_hash != NULL) {
2617 * We should propably wait for the SetProperty() reply
2618 * message, because ...
2620 g_hash_table_foreach(modem_hash, modem_power_down, NULL);
2623 * ... here we will cancel the call.
2625 g_hash_table_destroy(modem_hash);
2629 if (context_hash != NULL) {
2630 g_hash_table_destroy(context_hash);
2631 context_hash = NULL;
2634 connman_technology_driver_unregister(&tech_driver);
2635 connman_device_driver_unregister(&modem_driver);
2636 connman_network_driver_unregister(&network_driver);
2638 g_dbus_remove_watch(connection, cdma_netreg_watch);
2639 g_dbus_remove_watch(connection, cdma_cm_watch);
2640 g_dbus_remove_watch(connection, netreg_watch);
2641 g_dbus_remove_watch(connection, context_watch);
2642 g_dbus_remove_watch(connection, context_removed_watch);
2643 g_dbus_remove_watch(connection, context_added_watch);
2644 g_dbus_remove_watch(connection, sim_watch);
2645 g_dbus_remove_watch(connection, cm_watch);
2646 g_dbus_remove_watch(connection, modem_watch);
2647 g_dbus_remove_watch(connection, modem_added_watch);
2648 g_dbus_remove_watch(connection, modem_removed_watch);
2649 g_dbus_remove_watch(connection, watch);
2651 dbus_connection_unref(connection);
2654 CONNMAN_PLUGIN_DEFINE(ofono, "oFono telephony plugin", VERSION,
2655 CONNMAN_PLUGIN_PRIORITY_DEFAULT, ofono_init, ofono_exit)