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;
265 DBG("%s", modem->path);
267 index = modem->context->index;
269 if (index < 0 || modem->context->ipv4_address == NULL) {
270 connman_error("Invalid index and/or address");
274 service = connman_service_lookup_from_network(modem->network);
278 method = modem->context->ipv4_method;
279 if (method == CONNMAN_IPCONFIG_METHOD_FIXED ||
280 method == CONNMAN_IPCONFIG_METHOD_DHCP)
282 connman_service_create_ip4config(service, index);
283 connman_network_set_index(modem->network, index);
285 connman_network_set_ipv4_method(modem->network, method);
290 if (method == CONNMAN_IPCONFIG_METHOD_FIXED) {
291 connman_network_set_ipaddress(modem->network,
292 modem->context->ipv4_address);
295 method = modem->context->ipv6_method;
296 if (method == CONNMAN_IPCONFIG_METHOD_FIXED) {
297 connman_service_create_ip6config(service, index);
298 connman_network_set_ipv6_method(modem->network, method);
299 connman_network_set_ipaddress(modem->network,
300 modem->context->ipv6_address);
304 /* Set the nameservers */
305 if (modem->context->ipv4_nameservers != NULL &&
306 modem->context->ipv6_nameservers != NULL) {
307 nameservers = g_strdup_printf("%s %s",
308 modem->context->ipv4_nameservers,
309 modem->context->ipv6_nameservers);
310 connman_network_set_nameservers(modem->network, nameservers);
312 } else if (modem->context->ipv4_nameservers != NULL) {
313 connman_network_set_nameservers(modem->network,
314 modem->context->ipv4_nameservers);
315 } else if (modem->context->ipv6_nameservers != NULL) {
316 connman_network_set_nameservers(modem->network,
317 modem->context->ipv6_nameservers);
321 connman_network_set_connected(modem->network, TRUE);
324 static void set_disconnected(struct modem_data *modem)
326 DBG("%s", modem->path);
328 if (modem->network == NULL)
331 connman_network_set_connected(modem->network, FALSE);
334 typedef void (*set_property_cb)(struct modem_data *data,
335 connman_bool_t success);
336 typedef void (*get_properties_cb)(struct modem_data *data,
337 DBusMessageIter *dict);
339 struct property_info {
340 struct modem_data *modem;
342 const char *interface;
343 const char *property;
344 set_property_cb set_property_cb;
345 get_properties_cb get_properties_cb;
348 static void set_property_reply(DBusPendingCall *call, void *user_data)
350 struct property_info *info = user_data;
353 connman_bool_t success = TRUE;
355 DBG("%s path %s %s.%s", info->modem->path,
356 info->path, info->interface, info->property);
358 info->modem->call_set_property = NULL;
360 dbus_error_init(&error);
362 reply = dbus_pending_call_steal_reply(call);
364 if (dbus_set_error_from_message(&error, reply)) {
365 connman_error("Failed to change property: %s %s.%s: %s %s",
366 info->path, info->interface, info->property,
367 error.name, error.message);
368 dbus_error_free(&error);
372 if (info->set_property_cb != NULL)
373 (*info->set_property_cb)(info->modem, success);
375 dbus_message_unref(reply);
377 dbus_pending_call_unref(call);
380 static int set_property(struct modem_data *modem,
381 const char *path, const char *interface,
382 const char *property, int type, void *value,
383 set_property_cb notify)
385 DBusMessage *message;
386 DBusMessageIter iter;
387 struct property_info *info;
389 DBG("%s path %s %s.%s", modem->path, path, interface, property);
391 if (modem->call_set_property != NULL) {
392 DBG("Cancel pending SetProperty");
394 dbus_pending_call_cancel(modem->call_set_property);
395 modem->call_set_property = NULL;
398 message = dbus_message_new_method_call(OFONO_SERVICE, path,
399 interface, SET_PROPERTY);
403 dbus_message_iter_init_append(message, &iter);
404 connman_dbus_property_append_basic(&iter, property, type, value);
406 if (dbus_connection_send_with_reply(connection, message,
407 &modem->call_set_property, TIMEOUT) == FALSE) {
408 connman_error("Failed to change property: %s %s.%s",
409 path, interface, property);
410 dbus_message_unref(message);
414 if (modem->call_set_property == NULL) {
415 connman_error("D-Bus connection not available");
416 dbus_message_unref(message);
420 info = g_try_new0(struct property_info, 1);
422 dbus_message_unref(message);
428 info->interface = interface;
429 info->property = property;
430 info->set_property_cb = notify;
432 dbus_pending_call_set_notify(modem->call_set_property,
433 set_property_reply, info, g_free);
435 dbus_message_unref(message);
440 static void get_properties_reply(DBusPendingCall *call, void *user_data)
442 struct property_info *info = user_data;
443 DBusMessageIter array, dict;
447 DBG("%s path %s %s", info->modem->path, info->path, info->interface);
449 info->modem->call_get_properties = NULL;
451 dbus_error_init(&error);
453 reply = dbus_pending_call_steal_reply(call);
455 if (dbus_set_error_from_message(&error, reply)) {
456 connman_error("Failed to get properties: %s %s: %s %s",
457 info->path, info->interface,
458 error.name, error.message);
459 dbus_error_free(&error);
464 if (dbus_message_iter_init(reply, &array) == FALSE)
467 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
470 dbus_message_iter_recurse(&array, &dict);
472 if (info->get_properties_cb != NULL)
473 (*info->get_properties_cb)(info->modem, &dict);
477 dbus_message_unref(reply);
479 dbus_pending_call_unref(call);
482 static int get_properties(const char *path, const char *interface,
483 get_properties_cb notify,
484 struct modem_data *modem)
486 DBusMessage *message;
487 struct property_info *info;
489 DBG("%s path %s %s", modem->path, path, interface);
491 if (modem->call_get_properties != NULL) {
492 connman_error("Pending GetProperties");
496 message = dbus_message_new_method_call(OFONO_SERVICE, path,
497 interface, GET_PROPERTIES);
501 if (dbus_connection_send_with_reply(connection, message,
502 &modem->call_get_properties, TIMEOUT) == FALSE) {
503 connman_error("Failed to call %s.GetProperties()", interface);
504 dbus_message_unref(message);
508 if (modem->call_get_properties == NULL) {
509 connman_error("D-Bus connection not available");
510 dbus_message_unref(message);
514 info = g_try_new0(struct property_info, 1);
516 dbus_message_unref(message);
522 info->interface = interface;
523 info->get_properties_cb = notify;
525 dbus_pending_call_set_notify(modem->call_get_properties,
526 get_properties_reply, info, g_free);
528 dbus_message_unref(message);
533 static void context_set_active_reply(struct modem_data *modem,
534 connman_bool_t success)
536 DBG("%s", modem->path);
538 if (success == TRUE) {
540 * Don't handle do anything on success here. oFono will send
541 * the change via PropertyChanged singal.
547 * Active = True might fail due a timeout. That means oFono
548 * still tries to go online. If we retry to set Active = True,
549 * we just get a InProgress error message. Should we power
550 * cycle the modem in such cases?
553 if (modem->network == NULL) {
555 * In the case where we power down the device
556 * we don't wait for the reply, therefore the network
557 * might already be gone.
562 connman_network_set_error(modem->network,
563 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
566 static int context_set_active(struct modem_data *modem,
567 connman_bool_t active)
571 DBG("%s active %d", modem->path, active);
573 err = set_property(modem, modem->context->path,
574 OFONO_CONTEXT_INTERFACE,
575 "Active", DBUS_TYPE_BOOLEAN,
577 context_set_active_reply);
579 if (active == FALSE && err == -EINPROGRESS)
585 static void cdma_cm_set_powered_reply(struct modem_data *modem,
586 connman_bool_t success)
588 DBG("%s", modem->path);
590 if (success == TRUE) {
592 * Don't handle do anything on success here. oFono will send
593 * the change via PropertyChanged singal.
599 * Powered = True might fail due a timeout. That means oFono
600 * still tries to go online. If we retry to set Powered = True,
601 * we just get a InProgress error message. Should we power
602 * cycle the modem in such cases?
605 if (modem->network == NULL) {
607 * In the case where we power down the device
608 * we don't wait for the reply, therefore the network
609 * might already be gone.
614 connman_network_set_error(modem->network,
615 CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
618 static int cdma_cm_set_powered(struct modem_data *modem, connman_bool_t powered)
622 DBG("%s powered %d", modem->path, powered);
624 err = set_property(modem, modem->path, OFONO_CDMA_CM_INTERFACE,
625 "Powered", DBUS_TYPE_BOOLEAN,
627 cdma_cm_set_powered_reply);
629 if (powered == FALSE && err == -EINPROGRESS)
635 static int modem_set_online(struct modem_data *modem, connman_bool_t online)
637 DBG("%s online %d", modem->path, online);
639 return set_property(modem, modem->path,
640 OFONO_MODEM_INTERFACE,
641 "Online", DBUS_TYPE_BOOLEAN,
646 static int cm_set_powered(struct modem_data *modem, connman_bool_t powered)
650 DBG("%s powered %d", modem->path, powered);
652 err = set_property(modem, modem->path,
654 "Powered", DBUS_TYPE_BOOLEAN,
658 if (powered == FALSE && err == -EINPROGRESS)
664 static int modem_set_powered(struct modem_data *modem, connman_bool_t powered)
668 DBG("%s powered %d", modem->path, powered);
670 modem->set_powered = powered;
672 err = set_property(modem, modem->path,
673 OFONO_MODEM_INTERFACE,
674 "Powered", DBUS_TYPE_BOOLEAN,
678 if (powered == FALSE && err == -EINPROGRESS)
684 static connman_bool_t has_interface(uint8_t interfaces,
687 if ((interfaces & api) == api)
693 static uint8_t extract_interfaces(DBusMessageIter *array)
695 DBusMessageIter entry;
696 uint8_t interfaces = 0;
698 dbus_message_iter_recurse(array, &entry);
700 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
703 dbus_message_iter_get_basic(&entry, &name);
705 if (g_str_equal(name, OFONO_SIM_INTERFACE) == TRUE)
706 interfaces |= OFONO_API_SIM;
707 else if (g_str_equal(name, OFONO_NETREG_INTERFACE) == TRUE)
708 interfaces |= OFONO_API_NETREG;
709 else if (g_str_equal(name, OFONO_CM_INTERFACE) == TRUE)
710 interfaces |= OFONO_API_CM;
711 else if (g_str_equal(name, OFONO_CDMA_CM_INTERFACE) == TRUE)
712 interfaces |= OFONO_API_CDMA_CM;
713 else if (g_str_equal(name, OFONO_CDMA_NETREG_INTERFACE) == TRUE)
714 interfaces |= OFONO_API_CDMA_NETREG;
716 dbus_message_iter_next(&entry);
722 static char *extract_nameservers(DBusMessageIter *array)
724 DBusMessageIter entry;
725 char *nameservers = NULL;
728 dbus_message_iter_recurse(array, &entry);
730 while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
731 const char *nameserver;
733 dbus_message_iter_get_basic(&entry, &nameserver);
735 if (nameservers == NULL) {
736 nameservers = g_strdup(nameserver);
739 nameservers = g_strdup_printf("%s %s", tmp, nameserver);
743 dbus_message_iter_next(&entry);
749 static void extract_ipv4_settings(DBusMessageIter *array,
750 struct network_context *context)
752 DBusMessageIter dict;
753 char *address = NULL, *netmask = NULL, *gateway = NULL;
754 char *nameservers = NULL;
755 const char *interface = NULL;
758 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
761 dbus_message_iter_recurse(array, &dict);
763 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
764 DBusMessageIter entry, value;
765 const char *key, *val;
767 dbus_message_iter_recurse(&dict, &entry);
768 dbus_message_iter_get_basic(&entry, &key);
770 dbus_message_iter_next(&entry);
771 dbus_message_iter_recurse(&entry, &value);
773 if (g_str_equal(key, "Interface") == TRUE) {
774 dbus_message_iter_get_basic(&value, &interface);
776 DBG("Interface %s", interface);
778 index = connman_inet_ifindex(interface);
780 DBG("index %d", index);
781 } else if (g_str_equal(key, "Method") == TRUE) {
782 dbus_message_iter_get_basic(&value, &val);
784 DBG("Method %s", val);
786 if (g_strcmp0(val, "static") == 0) {
787 context->ipv4_method = CONNMAN_IPCONFIG_METHOD_FIXED;
788 } else if (g_strcmp0(val, "dhcp") == 0) {
789 context->ipv4_method = CONNMAN_IPCONFIG_METHOD_DHCP;
792 } else if (g_str_equal(key, "Address") == TRUE) {
793 dbus_message_iter_get_basic(&value, &val);
795 address = g_strdup(val);
797 DBG("Address %s", address);
798 } else if (g_str_equal(key, "Netmask") == TRUE) {
799 dbus_message_iter_get_basic(&value, &val);
801 netmask = g_strdup(val);
803 DBG("Netmask %s", netmask);
804 } else if (g_str_equal(key, "DomainNameServers") == TRUE) {
805 nameservers = extract_nameservers(&value);
807 DBG("Nameservers %s", nameservers);
808 } else if (g_str_equal(key, "Gateway") == TRUE) {
809 dbus_message_iter_get_basic(&value, &val);
811 gateway = g_strdup(val);
813 DBG("Gateway %s", gateway);
816 dbus_message_iter_next(&dict);
822 if (context->ipv4_method != CONNMAN_IPCONFIG_METHOD_FIXED)
825 context->ipv4_address = connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4);
826 if (context->ipv4_address == NULL)
829 context->index = index;
830 connman_ipaddress_set_ipv4(context->ipv4_address, address,
833 context->ipv4_nameservers = nameservers;
836 if (context->ipv4_nameservers != nameservers)
844 static void extract_ipv6_settings(DBusMessageIter *array,
845 struct network_context *context)
847 DBusMessageIter dict;
848 char *address = NULL, *gateway = NULL;
849 unsigned char prefix_length = 0;
850 char *nameservers = NULL;
851 const char *interface = NULL;
854 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
857 dbus_message_iter_recurse(array, &dict);
859 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
860 DBusMessageIter entry, value;
861 const char *key, *val;
863 dbus_message_iter_recurse(&dict, &entry);
864 dbus_message_iter_get_basic(&entry, &key);
866 dbus_message_iter_next(&entry);
867 dbus_message_iter_recurse(&entry, &value);
869 if (g_str_equal(key, "Interface") == TRUE) {
870 dbus_message_iter_get_basic(&value, &interface);
872 DBG("Interface %s", interface);
874 index = connman_inet_ifindex(interface);
876 DBG("index %d", index);
877 } else if (g_str_equal(key, "Address") == TRUE) {
878 dbus_message_iter_get_basic(&value, &val);
880 address = g_strdup(val);
882 DBG("Address %s", address);
883 } else if (g_str_equal(key, "PrefixLength") == TRUE) {
884 dbus_message_iter_get_basic(&value, &prefix_length);
886 DBG("prefix length %d", prefix_length);
887 } else if (g_str_equal(key, "DomainNameServers") == TRUE) {
888 nameservers = extract_nameservers(&value);
890 DBG("Nameservers %s", nameservers);
891 } else if (g_str_equal(key, "Gateway") == TRUE) {
892 dbus_message_iter_get_basic(&value, &val);
894 gateway = g_strdup(val);
896 DBG("Gateway %s", gateway);
899 dbus_message_iter_next(&dict);
905 context->ipv6_method = CONNMAN_IPCONFIG_METHOD_FIXED;
907 context->ipv6_address =
908 connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6);
909 if (context->ipv6_address == NULL)
912 context->index = index;
913 connman_ipaddress_set_ipv6(context->ipv6_address, address,
914 prefix_length, gateway);
916 context->ipv6_nameservers = nameservers;
919 if (context->ipv6_nameservers != nameservers)
926 static connman_bool_t ready_to_create_device(struct modem_data *modem)
929 * There are three different modem types which behave slightly
931 * - GSM modems will expose the SIM interface then the
933 * - CDMA modems will expose CM first and sometime later
934 * a unique serial number.
936 * This functions tests if we have the necessary information gathered
937 * before we are able to create a device.
940 if (modem->device != NULL)
943 if (modem->imsi != NULL || modem->serial != NULL)
949 static void create_device(struct modem_data *modem)
951 struct connman_device *device;
954 DBG("%s", modem->path);
956 if (modem->imsi != NULL)
958 else if (modem->serial != NULL)
959 ident = modem->serial;
961 if (connman_dbus_validate_ident(ident) == FALSE)
962 ident = connman_dbus_encode_string(ident);
964 ident = g_strdup(ident);
966 device = connman_device_create(ident, CONNMAN_DEVICE_TYPE_CELLULAR);
970 DBG("device %p", device);
972 connman_device_set_ident(device, ident);
974 connman_device_set_string(device, "Path", modem->path);
976 connman_device_set_data(device, modem);
978 if (connman_device_register(device) < 0) {
979 connman_error("Failed to register cellular device");
980 connman_device_unref(device);
984 modem->device = device;
986 connman_device_set_powered(modem->device, modem->online);
991 static void destroy_device(struct modem_data *modem)
993 DBG("%s", modem->path);
995 connman_device_set_powered(modem->device, FALSE);
997 if (modem->network != NULL) {
998 connman_device_remove_network(modem->device, modem->network);
999 connman_network_unref(modem->network);
1000 modem->network = NULL;
1003 connman_device_unregister(modem->device);
1004 connman_device_unref(modem->device);
1006 modem->device = NULL;
1009 static void add_network(struct modem_data *modem)
1013 DBG("%s", modem->path);
1015 if (modem->network != NULL)
1018 modem->network = connman_network_create(modem->context->path,
1019 CONNMAN_NETWORK_TYPE_CELLULAR);
1020 if (modem->network == NULL)
1023 DBG("network %p", modem->network);
1025 connman_network_set_data(modem->network, modem);
1027 connman_network_set_string(modem->network, "Path",
1028 modem->context->path);
1030 if (modem->name != NULL)
1031 connman_network_set_name(modem->network, modem->name);
1033 connman_network_set_name(modem->network, "");
1035 connman_network_set_strength(modem->network, modem->strength);
1037 group = get_ident(modem->context->path);
1038 connman_network_set_group(modem->network, group);
1040 connman_network_set_available(modem->network, TRUE);
1042 connman_network_set_bool(modem->network, "Roaming",
1045 if (connman_device_add_network(modem->device, modem->network) < 0) {
1046 connman_network_unref(modem->network);
1047 modem->network = NULL;
1052 static void remove_network(struct modem_data *modem)
1054 DBG("%s", modem->path);
1056 if (modem->network == NULL)
1059 DBG("network %p", modem->network);
1061 connman_device_remove_network(modem->device, modem->network);
1062 connman_network_unref(modem->network);
1063 modem->network = NULL;
1066 static int add_cm_context(struct modem_data *modem, const char *context_path,
1067 DBusMessageIter *dict)
1069 const char *context_type = NULL;
1070 struct network_context *context = NULL;
1071 connman_bool_t active = FALSE;
1073 DBG("%s context path %s", modem->path, context_path);
1075 if (modem->context != NULL) {
1077 * We have already assigned a context to this modem
1078 * and we do only support one Internet context.
1083 context = network_context_alloc(context_path);
1084 if (context == NULL)
1087 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1088 DBusMessageIter entry, value;
1091 dbus_message_iter_recurse(dict, &entry);
1092 dbus_message_iter_get_basic(&entry, &key);
1094 dbus_message_iter_next(&entry);
1095 dbus_message_iter_recurse(&entry, &value);
1097 if (g_str_equal(key, "Type") == TRUE) {
1098 dbus_message_iter_get_basic(&value, &context_type);
1100 DBG("%s context %s type %s", modem->path,
1101 context_path, context_type);
1102 } else if (g_str_equal(key, "Settings") == TRUE) {
1103 DBG("%s Settings", modem->path);
1105 extract_ipv4_settings(&value, context);
1106 } else if (g_str_equal(key, "IPv6.Settings") == TRUE) {
1107 DBG("%s IPv6.Settings", modem->path);
1109 extract_ipv6_settings(&value, context);
1110 } else if (g_str_equal(key, "Active") == TRUE) {
1111 dbus_message_iter_get_basic(&value, &active);
1113 DBG("%s Active %d", modem->path, active);
1114 } else if (g_str_equal(key, "AccessPointName") == TRUE) {
1117 dbus_message_iter_get_basic(&value, &apn);
1118 if (apn != NULL && strlen(apn) > 0)
1119 modem->valid_apn = TRUE;
1121 modem->valid_apn = FALSE;
1123 DBG("%s AccessPointName '%s'", modem->path, apn);
1125 dbus_message_iter_next(dict);
1128 if (g_strcmp0(context_type, "internet") != 0) {
1129 network_context_free(context);
1133 modem->context = context;
1134 modem->active = active;
1136 g_hash_table_replace(context_hash, g_strdup(context_path), modem);
1138 if (modem->valid_apn == TRUE && modem->attached == TRUE &&
1139 has_interface(modem->interfaces,
1140 OFONO_API_NETREG) == TRUE) {
1147 static void remove_cm_context(struct modem_data *modem,
1148 const char *context_path)
1150 if (modem->context == NULL)
1153 if (modem->network != NULL)
1154 remove_network(modem);
1156 g_hash_table_remove(context_hash, context_path);
1158 network_context_free(modem->context);
1159 modem->context = NULL;
1161 modem->valid_apn = FALSE;
1163 if (modem->network != NULL)
1164 remove_network(modem);
1167 static gboolean context_changed(DBusConnection *conn,
1168 DBusMessage *message,
1171 const char *context_path = dbus_message_get_path(message);
1172 struct modem_data *modem = NULL;
1173 DBusMessageIter iter, value;
1176 DBG("context_path %s", context_path);
1178 modem = g_hash_table_lookup(context_hash, context_path);
1182 if (dbus_message_iter_init(message, &iter) == FALSE)
1185 dbus_message_iter_get_basic(&iter, &key);
1187 dbus_message_iter_next(&iter);
1188 dbus_message_iter_recurse(&iter, &value);
1191 * oFono guarantees the ordering of Settings and
1192 * Active. Settings will always be send before Active = True.
1193 * That means we don't have to order here.
1195 if (g_str_equal(key, "Settings") == TRUE) {
1196 DBG("%s Settings", modem->path);
1198 extract_ipv4_settings(&value, modem->context);
1199 } else if (g_str_equal(key, "IPv6.Settings") == TRUE) {
1200 DBG("%s IPv6.Settings", modem->path);
1202 extract_ipv6_settings(&value, modem->context);
1203 } else if (g_str_equal(key, "Active") == TRUE) {
1204 dbus_message_iter_get_basic(&value, &modem->active);
1206 DBG("%s Active %d", modem->path, modem->active);
1208 if (modem->active == TRUE)
1209 set_connected(modem);
1211 set_disconnected(modem);
1212 } else if (g_str_equal(key, "AccessPointName") == TRUE) {
1215 dbus_message_iter_get_basic(&value, &apn);
1217 DBG("%s AccessPointName %s", modem->path, apn);
1219 if (apn != NULL && strlen(apn) > 0) {
1220 modem->valid_apn = TRUE;
1222 if (modem->network != NULL)
1225 if (modem->attached == FALSE)
1228 if (has_interface(modem->interfaces,
1229 OFONO_API_NETREG) == FALSE) {
1235 if (modem->active == TRUE)
1236 set_connected(modem);
1238 modem->valid_apn = FALSE;
1240 if (modem->network == NULL)
1243 remove_network(modem);
1250 static void cm_get_contexts_reply(DBusPendingCall *call, void *user_data)
1252 struct modem_data *modem = user_data;
1253 DBusMessageIter array, dict, entry, value;
1257 DBG("%s", modem->path);
1259 modem->call_get_contexts = NULL;
1261 reply = dbus_pending_call_steal_reply(call);
1263 dbus_error_init(&error);
1265 if (dbus_set_error_from_message(&error, reply) == TRUE) {
1266 connman_error("%s", error.message);
1267 dbus_error_free(&error);
1271 if (dbus_message_iter_init(reply, &array) == FALSE)
1274 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
1277 dbus_message_iter_recurse(&array, &dict);
1279 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT) {
1280 const char *context_path;
1282 dbus_message_iter_recurse(&dict, &entry);
1283 dbus_message_iter_get_basic(&entry, &context_path);
1285 dbus_message_iter_next(&entry);
1286 dbus_message_iter_recurse(&entry, &value);
1288 if (add_cm_context(modem, context_path, &value) == 0)
1291 dbus_message_iter_next(&dict);
1295 dbus_message_unref(reply);
1297 dbus_pending_call_unref(call);
1300 static int cm_get_contexts(struct modem_data *modem)
1302 DBusMessage *message;
1304 DBG("%s", modem->path);
1306 if (modem->call_get_contexts != NULL)
1309 message = dbus_message_new_method_call(OFONO_SERVICE, modem->path,
1310 OFONO_CM_INTERFACE, GET_CONTEXTS);
1311 if (message == NULL)
1314 if (dbus_connection_send_with_reply(connection, message,
1315 &modem->call_get_contexts, TIMEOUT) == FALSE) {
1316 connman_error("Failed to call GetContexts()");
1317 dbus_message_unref(message);
1321 if (modem->call_get_contexts == NULL) {
1322 connman_error("D-Bus connection not available");
1323 dbus_message_unref(message);
1327 dbus_pending_call_set_notify(modem->call_get_contexts,
1328 cm_get_contexts_reply,
1331 dbus_message_unref(message);
1333 return -EINPROGRESS;
1336 static gboolean cm_context_added(DBusConnection *conn,
1337 DBusMessage *message,
1340 const char *path = dbus_message_get_path(message);
1342 struct modem_data *modem;
1343 DBusMessageIter iter, properties;
1347 modem = g_hash_table_lookup(modem_hash, path);
1351 if (dbus_message_iter_init(message, &iter) == FALSE)
1354 dbus_message_iter_get_basic(&iter, &context_path);
1356 dbus_message_iter_next(&iter);
1357 dbus_message_iter_recurse(&iter, &properties);
1359 if (add_cm_context(modem, context_path, &properties) != 0)
1365 static gboolean cm_context_removed(DBusConnection *conn,
1366 DBusMessage *message,
1369 const char *path = dbus_message_get_path(message);
1370 const char *context_path;
1371 struct modem_data *modem;
1372 DBusMessageIter iter;
1374 DBG("context path %s", path);
1376 if (dbus_message_iter_init(message, &iter) == FALSE)
1379 dbus_message_iter_get_basic(&iter, &context_path);
1381 modem = g_hash_table_lookup(context_hash, context_path);
1385 remove_cm_context(modem, context_path);
1390 static void netreg_update_name(struct modem_data *modem,
1391 DBusMessageIter* value)
1395 dbus_message_iter_get_basic(value, &name);
1397 DBG("%s Name %s", modem->path, name);
1399 g_free(modem->name);
1400 modem->name = g_strdup(name);
1402 if (modem->network == NULL)
1405 connman_network_set_name(modem->network, modem->name);
1406 connman_network_update(modem->network);
1409 static void netreg_update_strength(struct modem_data *modem,
1410 DBusMessageIter *value)
1412 dbus_message_iter_get_basic(value, &modem->strength);
1414 DBG("%s Strength %d", modem->path, modem->strength);
1416 if (modem->network == NULL)
1421 * We don't have 2 signal notifications we always report the strength
1422 * signal. data_strength is always equal to 0.
1425 * In the case we have a data_strength signal (from 1xEVDO network)
1426 * we don't need to update the value with strength signal (from 1xCDMA)
1427 * because the modem is registered to 1xEVDO network for data call.
1428 * In case we have no data_strength signal (not registered to 1xEVDO
1429 * network), we must report the strength signal (registered to 1xCDMA
1430 * network e.g slow mode).
1432 if (modem->data_strength != 0)
1435 connman_network_set_strength(modem->network, modem->strength);
1436 connman_network_update(modem->network);
1439 /* Retrieve 1xEVDO Data Strength signal */
1440 static void netreg_update_datastrength(struct modem_data *modem,
1441 DBusMessageIter *value)
1443 dbus_message_iter_get_basic(value, &modem->data_strength);
1445 DBG("%s Data Strength %d", modem->path, modem->data_strength);
1447 if (modem->network == NULL)
1451 * CDMA modem is not registered to 1xEVDO network, let
1452 * update_signal_strength() reporting the value on the Strength signal
1455 if (modem->data_strength == 0)
1458 connman_network_set_strength(modem->network, modem->data_strength);
1459 connman_network_update(modem->network);
1462 static void netreg_update_roaming(struct modem_data *modem,
1463 DBusMessageIter *value)
1466 connman_bool_t roaming;
1468 dbus_message_iter_get_basic(value, &status);
1470 if (g_str_equal(status, "roaming") == TRUE)
1475 if (roaming == modem->roaming)
1478 modem->roaming = roaming;
1480 if (modem->network == NULL)
1483 connman_network_set_bool(modem->network,
1484 "Roaming", modem->roaming);
1485 connman_network_update(modem->network);
1488 static void netreg_update_regdom(struct modem_data *modem,
1489 DBusMessageIter *value)
1491 char *mobile_country_code;
1495 dbus_message_iter_get_basic(value, &mobile_country_code);
1497 DBG("%s MobileContryCode %s", modem->path, mobile_country_code);
1500 mcc = atoi(mobile_country_code);
1501 if (mcc > 799 || mcc < 200)
1504 alpha2 = mcc_country_codes[mcc - 200];
1506 connman_technology_set_regdom(alpha2);
1509 static gboolean netreg_changed(DBusConnection *conn, DBusMessage *message,
1512 const char *path = dbus_message_get_path(message);
1513 struct modem_data *modem;
1514 DBusMessageIter iter, value;
1517 modem = g_hash_table_lookup(modem_hash, path);
1521 if (modem->ignore == TRUE)
1524 if (dbus_message_iter_init(message, &iter) == FALSE)
1527 dbus_message_iter_get_basic(&iter, &key);
1529 dbus_message_iter_next(&iter);
1530 dbus_message_iter_recurse(&iter, &value);
1532 if (g_str_equal(key, "Name") == TRUE)
1533 netreg_update_name(modem, &value);
1534 else if (g_str_equal(key, "Strength") == TRUE)
1535 netreg_update_strength(modem, &value);
1536 else if (g_str_equal(key, "Status") == TRUE)
1537 netreg_update_roaming(modem, &value);
1538 else if (g_str_equal(key, "MobileCountryCode") == TRUE)
1539 netreg_update_regdom(modem, &value);
1544 static void netreg_properties_reply(struct modem_data *modem,
1545 DBusMessageIter *dict)
1547 DBG("%s", modem->path);
1549 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1550 DBusMessageIter entry, value;
1553 dbus_message_iter_recurse(dict, &entry);
1554 dbus_message_iter_get_basic(&entry, &key);
1556 dbus_message_iter_next(&entry);
1557 dbus_message_iter_recurse(&entry, &value);
1559 if (g_str_equal(key, "Name") == TRUE)
1560 netreg_update_name(modem, &value);
1561 else if (g_str_equal(key, "Strength") == TRUE)
1562 netreg_update_strength(modem, &value);
1563 else if (g_str_equal(key, "Status") == TRUE)
1564 netreg_update_roaming(modem, &value);
1565 else if (g_str_equal(key, "MobileCountryCode") == TRUE)
1566 netreg_update_regdom(modem, &value);
1568 dbus_message_iter_next(dict);
1571 if (modem->context == NULL) {
1573 * netgreg_get_properties() was issued after we got
1574 * cm_get_contexts_reply() where we create the
1575 * context. Though before we got the
1576 * netreg_properties_reply the context was removed
1577 * again. Therefore we have to skip the network
1583 if (modem->valid_apn == TRUE)
1586 if (modem->active == TRUE)
1587 set_connected(modem);
1590 static int netreg_get_properties(struct modem_data *modem)
1592 return get_properties(modem->path, OFONO_NETREG_INTERFACE,
1593 netreg_properties_reply, modem);
1596 static void add_cdma_network(struct modem_data *modem)
1598 /* Be sure that device is created before adding CDMA network */
1599 if (modem->device == NULL)
1603 * CDMA modems don't need contexts for data call, however the current
1604 * add_network() logic needs one, so we create one to proceed.
1606 if (modem->context == NULL)
1607 modem->context = network_context_alloc(modem->path);
1609 if (modem->name == NULL)
1610 modem->name = g_strdup("CDMA Network");
1614 if (modem->cdma_cm_powered == TRUE)
1615 set_connected(modem);
1618 static gboolean cdma_netreg_changed(DBusConnection *conn,
1619 DBusMessage *message,
1622 const char *path = dbus_message_get_path(message);
1623 struct modem_data *modem;
1624 DBusMessageIter iter, value;
1629 modem = g_hash_table_lookup(modem_hash, path);
1633 if (modem->ignore == TRUE)
1636 if (dbus_message_iter_init(message, &iter) == FALSE)
1639 dbus_message_iter_get_basic(&iter, &key);
1641 dbus_message_iter_next(&iter);
1642 dbus_message_iter_recurse(&iter, &value);
1644 if (g_str_equal(key, "Name") == TRUE)
1645 netreg_update_name(modem, &value);
1646 else if (g_str_equal(key, "Strength") == TRUE)
1647 netreg_update_strength(modem, &value);
1648 else if (g_str_equal(key, "DataStrength") == TRUE)
1649 netreg_update_datastrength(modem, &value);
1650 else if (g_str_equal(key, "Status") == TRUE)
1651 netreg_update_roaming(modem, &value);
1653 add_cdma_network(modem);
1658 static void cdma_netreg_properties_reply(struct modem_data *modem,
1659 DBusMessageIter *dict)
1661 DBG("%s", modem->path);
1663 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1664 DBusMessageIter entry, value;
1667 dbus_message_iter_recurse(dict, &entry);
1668 dbus_message_iter_get_basic(&entry, &key);
1670 dbus_message_iter_next(&entry);
1671 dbus_message_iter_recurse(&entry, &value);
1673 if (g_str_equal(key, "Name") == TRUE)
1674 netreg_update_name(modem, &value);
1675 else if (g_str_equal(key, "Strength") == TRUE)
1676 netreg_update_strength(modem, &value);
1677 else if (g_str_equal(key, "DataStrength") == TRUE)
1678 netreg_update_datastrength(modem, &value);
1679 else if (g_str_equal(key, "Status") == TRUE)
1680 netreg_update_roaming(modem, &value);
1682 dbus_message_iter_next(dict);
1685 add_cdma_network(modem);
1688 static int cdma_netreg_get_properties(struct modem_data *modem)
1690 return get_properties(modem->path, OFONO_CDMA_NETREG_INTERFACE,
1691 cdma_netreg_properties_reply, modem);
1694 static void cm_update_attached(struct modem_data *modem,
1695 DBusMessageIter *value)
1697 dbus_message_iter_get_basic(value, &modem->attached);
1699 DBG("%s Attached %d", modem->path, modem->attached);
1701 if (modem->attached == FALSE)
1704 if (has_interface(modem->interfaces,
1705 OFONO_API_NETREG) == FALSE) {
1709 netreg_get_properties(modem);
1712 static void cm_update_powered(struct modem_data *modem,
1713 DBusMessageIter *value)
1715 dbus_message_iter_get_basic(value, &modem->cm_powered);
1717 DBG("%s ConnnectionManager Powered %d", modem->path,
1720 if (modem->cm_powered == TRUE)
1723 cm_set_powered(modem, TRUE);
1726 static gboolean cm_changed(DBusConnection *conn, DBusMessage *message,
1729 const char *path = dbus_message_get_path(message);
1730 struct modem_data *modem;
1731 DBusMessageIter iter, value;
1734 modem = g_hash_table_lookup(modem_hash, path);
1738 if (modem->ignore == TRUE)
1741 if (dbus_message_iter_init(message, &iter) == FALSE)
1744 dbus_message_iter_get_basic(&iter, &key);
1746 dbus_message_iter_next(&iter);
1747 dbus_message_iter_recurse(&iter, &value);
1749 if (g_str_equal(key, "Attached") == TRUE)
1750 cm_update_attached(modem, &value);
1751 else if (g_str_equal(key, "Powered") == TRUE)
1752 cm_update_powered(modem, &value);
1757 static void cdma_cm_update_powered(struct modem_data *modem,
1758 DBusMessageIter *value)
1760 dbus_message_iter_get_basic(value, &modem->cdma_cm_powered);
1762 DBG("%s CDMA cm Powered %d", modem->path, modem->cdma_cm_powered);
1764 if (modem->network == NULL)
1767 if (modem->cdma_cm_powered == TRUE)
1768 set_connected(modem);
1770 set_disconnected(modem);
1773 static void cdma_cm_update_settings(struct modem_data *modem,
1774 DBusMessageIter *value)
1776 DBG("%s Settings", modem->path);
1778 extract_ipv4_settings(value, modem->context);
1781 static gboolean cdma_cm_changed(DBusConnection *conn,
1782 DBusMessage *message, void *user_data)
1784 const char *path = dbus_message_get_path(message);
1785 struct modem_data *modem;
1786 DBusMessageIter iter, value;
1789 modem = g_hash_table_lookup(modem_hash, path);
1793 if (modem->online == TRUE && modem->network == NULL)
1794 cdma_netreg_get_properties(modem);
1796 if (dbus_message_iter_init(message, &iter) == FALSE)
1799 dbus_message_iter_get_basic(&iter, &key);
1801 dbus_message_iter_next(&iter);
1802 dbus_message_iter_recurse(&iter, &value);
1804 if (g_str_equal(key, "Powered") == TRUE)
1805 cdma_cm_update_powered(modem, &value);
1806 if (g_str_equal(key, "Settings") == TRUE)
1807 cdma_cm_update_settings(modem, &value);
1812 static void cm_properties_reply(struct modem_data *modem, DBusMessageIter *dict)
1814 DBG("%s", modem->path);
1816 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1817 DBusMessageIter entry, value;
1820 dbus_message_iter_recurse(dict, &entry);
1821 dbus_message_iter_get_basic(&entry, &key);
1823 dbus_message_iter_next(&entry);
1824 dbus_message_iter_recurse(&entry, &value);
1826 if (g_str_equal(key, "Attached") == TRUE)
1827 cm_update_attached(modem, &value);
1828 else if (g_str_equal(key, "Powered") == TRUE)
1829 cm_update_powered(modem, &value);
1831 dbus_message_iter_next(dict);
1835 static int cm_get_properties(struct modem_data *modem)
1837 return get_properties(modem->path, OFONO_CM_INTERFACE,
1838 cm_properties_reply, modem);
1841 static void cdma_cm_properties_reply(struct modem_data *modem,
1842 DBusMessageIter *dict)
1844 DBG("%s", modem->path);
1846 if (modem->online == TRUE)
1847 cdma_netreg_get_properties(modem);
1849 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1850 DBusMessageIter entry, value;
1853 dbus_message_iter_recurse(dict, &entry);
1854 dbus_message_iter_get_basic(&entry, &key);
1856 dbus_message_iter_next(&entry);
1857 dbus_message_iter_recurse(&entry, &value);
1859 if (g_str_equal(key, "Powered") == TRUE)
1860 cdma_cm_update_powered(modem, &value);
1861 if (g_str_equal(key, "Settings") == TRUE)
1862 cdma_cm_update_settings(modem, &value);
1864 dbus_message_iter_next(dict);
1868 static int cdma_cm_get_properties(struct modem_data *modem)
1870 return get_properties(modem->path, OFONO_CDMA_CM_INTERFACE,
1871 cdma_cm_properties_reply, modem);
1874 static void sim_update_imsi(struct modem_data *modem,
1875 DBusMessageIter* value)
1879 dbus_message_iter_get_basic(value, &imsi);
1881 DBG("%s imsi %s", modem->path, imsi);
1883 g_free(modem->imsi);
1884 modem->imsi = g_strdup(imsi);
1887 static gboolean sim_changed(DBusConnection *conn, DBusMessage *message,
1890 const char *path = dbus_message_get_path(message);
1891 struct modem_data *modem;
1892 DBusMessageIter iter, value;
1895 modem = g_hash_table_lookup(modem_hash, path);
1899 if (modem->ignore == TRUE)
1902 if (dbus_message_iter_init(message, &iter) == FALSE)
1905 dbus_message_iter_get_basic(&iter, &key);
1907 dbus_message_iter_next(&iter);
1908 dbus_message_iter_recurse(&iter, &value);
1910 if (g_str_equal(key, "SubscriberIdentity") == TRUE) {
1911 sim_update_imsi(modem, &value);
1913 if (ready_to_create_device(modem) == FALSE)
1917 * This is a GSM modem. Create the device and
1918 * register it at the core. Enabling (setting
1919 * it online is done through the
1920 * modem_enable() callback.
1922 create_device(modem);
1928 static void sim_properties_reply(struct modem_data *modem,
1929 DBusMessageIter *dict)
1931 DBG("%s", modem->path);
1933 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1934 DBusMessageIter entry, value;
1937 dbus_message_iter_recurse(dict, &entry);
1938 dbus_message_iter_get_basic(&entry, &key);
1940 dbus_message_iter_next(&entry);
1941 dbus_message_iter_recurse(&entry, &value);
1943 if (g_str_equal(key, "SubscriberIdentity") == TRUE) {
1944 sim_update_imsi(modem, &value);
1946 if (ready_to_create_device(modem) == FALSE)
1950 * This is a GSM modem. Create the device and
1951 * register it at the core. Enabling (setting
1952 * it online is done through the
1953 * modem_enable() callback.
1955 create_device(modem);
1957 if (modem->online == FALSE)
1961 * The modem is already online and we have the CM interface.
1962 * There will be no interface update and therefore our
1963 * state machine will not go to next step. We have to
1964 * trigger it from here.
1966 if (has_interface(modem->interfaces, OFONO_API_CM) == TRUE) {
1967 cm_get_properties(modem);
1968 cm_get_contexts(modem);
1973 dbus_message_iter_next(dict);
1977 static int sim_get_properties(struct modem_data *modem)
1979 return get_properties(modem->path, OFONO_SIM_INTERFACE,
1980 sim_properties_reply, modem);
1983 static connman_bool_t api_added(uint8_t old_iface, uint8_t new_iface,
1986 if (has_interface(old_iface, api) == FALSE &&
1987 has_interface(new_iface, api) == TRUE) {
1988 DBG("%s added", api2string(api));
1995 static connman_bool_t api_removed(uint8_t old_iface, uint8_t new_iface,
1998 if (has_interface(old_iface, api) == TRUE &&
1999 has_interface(new_iface, api) == FALSE) {
2000 DBG("%s removed", api2string(api));
2007 static void modem_update_interfaces(struct modem_data *modem,
2011 DBG("%s", modem->path);
2013 if (api_added(old_ifaces, new_ifaces, OFONO_API_SIM) == TRUE) {
2014 if (modem->imsi == NULL &&
2015 modem->set_powered == FALSE) {
2017 * Only use do GetProperties() when
2018 * device has not been powered up.
2020 sim_get_properties(modem);
2024 if (api_added(old_ifaces, new_ifaces, OFONO_API_CM) == TRUE) {
2025 if (modem->device != NULL) {
2026 cm_get_properties(modem);
2027 cm_get_contexts(modem);
2031 if (api_added(old_ifaces, new_ifaces, OFONO_API_CDMA_CM) == TRUE) {
2032 if (ready_to_create_device(modem) == TRUE)
2033 create_device(modem);
2035 if (modem->device != NULL)
2036 cdma_cm_get_properties(modem);
2039 if (api_added(old_ifaces, new_ifaces, OFONO_API_NETREG) == TRUE) {
2040 if (modem->attached == TRUE)
2041 netreg_get_properties(modem);
2044 if (api_added(old_ifaces, new_ifaces, OFONO_API_CDMA_NETREG) == TRUE) {
2045 cdma_netreg_get_properties(modem);
2048 if (api_removed(old_ifaces, new_ifaces, OFONO_API_CM) == TRUE) {
2049 remove_cm_context(modem, modem->context->path);
2052 if (api_removed(old_ifaces, new_ifaces, OFONO_API_CDMA_CM) == TRUE) {
2053 remove_cm_context(modem, modem->context->path);
2056 if (api_removed(old_ifaces, new_ifaces, OFONO_API_NETREG) == TRUE) {
2057 remove_network(modem);
2060 if (api_removed(old_ifaces, new_ifaces, OFONO_API_CDMA_NETREG == TRUE)) {
2061 remove_network(modem);
2065 static gboolean modem_changed(DBusConnection *conn, DBusMessage *message,
2068 const char *path = dbus_message_get_path(message);
2069 struct modem_data *modem;
2070 DBusMessageIter iter, value;
2073 modem = g_hash_table_lookup(modem_hash, path);
2077 if (modem->ignore == TRUE)
2080 if (dbus_message_iter_init(message, &iter) == FALSE)
2083 dbus_message_iter_get_basic(&iter, &key);
2085 dbus_message_iter_next(&iter);
2086 dbus_message_iter_recurse(&iter, &value);
2088 if (g_str_equal(key, "Powered") == TRUE) {
2089 dbus_message_iter_get_basic(&value, &modem->powered);
2091 DBG("%s Powered %d", modem->path, modem->powered);
2093 if (modem->powered == FALSE)
2094 modem_set_powered(modem, TRUE);
2095 } else if (g_str_equal(key, "Online") == TRUE) {
2096 dbus_message_iter_get_basic(&value, &modem->online);
2098 DBG("%s Online %d", modem->path, modem->online);
2100 if (modem->device == NULL)
2103 connman_device_set_powered(modem->device, modem->online);
2104 } else if (g_str_equal(key, "Interfaces") == TRUE) {
2107 interfaces = extract_interfaces(&value);
2109 if (interfaces == modem->interfaces)
2112 DBG("%s Interfaces 0x%02x", modem->path, interfaces);
2114 modem_update_interfaces(modem, modem->interfaces, interfaces);
2116 modem->interfaces = interfaces;
2117 } else if (g_str_equal(key, "Serial") == TRUE) {
2120 dbus_message_iter_get_basic(&value, &serial);
2122 g_free(modem->serial);
2123 modem->serial = g_strdup(serial);
2125 DBG("%s Serial %s", modem->path, modem->serial);
2127 if (has_interface(modem->interfaces,
2128 OFONO_API_CDMA_CM) == TRUE) {
2129 if (ready_to_create_device(modem) == TRUE)
2130 create_device(modem);
2137 static void add_modem(const char *path, DBusMessageIter *prop)
2139 struct modem_data *modem;
2143 modem = g_hash_table_lookup(modem_hash, path);
2144 if (modem != NULL) {
2146 * When oFono powers up we ask for the modems and oFono is
2147 * reporting with modem_added signal the modems. Only
2153 modem = g_try_new0(struct modem_data, 1);
2157 modem->path = g_strdup(path);
2159 g_hash_table_insert(modem_hash, g_strdup(path), modem);
2161 while (dbus_message_iter_get_arg_type(prop) == DBUS_TYPE_DICT_ENTRY) {
2162 DBusMessageIter entry, value;
2165 dbus_message_iter_recurse(prop, &entry);
2166 dbus_message_iter_get_basic(&entry, &key);
2168 dbus_message_iter_next(&entry);
2169 dbus_message_iter_recurse(&entry, &value);
2171 if (g_str_equal(key, "Powered") == TRUE) {
2172 dbus_message_iter_get_basic(&value, &modem->powered);
2174 DBG("%s Powered %d", modem->path, modem->powered);
2175 } else if (g_str_equal(key, "Online") == TRUE) {
2176 dbus_message_iter_get_basic(&value, &modem->online);
2178 DBG("%s Online %d", modem->path, modem->online);
2179 } else if (g_str_equal(key, "Interfaces") == TRUE) {
2180 modem->interfaces = extract_interfaces(&value);
2182 DBG("%s Interfaces 0x%02x", modem->path,
2184 } else if (g_str_equal(key, "Serial") == TRUE) {
2187 dbus_message_iter_get_basic(&value, &serial);
2188 modem->serial = g_strdup(serial);
2190 DBG("%s Serial %s", modem->path, modem->serial);
2191 } else if (g_str_equal(key, "Type") == TRUE) {
2194 dbus_message_iter_get_basic(&value, &type);
2196 DBG("%s Type %s", modem->path, type);
2197 if (g_strcmp0(type, "hardware") != 0) {
2198 DBG("%s Ignore this modem", modem->path);
2199 modem->ignore = TRUE;
2203 dbus_message_iter_next(prop);
2206 if (modem->ignore == TRUE)
2209 if (modem->powered == FALSE) {
2210 modem_set_powered(modem, TRUE);
2214 modem_update_interfaces(modem, 0, modem->interfaces);
2217 static void modem_power_down(gpointer key, gpointer value, gpointer user_data)
2219 struct modem_data *modem = value;
2221 DBG("%s", modem->path);
2223 if (modem->ignore == TRUE)
2226 modem_set_powered(modem, FALSE);
2229 static void remove_modem(gpointer data)
2231 struct modem_data *modem = data;
2233 DBG("%s", modem->path);
2235 if (modem->call_set_property != NULL)
2236 dbus_pending_call_cancel(modem->call_set_property);
2238 if (modem->call_get_properties != NULL)
2239 dbus_pending_call_cancel(modem->call_get_properties);
2241 if (modem->call_get_contexts != NULL)
2242 dbus_pending_call_cancel(modem->call_get_contexts);
2244 if (modem->device != NULL)
2245 destroy_device(modem);
2247 if (modem->context != NULL)
2248 remove_cm_context(modem, modem->context->path);
2250 g_free(modem->serial);
2251 g_free(modem->name);
2252 g_free(modem->imsi);
2253 g_free(modem->path);
2258 static gboolean modem_added(DBusConnection *conn,
2259 DBusMessage *message, void *user_data)
2261 DBusMessageIter iter, properties;
2266 if (dbus_message_iter_init(message, &iter) == FALSE)
2269 dbus_message_iter_get_basic(&iter, &path);
2271 dbus_message_iter_next(&iter);
2272 dbus_message_iter_recurse(&iter, &properties);
2274 add_modem(path, &properties);
2279 static gboolean modem_removed(DBusConnection *conn,
2280 DBusMessage *message, void *user_data)
2282 DBusMessageIter iter;
2287 if (dbus_message_iter_init(message, &iter) == FALSE)
2290 dbus_message_iter_get_basic(&iter, &path);
2292 g_hash_table_remove(modem_hash, path);
2297 static void manager_get_modems_reply(DBusPendingCall *call, void *user_data)
2301 DBusMessageIter array, dict;
2305 reply = dbus_pending_call_steal_reply(call);
2307 dbus_error_init(&error);
2309 if (dbus_set_error_from_message(&error, reply) == TRUE) {
2310 connman_error("%s", error.message);
2311 dbus_error_free(&error);
2315 if (dbus_message_iter_init(reply, &array) == FALSE)
2318 dbus_message_iter_recurse(&array, &dict);
2320 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT) {
2321 DBusMessageIter value, properties;
2324 dbus_message_iter_recurse(&dict, &value);
2325 dbus_message_iter_get_basic(&value, &path);
2327 dbus_message_iter_next(&value);
2328 dbus_message_iter_recurse(&value, &properties);
2330 add_modem(path, &properties);
2332 dbus_message_iter_next(&dict);
2336 dbus_message_unref(reply);
2338 dbus_pending_call_unref(call);
2341 static int manager_get_modems(void)
2343 DBusMessage *message;
2344 DBusPendingCall *call;
2348 message = dbus_message_new_method_call(OFONO_SERVICE, "/",
2349 OFONO_MANAGER_INTERFACE, GET_MODEMS);
2350 if (message == NULL)
2353 if (dbus_connection_send_with_reply(connection, message,
2354 &call, TIMEOUT) == FALSE) {
2355 connman_error("Failed to call GetModems()");
2356 dbus_message_unref(message);
2361 connman_error("D-Bus connection not available");
2362 dbus_message_unref(message);
2366 dbus_pending_call_set_notify(call, manager_get_modems_reply,
2369 dbus_message_unref(message);
2371 return -EINPROGRESS;
2374 static void ofono_connect(DBusConnection *conn, void *user_data)
2378 modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2379 g_free, remove_modem);
2380 if (modem_hash == NULL)
2383 context_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2385 if (context_hash == NULL) {
2386 g_hash_table_destroy(modem_hash);
2390 manager_get_modems();
2393 static void ofono_disconnect(DBusConnection *conn, void *user_data)
2397 if (modem_hash == NULL || context_hash == NULL)
2400 g_hash_table_destroy(modem_hash);
2403 g_hash_table_destroy(context_hash);
2404 context_hash = NULL;
2407 static int network_probe(struct connman_network *network)
2409 struct modem_data *modem = connman_network_get_data(network);
2411 DBG("%s network %p", modem->path, network);
2416 static void network_remove(struct connman_network *network)
2418 struct modem_data *modem = connman_network_get_data(network);
2420 DBG("%s network %p", modem->path, network);
2423 static int network_connect(struct connman_network *network)
2425 struct modem_data *modem = connman_network_get_data(network);
2427 DBG("%s network %p", modem->path, network);
2429 if (has_interface(modem->interfaces, OFONO_API_CM) == TRUE)
2430 return context_set_active(modem, TRUE);
2431 else if (has_interface(modem->interfaces, OFONO_API_CDMA_CM) == TRUE)
2432 return cdma_cm_set_powered(modem, TRUE);
2434 connman_error("Connection manager interface not available");
2439 static int network_disconnect(struct connman_network *network)
2441 struct modem_data *modem = connman_network_get_data(network);
2443 DBG("%s network %p", modem->path, network);
2445 if (has_interface(modem->interfaces, OFONO_API_CM) == TRUE)
2446 return context_set_active(modem, FALSE);
2447 else if (has_interface(modem->interfaces, OFONO_API_CDMA_CM) == TRUE)
2448 return cdma_cm_set_powered(modem, FALSE);
2450 connman_error("Connection manager interface not available");
2455 static struct connman_network_driver network_driver = {
2457 .type = CONNMAN_NETWORK_TYPE_CELLULAR,
2458 .probe = network_probe,
2459 .remove = network_remove,
2460 .connect = network_connect,
2461 .disconnect = network_disconnect,
2464 static int modem_probe(struct connman_device *device)
2466 struct modem_data *modem = connman_device_get_data(device);
2468 DBG("%s device %p", modem->path, device);
2473 static void modem_remove(struct connman_device *device)
2475 struct modem_data *modem = connman_device_get_data(device);
2477 DBG("%s device %p", modem->path, device);
2480 static int modem_enable(struct connman_device *device)
2482 struct modem_data *modem = connman_device_get_data(device);
2484 DBG("%s device %p", modem->path, device);
2486 if (modem->online == TRUE)
2489 return modem_set_online(modem, TRUE);
2492 static int modem_disable(struct connman_device *device)
2494 struct modem_data *modem = connman_device_get_data(device);
2496 DBG("%s device %p", modem->path, device);
2498 if (modem->online == FALSE)
2501 return modem_set_online(modem, FALSE);
2504 static struct connman_device_driver modem_driver = {
2506 .type = CONNMAN_DEVICE_TYPE_CELLULAR,
2507 .probe = modem_probe,
2508 .remove = modem_remove,
2509 .enable = modem_enable,
2510 .disable = modem_disable,
2513 static int tech_probe(struct connman_technology *technology)
2518 static void tech_remove(struct connman_technology *technology)
2522 static struct connman_technology_driver tech_driver = {
2524 .type = CONNMAN_SERVICE_TYPE_CELLULAR,
2525 .probe = tech_probe,
2526 .remove = tech_remove,
2530 static guint modem_added_watch;
2531 static guint modem_removed_watch;
2532 static guint modem_watch;
2533 static guint cm_watch;
2534 static guint sim_watch;
2535 static guint context_added_watch;
2536 static guint context_removed_watch;
2537 static guint netreg_watch;
2538 static guint context_watch;
2539 static guint cdma_cm_watch;
2540 static guint cdma_netreg_watch;
2542 static int ofono_init(void)
2548 connection = connman_dbus_get_connection();
2549 if (connection == NULL)
2552 watch = g_dbus_add_service_watch(connection,
2553 OFONO_SERVICE, ofono_connect,
2554 ofono_disconnect, NULL, NULL);
2556 modem_added_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE,
2557 NULL, OFONO_MANAGER_INTERFACE,
2562 modem_removed_watch = g_dbus_add_signal_watch(connection,
2563 OFONO_SERVICE, NULL,
2564 OFONO_MANAGER_INTERFACE,
2569 modem_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE, NULL,
2570 OFONO_MODEM_INTERFACE,
2575 cm_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE, NULL,
2581 sim_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE, NULL,
2582 OFONO_SIM_INTERFACE,
2587 context_added_watch = g_dbus_add_signal_watch(connection,
2588 OFONO_SERVICE, NULL,
2594 context_removed_watch = g_dbus_add_signal_watch(connection,
2595 OFONO_SERVICE, NULL,
2601 context_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE,
2602 NULL, OFONO_CONTEXT_INTERFACE,
2607 netreg_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE, NULL,
2608 OFONO_NETREG_INTERFACE,
2613 cdma_cm_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE,
2614 NULL, OFONO_CDMA_CM_INTERFACE,
2619 cdma_netreg_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE,
2620 NULL, OFONO_CDMA_NETREG_INTERFACE,
2622 cdma_netreg_changed,
2626 if (watch == 0 || modem_added_watch == 0 || modem_removed_watch == 0 ||
2627 modem_watch == 0 || cm_watch == 0 || sim_watch == 0 ||
2628 context_added_watch == 0 ||
2629 context_removed_watch == 0 ||
2630 context_watch == 0 || netreg_watch == 0 ||
2631 cdma_cm_watch == 0 || cdma_netreg_watch == 0) {
2636 err = connman_network_driver_register(&network_driver);
2640 err = connman_device_driver_register(&modem_driver);
2642 connman_network_driver_unregister(&network_driver);
2646 err = connman_technology_driver_register(&tech_driver);
2648 connman_device_driver_unregister(&modem_driver);
2649 connman_network_driver_unregister(&network_driver);
2656 g_dbus_remove_watch(connection, cdma_netreg_watch);
2657 g_dbus_remove_watch(connection, cdma_cm_watch);
2658 g_dbus_remove_watch(connection, netreg_watch);
2659 g_dbus_remove_watch(connection, context_watch);
2660 g_dbus_remove_watch(connection, context_removed_watch);
2661 g_dbus_remove_watch(connection, context_added_watch);
2662 g_dbus_remove_watch(connection, sim_watch);
2663 g_dbus_remove_watch(connection, cm_watch);
2664 g_dbus_remove_watch(connection, modem_watch);
2665 g_dbus_remove_watch(connection, modem_removed_watch);
2666 g_dbus_remove_watch(connection, modem_added_watch);
2667 g_dbus_remove_watch(connection, watch);
2668 dbus_connection_unref(connection);
2673 static void ofono_exit(void)
2677 if (modem_hash != NULL) {
2679 * We should propably wait for the SetProperty() reply
2680 * message, because ...
2682 g_hash_table_foreach(modem_hash, modem_power_down, NULL);
2685 * ... here we will cancel the call.
2687 g_hash_table_destroy(modem_hash);
2691 if (context_hash != NULL) {
2692 g_hash_table_destroy(context_hash);
2693 context_hash = NULL;
2696 connman_technology_driver_unregister(&tech_driver);
2697 connman_device_driver_unregister(&modem_driver);
2698 connman_network_driver_unregister(&network_driver);
2700 g_dbus_remove_watch(connection, cdma_netreg_watch);
2701 g_dbus_remove_watch(connection, cdma_cm_watch);
2702 g_dbus_remove_watch(connection, netreg_watch);
2703 g_dbus_remove_watch(connection, context_watch);
2704 g_dbus_remove_watch(connection, context_removed_watch);
2705 g_dbus_remove_watch(connection, context_added_watch);
2706 g_dbus_remove_watch(connection, sim_watch);
2707 g_dbus_remove_watch(connection, cm_watch);
2708 g_dbus_remove_watch(connection, modem_watch);
2709 g_dbus_remove_watch(connection, modem_added_watch);
2710 g_dbus_remove_watch(connection, modem_removed_watch);
2711 g_dbus_remove_watch(connection, watch);
2713 dbus_connection_unref(connection);
2716 CONNMAN_PLUGIN_DEFINE(ofono, "oFono telephony plugin", VERSION,
2717 CONNMAN_PLUGIN_PRIORITY_DEFAULT, ofono_init, ofono_exit)