5 * Copyright (C) 2007-2012 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 OFONO_SERVICE "org.ofono"
48 #define OFONO_MANAGER_INTERFACE OFONO_SERVICE ".Manager"
49 #define OFONO_MODEM_INTERFACE OFONO_SERVICE ".Modem"
50 #define OFONO_SIM_INTERFACE OFONO_SERVICE ".SimManager"
51 #define OFONO_NETREG_INTERFACE OFONO_SERVICE ".NetworkRegistration"
52 #define OFONO_CM_INTERFACE OFONO_SERVICE ".ConnectionManager"
53 #define OFONO_CONTEXT_INTERFACE OFONO_SERVICE ".ConnectionContext"
54 #define OFONO_CDMA_CM_INTERFACE OFONO_SERVICE ".cdma.ConnectionManager"
55 #define OFONO_CDMA_NETREG_INTERFACE OFONO_SERVICE ".cdma.NetworkRegistration"
57 #define MODEM_ADDED "ModemAdded"
58 #define MODEM_REMOVED "ModemRemoved"
59 #define PROPERTY_CHANGED "PropertyChanged"
60 #define CONTEXT_ADDED "ContextAdded"
61 #define CONTEXT_REMOVED "ContextRemoved"
63 #define GET_PROPERTIES "GetProperties"
64 #define SET_PROPERTY "SetProperty"
65 #define GET_MODEMS "GetModems"
66 #define GET_CONTEXTS "GetContexts"
72 OFONO_API_NETREG = 0x2,
74 OFONO_API_CDMA_NETREG = 0x8,
75 OFONO_API_CDMA_CM = 0x10,
79 * The way this plugin works is following:
81 * powered -> SubscriberIdentity or Online = True -> gprs, context ->
82 * attached -> netreg -> ready
84 * Depending on the modem type, this plugin will behave differently.
88 * When a new modem appears, the plugin always powers it up. This
89 * allows the plugin to create a connman_device. The core will call
90 * modem_enable() if the technology is enabled. modem_enable() will
91 * then set the modem online. If the technology is disabled then
92 * modem_disable() will just set the modem offline. The modem is
93 * always kept powered all the time.
95 * After setting the modem online the plugin waits for the
96 * ConnectionManager and ConnectionContext to appear. When the context
97 * signals that it is attached and the NetworkRegistration interface
98 * appears, a new Service will be created and registered at the core.
100 * When asked to connect to the network (network_connect()) the plugin
101 * will set the Active property on the context. If this operation is
102 * successful the modem is connected to the network. oFono will inform
103 * the plugin about IP configuration through the updating the context's
108 * When a new modem appears, the plugin always powers it up. This
109 * allows the plugin to create connman_device either using IMSI either
110 * using modem Serial if the modem got a SIM interface or not.
112 * As for GSM, the core will call modem_enable() if the technology
113 * is enabled. modem_enable() will then set the modem online.
114 * If the technology is disabled then modem_disable() will just set the
115 * modem offline. The modem is always kept powered all the time.
117 * After setting the modem online the plugin waits for CdmaConnectionManager
118 * interface to appear. Then, once CdmaNetworkRegistration appears, a new
119 * Service will be created and registered at the core.
121 * When asked to connect to the network (network_connect()) the plugin
122 * will power up the CdmaConnectionManager interface.
123 * If the operation is successful the modem is connected to the network.
124 * oFono will inform the plugin about IP configuration through the
125 * updating CdmaConnectionManager settings properties.
128 static DBusConnection *connection;
130 static GHashTable *modem_hash;
131 static GHashTable *context_hash;
133 struct network_context {
137 enum connman_ipconfig_method ipv4_method;
138 struct connman_ipaddress *ipv4_address;
139 char *ipv4_nameservers;
141 enum connman_ipconfig_method ipv6_method;
142 struct connman_ipaddress *ipv6_address;
143 char *ipv6_nameservers;
149 struct connman_device *device;
150 struct connman_network *network;
152 struct network_context *context;
154 /* Modem Interface */
156 connman_bool_t powered;
157 connman_bool_t online;
159 connman_bool_t ignore;
161 connman_bool_t set_powered;
163 /* CDMA ConnectionManager Interface */
164 connman_bool_t cdma_cm_powered;
166 /* ConnectionManager Interface */
167 connman_bool_t attached;
168 connman_bool_t cm_powered;
170 /* ConnectionContext Interface */
171 connman_bool_t active;
172 connman_bool_t set_active;
173 connman_bool_t valid_apn; /* APN is 'valid' if length > 0 */
175 /* SimManager Interface */
178 /* Netreg Interface */
181 uint8_t data_strength; /* 1xEVDO signal strength */
182 connman_bool_t roaming;
185 DBusPendingCall *call_set_property;
186 DBusPendingCall *call_get_properties;
187 DBusPendingCall *call_get_contexts;
190 static const char *api2string(enum ofono_api api)
195 case OFONO_API_NETREG:
199 case OFONO_API_CDMA_NETREG:
200 return "cdma-netreg";
201 case OFONO_API_CDMA_CM:
208 static char *get_ident(const char *path)
215 pos = strrchr(path, '/');
222 static struct network_context *network_context_alloc(const char *path)
224 struct network_context *context;
226 context = g_try_new0(struct network_context, 1);
230 context->path = g_strdup(path);
233 context->ipv4_method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
234 context->ipv4_address = NULL;
235 context->ipv4_nameservers = NULL;
237 context->ipv6_method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
238 context->ipv6_address = NULL;
239 context->ipv6_nameservers = NULL;
244 static void network_context_free(struct network_context *context)
246 g_free(context->path);
248 connman_ipaddress_free(context->ipv4_address);
249 g_free(context->ipv4_nameservers);
251 connman_ipaddress_free(context->ipv6_address);
252 g_free(context->ipv6_nameservers);
257 static void set_connected(struct modem_data *modem)
259 struct connman_service *service;
260 connman_bool_t setip = FALSE;
261 enum connman_ipconfig_method method;
264 DBG("%s", modem->path);
266 index = modem->context->index;
268 if (index < 0 || modem->context->ipv4_address == NULL) {
269 connman_error("Invalid index and/or address");
273 service = connman_service_lookup_from_network(modem->network);
277 method = modem->context->ipv4_method;
278 if (method == CONNMAN_IPCONFIG_METHOD_FIXED ||
279 method == CONNMAN_IPCONFIG_METHOD_DHCP)
281 connman_service_create_ip4config(service, index);
282 connman_network_set_index(modem->network, index);
284 connman_network_set_ipv4_method(modem->network, method);
289 if (method == CONNMAN_IPCONFIG_METHOD_FIXED) {
290 connman_network_set_ipaddress(modem->network,
291 modem->context->ipv4_address);
292 connman_network_set_nameservers(modem->network,
293 modem->context->ipv4_nameservers);
296 method = modem->context->ipv6_method;
297 if (method == CONNMAN_IPCONFIG_METHOD_FIXED) {
298 connman_service_create_ip6config(service, index);
299 connman_network_set_ipv6_method(modem->network, method);
300 connman_network_set_ipaddress(modem->network,
301 modem->context->ipv6_address);
306 connman_network_set_connected(modem->network, TRUE);
309 static void set_disconnected(struct modem_data *modem)
311 DBG("%s", modem->path);
313 if (modem->network == NULL)
316 connman_network_set_connected(modem->network, FALSE);
319 typedef void (*set_property_cb)(struct modem_data *data,
320 connman_bool_t success);
321 typedef void (*get_properties_cb)(struct modem_data *data,
322 DBusMessageIter *dict);
324 struct property_info {
325 struct modem_data *modem;
327 const char *interface;
328 const char *property;
329 set_property_cb set_property_cb;
330 get_properties_cb get_properties_cb;
333 static void set_property_reply(DBusPendingCall *call, void *user_data)
335 struct property_info *info = user_data;
338 connman_bool_t success = TRUE;
340 DBG("%s path %s %s.%s", info->modem->path,
341 info->path, info->interface, info->property);
343 info->modem->call_set_property = NULL;
345 dbus_error_init(&error);
347 reply = dbus_pending_call_steal_reply(call);
349 if (dbus_set_error_from_message(&error, reply)) {
350 connman_error("Failed to change property: %s %s.%s: %s %s",
351 info->path, info->interface, info->property,
352 error.name, error.message);
353 dbus_error_free(&error);
357 if (info->set_property_cb != NULL)
358 (*info->set_property_cb)(info->modem, success);
360 dbus_message_unref(reply);
362 dbus_pending_call_unref(call);
365 static int set_property(struct modem_data *modem,
366 const char *path, const char *interface,
367 const char *property, int type, void *value,
368 set_property_cb notify)
370 DBusMessage *message;
371 DBusMessageIter iter;
372 struct property_info *info;
374 DBG("%s path %s %s.%s", modem->path, path, interface, property);
376 if (modem->call_set_property != NULL) {
377 DBG("Cancel pending SetProperty");
379 dbus_pending_call_cancel(modem->call_set_property);
380 modem->call_set_property = NULL;
383 message = dbus_message_new_method_call(OFONO_SERVICE, path,
384 interface, SET_PROPERTY);
388 dbus_message_iter_init_append(message, &iter);
389 connman_dbus_property_append_basic(&iter, property, type, value);
391 if (dbus_connection_send_with_reply(connection, message,
392 &modem->call_set_property, TIMEOUT) == FALSE) {
393 connman_error("Failed to change property: %s %s.%s",
394 path, interface, property);
395 dbus_message_unref(message);
399 if (modem->call_set_property == NULL) {
400 connman_error("D-Bus connection not available");
401 dbus_message_unref(message);
405 info = g_try_new0(struct property_info, 1);
407 dbus_message_unref(message);
413 info->interface = interface;
414 info->property = property;
415 info->set_property_cb = notify;
417 dbus_pending_call_set_notify(modem->call_set_property,
418 set_property_reply, info, g_free);
420 dbus_message_unref(message);
425 static void get_properties_reply(DBusPendingCall *call, void *user_data)
427 struct property_info *info = user_data;
428 DBusMessageIter array, dict;
432 DBG("%s path %s %s", info->modem->path, info->path, info->interface);
434 info->modem->call_get_properties = NULL;
436 dbus_error_init(&error);
438 reply = dbus_pending_call_steal_reply(call);
440 if (dbus_set_error_from_message(&error, reply)) {
441 connman_error("Failed to get properties: %s %s: %s %s",
442 info->path, info->interface,
443 error.name, error.message);
444 dbus_error_free(&error);
449 if (dbus_message_iter_init(reply, &array) == FALSE)
452 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
455 dbus_message_iter_recurse(&array, &dict);
457 if (info->get_properties_cb != NULL)
458 (*info->get_properties_cb)(info->modem, &dict);
462 dbus_message_unref(reply);
464 dbus_pending_call_unref(call);
467 static int get_properties(const char *path, const char *interface,
468 get_properties_cb notify,
469 struct modem_data *modem)
471 DBusMessage *message;
472 struct property_info *info;
474 DBG("%s path %s %s", modem->path, path, interface);
476 if (modem->call_get_properties != NULL) {
477 connman_error("Pending GetProperties");
481 message = dbus_message_new_method_call(OFONO_SERVICE, path,
482 interface, GET_PROPERTIES);
486 if (dbus_connection_send_with_reply(connection, message,
487 &modem->call_get_properties, TIMEOUT) == FALSE) {
488 connman_error("Failed to call %s.GetProperties()", interface);
489 dbus_message_unref(message);
493 if (modem->call_get_properties == NULL) {
494 connman_error("D-Bus connection not available");
495 dbus_message_unref(message);
499 info = g_try_new0(struct property_info, 1);
501 dbus_message_unref(message);
507 info->interface = interface;
508 info->get_properties_cb = notify;
510 dbus_pending_call_set_notify(modem->call_get_properties,
511 get_properties_reply, info, g_free);
513 dbus_message_unref(message);
518 static void context_set_active_reply(struct modem_data *modem,
519 connman_bool_t success)
521 DBG("%s", modem->path);
523 if (success == TRUE) {
525 * Don't handle do anything on success here. oFono will send
526 * the change via PropertyChanged singal.
532 * Active = True might fail due a timeout. That means oFono
533 * still tries to go online. If we retry to set Active = True,
534 * we just get a InProgress error message. Should we power
535 * cycle the modem in such cases?
538 if (modem->network == NULL) {
540 * In the case where we power down the device
541 * we don't wait for the reply, therefore the network
542 * might already be gone.
547 connman_network_set_error(modem->network,
548 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
551 static int context_set_active(struct modem_data *modem,
552 connman_bool_t active)
556 DBG("%s active %d", modem->path, active);
558 err = set_property(modem, modem->context->path,
559 OFONO_CONTEXT_INTERFACE,
560 "Active", DBUS_TYPE_BOOLEAN,
562 context_set_active_reply);
564 if (active == FALSE && err == -EINPROGRESS)
570 static void cdma_cm_set_powered_reply(struct modem_data *modem,
571 connman_bool_t success)
573 DBG("%s", modem->path);
575 if (success == TRUE) {
577 * Don't handle do anything on success here. oFono will send
578 * the change via PropertyChanged singal.
584 * Powered = True might fail due a timeout. That means oFono
585 * still tries to go online. If we retry to set Powered = True,
586 * we just get a InProgress error message. Should we power
587 * cycle the modem in such cases?
590 if (modem->network == NULL) {
592 * In the case where we power down the device
593 * we don't wait for the reply, therefore the network
594 * might already be gone.
599 connman_network_set_error(modem->network,
600 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
603 static int cdma_cm_set_powered(struct modem_data *modem, connman_bool_t powered)
607 DBG("%s powered %d", modem->path, powered);
609 err = set_property(modem, modem->path, OFONO_CDMA_CM_INTERFACE,
610 "Powered", DBUS_TYPE_BOOLEAN,
612 cdma_cm_set_powered_reply);
614 if (powered == FALSE && err == -EINPROGRESS)
620 static int modem_set_online(struct modem_data *modem, connman_bool_t online)
622 DBG("%s online %d", modem->path, online);
624 return set_property(modem, modem->path,
625 OFONO_MODEM_INTERFACE,
626 "Online", DBUS_TYPE_BOOLEAN,
631 static int cm_set_powered(struct modem_data *modem, connman_bool_t powered)
635 DBG("%s powered %d", modem->path, powered);
637 err = set_property(modem, modem->path,
639 "Powered", DBUS_TYPE_BOOLEAN,
643 if (powered == FALSE && err == -EINPROGRESS)
649 static int modem_set_powered(struct modem_data *modem, connman_bool_t powered)
653 DBG("%s powered %d", modem->path, powered);
655 modem->set_powered = powered;
657 err = set_property(modem, modem->path,
658 OFONO_MODEM_INTERFACE,
659 "Powered", DBUS_TYPE_BOOLEAN,
663 if (powered == FALSE && err == -EINPROGRESS)
669 static connman_bool_t has_interface(uint8_t interfaces,
672 if ((interfaces & api) == api)
678 static uint8_t extract_interfaces(DBusMessageIter *array)
680 DBusMessageIter entry;
681 uint8_t interfaces = 0;
683 dbus_message_iter_recurse(array, &entry);
685 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
688 dbus_message_iter_get_basic(&entry, &name);
690 if (g_str_equal(name, OFONO_SIM_INTERFACE) == TRUE)
691 interfaces |= OFONO_API_SIM;
692 else if (g_str_equal(name, OFONO_NETREG_INTERFACE) == TRUE)
693 interfaces |= OFONO_API_NETREG;
694 else if (g_str_equal(name, OFONO_CM_INTERFACE) == TRUE)
695 interfaces |= OFONO_API_CM;
696 else if (g_str_equal(name, OFONO_CDMA_CM_INTERFACE) == TRUE)
697 interfaces |= OFONO_API_CDMA_CM;
698 else if (g_str_equal(name, OFONO_CDMA_NETREG_INTERFACE) == TRUE)
699 interfaces |= OFONO_API_CDMA_NETREG;
701 dbus_message_iter_next(&entry);
707 static char *extract_nameservers(DBusMessageIter *array)
709 DBusMessageIter entry;
710 char *nameservers = NULL;
713 dbus_message_iter_recurse(array, &entry);
715 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
716 const char *nameserver;
718 dbus_message_iter_get_basic(&entry, &nameserver);
720 if (nameservers == NULL) {
721 nameservers = g_strdup(nameserver);
724 nameservers = g_strdup_printf("%s %s", tmp, nameserver);
728 dbus_message_iter_next(&entry);
734 static void extract_ipv4_settings(DBusMessageIter *array,
735 struct network_context *context)
737 DBusMessageIter dict;
738 char *address = NULL, *netmask = NULL, *gateway = NULL;
739 char *nameservers = NULL;
740 const char *interface = NULL;
743 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
746 dbus_message_iter_recurse(array, &dict);
748 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
749 DBusMessageIter entry, value;
750 const char *key, *val;
752 dbus_message_iter_recurse(&dict, &entry);
753 dbus_message_iter_get_basic(&entry, &key);
755 dbus_message_iter_next(&entry);
756 dbus_message_iter_recurse(&entry, &value);
758 if (g_str_equal(key, "Interface") == TRUE) {
759 dbus_message_iter_get_basic(&value, &interface);
761 DBG("Interface %s", interface);
763 index = connman_inet_ifindex(interface);
765 DBG("index %d", index);
766 } else if (g_str_equal(key, "Method") == TRUE) {
767 dbus_message_iter_get_basic(&value, &val);
769 DBG("Method %s", val);
771 if (g_strcmp0(val, "static") == 0) {
772 context->ipv4_method = CONNMAN_IPCONFIG_METHOD_FIXED;
773 } else if (g_strcmp0(val, "dhcp") == 0) {
774 context->ipv4_method = CONNMAN_IPCONFIG_METHOD_DHCP;
777 } else if (g_str_equal(key, "Address") == TRUE) {
778 dbus_message_iter_get_basic(&value, &val);
780 address = g_strdup(val);
782 DBG("Address %s", address);
783 } else if (g_str_equal(key, "Netmask") == TRUE) {
784 dbus_message_iter_get_basic(&value, &val);
786 netmask = g_strdup(val);
788 DBG("Netmask %s", netmask);
789 } else if (g_str_equal(key, "DomainNameServers") == TRUE) {
790 nameservers = extract_nameservers(&value);
792 DBG("Nameservers %s", nameservers);
793 } else if (g_str_equal(key, "Gateway") == TRUE) {
794 dbus_message_iter_get_basic(&value, &val);
796 gateway = g_strdup(val);
798 DBG("Gateway %s", gateway);
801 dbus_message_iter_next(&dict);
807 if (context->ipv4_method != CONNMAN_IPCONFIG_METHOD_FIXED)
810 context->ipv4_address = connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4);
811 if (context->ipv4_address == NULL)
814 context->index = index;
815 connman_ipaddress_set_ipv4(context->ipv4_address, address,
818 context->ipv4_nameservers = nameservers;
821 if (context->ipv4_nameservers != nameservers)
829 static void extract_ipv6_settings(DBusMessageIter *array,
830 struct network_context *context)
832 DBusMessageIter dict;
833 char *address = NULL, *gateway = NULL;
834 unsigned char prefix_length = 0;
835 char *nameservers = NULL;
836 const char *interface = NULL;
839 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
842 dbus_message_iter_recurse(array, &dict);
844 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
845 DBusMessageIter entry, value;
846 const char *key, *val;
848 dbus_message_iter_recurse(&dict, &entry);
849 dbus_message_iter_get_basic(&entry, &key);
851 dbus_message_iter_next(&entry);
852 dbus_message_iter_recurse(&entry, &value);
854 if (g_str_equal(key, "Interface") == TRUE) {
855 dbus_message_iter_get_basic(&value, &interface);
857 DBG("Interface %s", interface);
859 index = connman_inet_ifindex(interface);
861 DBG("index %d", index);
862 } else if (g_str_equal(key, "Address") == TRUE) {
863 dbus_message_iter_get_basic(&value, &val);
865 address = g_strdup(val);
867 DBG("Address %s", address);
868 } else if (g_str_equal(key, "PrefixLength") == TRUE) {
869 dbus_message_iter_get_basic(&value, &prefix_length);
871 DBG("prefix length %d", prefix_length);
872 } else if (g_str_equal(key, "DomainNameServers") == TRUE) {
873 nameservers = extract_nameservers(&value);
875 DBG("Nameservers %s", nameservers);
876 } else if (g_str_equal(key, "Gateway") == TRUE) {
877 dbus_message_iter_get_basic(&value, &val);
879 gateway = g_strdup(val);
881 DBG("Gateway %s", gateway);
884 dbus_message_iter_next(&dict);
890 context->ipv6_method = CONNMAN_IPCONFIG_METHOD_FIXED;
892 context->ipv6_address =
893 connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6);
894 if (context->ipv6_address == NULL)
897 context->index = index;
898 connman_ipaddress_set_ipv6(context->ipv6_address, address,
899 prefix_length, gateway);
901 context->ipv6_nameservers = nameservers;
904 if (context->ipv6_nameservers != nameservers)
911 static connman_bool_t ready_to_create_device(struct modem_data *modem)
914 * There are three different modem types which behave slightly
916 * - GSM modems will expose the SIM interface then the
918 * - CDMA modems will expose CM first and sometime later
919 * a unique serial number.
921 * This functions tests if we have the necessary information gathered
922 * before we are able to create a device.
925 if (modem->device != NULL)
928 if (modem->imsi != NULL || modem->serial != NULL)
934 static void create_device(struct modem_data *modem)
936 struct connman_device *device;
939 DBG("%s", modem->path);
941 if (modem->imsi != NULL)
943 else if (modem->serial != NULL)
944 ident = modem->serial;
946 if (connman_dbus_validate_ident(ident) == FALSE)
947 ident = connman_dbus_encode_string(ident);
949 ident = g_strdup(ident);
951 device = connman_device_create(ident, CONNMAN_DEVICE_TYPE_CELLULAR);
955 DBG("device %p", device);
957 connman_device_set_ident(device, ident);
959 connman_device_set_string(device, "Path", modem->path);
961 connman_device_set_data(device, modem);
963 if (connman_device_register(device) < 0) {
964 connman_error("Failed to register cellular device");
965 connman_device_unref(device);
969 modem->device = device;
971 connman_device_set_powered(modem->device, modem->online);
976 static void destroy_device(struct modem_data *modem)
978 DBG("%s", modem->path);
980 connman_device_set_powered(modem->device, FALSE);
982 if (modem->network != NULL) {
983 connman_device_remove_network(modem->device, modem->network);
984 connman_network_unref(modem->network);
985 modem->network = NULL;
988 connman_device_unregister(modem->device);
989 connman_device_unref(modem->device);
991 modem->device = NULL;
994 static void add_network(struct modem_data *modem)
998 DBG("%s", modem->path);
1000 if (modem->network != NULL)
1003 modem->network = connman_network_create(modem->context->path,
1004 CONNMAN_NETWORK_TYPE_CELLULAR);
1005 if (modem->network == NULL)
1008 DBG("network %p", modem->network);
1010 connman_network_set_data(modem->network, modem);
1012 connman_network_set_string(modem->network, "Path",
1013 modem->context->path);
1015 if (modem->name != NULL)
1016 connman_network_set_name(modem->network, modem->name);
1018 connman_network_set_name(modem->network, "");
1020 connman_network_set_strength(modem->network, modem->strength);
1022 group = get_ident(modem->context->path);
1023 connman_network_set_group(modem->network, group);
1025 connman_network_set_available(modem->network, TRUE);
1027 connman_network_set_bool(modem->network, "Roaming",
1030 if (connman_device_add_network(modem->device, modem->network) < 0) {
1031 connman_network_unref(modem->network);
1032 modem->network = NULL;
1037 static void remove_network(struct modem_data *modem)
1039 DBG("%s", modem->path);
1041 if (modem->network == NULL)
1044 DBG("network %p", modem->network);
1046 connman_device_remove_network(modem->device, modem->network);
1047 connman_network_unref(modem->network);
1048 modem->network = NULL;
1051 static int add_cm_context(struct modem_data *modem, const char *context_path,
1052 DBusMessageIter *dict)
1054 const char *context_type = NULL;
1055 struct network_context *context = NULL;
1056 connman_bool_t active = FALSE;
1058 DBG("%s context path %s", modem->path, context_path);
1060 if (modem->context != NULL) {
1062 * We have already assigned a context to this modem
1063 * and we do only support one Internet context.
1068 context = network_context_alloc(context_path);
1069 if (context == NULL)
1072 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1073 DBusMessageIter entry, value;
1076 dbus_message_iter_recurse(dict, &entry);
1077 dbus_message_iter_get_basic(&entry, &key);
1079 dbus_message_iter_next(&entry);
1080 dbus_message_iter_recurse(&entry, &value);
1082 if (g_str_equal(key, "Type") == TRUE) {
1083 dbus_message_iter_get_basic(&value, &context_type);
1085 DBG("%s context %s type %s", modem->path,
1086 context_path, context_type);
1087 } else if (g_str_equal(key, "Settings") == TRUE) {
1088 DBG("%s Settings", modem->path);
1090 extract_ipv4_settings(&value, context);
1091 } else if (g_str_equal(key, "IPv6.Settings") == TRUE) {
1092 DBG("%s IPv6.Settings", modem->path);
1094 extract_ipv6_settings(&value, context);
1095 } else if (g_str_equal(key, "Active") == TRUE) {
1096 dbus_message_iter_get_basic(&value, &active);
1098 DBG("%s Active %d", modem->path, active);
1099 } else if (g_str_equal(key, "AccessPointName") == TRUE) {
1102 dbus_message_iter_get_basic(&value, &apn);
1103 if (apn != NULL && strlen(apn) > 0)
1104 modem->valid_apn = TRUE;
1106 modem->valid_apn = FALSE;
1108 DBG("%s AccessPointName '%s'", modem->path, apn);
1110 dbus_message_iter_next(dict);
1113 if (g_strcmp0(context_type, "internet") != 0) {
1114 network_context_free(context);
1118 modem->context = context;
1119 modem->active = active;
1121 g_hash_table_replace(context_hash, g_strdup(context_path), modem);
1123 if (modem->valid_apn == TRUE && modem->attached == TRUE &&
1124 has_interface(modem->interfaces,
1125 OFONO_API_NETREG) == TRUE) {
1132 static void remove_cm_context(struct modem_data *modem,
1133 const char *context_path)
1135 if (modem->context == NULL)
1138 if (modem->network != NULL)
1139 remove_network(modem);
1141 g_hash_table_remove(context_hash, context_path);
1143 network_context_free(modem->context);
1144 modem->context = NULL;
1146 modem->valid_apn = FALSE;
1148 if (modem->network != NULL)
1149 remove_network(modem);
1152 static gboolean context_changed(DBusConnection *conn,
1153 DBusMessage *message,
1156 const char *context_path = dbus_message_get_path(message);
1157 struct modem_data *modem = NULL;
1158 DBusMessageIter iter, value;
1161 DBG("context_path %s", context_path);
1163 modem = g_hash_table_lookup(context_hash, context_path);
1167 if (dbus_message_iter_init(message, &iter) == FALSE)
1170 dbus_message_iter_get_basic(&iter, &key);
1172 dbus_message_iter_next(&iter);
1173 dbus_message_iter_recurse(&iter, &value);
1176 * oFono guarantees the ordering of Settings and
1177 * Active. Settings will always be send before Active = True.
1178 * That means we don't have to order here.
1180 if (g_str_equal(key, "Settings") == TRUE) {
1181 DBG("%s Settings", modem->path);
1183 extract_ipv4_settings(&value, modem->context);
1184 } else if (g_str_equal(key, "IPv6.Settings") == TRUE) {
1185 DBG("%s IPv6.Settings", modem->path);
1187 extract_ipv6_settings(&value, modem->context);
1188 } else if (g_str_equal(key, "Active") == TRUE) {
1189 dbus_message_iter_get_basic(&value, &modem->active);
1191 DBG("%s Active %d", modem->path, modem->active);
1193 if (modem->active == TRUE)
1194 set_connected(modem);
1196 set_disconnected(modem);
1197 } else if (g_str_equal(key, "AccessPointName") == TRUE) {
1200 dbus_message_iter_get_basic(&value, &apn);
1202 DBG("%s AccessPointName %s", modem->path, apn);
1204 if (apn != NULL && strlen(apn) > 0) {
1205 modem->valid_apn = TRUE;
1207 if (modem->network != NULL)
1210 if (modem->attached == FALSE)
1213 if (has_interface(modem->interfaces,
1214 OFONO_API_NETREG) == FALSE) {
1220 if (modem->active == TRUE)
1221 set_connected(modem);
1223 modem->valid_apn = FALSE;
1225 if (modem->network == NULL)
1228 remove_network(modem);
1235 static void cm_get_contexts_reply(DBusPendingCall *call, void *user_data)
1237 struct modem_data *modem = user_data;
1238 DBusMessageIter array, dict, entry, value;
1242 DBG("%s", modem->path);
1244 modem->call_get_contexts = NULL;
1246 reply = dbus_pending_call_steal_reply(call);
1248 dbus_error_init(&error);
1250 if (dbus_set_error_from_message(&error, reply) == TRUE) {
1251 connman_error("%s", error.message);
1252 dbus_error_free(&error);
1256 if (dbus_message_iter_init(reply, &array) == FALSE)
1259 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
1262 dbus_message_iter_recurse(&array, &dict);
1264 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT) {
1265 const char *context_path;
1267 dbus_message_iter_recurse(&dict, &entry);
1268 dbus_message_iter_get_basic(&entry, &context_path);
1270 dbus_message_iter_next(&entry);
1271 dbus_message_iter_recurse(&entry, &value);
1273 if (add_cm_context(modem, context_path, &value) == 0)
1276 dbus_message_iter_next(&dict);
1280 dbus_message_unref(reply);
1282 dbus_pending_call_unref(call);
1285 static int cm_get_contexts(struct modem_data *modem)
1287 DBusMessage *message;
1289 DBG("%s", modem->path);
1291 if (modem->call_get_contexts != NULL)
1294 message = dbus_message_new_method_call(OFONO_SERVICE, modem->path,
1295 OFONO_CM_INTERFACE, GET_CONTEXTS);
1296 if (message == NULL)
1299 if (dbus_connection_send_with_reply(connection, message,
1300 &modem->call_get_contexts, TIMEOUT) == FALSE) {
1301 connman_error("Failed to call GetContexts()");
1302 dbus_message_unref(message);
1306 if (modem->call_get_contexts == NULL) {
1307 connman_error("D-Bus connection not available");
1308 dbus_message_unref(message);
1312 dbus_pending_call_set_notify(modem->call_get_contexts,
1313 cm_get_contexts_reply,
1316 dbus_message_unref(message);
1318 return -EINPROGRESS;
1321 static gboolean cm_context_added(DBusConnection *conn,
1322 DBusMessage *message,
1325 const char *path = dbus_message_get_path(message);
1327 struct modem_data *modem;
1328 DBusMessageIter iter, properties;
1332 modem = g_hash_table_lookup(modem_hash, path);
1336 if (dbus_message_iter_init(message, &iter) == FALSE)
1339 dbus_message_iter_get_basic(&iter, &context_path);
1341 dbus_message_iter_next(&iter);
1342 dbus_message_iter_recurse(&iter, &properties);
1344 if (add_cm_context(modem, context_path, &properties) != 0)
1350 static gboolean cm_context_removed(DBusConnection *conn,
1351 DBusMessage *message,
1354 const char *path = dbus_message_get_path(message);
1355 const char *context_path;
1356 struct modem_data *modem;
1357 DBusMessageIter iter;
1359 DBG("context path %s", path);
1361 if (dbus_message_iter_init(message, &iter) == FALSE)
1364 dbus_message_iter_get_basic(&iter, &context_path);
1366 modem = g_hash_table_lookup(context_hash, context_path);
1370 remove_cm_context(modem, context_path);
1375 static void netreg_update_name(struct modem_data *modem,
1376 DBusMessageIter* value)
1380 dbus_message_iter_get_basic(value, &name);
1382 DBG("%s Name %s", modem->path, name);
1384 g_free(modem->name);
1385 modem->name = g_strdup(name);
1387 if (modem->network == NULL)
1390 connman_network_set_name(modem->network, modem->name);
1391 connman_network_update(modem->network);
1394 static void netreg_update_strength(struct modem_data *modem,
1395 DBusMessageIter *value)
1397 dbus_message_iter_get_basic(value, &modem->strength);
1399 DBG("%s Strength %d", modem->path, modem->strength);
1401 if (modem->network == NULL)
1406 * We don't have 2 signal notifications we always report the strength
1407 * signal. data_strength is always equal to 0.
1410 * In the case we have a data_strength signal (from 1xEVDO network)
1411 * we don't need to update the value with strength signal (from 1xCDMA)
1412 * because the modem is registered to 1xEVDO network for data call.
1413 * In case we have no data_strength signal (not registered to 1xEVDO
1414 * network), we must report the strength signal (registered to 1xCDMA
1415 * network e.g slow mode).
1417 if (modem->data_strength != 0)
1420 connman_network_set_strength(modem->network, modem->strength);
1421 connman_network_update(modem->network);
1424 /* Retrieve 1xEVDO Data Strength signal */
1425 static void netreg_update_datastrength(struct modem_data *modem,
1426 DBusMessageIter *value)
1428 dbus_message_iter_get_basic(value, &modem->data_strength);
1430 DBG("%s Data Strength %d", modem->path, modem->data_strength);
1432 if (modem->network == NULL)
1436 * CDMA modem is not registered to 1xEVDO network, let
1437 * update_signal_strength() reporting the value on the Strength signal
1440 if (modem->data_strength == 0)
1443 connman_network_set_strength(modem->network, modem->data_strength);
1444 connman_network_update(modem->network);
1447 static void netreg_update_roaming(struct modem_data *modem,
1448 DBusMessageIter *value)
1451 connman_bool_t roaming;
1453 dbus_message_iter_get_basic(value, &status);
1455 if (g_str_equal(status, "roaming") == TRUE)
1460 if (roaming == modem->roaming)
1463 modem->roaming = roaming;
1465 if (modem->network == NULL)
1468 connman_network_set_bool(modem->network,
1469 "Roaming", modem->roaming);
1470 connman_network_update(modem->network);
1473 static void netreg_update_regdom(struct modem_data *modem,
1474 DBusMessageIter *value)
1476 char *mobile_country_code;
1480 dbus_message_iter_get_basic(value, &mobile_country_code);
1482 DBG("%s MobileContryCode %s", modem->path, mobile_country_code);
1485 mcc = atoi(mobile_country_code);
1486 if (mcc > 799 || mcc < 200)
1489 alpha2 = mcc_country_codes[mcc - 200];
1491 connman_technology_set_regdom(alpha2);
1494 static gboolean netreg_changed(DBusConnection *conn, DBusMessage *message,
1497 const char *path = dbus_message_get_path(message);
1498 struct modem_data *modem;
1499 DBusMessageIter iter, value;
1502 modem = g_hash_table_lookup(modem_hash, path);
1506 if (modem->ignore == TRUE)
1509 if (dbus_message_iter_init(message, &iter) == FALSE)
1512 dbus_message_iter_get_basic(&iter, &key);
1514 dbus_message_iter_next(&iter);
1515 dbus_message_iter_recurse(&iter, &value);
1517 if (g_str_equal(key, "Name") == TRUE)
1518 netreg_update_name(modem, &value);
1519 else if (g_str_equal(key, "Strength") == TRUE)
1520 netreg_update_strength(modem, &value);
1521 else if (g_str_equal(key, "Status") == TRUE)
1522 netreg_update_roaming(modem, &value);
1523 else if (g_str_equal(key, "MobileCountryCode") == TRUE)
1524 netreg_update_regdom(modem, &value);
1529 static void netreg_properties_reply(struct modem_data *modem,
1530 DBusMessageIter *dict)
1532 DBG("%s", modem->path);
1534 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1535 DBusMessageIter entry, value;
1538 dbus_message_iter_recurse(dict, &entry);
1539 dbus_message_iter_get_basic(&entry, &key);
1541 dbus_message_iter_next(&entry);
1542 dbus_message_iter_recurse(&entry, &value);
1544 if (g_str_equal(key, "Name") == TRUE)
1545 netreg_update_name(modem, &value);
1546 else if (g_str_equal(key, "Strength") == TRUE)
1547 netreg_update_strength(modem, &value);
1548 else if (g_str_equal(key, "Status") == TRUE)
1549 netreg_update_roaming(modem, &value);
1550 else if (g_str_equal(key, "MobileCountryCode") == TRUE)
1551 netreg_update_regdom(modem, &value);
1553 dbus_message_iter_next(dict);
1556 if (modem->context == NULL) {
1558 * netgreg_get_properties() was issued after we got
1559 * cm_get_contexts_reply() where we create the
1560 * context. Though before we got the
1561 * netreg_properties_reply the context was removed
1562 * again. Therefore we have to skip the network
1568 if (modem->valid_apn == TRUE)
1571 if (modem->active == TRUE)
1572 set_connected(modem);
1575 static int netreg_get_properties(struct modem_data *modem)
1577 return get_properties(modem->path, OFONO_NETREG_INTERFACE,
1578 netreg_properties_reply, modem);
1581 static void add_cdma_network(struct modem_data *modem)
1583 /* Be sure that device is created before adding CDMA network */
1584 if (modem->device == NULL)
1588 * CDMA modems don't need contexts for data call, however the current
1589 * add_network() logic needs one, so we create one to proceed.
1591 if (modem->context == NULL)
1592 modem->context = network_context_alloc(modem->path);
1594 if (modem->name == NULL)
1595 modem->name = g_strdup("CDMA Network");
1599 if (modem->cdma_cm_powered == TRUE)
1600 set_connected(modem);
1603 static gboolean cdma_netreg_changed(DBusConnection *conn,
1604 DBusMessage *message,
1607 const char *path = dbus_message_get_path(message);
1608 struct modem_data *modem;
1609 DBusMessageIter iter, value;
1614 modem = g_hash_table_lookup(modem_hash, path);
1618 if (modem->ignore == TRUE)
1621 if (dbus_message_iter_init(message, &iter) == FALSE)
1624 dbus_message_iter_get_basic(&iter, &key);
1626 dbus_message_iter_next(&iter);
1627 dbus_message_iter_recurse(&iter, &value);
1629 if (g_str_equal(key, "Name") == TRUE)
1630 netreg_update_name(modem, &value);
1631 else if (g_str_equal(key, "Strength") == TRUE)
1632 netreg_update_strength(modem, &value);
1633 else if (g_str_equal(key, "DataStrength") == TRUE)
1634 netreg_update_datastrength(modem, &value);
1635 else if (g_str_equal(key, "Status") == TRUE)
1636 netreg_update_roaming(modem, &value);
1638 add_cdma_network(modem);
1643 static void cdma_netreg_properties_reply(struct modem_data *modem,
1644 DBusMessageIter *dict)
1646 DBG("%s", modem->path);
1648 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1649 DBusMessageIter entry, value;
1652 dbus_message_iter_recurse(dict, &entry);
1653 dbus_message_iter_get_basic(&entry, &key);
1655 dbus_message_iter_next(&entry);
1656 dbus_message_iter_recurse(&entry, &value);
1658 if (g_str_equal(key, "Name") == TRUE)
1659 netreg_update_name(modem, &value);
1660 else if (g_str_equal(key, "Strength") == TRUE)
1661 netreg_update_strength(modem, &value);
1662 else if (g_str_equal(key, "DataStrength") == TRUE)
1663 netreg_update_datastrength(modem, &value);
1664 else if (g_str_equal(key, "Status") == TRUE)
1665 netreg_update_roaming(modem, &value);
1667 dbus_message_iter_next(dict);
1670 add_cdma_network(modem);
1673 static int cdma_netreg_get_properties(struct modem_data *modem)
1675 return get_properties(modem->path, OFONO_CDMA_NETREG_INTERFACE,
1676 cdma_netreg_properties_reply, modem);
1679 static void cm_update_attached(struct modem_data *modem,
1680 DBusMessageIter *value)
1682 dbus_message_iter_get_basic(value, &modem->attached);
1684 DBG("%s Attached %d", modem->path, modem->attached);
1686 if (modem->attached == FALSE)
1689 if (has_interface(modem->interfaces,
1690 OFONO_API_NETREG) == FALSE) {
1694 netreg_get_properties(modem);
1697 static void cm_update_powered(struct modem_data *modem,
1698 DBusMessageIter *value)
1700 dbus_message_iter_get_basic(value, &modem->cm_powered);
1702 DBG("%s ConnnectionManager Powered %d", modem->path,
1705 if (modem->cm_powered == TRUE)
1708 cm_set_powered(modem, TRUE);
1711 static gboolean cm_changed(DBusConnection *conn, DBusMessage *message,
1714 const char *path = dbus_message_get_path(message);
1715 struct modem_data *modem;
1716 DBusMessageIter iter, value;
1719 modem = g_hash_table_lookup(modem_hash, path);
1723 if (modem->ignore == TRUE)
1726 if (dbus_message_iter_init(message, &iter) == FALSE)
1729 dbus_message_iter_get_basic(&iter, &key);
1731 dbus_message_iter_next(&iter);
1732 dbus_message_iter_recurse(&iter, &value);
1734 if (g_str_equal(key, "Attached") == TRUE)
1735 cm_update_attached(modem, &value);
1736 else if (g_str_equal(key, "Powered") == TRUE)
1737 cm_update_powered(modem, &value);
1742 static void cdma_cm_update_powered(struct modem_data *modem,
1743 DBusMessageIter *value)
1745 dbus_message_iter_get_basic(value, &modem->cdma_cm_powered);
1747 DBG("%s CDMA cm Powered %d", modem->path, modem->cdma_cm_powered);
1749 if (modem->network == NULL)
1752 if (modem->cdma_cm_powered == TRUE)
1753 set_connected(modem);
1755 set_disconnected(modem);
1758 static void cdma_cm_update_settings(struct modem_data *modem,
1759 DBusMessageIter *value)
1761 DBG("%s Settings", modem->path);
1763 extract_ipv4_settings(value, modem->context);
1766 static gboolean cdma_cm_changed(DBusConnection *conn,
1767 DBusMessage *message, void *user_data)
1769 const char *path = dbus_message_get_path(message);
1770 struct modem_data *modem;
1771 DBusMessageIter iter, value;
1774 modem = g_hash_table_lookup(modem_hash, path);
1778 if (modem->online == TRUE && modem->network == NULL)
1779 cdma_netreg_get_properties(modem);
1781 if (dbus_message_iter_init(message, &iter) == FALSE)
1784 dbus_message_iter_get_basic(&iter, &key);
1786 dbus_message_iter_next(&iter);
1787 dbus_message_iter_recurse(&iter, &value);
1789 if (g_str_equal(key, "Powered") == TRUE)
1790 cdma_cm_update_powered(modem, &value);
1791 if (g_str_equal(key, "Settings") == TRUE)
1792 cdma_cm_update_settings(modem, &value);
1797 static void cm_properties_reply(struct modem_data *modem, DBusMessageIter *dict)
1799 DBG("%s", modem->path);
1801 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1802 DBusMessageIter entry, value;
1805 dbus_message_iter_recurse(dict, &entry);
1806 dbus_message_iter_get_basic(&entry, &key);
1808 dbus_message_iter_next(&entry);
1809 dbus_message_iter_recurse(&entry, &value);
1811 if (g_str_equal(key, "Attached") == TRUE)
1812 cm_update_attached(modem, &value);
1813 else if (g_str_equal(key, "Powered") == TRUE)
1814 cm_update_powered(modem, &value);
1816 dbus_message_iter_next(dict);
1820 static int cm_get_properties(struct modem_data *modem)
1822 return get_properties(modem->path, OFONO_CM_INTERFACE,
1823 cm_properties_reply, modem);
1826 static void cdma_cm_properties_reply(struct modem_data *modem,
1827 DBusMessageIter *dict)
1829 DBG("%s", modem->path);
1831 if (modem->online == TRUE)
1832 cdma_netreg_get_properties(modem);
1834 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1835 DBusMessageIter entry, value;
1838 dbus_message_iter_recurse(dict, &entry);
1839 dbus_message_iter_get_basic(&entry, &key);
1841 dbus_message_iter_next(&entry);
1842 dbus_message_iter_recurse(&entry, &value);
1844 if (g_str_equal(key, "Powered") == TRUE)
1845 cdma_cm_update_powered(modem, &value);
1846 if (g_str_equal(key, "Settings") == TRUE)
1847 cdma_cm_update_settings(modem, &value);
1849 dbus_message_iter_next(dict);
1853 static int cdma_cm_get_properties(struct modem_data *modem)
1855 return get_properties(modem->path, OFONO_CDMA_CM_INTERFACE,
1856 cdma_cm_properties_reply, modem);
1859 static void sim_update_imsi(struct modem_data *modem,
1860 DBusMessageIter* value)
1864 dbus_message_iter_get_basic(value, &imsi);
1866 DBG("%s imsi %s", modem->path, imsi);
1868 g_free(modem->imsi);
1869 modem->imsi = g_strdup(imsi);
1872 static gboolean sim_changed(DBusConnection *conn, DBusMessage *message,
1875 const char *path = dbus_message_get_path(message);
1876 struct modem_data *modem;
1877 DBusMessageIter iter, value;
1880 modem = g_hash_table_lookup(modem_hash, path);
1884 if (modem->ignore == TRUE)
1887 if (dbus_message_iter_init(message, &iter) == FALSE)
1890 dbus_message_iter_get_basic(&iter, &key);
1892 dbus_message_iter_next(&iter);
1893 dbus_message_iter_recurse(&iter, &value);
1895 if (g_str_equal(key, "SubscriberIdentity") == TRUE) {
1896 sim_update_imsi(modem, &value);
1898 if (ready_to_create_device(modem) == FALSE)
1902 * This is a GSM modem. Create the device and
1903 * register it at the core. Enabling (setting
1904 * it online is done through the
1905 * modem_enable() callback.
1907 create_device(modem);
1913 static void sim_properties_reply(struct modem_data *modem,
1914 DBusMessageIter *dict)
1916 DBG("%s", modem->path);
1918 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1919 DBusMessageIter entry, value;
1922 dbus_message_iter_recurse(dict, &entry);
1923 dbus_message_iter_get_basic(&entry, &key);
1925 dbus_message_iter_next(&entry);
1926 dbus_message_iter_recurse(&entry, &value);
1928 if (g_str_equal(key, "SubscriberIdentity") == TRUE) {
1929 sim_update_imsi(modem, &value);
1931 if (ready_to_create_device(modem) == FALSE)
1935 * This is a GSM modem. Create the device and
1936 * register it at the core. Enabling (setting
1937 * it online is done through the
1938 * modem_enable() callback.
1940 create_device(modem);
1942 if (modem->online == FALSE)
1946 * The modem is already online and we have the CM interface.
1947 * There will be no interface update and therefore our
1948 * state machine will not go to next step. We have to
1949 * trigger it from here.
1951 if (has_interface(modem->interfaces, OFONO_API_CM) == TRUE) {
1952 cm_get_properties(modem);
1953 cm_get_contexts(modem);
1958 dbus_message_iter_next(dict);
1962 static int sim_get_properties(struct modem_data *modem)
1964 return get_properties(modem->path, OFONO_SIM_INTERFACE,
1965 sim_properties_reply, modem);
1968 static connman_bool_t api_added(uint8_t old_iface, uint8_t new_iface,
1971 if (has_interface(old_iface, api) == FALSE &&
1972 has_interface(new_iface, api) == TRUE) {
1973 DBG("%s added", api2string(api));
1980 static connman_bool_t api_removed(uint8_t old_iface, uint8_t new_iface,
1983 if (has_interface(old_iface, api) == TRUE &&
1984 has_interface(new_iface, api) == FALSE) {
1985 DBG("%s removed", api2string(api));
1992 static void modem_update_interfaces(struct modem_data *modem,
1996 DBG("%s", modem->path);
1998 if (api_added(old_ifaces, new_ifaces, OFONO_API_SIM) == TRUE) {
1999 if (modem->imsi == NULL &&
2000 modem->set_powered == FALSE) {
2002 * Only use do GetProperties() when
2003 * device has not been powered up.
2005 sim_get_properties(modem);
2009 if (api_added(old_ifaces, new_ifaces, OFONO_API_CM) == TRUE) {
2010 if (modem->device != NULL) {
2011 cm_get_properties(modem);
2012 cm_get_contexts(modem);
2016 if (api_added(old_ifaces, new_ifaces, OFONO_API_CDMA_CM) == TRUE) {
2017 if (ready_to_create_device(modem) == TRUE)
2018 create_device(modem);
2020 if (modem->device != NULL)
2021 cdma_cm_get_properties(modem);
2024 if (api_added(old_ifaces, new_ifaces, OFONO_API_NETREG) == TRUE) {
2025 if (modem->attached == TRUE)
2026 netreg_get_properties(modem);
2029 if (api_added(old_ifaces, new_ifaces, OFONO_API_CDMA_NETREG) == TRUE) {
2030 cdma_netreg_get_properties(modem);
2033 if (api_removed(old_ifaces, new_ifaces, OFONO_API_CM) == TRUE) {
2034 remove_cm_context(modem, modem->context->path);
2037 if (api_removed(old_ifaces, new_ifaces, OFONO_API_CDMA_CM) == TRUE) {
2038 remove_cm_context(modem, modem->context->path);
2041 if (api_removed(old_ifaces, new_ifaces, OFONO_API_NETREG) == TRUE) {
2042 remove_network(modem);
2045 if (api_removed(old_ifaces, new_ifaces, OFONO_API_CDMA_NETREG == TRUE)) {
2046 remove_network(modem);
2050 static gboolean modem_changed(DBusConnection *conn, DBusMessage *message,
2053 const char *path = dbus_message_get_path(message);
2054 struct modem_data *modem;
2055 DBusMessageIter iter, value;
2058 modem = g_hash_table_lookup(modem_hash, path);
2062 if (modem->ignore == TRUE)
2065 if (dbus_message_iter_init(message, &iter) == FALSE)
2068 dbus_message_iter_get_basic(&iter, &key);
2070 dbus_message_iter_next(&iter);
2071 dbus_message_iter_recurse(&iter, &value);
2073 if (g_str_equal(key, "Powered") == TRUE) {
2074 dbus_message_iter_get_basic(&value, &modem->powered);
2076 DBG("%s Powered %d", modem->path, modem->powered);
2078 if (modem->powered == FALSE)
2079 modem_set_powered(modem, TRUE);
2080 } else if (g_str_equal(key, "Online") == TRUE) {
2081 dbus_message_iter_get_basic(&value, &modem->online);
2083 DBG("%s Online %d", modem->path, modem->online);
2085 if (modem->device == NULL)
2088 connman_device_set_powered(modem->device, modem->online);
2089 } else if (g_str_equal(key, "Interfaces") == TRUE) {
2092 interfaces = extract_interfaces(&value);
2094 if (interfaces == modem->interfaces)
2097 DBG("%s Interfaces 0x%02x", modem->path, interfaces);
2099 modem_update_interfaces(modem, modem->interfaces, interfaces);
2101 modem->interfaces = interfaces;
2102 } else if (g_str_equal(key, "Serial") == TRUE) {
2105 dbus_message_iter_get_basic(&value, &serial);
2107 g_free(modem->serial);
2108 modem->serial = g_strdup(serial);
2110 DBG("%s Serial %s", modem->path, modem->serial);
2112 if (has_interface(modem->interfaces,
2113 OFONO_API_CDMA_CM) == TRUE) {
2114 if (ready_to_create_device(modem) == TRUE)
2115 create_device(modem);
2122 static void add_modem(const char *path, DBusMessageIter *prop)
2124 struct modem_data *modem;
2128 modem = g_hash_table_lookup(modem_hash, path);
2129 if (modem != NULL) {
2131 * When oFono powers up we ask for the modems and oFono is
2132 * reporting with modem_added signal the modems. Only
2138 modem = g_try_new0(struct modem_data, 1);
2142 modem->path = g_strdup(path);
2144 g_hash_table_insert(modem_hash, g_strdup(path), modem);
2146 while (dbus_message_iter_get_arg_type(prop) == DBUS_TYPE_DICT_ENTRY) {
2147 DBusMessageIter entry, value;
2150 dbus_message_iter_recurse(prop, &entry);
2151 dbus_message_iter_get_basic(&entry, &key);
2153 dbus_message_iter_next(&entry);
2154 dbus_message_iter_recurse(&entry, &value);
2156 if (g_str_equal(key, "Powered") == TRUE) {
2157 dbus_message_iter_get_basic(&value, &modem->powered);
2159 DBG("%s Powered %d", modem->path, modem->powered);
2160 } else if (g_str_equal(key, "Online") == TRUE) {
2161 dbus_message_iter_get_basic(&value, &modem->online);
2163 DBG("%s Online %d", modem->path, modem->online);
2164 } else if (g_str_equal(key, "Interfaces") == TRUE) {
2165 modem->interfaces = extract_interfaces(&value);
2167 DBG("%s Interfaces 0x%02x", modem->path,
2169 } else if (g_str_equal(key, "Serial") == TRUE) {
2172 dbus_message_iter_get_basic(&value, &serial);
2173 modem->serial = g_strdup(serial);
2175 DBG("%s Serial %s", modem->path, modem->serial);
2176 } else if (g_str_equal(key, "Type") == TRUE) {
2179 dbus_message_iter_get_basic(&value, &type);
2181 DBG("%s Type %s", modem->path, type);
2182 if (g_strcmp0(type, "hardware") != 0) {
2183 DBG("%s Ignore this modem", modem->path);
2184 modem->ignore = TRUE;
2188 dbus_message_iter_next(prop);
2191 if (modem->ignore == TRUE)
2194 if (modem->powered == FALSE) {
2195 modem_set_powered(modem, TRUE);
2199 modem_update_interfaces(modem, 0, modem->interfaces);
2202 static void modem_power_down(gpointer key, gpointer value, gpointer user_data)
2204 struct modem_data *modem = value;
2206 DBG("%s", modem->path);
2208 if (modem->ignore == TRUE)
2211 modem_set_powered(modem, FALSE);
2214 static void remove_modem(gpointer data)
2216 struct modem_data *modem = data;
2218 DBG("%s", modem->path);
2220 if (modem->call_set_property != NULL)
2221 dbus_pending_call_cancel(modem->call_set_property);
2223 if (modem->call_get_properties != NULL)
2224 dbus_pending_call_cancel(modem->call_get_properties);
2226 if (modem->call_get_contexts != NULL)
2227 dbus_pending_call_cancel(modem->call_get_contexts);
2229 if (modem->device != NULL)
2230 destroy_device(modem);
2232 if (modem->context != NULL)
2233 remove_cm_context(modem, modem->context->path);
2235 g_free(modem->serial);
2236 g_free(modem->name);
2237 g_free(modem->imsi);
2238 g_free(modem->path);
2243 static gboolean modem_added(DBusConnection *conn,
2244 DBusMessage *message, void *user_data)
2246 DBusMessageIter iter, properties;
2251 if (dbus_message_iter_init(message, &iter) == FALSE)
2254 dbus_message_iter_get_basic(&iter, &path);
2256 dbus_message_iter_next(&iter);
2257 dbus_message_iter_recurse(&iter, &properties);
2259 add_modem(path, &properties);
2264 static gboolean modem_removed(DBusConnection *conn,
2265 DBusMessage *message, void *user_data)
2267 DBusMessageIter iter;
2272 if (dbus_message_iter_init(message, &iter) == FALSE)
2275 dbus_message_iter_get_basic(&iter, &path);
2277 g_hash_table_remove(modem_hash, path);
2282 static void manager_get_modems_reply(DBusPendingCall *call, void *user_data)
2286 DBusMessageIter array, dict;
2290 reply = dbus_pending_call_steal_reply(call);
2292 dbus_error_init(&error);
2294 if (dbus_set_error_from_message(&error, reply) == TRUE) {
2295 connman_error("%s", error.message);
2296 dbus_error_free(&error);
2300 if (dbus_message_iter_init(reply, &array) == FALSE)
2303 dbus_message_iter_recurse(&array, &dict);
2305 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT) {
2306 DBusMessageIter value, properties;
2309 dbus_message_iter_recurse(&dict, &value);
2310 dbus_message_iter_get_basic(&value, &path);
2312 dbus_message_iter_next(&value);
2313 dbus_message_iter_recurse(&value, &properties);
2315 add_modem(path, &properties);
2317 dbus_message_iter_next(&dict);
2321 dbus_message_unref(reply);
2323 dbus_pending_call_unref(call);
2326 static int manager_get_modems(void)
2328 DBusMessage *message;
2329 DBusPendingCall *call;
2333 message = dbus_message_new_method_call(OFONO_SERVICE, "/",
2334 OFONO_MANAGER_INTERFACE, GET_MODEMS);
2335 if (message == NULL)
2338 if (dbus_connection_send_with_reply(connection, message,
2339 &call, TIMEOUT) == FALSE) {
2340 connman_error("Failed to call GetModems()");
2341 dbus_message_unref(message);
2346 connman_error("D-Bus connection not available");
2347 dbus_message_unref(message);
2351 dbus_pending_call_set_notify(call, manager_get_modems_reply,
2354 dbus_message_unref(message);
2356 return -EINPROGRESS;
2359 static void ofono_connect(DBusConnection *conn, void *user_data)
2363 modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2364 g_free, remove_modem);
2365 if (modem_hash == NULL)
2368 context_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2370 if (context_hash == NULL) {
2371 g_hash_table_destroy(modem_hash);
2375 manager_get_modems();
2378 static void ofono_disconnect(DBusConnection *conn, void *user_data)
2382 if (modem_hash == NULL || context_hash == NULL)
2385 g_hash_table_destroy(modem_hash);
2388 g_hash_table_destroy(context_hash);
2389 context_hash = NULL;
2392 static int network_probe(struct connman_network *network)
2394 struct modem_data *modem = connman_network_get_data(network);
2396 DBG("%s network %p", modem->path, network);
2401 static void network_remove(struct connman_network *network)
2403 struct modem_data *modem = connman_network_get_data(network);
2405 DBG("%s network %p", modem->path, network);
2408 static int network_connect(struct connman_network *network)
2410 struct modem_data *modem = connman_network_get_data(network);
2412 DBG("%s network %p", modem->path, network);
2414 if (has_interface(modem->interfaces, OFONO_API_CM) == TRUE)
2415 return context_set_active(modem, TRUE);
2416 else if (has_interface(modem->interfaces, OFONO_API_CDMA_CM) == TRUE)
2417 return cdma_cm_set_powered(modem, TRUE);
2419 connman_error("Connection manager interface not available");
2424 static int network_disconnect(struct connman_network *network)
2426 struct modem_data *modem = connman_network_get_data(network);
2428 DBG("%s network %p", modem->path, network);
2430 if (has_interface(modem->interfaces, OFONO_API_CM) == TRUE)
2431 return context_set_active(modem, FALSE);
2432 else if (has_interface(modem->interfaces, OFONO_API_CDMA_CM) == TRUE)
2433 return cdma_cm_set_powered(modem, FALSE);
2435 connman_error("Connection manager interface not available");
2440 static struct connman_network_driver network_driver = {
2442 .type = CONNMAN_NETWORK_TYPE_CELLULAR,
2443 .probe = network_probe,
2444 .remove = network_remove,
2445 .connect = network_connect,
2446 .disconnect = network_disconnect,
2449 static int modem_probe(struct connman_device *device)
2451 struct modem_data *modem = connman_device_get_data(device);
2453 DBG("%s device %p", modem->path, device);
2458 static void modem_remove(struct connman_device *device)
2460 struct modem_data *modem = connman_device_get_data(device);
2462 DBG("%s device %p", modem->path, device);
2465 static int modem_enable(struct connman_device *device)
2467 struct modem_data *modem = connman_device_get_data(device);
2469 DBG("%s device %p", modem->path, device);
2471 if (modem->online == TRUE)
2474 return modem_set_online(modem, TRUE);
2477 static int modem_disable(struct connman_device *device)
2479 struct modem_data *modem = connman_device_get_data(device);
2481 DBG("%s device %p", modem->path, device);
2483 if (modem->online == FALSE)
2486 return modem_set_online(modem, FALSE);
2489 static struct connman_device_driver modem_driver = {
2491 .type = CONNMAN_DEVICE_TYPE_CELLULAR,
2492 .probe = modem_probe,
2493 .remove = modem_remove,
2494 .enable = modem_enable,
2495 .disable = modem_disable,
2498 static int tech_probe(struct connman_technology *technology)
2503 static void tech_remove(struct connman_technology *technology)
2507 static struct connman_technology_driver tech_driver = {
2509 .type = CONNMAN_SERVICE_TYPE_CELLULAR,
2510 .probe = tech_probe,
2511 .remove = tech_remove,
2515 static guint modem_added_watch;
2516 static guint modem_removed_watch;
2517 static guint modem_watch;
2518 static guint cm_watch;
2519 static guint sim_watch;
2520 static guint context_added_watch;
2521 static guint context_removed_watch;
2522 static guint netreg_watch;
2523 static guint context_watch;
2524 static guint cdma_cm_watch;
2525 static guint cdma_netreg_watch;
2527 static int ofono_init(void)
2533 connection = connman_dbus_get_connection();
2534 if (connection == NULL)
2537 watch = g_dbus_add_service_watch(connection,
2538 OFONO_SERVICE, ofono_connect,
2539 ofono_disconnect, NULL, NULL);
2541 modem_added_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE,
2542 NULL, OFONO_MANAGER_INTERFACE,
2547 modem_removed_watch = g_dbus_add_signal_watch(connection,
2548 OFONO_SERVICE, NULL,
2549 OFONO_MANAGER_INTERFACE,
2554 modem_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE, NULL,
2555 OFONO_MODEM_INTERFACE,
2560 cm_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE, NULL,
2566 sim_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE, NULL,
2567 OFONO_SIM_INTERFACE,
2572 context_added_watch = g_dbus_add_signal_watch(connection,
2573 OFONO_SERVICE, NULL,
2579 context_removed_watch = g_dbus_add_signal_watch(connection,
2580 OFONO_SERVICE, NULL,
2586 context_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE,
2587 NULL, OFONO_CONTEXT_INTERFACE,
2592 netreg_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE, NULL,
2593 OFONO_NETREG_INTERFACE,
2598 cdma_cm_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE,
2599 NULL, OFONO_CDMA_CM_INTERFACE,
2604 cdma_netreg_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE,
2605 NULL, OFONO_CDMA_NETREG_INTERFACE,
2607 cdma_netreg_changed,
2611 if (watch == 0 || modem_added_watch == 0 || modem_removed_watch == 0 ||
2612 modem_watch == 0 || cm_watch == 0 || sim_watch == 0 ||
2613 context_added_watch == 0 ||
2614 context_removed_watch == 0 ||
2615 context_watch == 0 || netreg_watch == 0 ||
2616 cdma_cm_watch == 0 || cdma_netreg_watch == 0) {
2621 err = connman_network_driver_register(&network_driver);
2625 err = connman_device_driver_register(&modem_driver);
2627 connman_network_driver_unregister(&network_driver);
2631 err = connman_technology_driver_register(&tech_driver);
2633 connman_device_driver_unregister(&modem_driver);
2634 connman_network_driver_unregister(&network_driver);
2641 g_dbus_remove_watch(connection, cdma_netreg_watch);
2642 g_dbus_remove_watch(connection, cdma_cm_watch);
2643 g_dbus_remove_watch(connection, netreg_watch);
2644 g_dbus_remove_watch(connection, context_watch);
2645 g_dbus_remove_watch(connection, context_removed_watch);
2646 g_dbus_remove_watch(connection, context_added_watch);
2647 g_dbus_remove_watch(connection, sim_watch);
2648 g_dbus_remove_watch(connection, cm_watch);
2649 g_dbus_remove_watch(connection, modem_watch);
2650 g_dbus_remove_watch(connection, modem_removed_watch);
2651 g_dbus_remove_watch(connection, modem_added_watch);
2652 g_dbus_remove_watch(connection, watch);
2653 dbus_connection_unref(connection);
2658 static void ofono_exit(void)
2662 if (modem_hash != NULL) {
2664 * We should propably wait for the SetProperty() reply
2665 * message, because ...
2667 g_hash_table_foreach(modem_hash, modem_power_down, NULL);
2670 * ... here we will cancel the call.
2672 g_hash_table_destroy(modem_hash);
2676 if (context_hash != NULL) {
2677 g_hash_table_destroy(context_hash);
2678 context_hash = NULL;
2681 connman_technology_driver_unregister(&tech_driver);
2682 connman_device_driver_unregister(&modem_driver);
2683 connman_network_driver_unregister(&network_driver);
2685 g_dbus_remove_watch(connection, cdma_netreg_watch);
2686 g_dbus_remove_watch(connection, cdma_cm_watch);
2687 g_dbus_remove_watch(connection, netreg_watch);
2688 g_dbus_remove_watch(connection, context_watch);
2689 g_dbus_remove_watch(connection, context_removed_watch);
2690 g_dbus_remove_watch(connection, context_added_watch);
2691 g_dbus_remove_watch(connection, sim_watch);
2692 g_dbus_remove_watch(connection, cm_watch);
2693 g_dbus_remove_watch(connection, modem_watch);
2694 g_dbus_remove_watch(connection, modem_added_watch);
2695 g_dbus_remove_watch(connection, modem_removed_watch);
2696 g_dbus_remove_watch(connection, watch);
2698 dbus_connection_unref(connection);
2701 CONNMAN_PLUGIN_DEFINE(ofono, "oFono telephony plugin", VERSION,
2702 CONNMAN_PLUGIN_PRIORITY_DEFAULT, ofono_init, ofono_exit)