5 * Copyright (C) 2007-2013 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 */
163 /* CDMA ConnectionManager Interface */
164 bool cdma_cm_powered;
166 /* ConnectionManager Interface */
170 /* ConnectionContext Interface */
172 bool valid_apn; /* APN is 'valid' if length > 0 */
174 /* SimManager Interface */
177 /* Netreg Interface */
180 uint8_t data_strength; /* 1xEVDO signal strength */
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;
261 enum connman_ipconfig_method method;
265 DBG("%s", modem->path);
267 index = modem->context->index;
269 method = modem->context->ipv4_method;
270 if (index < 0 || (!modem->context->ipv4_address &&
271 method == CONNMAN_IPCONFIG_METHOD_FIXED)) {
272 connman_error("Invalid index and/or address");
276 service = connman_service_lookup_from_network(modem->network);
280 if (method == CONNMAN_IPCONFIG_METHOD_FIXED ||
281 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 &&
306 modem->context->ipv6_nameservers) {
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) {
313 connman_network_set_nameservers(modem->network,
314 modem->context->ipv4_nameservers);
315 } else if (modem->context->ipv6_nameservers) {
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);
331 connman_network_set_connected(modem->network, false);
334 typedef void (*set_property_cb)(struct modem_data *data,
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;
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)
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) {
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)) {
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) {
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))
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)
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) {
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)) {
503 connman_error("Failed to call %s.GetProperties()", interface);
504 dbus_message_unref(message);
508 if (!modem->call_get_properties) {
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,
536 DBG("%s", modem->path);
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) {
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,
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 && err == -EINPROGRESS)
585 static void cdma_cm_set_powered_reply(struct modem_data *modem,
588 DBG("%s", modem->path);
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) {
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, dbus_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 && err == -EINPROGRESS)
635 static int modem_set_online(struct modem_data *modem, dbus_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, dbus_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 && err == -EINPROGRESS)
664 static int modem_set_powered(struct modem_data *modem, dbus_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 && err == -EINPROGRESS)
684 static bool 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))
706 interfaces |= OFONO_API_SIM;
707 else if (g_str_equal(name, OFONO_NETREG_INTERFACE))
708 interfaces |= OFONO_API_NETREG;
709 else if (g_str_equal(name, OFONO_CM_INTERFACE))
710 interfaces |= OFONO_API_CM;
711 else if (g_str_equal(name, OFONO_CDMA_CM_INTERFACE))
712 interfaces |= OFONO_API_CDMA_CM;
713 else if (g_str_equal(name, OFONO_CDMA_NETREG_INTERFACE))
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);
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")) {
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")) {
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;
791 } else if (g_str_equal(key, "Address")) {
792 dbus_message_iter_get_basic(&value, &val);
794 address = g_strdup(val);
796 DBG("Address %s", address);
797 } else if (g_str_equal(key, "Netmask")) {
798 dbus_message_iter_get_basic(&value, &val);
800 netmask = g_strdup(val);
802 DBG("Netmask %s", netmask);
803 } else if (g_str_equal(key, "DomainNameServers")) {
804 nameservers = extract_nameservers(&value);
806 DBG("Nameservers %s", nameservers);
807 } else if (g_str_equal(key, "Gateway")) {
808 dbus_message_iter_get_basic(&value, &val);
810 gateway = g_strdup(val);
812 DBG("Gateway %s", gateway);
815 dbus_message_iter_next(&dict);
821 context->index = index;
823 if (context->ipv4_method != CONNMAN_IPCONFIG_METHOD_FIXED)
826 context->ipv4_address = connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4);
827 if (!context->ipv4_address) {
832 connman_ipaddress_set_ipv4(context->ipv4_address, address,
835 g_free(context->ipv4_nameservers);
836 context->ipv4_nameservers = nameservers;
839 if (context->ipv4_nameservers != nameservers)
847 static void extract_ipv6_settings(DBusMessageIter *array,
848 struct network_context *context)
850 DBusMessageIter dict;
851 char *address = NULL, *gateway = NULL;
852 unsigned char prefix_length = 0;
853 char *nameservers = NULL;
854 const char *interface = NULL;
857 if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
860 dbus_message_iter_recurse(array, &dict);
862 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
863 DBusMessageIter entry, value;
864 const char *key, *val;
866 dbus_message_iter_recurse(&dict, &entry);
867 dbus_message_iter_get_basic(&entry, &key);
869 dbus_message_iter_next(&entry);
870 dbus_message_iter_recurse(&entry, &value);
872 if (g_str_equal(key, "Interface")) {
873 dbus_message_iter_get_basic(&value, &interface);
875 DBG("Interface %s", interface);
877 index = connman_inet_ifindex(interface);
879 DBG("index %d", index);
880 } else if (g_str_equal(key, "Address")) {
881 dbus_message_iter_get_basic(&value, &val);
883 address = g_strdup(val);
885 DBG("Address %s", address);
886 } else if (g_str_equal(key, "PrefixLength")) {
887 dbus_message_iter_get_basic(&value, &prefix_length);
889 DBG("prefix length %d", prefix_length);
890 } else if (g_str_equal(key, "DomainNameServers")) {
891 nameservers = extract_nameservers(&value);
893 DBG("Nameservers %s", nameservers);
894 } else if (g_str_equal(key, "Gateway")) {
895 dbus_message_iter_get_basic(&value, &val);
897 gateway = g_strdup(val);
899 DBG("Gateway %s", gateway);
902 dbus_message_iter_next(&dict);
908 context->ipv6_method = CONNMAN_IPCONFIG_METHOD_FIXED;
910 context->ipv6_address =
911 connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6);
912 if (!context->ipv6_address)
915 context->index = index;
916 connman_ipaddress_set_ipv6(context->ipv6_address, address,
917 prefix_length, gateway);
919 g_free(context->ipv6_nameservers);
920 context->ipv6_nameservers = nameservers;
923 if (context->ipv6_nameservers != nameservers)
930 static bool ready_to_create_device(struct modem_data *modem)
933 * There are three different modem types which behave slightly
935 * - GSM modems will expose the SIM interface then the
937 * - CDMA modems will expose CM first and sometime later
938 * a unique serial number.
940 * This functions tests if we have the necessary information gathered
941 * before we are able to create a device.
947 if (modem->imsi || modem->serial)
953 static void create_device(struct modem_data *modem)
955 struct connman_device *device;
958 DBG("%s", modem->path);
962 else if (modem->serial)
963 ident = modem->serial;
965 if (!connman_dbus_validate_ident(ident))
966 ident = connman_dbus_encode_string(ident);
968 ident = g_strdup(ident);
970 device = connman_device_create("ofono", CONNMAN_DEVICE_TYPE_CELLULAR);
974 DBG("device %p", device);
976 connman_device_set_ident(device, ident);
978 connman_device_set_string(device, "Path", modem->path);
980 connman_device_set_data(device, modem);
982 if (connman_device_register(device) < 0) {
983 connman_error("Failed to register cellular device");
984 connman_device_unref(device);
988 modem->device = device;
990 connman_device_set_powered(modem->device, modem->online);
995 static void destroy_device(struct modem_data *modem)
997 DBG("%s", modem->path);
999 connman_device_set_powered(modem->device, false);
1001 if (modem->network) {
1002 connman_device_remove_network(modem->device, modem->network);
1003 connman_network_unref(modem->network);
1004 modem->network = NULL;
1007 connman_device_unregister(modem->device);
1008 connman_device_unref(modem->device);
1010 modem->device = NULL;
1013 static void add_network(struct modem_data *modem)
1017 DBG("%s", modem->path);
1022 modem->network = connman_network_create(modem->context->path,
1023 CONNMAN_NETWORK_TYPE_CELLULAR);
1024 if (!modem->network)
1027 DBG("network %p", modem->network);
1029 connman_network_set_data(modem->network, modem);
1031 connman_network_set_string(modem->network, "Path",
1032 modem->context->path);
1035 connman_network_set_name(modem->network, modem->name);
1037 connman_network_set_name(modem->network, "");
1039 connman_network_set_strength(modem->network, modem->strength);
1041 group = get_ident(modem->context->path);
1042 connman_network_set_group(modem->network, group);
1044 connman_network_set_bool(modem->network, "Roaming",
1047 if (connman_device_add_network(modem->device, modem->network) < 0) {
1048 connman_network_unref(modem->network);
1049 modem->network = NULL;
1054 static void remove_network(struct modem_data *modem)
1056 DBG("%s", modem->path);
1058 if (!modem->network)
1061 DBG("network %p", modem->network);
1063 connman_device_remove_network(modem->device, modem->network);
1064 connman_network_unref(modem->network);
1065 modem->network = NULL;
1068 static int add_cm_context(struct modem_data *modem, const char *context_path,
1069 DBusMessageIter *dict)
1071 const char *context_type = NULL;
1072 struct network_context *context = NULL;
1073 dbus_bool_t active = FALSE;
1075 DBG("%s context path %s", modem->path, context_path);
1077 if (modem->context) {
1079 * We have already assigned a context to this modem
1080 * and we do only support one Internet context.
1085 context = network_context_alloc(context_path);
1089 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1090 DBusMessageIter entry, value;
1093 dbus_message_iter_recurse(dict, &entry);
1094 dbus_message_iter_get_basic(&entry, &key);
1096 dbus_message_iter_next(&entry);
1097 dbus_message_iter_recurse(&entry, &value);
1099 if (g_str_equal(key, "Type")) {
1100 dbus_message_iter_get_basic(&value, &context_type);
1102 DBG("%s context %s type %s", modem->path,
1103 context_path, context_type);
1104 } else if (g_str_equal(key, "Settings")) {
1105 DBG("%s Settings", modem->path);
1107 extract_ipv4_settings(&value, context);
1108 } else if (g_str_equal(key, "IPv6.Settings")) {
1109 DBG("%s IPv6.Settings", modem->path);
1111 extract_ipv6_settings(&value, context);
1112 } else if (g_str_equal(key, "Active")) {
1113 dbus_message_iter_get_basic(&value, &active);
1115 DBG("%s Active %d", modem->path, active);
1116 } else if (g_str_equal(key, "AccessPointName")) {
1119 dbus_message_iter_get_basic(&value, &apn);
1120 if (apn && strlen(apn) > 0)
1121 modem->valid_apn = true;
1123 modem->valid_apn = false;
1125 DBG("%s AccessPointName '%s'", modem->path, apn);
1127 dbus_message_iter_next(dict);
1130 if (g_strcmp0(context_type, "internet") != 0) {
1131 network_context_free(context);
1135 modem->context = context;
1136 modem->active = active;
1138 g_hash_table_replace(context_hash, g_strdup(context_path), modem);
1140 if (modem->valid_apn && modem->attached &&
1141 has_interface(modem->interfaces,
1142 OFONO_API_NETREG)) {
1149 static void remove_cm_context(struct modem_data *modem,
1150 const char *context_path)
1152 if (!modem->context)
1156 remove_network(modem);
1158 g_hash_table_remove(context_hash, context_path);
1160 network_context_free(modem->context);
1161 modem->context = NULL;
1163 modem->valid_apn = false;
1166 remove_network(modem);
1169 static gboolean context_changed(DBusConnection *conn,
1170 DBusMessage *message,
1173 const char *context_path = dbus_message_get_path(message);
1174 struct modem_data *modem = NULL;
1175 DBusMessageIter iter, value;
1178 DBG("context_path %s", context_path);
1180 modem = g_hash_table_lookup(context_hash, context_path);
1184 if (!dbus_message_iter_init(message, &iter))
1187 dbus_message_iter_get_basic(&iter, &key);
1189 dbus_message_iter_next(&iter);
1190 dbus_message_iter_recurse(&iter, &value);
1193 * oFono guarantees the ordering of Settings and
1194 * Active. Settings will always be send before Active = True.
1195 * That means we don't have to order here.
1197 if (g_str_equal(key, "Settings")) {
1198 DBG("%s Settings", modem->path);
1200 extract_ipv4_settings(&value, modem->context);
1201 } else if (g_str_equal(key, "IPv6.Settings")) {
1202 DBG("%s IPv6.Settings", modem->path);
1204 extract_ipv6_settings(&value, modem->context);
1205 } else if (g_str_equal(key, "Active")) {
1208 dbus_message_iter_get_basic(&value, &active);
1209 modem->active = active;
1211 DBG("%s Active %d", modem->path, modem->active);
1214 set_connected(modem);
1216 set_disconnected(modem);
1217 } else if (g_str_equal(key, "AccessPointName")) {
1220 dbus_message_iter_get_basic(&value, &apn);
1222 DBG("%s AccessPointName %s", modem->path, apn);
1224 if (apn && strlen(apn) > 0) {
1225 modem->valid_apn = true;
1230 if (!modem->attached)
1233 if (!has_interface(modem->interfaces,
1240 set_connected(modem);
1242 modem->valid_apn = false;
1244 if (!modem->network)
1247 remove_network(modem);
1254 static void cm_get_contexts_reply(DBusPendingCall *call, void *user_data)
1256 struct modem_data *modem = user_data;
1257 DBusMessageIter array, dict, entry, value;
1261 DBG("%s", modem->path);
1263 modem->call_get_contexts = NULL;
1265 reply = dbus_pending_call_steal_reply(call);
1267 dbus_error_init(&error);
1269 if (dbus_set_error_from_message(&error, reply)) {
1270 connman_error("%s", error.message);
1271 dbus_error_free(&error);
1275 if (!dbus_message_iter_init(reply, &array))
1278 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_ARRAY)
1281 dbus_message_iter_recurse(&array, &dict);
1283 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT) {
1284 const char *context_path;
1286 dbus_message_iter_recurse(&dict, &entry);
1287 dbus_message_iter_get_basic(&entry, &context_path);
1289 dbus_message_iter_next(&entry);
1290 dbus_message_iter_recurse(&entry, &value);
1292 if (add_cm_context(modem, context_path, &value) == 0)
1295 dbus_message_iter_next(&dict);
1299 dbus_message_unref(reply);
1301 dbus_pending_call_unref(call);
1304 static int cm_get_contexts(struct modem_data *modem)
1306 DBusMessage *message;
1308 DBG("%s", modem->path);
1310 if (modem->call_get_contexts)
1313 message = dbus_message_new_method_call(OFONO_SERVICE, modem->path,
1314 OFONO_CM_INTERFACE, GET_CONTEXTS);
1318 if (!dbus_connection_send_with_reply(connection, message,
1319 &modem->call_get_contexts, TIMEOUT)) {
1320 connman_error("Failed to call GetContexts()");
1321 dbus_message_unref(message);
1325 if (!modem->call_get_contexts) {
1326 connman_error("D-Bus connection not available");
1327 dbus_message_unref(message);
1331 dbus_pending_call_set_notify(modem->call_get_contexts,
1332 cm_get_contexts_reply,
1335 dbus_message_unref(message);
1337 return -EINPROGRESS;
1340 static gboolean cm_context_added(DBusConnection *conn,
1341 DBusMessage *message,
1344 const char *path = dbus_message_get_path(message);
1346 struct modem_data *modem;
1347 DBusMessageIter iter, properties;
1351 modem = g_hash_table_lookup(modem_hash, path);
1355 if (!dbus_message_iter_init(message, &iter))
1358 dbus_message_iter_get_basic(&iter, &context_path);
1360 dbus_message_iter_next(&iter);
1361 dbus_message_iter_recurse(&iter, &properties);
1363 if (add_cm_context(modem, context_path, &properties) != 0)
1369 static gboolean cm_context_removed(DBusConnection *conn,
1370 DBusMessage *message,
1373 const char *path = dbus_message_get_path(message);
1374 const char *context_path;
1375 struct modem_data *modem;
1376 DBusMessageIter iter;
1378 DBG("context path %s", path);
1380 if (!dbus_message_iter_init(message, &iter))
1383 dbus_message_iter_get_basic(&iter, &context_path);
1385 modem = g_hash_table_lookup(context_hash, context_path);
1389 remove_cm_context(modem, context_path);
1394 static void netreg_update_name(struct modem_data *modem,
1395 DBusMessageIter* value)
1399 dbus_message_iter_get_basic(value, &name);
1401 DBG("%s Name %s", modem->path, name);
1403 g_free(modem->name);
1404 modem->name = g_strdup(name);
1406 if (!modem->network)
1409 connman_network_set_name(modem->network, modem->name);
1410 connman_network_update(modem->network);
1413 static void netreg_update_strength(struct modem_data *modem,
1414 DBusMessageIter *value)
1416 dbus_message_iter_get_basic(value, &modem->strength);
1418 DBG("%s Strength %d", modem->path, modem->strength);
1420 if (!modem->network)
1425 * We don't have 2 signal notifications we always report the strength
1426 * signal. data_strength is always equal to 0.
1429 * In the case we have a data_strength signal (from 1xEVDO network)
1430 * we don't need to update the value with strength signal (from 1xCDMA)
1431 * because the modem is registered to 1xEVDO network for data call.
1432 * In case we have no data_strength signal (not registered to 1xEVDO
1433 * network), we must report the strength signal (registered to 1xCDMA
1434 * network e.g slow mode).
1436 if (modem->data_strength != 0)
1439 connman_network_set_strength(modem->network, modem->strength);
1440 connman_network_update(modem->network);
1443 /* Retrieve 1xEVDO Data Strength signal */
1444 static void netreg_update_datastrength(struct modem_data *modem,
1445 DBusMessageIter *value)
1447 dbus_message_iter_get_basic(value, &modem->data_strength);
1449 DBG("%s Data Strength %d", modem->path, modem->data_strength);
1451 if (!modem->network)
1455 * CDMA modem is not registered to 1xEVDO network, let
1456 * update_signal_strength() reporting the value on the Strength signal
1459 if (modem->data_strength == 0)
1462 connman_network_set_strength(modem->network, modem->data_strength);
1463 connman_network_update(modem->network);
1466 static void netreg_update_status(struct modem_data *modem,
1467 DBusMessageIter *value)
1472 dbus_message_iter_get_basic(value, &status);
1474 roaming = g_str_equal(status, "roaming");
1475 modem->registered = roaming || g_str_equal(status, "registered");
1477 if (roaming == modem->roaming)
1480 modem->roaming = roaming;
1482 if (!modem->network)
1485 connman_network_set_bool(modem->network,
1486 "Roaming", modem->roaming);
1487 connman_network_update(modem->network);
1490 static void netreg_update_regdom(struct modem_data *modem,
1491 DBusMessageIter *value)
1493 char *mobile_country_code;
1497 dbus_message_iter_get_basic(value, &mobile_country_code);
1499 DBG("%s MobileContryCode %s", modem->path, mobile_country_code);
1502 mcc = atoi(mobile_country_code);
1503 if (mcc > 799 || mcc < 200)
1506 alpha2 = mcc_country_codes[mcc - 200];
1508 connman_technology_set_regdom(alpha2);
1511 static gboolean netreg_changed(DBusConnection *conn, DBusMessage *message,
1514 const char *path = dbus_message_get_path(message);
1515 struct modem_data *modem;
1516 DBusMessageIter iter, value;
1519 modem = g_hash_table_lookup(modem_hash, path);
1526 if (!dbus_message_iter_init(message, &iter))
1529 dbus_message_iter_get_basic(&iter, &key);
1531 dbus_message_iter_next(&iter);
1532 dbus_message_iter_recurse(&iter, &value);
1534 if (g_str_equal(key, "Name"))
1535 netreg_update_name(modem, &value);
1536 else if (g_str_equal(key, "Strength"))
1537 netreg_update_strength(modem, &value);
1538 else if (g_str_equal(key, "Status"))
1539 netreg_update_status(modem, &value);
1540 else if (g_str_equal(key, "MobileCountryCode"))
1541 netreg_update_regdom(modem, &value);
1546 static void netreg_properties_reply(struct modem_data *modem,
1547 DBusMessageIter *dict)
1549 DBG("%s", modem->path);
1551 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1552 DBusMessageIter entry, value;
1555 dbus_message_iter_recurse(dict, &entry);
1556 dbus_message_iter_get_basic(&entry, &key);
1558 dbus_message_iter_next(&entry);
1559 dbus_message_iter_recurse(&entry, &value);
1561 if (g_str_equal(key, "Name"))
1562 netreg_update_name(modem, &value);
1563 else if (g_str_equal(key, "Strength"))
1564 netreg_update_strength(modem, &value);
1565 else if (g_str_equal(key, "Status"))
1566 netreg_update_status(modem, &value);
1567 else if (g_str_equal(key, "MobileCountryCode"))
1568 netreg_update_regdom(modem, &value);
1570 dbus_message_iter_next(dict);
1573 if (!modem->context) {
1575 * netgreg_get_properties() was issued after we got
1576 * cm_get_contexts_reply() where we create the
1577 * context. Though before we got the
1578 * netreg_properties_reply the context was removed
1579 * again. Therefore we have to skip the network
1585 if (modem->valid_apn)
1589 set_connected(modem);
1592 static int netreg_get_properties(struct modem_data *modem)
1594 return get_properties(modem->path, OFONO_NETREG_INTERFACE,
1595 netreg_properties_reply, modem);
1598 static void add_cdma_network(struct modem_data *modem)
1600 /* Be sure that device is created before adding CDMA network */
1605 * CDMA modems don't need contexts for data call, however the current
1606 * add_network() logic needs one, so we create one to proceed.
1608 if (!modem->context)
1609 modem->context = network_context_alloc(modem->path);
1612 modem->name = g_strdup("CDMA Network");
1616 if (modem->cdma_cm_powered)
1617 set_connected(modem);
1620 static gboolean cdma_netreg_changed(DBusConnection *conn,
1621 DBusMessage *message,
1624 const char *path = dbus_message_get_path(message);
1625 struct modem_data *modem;
1626 DBusMessageIter iter, value;
1631 modem = g_hash_table_lookup(modem_hash, path);
1638 if (!dbus_message_iter_init(message, &iter))
1641 dbus_message_iter_get_basic(&iter, &key);
1643 dbus_message_iter_next(&iter);
1644 dbus_message_iter_recurse(&iter, &value);
1646 if (g_str_equal(key, "Name"))
1647 netreg_update_name(modem, &value);
1648 else if (g_str_equal(key, "Strength"))
1649 netreg_update_strength(modem, &value);
1650 else if (g_str_equal(key, "DataStrength"))
1651 netreg_update_datastrength(modem, &value);
1652 else if (g_str_equal(key, "Status"))
1653 netreg_update_status(modem, &value);
1655 if (modem->registered)
1656 add_cdma_network(modem);
1658 remove_network(modem);
1663 static void cdma_netreg_properties_reply(struct modem_data *modem,
1664 DBusMessageIter *dict)
1666 DBG("%s", modem->path);
1668 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1669 DBusMessageIter entry, value;
1672 dbus_message_iter_recurse(dict, &entry);
1673 dbus_message_iter_get_basic(&entry, &key);
1675 dbus_message_iter_next(&entry);
1676 dbus_message_iter_recurse(&entry, &value);
1678 if (g_str_equal(key, "Name"))
1679 netreg_update_name(modem, &value);
1680 else if (g_str_equal(key, "Strength"))
1681 netreg_update_strength(modem, &value);
1682 else if (g_str_equal(key, "DataStrength"))
1683 netreg_update_datastrength(modem, &value);
1684 else if (g_str_equal(key, "Status"))
1685 netreg_update_status(modem, &value);
1687 dbus_message_iter_next(dict);
1690 if (modem->registered)
1691 add_cdma_network(modem);
1693 remove_network(modem);
1696 static int cdma_netreg_get_properties(struct modem_data *modem)
1698 return get_properties(modem->path, OFONO_CDMA_NETREG_INTERFACE,
1699 cdma_netreg_properties_reply, modem);
1702 static void cm_update_attached(struct modem_data *modem,
1703 DBusMessageIter *value)
1705 dbus_bool_t attached;
1707 dbus_message_iter_get_basic(value, &attached);
1708 modem->attached = attached;
1710 DBG("%s Attached %d", modem->path, modem->attached);
1712 if (!modem->attached) {
1713 remove_network(modem);
1717 if (!has_interface(modem->interfaces, OFONO_API_NETREG))
1720 netreg_get_properties(modem);
1723 static void cm_update_powered(struct modem_data *modem,
1724 DBusMessageIter *value)
1726 dbus_bool_t cm_powered;
1728 dbus_message_iter_get_basic(value, &cm_powered);
1729 modem->cm_powered = cm_powered;
1731 DBG("%s ConnnectionManager Powered %d", modem->path,
1734 if (modem->cm_powered)
1737 cm_set_powered(modem, TRUE);
1740 static gboolean cm_changed(DBusConnection *conn, DBusMessage *message,
1743 const char *path = dbus_message_get_path(message);
1744 struct modem_data *modem;
1745 DBusMessageIter iter, value;
1748 modem = g_hash_table_lookup(modem_hash, path);
1755 if (!dbus_message_iter_init(message, &iter))
1758 dbus_message_iter_get_basic(&iter, &key);
1760 dbus_message_iter_next(&iter);
1761 dbus_message_iter_recurse(&iter, &value);
1763 if (g_str_equal(key, "Attached"))
1764 cm_update_attached(modem, &value);
1765 else if (g_str_equal(key, "Powered"))
1766 cm_update_powered(modem, &value);
1771 static void cdma_cm_update_powered(struct modem_data *modem,
1772 DBusMessageIter *value)
1774 dbus_bool_t cdma_cm_powered;
1776 dbus_message_iter_get_basic(value, &cdma_cm_powered);
1777 modem->cdma_cm_powered = cdma_cm_powered;
1779 DBG("%s CDMA cm Powered %d", modem->path, modem->cdma_cm_powered);
1781 if (!modem->network)
1784 if (modem->cdma_cm_powered)
1785 set_connected(modem);
1787 set_disconnected(modem);
1790 static void cdma_cm_update_settings(struct modem_data *modem,
1791 DBusMessageIter *value)
1793 DBG("%s Settings", modem->path);
1795 extract_ipv4_settings(value, modem->context);
1798 static gboolean cdma_cm_changed(DBusConnection *conn,
1799 DBusMessage *message, void *user_data)
1801 const char *path = dbus_message_get_path(message);
1802 struct modem_data *modem;
1803 DBusMessageIter iter, value;
1806 modem = g_hash_table_lookup(modem_hash, path);
1810 if (modem->online && !modem->network)
1811 cdma_netreg_get_properties(modem);
1813 if (!dbus_message_iter_init(message, &iter))
1816 dbus_message_iter_get_basic(&iter, &key);
1818 dbus_message_iter_next(&iter);
1819 dbus_message_iter_recurse(&iter, &value);
1821 if (g_str_equal(key, "Powered"))
1822 cdma_cm_update_powered(modem, &value);
1823 if (g_str_equal(key, "Settings"))
1824 cdma_cm_update_settings(modem, &value);
1829 static void cm_properties_reply(struct modem_data *modem, DBusMessageIter *dict)
1831 DBG("%s", modem->path);
1833 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1834 DBusMessageIter entry, value;
1837 dbus_message_iter_recurse(dict, &entry);
1838 dbus_message_iter_get_basic(&entry, &key);
1840 dbus_message_iter_next(&entry);
1841 dbus_message_iter_recurse(&entry, &value);
1843 if (g_str_equal(key, "Attached"))
1844 cm_update_attached(modem, &value);
1845 else if (g_str_equal(key, "Powered"))
1846 cm_update_powered(modem, &value);
1848 dbus_message_iter_next(dict);
1852 static int cm_get_properties(struct modem_data *modem)
1854 return get_properties(modem->path, OFONO_CM_INTERFACE,
1855 cm_properties_reply, modem);
1858 static void cdma_cm_properties_reply(struct modem_data *modem,
1859 DBusMessageIter *dict)
1861 DBG("%s", modem->path);
1864 cdma_netreg_get_properties(modem);
1866 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1867 DBusMessageIter entry, value;
1870 dbus_message_iter_recurse(dict, &entry);
1871 dbus_message_iter_get_basic(&entry, &key);
1873 dbus_message_iter_next(&entry);
1874 dbus_message_iter_recurse(&entry, &value);
1876 if (g_str_equal(key, "Powered"))
1877 cdma_cm_update_powered(modem, &value);
1878 if (g_str_equal(key, "Settings"))
1879 cdma_cm_update_settings(modem, &value);
1881 dbus_message_iter_next(dict);
1885 static int cdma_cm_get_properties(struct modem_data *modem)
1887 return get_properties(modem->path, OFONO_CDMA_CM_INTERFACE,
1888 cdma_cm_properties_reply, modem);
1891 static void sim_update_imsi(struct modem_data *modem,
1892 DBusMessageIter *value)
1896 dbus_message_iter_get_basic(value, &imsi);
1898 DBG("%s imsi %s", modem->path, imsi);
1900 g_free(modem->imsi);
1901 modem->imsi = g_strdup(imsi);
1904 static gboolean sim_changed(DBusConnection *conn, DBusMessage *message,
1907 const char *path = dbus_message_get_path(message);
1908 struct modem_data *modem;
1909 DBusMessageIter iter, value;
1912 modem = g_hash_table_lookup(modem_hash, path);
1919 if (!dbus_message_iter_init(message, &iter))
1922 dbus_message_iter_get_basic(&iter, &key);
1924 dbus_message_iter_next(&iter);
1925 dbus_message_iter_recurse(&iter, &value);
1927 if (g_str_equal(key, "SubscriberIdentity")) {
1928 sim_update_imsi(modem, &value);
1930 if (!ready_to_create_device(modem))
1934 * This is a GSM modem. Create the device and
1935 * register it at the core. Enabling (setting
1936 * it online is done through the
1937 * modem_enable() callback.
1939 create_device(modem);
1945 static void sim_properties_reply(struct modem_data *modem,
1946 DBusMessageIter *dict)
1948 DBG("%s", modem->path);
1950 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
1951 DBusMessageIter entry, value;
1954 dbus_message_iter_recurse(dict, &entry);
1955 dbus_message_iter_get_basic(&entry, &key);
1957 dbus_message_iter_next(&entry);
1958 dbus_message_iter_recurse(&entry, &value);
1960 if (g_str_equal(key, "SubscriberIdentity")) {
1961 sim_update_imsi(modem, &value);
1963 if (!ready_to_create_device(modem))
1967 * This is a GSM modem. Create the device and
1968 * register it at the core. Enabling (setting
1969 * it online is done through the
1970 * modem_enable() callback.
1972 create_device(modem);
1978 * The modem is already online and we have the CM interface.
1979 * There will be no interface update and therefore our
1980 * state machine will not go to next step. We have to
1981 * trigger it from here.
1983 if (has_interface(modem->interfaces, OFONO_API_CM)) {
1984 cm_get_properties(modem);
1985 cm_get_contexts(modem);
1990 dbus_message_iter_next(dict);
1994 static int sim_get_properties(struct modem_data *modem)
1996 return get_properties(modem->path, OFONO_SIM_INTERFACE,
1997 sim_properties_reply, modem);
2000 static bool api_added(uint8_t old_iface, uint8_t new_iface,
2003 if (!has_interface(old_iface, api) &&
2004 has_interface(new_iface, api)) {
2005 DBG("%s added", api2string(api));
2012 static bool api_removed(uint8_t old_iface, uint8_t new_iface,
2015 if (has_interface(old_iface, api) &&
2016 !has_interface(new_iface, api)) {
2017 DBG("%s removed", api2string(api));
2024 static void modem_update_interfaces(struct modem_data *modem,
2028 DBG("%s", modem->path);
2030 if (api_added(old_ifaces, new_ifaces, OFONO_API_SIM)) {
2032 !modem->set_powered) {
2034 * Only use do GetProperties() when
2035 * device has not been powered up.
2037 sim_get_properties(modem);
2041 if (api_added(old_ifaces, new_ifaces, OFONO_API_CM)) {
2042 if (modem->device) {
2043 cm_get_properties(modem);
2044 cm_get_contexts(modem);
2048 if (api_added(old_ifaces, new_ifaces, OFONO_API_CDMA_CM)) {
2049 if (ready_to_create_device(modem)) {
2050 create_device(modem);
2051 if (modem->registered)
2052 add_cdma_network(modem);
2056 cdma_cm_get_properties(modem);
2059 if (api_added(old_ifaces, new_ifaces, OFONO_API_NETREG)) {
2060 if (modem->attached)
2061 netreg_get_properties(modem);
2064 if (api_added(old_ifaces, new_ifaces, OFONO_API_CDMA_NETREG))
2065 cdma_netreg_get_properties(modem);
2067 if (api_removed(old_ifaces, new_ifaces, OFONO_API_CM))
2068 remove_cm_context(modem, modem->context->path);
2070 if (api_removed(old_ifaces, new_ifaces, OFONO_API_CDMA_CM))
2071 remove_cm_context(modem, modem->context->path);
2073 if (api_removed(old_ifaces, new_ifaces, OFONO_API_NETREG))
2074 remove_network(modem);
2076 if (api_removed(old_ifaces, new_ifaces, OFONO_API_CDMA_NETREG))
2077 remove_network(modem);
2080 static gboolean modem_changed(DBusConnection *conn, DBusMessage *message,
2083 const char *path = dbus_message_get_path(message);
2084 struct modem_data *modem;
2085 DBusMessageIter iter, value;
2088 modem = g_hash_table_lookup(modem_hash, path);
2095 if (!dbus_message_iter_init(message, &iter))
2098 dbus_message_iter_get_basic(&iter, &key);
2100 dbus_message_iter_next(&iter);
2101 dbus_message_iter_recurse(&iter, &value);
2103 if (g_str_equal(key, "Powered")) {
2104 dbus_bool_t powered;
2106 dbus_message_iter_get_basic(&value, &powered);
2107 modem->powered = powered;
2109 DBG("%s Powered %d", modem->path, modem->powered);
2111 if (!modem->powered)
2112 modem_set_powered(modem, TRUE);
2113 } else if (g_str_equal(key, "Online")) {
2116 dbus_message_iter_get_basic(&value, &online);
2117 modem->online = online;
2119 DBG("%s Online %d", modem->path, modem->online);
2124 connman_device_set_powered(modem->device, modem->online);
2125 } else if (g_str_equal(key, "Interfaces")) {
2128 interfaces = extract_interfaces(&value);
2130 if (interfaces == modem->interfaces)
2133 DBG("%s Interfaces 0x%02x", modem->path, interfaces);
2135 modem_update_interfaces(modem, modem->interfaces, interfaces);
2137 modem->interfaces = interfaces;
2138 } else if (g_str_equal(key, "Serial")) {
2141 dbus_message_iter_get_basic(&value, &serial);
2143 g_free(modem->serial);
2144 modem->serial = g_strdup(serial);
2146 DBG("%s Serial %s", modem->path, modem->serial);
2148 if (has_interface(modem->interfaces,
2149 OFONO_API_CDMA_CM)) {
2150 if (ready_to_create_device(modem)) {
2151 create_device(modem);
2152 if (modem->registered)
2153 add_cdma_network(modem);
2161 static void add_modem(const char *path, DBusMessageIter *prop)
2163 struct modem_data *modem;
2167 modem = g_hash_table_lookup(modem_hash, path);
2170 * When oFono powers up we ask for the modems and oFono is
2171 * reporting with modem_added signal the modems. Only
2177 modem = g_try_new0(struct modem_data, 1);
2181 modem->path = g_strdup(path);
2183 g_hash_table_insert(modem_hash, g_strdup(path), modem);
2185 while (dbus_message_iter_get_arg_type(prop) == DBUS_TYPE_DICT_ENTRY) {
2186 DBusMessageIter entry, value;
2189 dbus_message_iter_recurse(prop, &entry);
2190 dbus_message_iter_get_basic(&entry, &key);
2192 dbus_message_iter_next(&entry);
2193 dbus_message_iter_recurse(&entry, &value);
2195 if (g_str_equal(key, "Powered")) {
2196 dbus_bool_t powered;
2198 dbus_message_iter_get_basic(&value, &powered);
2199 modem->powered = powered;
2201 DBG("%s Powered %d", modem->path, modem->powered);
2202 } else if (g_str_equal(key, "Online")) {
2205 dbus_message_iter_get_basic(&value, &online);
2206 modem->online = online;
2208 DBG("%s Online %d", modem->path, modem->online);
2209 } else if (g_str_equal(key, "Interfaces")) {
2210 modem->interfaces = extract_interfaces(&value);
2212 DBG("%s Interfaces 0x%02x", modem->path,
2214 } else if (g_str_equal(key, "Serial")) {
2217 dbus_message_iter_get_basic(&value, &serial);
2218 modem->serial = g_strdup(serial);
2220 DBG("%s Serial %s", modem->path, modem->serial);
2221 } else if (g_str_equal(key, "Type")) {
2224 dbus_message_iter_get_basic(&value, &type);
2226 DBG("%s Type %s", modem->path, type);
2227 if (g_strcmp0(type, "hardware") != 0) {
2228 DBG("%s Ignore this modem", modem->path);
2229 modem->ignore = true;
2233 dbus_message_iter_next(prop);
2239 if (!modem->powered) {
2240 modem_set_powered(modem, TRUE);
2244 modem_update_interfaces(modem, 0, modem->interfaces);
2247 static void modem_power_down(gpointer key, gpointer value, gpointer user_data)
2249 struct modem_data *modem = value;
2251 DBG("%s", modem->path);
2256 modem_set_powered(modem, FALSE);
2259 static void remove_modem(gpointer data)
2261 struct modem_data *modem = data;
2263 DBG("%s", modem->path);
2265 if (modem->call_set_property)
2266 dbus_pending_call_cancel(modem->call_set_property);
2268 if (modem->call_get_properties)
2269 dbus_pending_call_cancel(modem->call_get_properties);
2271 if (modem->call_get_contexts)
2272 dbus_pending_call_cancel(modem->call_get_contexts);
2275 destroy_device(modem);
2278 remove_cm_context(modem, modem->context->path);
2280 g_free(modem->serial);
2281 g_free(modem->name);
2282 g_free(modem->imsi);
2283 g_free(modem->path);
2288 static gboolean modem_added(DBusConnection *conn,
2289 DBusMessage *message, void *user_data)
2291 DBusMessageIter iter, properties;
2296 if (!dbus_message_iter_init(message, &iter))
2299 dbus_message_iter_get_basic(&iter, &path);
2301 dbus_message_iter_next(&iter);
2302 dbus_message_iter_recurse(&iter, &properties);
2304 add_modem(path, &properties);
2309 static gboolean modem_removed(DBusConnection *conn,
2310 DBusMessage *message, void *user_data)
2312 DBusMessageIter iter;
2317 if (!dbus_message_iter_init(message, &iter))
2320 dbus_message_iter_get_basic(&iter, &path);
2322 g_hash_table_remove(modem_hash, path);
2327 static void manager_get_modems_reply(DBusPendingCall *call, void *user_data)
2331 DBusMessageIter array, dict;
2335 reply = dbus_pending_call_steal_reply(call);
2337 dbus_error_init(&error);
2339 if (dbus_set_error_from_message(&error, reply)) {
2340 connman_error("%s", error.message);
2341 dbus_error_free(&error);
2345 if (!dbus_message_iter_init(reply, &array))
2348 dbus_message_iter_recurse(&array, &dict);
2350 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT) {
2351 DBusMessageIter value, properties;
2354 dbus_message_iter_recurse(&dict, &value);
2355 dbus_message_iter_get_basic(&value, &path);
2357 dbus_message_iter_next(&value);
2358 dbus_message_iter_recurse(&value, &properties);
2360 add_modem(path, &properties);
2362 dbus_message_iter_next(&dict);
2366 dbus_message_unref(reply);
2368 dbus_pending_call_unref(call);
2371 static int manager_get_modems(void)
2373 DBusMessage *message;
2374 DBusPendingCall *call;
2378 message = dbus_message_new_method_call(OFONO_SERVICE, "/",
2379 OFONO_MANAGER_INTERFACE, GET_MODEMS);
2383 if (!dbus_connection_send_with_reply(connection, message,
2385 connman_error("Failed to call GetModems()");
2386 dbus_message_unref(message);
2391 connman_error("D-Bus connection not available");
2392 dbus_message_unref(message);
2396 dbus_pending_call_set_notify(call, manager_get_modems_reply,
2399 dbus_message_unref(message);
2401 return -EINPROGRESS;
2404 static void ofono_connect(DBusConnection *conn, void *user_data)
2408 modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2409 g_free, remove_modem);
2413 context_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2415 if (!context_hash) {
2416 g_hash_table_destroy(modem_hash);
2420 manager_get_modems();
2423 static void ofono_disconnect(DBusConnection *conn, void *user_data)
2427 if (!modem_hash || !context_hash)
2430 g_hash_table_destroy(modem_hash);
2433 g_hash_table_destroy(context_hash);
2434 context_hash = NULL;
2437 static int network_probe(struct connman_network *network)
2439 struct modem_data *modem = connman_network_get_data(network);
2441 DBG("%s network %p", modem->path, network);
2446 static void network_remove(struct connman_network *network)
2448 struct modem_data *modem = connman_network_get_data(network);
2450 DBG("%s network %p", modem->path, network);
2453 static int network_connect(struct connman_network *network)
2455 struct modem_data *modem = connman_network_get_data(network);
2457 DBG("%s network %p", modem->path, network);
2459 if (has_interface(modem->interfaces, OFONO_API_CM))
2460 return context_set_active(modem, TRUE);
2461 else if (has_interface(modem->interfaces, OFONO_API_CDMA_CM))
2462 return cdma_cm_set_powered(modem, TRUE);
2464 connman_error("Connection manager interface not available");
2469 static int network_disconnect(struct connman_network *network)
2471 struct modem_data *modem = connman_network_get_data(network);
2473 DBG("%s network %p", modem->path, network);
2475 if (has_interface(modem->interfaces, OFONO_API_CM))
2476 return context_set_active(modem, FALSE);
2477 else if (has_interface(modem->interfaces, OFONO_API_CDMA_CM))
2478 return cdma_cm_set_powered(modem, FALSE);
2480 connman_error("Connection manager interface not available");
2485 static struct connman_network_driver network_driver = {
2487 .type = CONNMAN_NETWORK_TYPE_CELLULAR,
2488 .probe = network_probe,
2489 .remove = network_remove,
2490 .connect = network_connect,
2491 .disconnect = network_disconnect,
2494 static int modem_probe(struct connman_device *device)
2496 struct modem_data *modem = connman_device_get_data(device);
2498 DBG("%s device %p", modem->path, device);
2503 static void modem_remove(struct connman_device *device)
2505 struct modem_data *modem = connman_device_get_data(device);
2507 DBG("%s device %p", modem->path, device);
2510 static int modem_enable(struct connman_device *device)
2512 struct modem_data *modem = connman_device_get_data(device);
2514 DBG("%s device %p", modem->path, device);
2519 return modem_set_online(modem, TRUE);
2522 static int modem_disable(struct connman_device *device)
2524 struct modem_data *modem = connman_device_get_data(device);
2526 DBG("%s device %p", modem->path, device);
2531 return modem_set_online(modem, FALSE);
2534 static struct connman_device_driver modem_driver = {
2536 .type = CONNMAN_DEVICE_TYPE_CELLULAR,
2537 .probe = modem_probe,
2538 .remove = modem_remove,
2539 .enable = modem_enable,
2540 .disable = modem_disable,
2543 static int tech_probe(struct connman_technology *technology)
2548 static void tech_remove(struct connman_technology *technology)
2552 static struct connman_technology_driver tech_driver = {
2554 .type = CONNMAN_SERVICE_TYPE_CELLULAR,
2555 .probe = tech_probe,
2556 .remove = tech_remove,
2560 static guint modem_added_watch;
2561 static guint modem_removed_watch;
2562 static guint modem_watch;
2563 static guint cm_watch;
2564 static guint sim_watch;
2565 static guint context_added_watch;
2566 static guint context_removed_watch;
2567 static guint netreg_watch;
2568 static guint context_watch;
2569 static guint cdma_cm_watch;
2570 static guint cdma_netreg_watch;
2572 static int ofono_init(void)
2578 connection = connman_dbus_get_connection();
2582 watch = g_dbus_add_service_watch(connection,
2583 OFONO_SERVICE, ofono_connect,
2584 ofono_disconnect, NULL, NULL);
2586 modem_added_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE,
2587 NULL, OFONO_MANAGER_INTERFACE,
2592 modem_removed_watch = g_dbus_add_signal_watch(connection,
2593 OFONO_SERVICE, NULL,
2594 OFONO_MANAGER_INTERFACE,
2599 modem_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE, NULL,
2600 OFONO_MODEM_INTERFACE,
2605 cm_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE, NULL,
2611 sim_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE, NULL,
2612 OFONO_SIM_INTERFACE,
2617 context_added_watch = g_dbus_add_signal_watch(connection,
2618 OFONO_SERVICE, NULL,
2624 context_removed_watch = g_dbus_add_signal_watch(connection,
2625 OFONO_SERVICE, NULL,
2631 context_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE,
2632 NULL, OFONO_CONTEXT_INTERFACE,
2637 netreg_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE, NULL,
2638 OFONO_NETREG_INTERFACE,
2643 cdma_cm_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE,
2644 NULL, OFONO_CDMA_CM_INTERFACE,
2649 cdma_netreg_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE,
2650 NULL, OFONO_CDMA_NETREG_INTERFACE,
2652 cdma_netreg_changed,
2656 if (watch == 0 || modem_added_watch == 0 || modem_removed_watch == 0 ||
2657 modem_watch == 0 || cm_watch == 0 || sim_watch == 0 ||
2658 context_added_watch == 0 ||
2659 context_removed_watch == 0 ||
2660 context_watch == 0 || netreg_watch == 0 ||
2661 cdma_cm_watch == 0 || cdma_netreg_watch == 0) {
2666 err = connman_network_driver_register(&network_driver);
2670 err = connman_device_driver_register(&modem_driver);
2672 connman_network_driver_unregister(&network_driver);
2676 err = connman_technology_driver_register(&tech_driver);
2678 connman_device_driver_unregister(&modem_driver);
2679 connman_network_driver_unregister(&network_driver);
2686 g_dbus_remove_watch(connection, cdma_netreg_watch);
2687 g_dbus_remove_watch(connection, cdma_cm_watch);
2688 g_dbus_remove_watch(connection, netreg_watch);
2689 g_dbus_remove_watch(connection, context_watch);
2690 g_dbus_remove_watch(connection, context_removed_watch);
2691 g_dbus_remove_watch(connection, context_added_watch);
2692 g_dbus_remove_watch(connection, sim_watch);
2693 g_dbus_remove_watch(connection, cm_watch);
2694 g_dbus_remove_watch(connection, modem_watch);
2695 g_dbus_remove_watch(connection, modem_removed_watch);
2696 g_dbus_remove_watch(connection, modem_added_watch);
2697 g_dbus_remove_watch(connection, watch);
2698 dbus_connection_unref(connection);
2703 static void ofono_exit(void)
2709 * We should propably wait for the SetProperty() reply
2710 * message, because ...
2712 g_hash_table_foreach(modem_hash, modem_power_down, NULL);
2715 * ... here we will cancel the call.
2717 g_hash_table_destroy(modem_hash);
2722 g_hash_table_destroy(context_hash);
2723 context_hash = NULL;
2726 connman_technology_driver_unregister(&tech_driver);
2727 connman_device_driver_unregister(&modem_driver);
2728 connman_network_driver_unregister(&network_driver);
2730 g_dbus_remove_watch(connection, cdma_netreg_watch);
2731 g_dbus_remove_watch(connection, cdma_cm_watch);
2732 g_dbus_remove_watch(connection, netreg_watch);
2733 g_dbus_remove_watch(connection, context_watch);
2734 g_dbus_remove_watch(connection, context_removed_watch);
2735 g_dbus_remove_watch(connection, context_added_watch);
2736 g_dbus_remove_watch(connection, sim_watch);
2737 g_dbus_remove_watch(connection, cm_watch);
2738 g_dbus_remove_watch(connection, modem_watch);
2739 g_dbus_remove_watch(connection, modem_added_watch);
2740 g_dbus_remove_watch(connection, modem_removed_watch);
2741 g_dbus_remove_watch(connection, watch);
2743 dbus_connection_unref(connection);
2746 CONNMAN_PLUGIN_DEFINE(ofono, "oFono telephony plugin", VERSION,
2747 CONNMAN_PLUGIN_PRIORITY_DEFAULT, ofono_init, ofono_exit)