summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rwxr-xr-x[-rw-r--r--]plugins/bluetooth.c36
-rwxr-xr-x[-rw-r--r--]plugins/connman-nmcompat.conf4
-rwxr-xr-x[-rw-r--r--]plugins/dundee.c0
-rwxr-xr-x[-rw-r--r--]plugins/ethernet.c0
-rwxr-xr-x[-rw-r--r--]plugins/gadget.c87
-rwxr-xr-x[-rw-r--r--]plugins/hh2serial-gps.c0
-rwxr-xr-x[-rw-r--r--]plugins/iospm.c0
-rwxr-xr-x[-rw-r--r--]plugins/loopback.c53
-rwxr-xr-x[-rw-r--r--]plugins/mcc.h0
-rwxr-xr-x[-rw-r--r--]plugins/neard.c0
-rwxr-xr-x[-rw-r--r--]plugins/nmcompat.c0
-rwxr-xr-x[-rw-r--r--]plugins/ofono.c0
-rwxr-xr-x[-rw-r--r--]plugins/pacrunner.c0
-rwxr-xr-x[-rw-r--r--]plugins/polkit.c0
-rwxr-xr-x[-rw-r--r--]plugins/polkit.policy0
-rwxr-xr-x[-rw-r--r--]plugins/session_policy_local.c0
-rwxr-xr-xplugins/telephony.c1934
-rwxr-xr-x[-rw-r--r--]plugins/tist.c0
-rwxr-xr-x[-rw-r--r--]plugins/vpn.c2
-rwxr-xr-x[-rw-r--r--]plugins/wifi.c902
20 files changed, 2994 insertions, 24 deletions
diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
index f759a902..f89edfa0 100644..100755
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -192,8 +192,14 @@ static bool pan_connect(struct bluetooth_pan *pan,
return false;
}
+#if defined TIZEN_EXT
+ if (pan->network) {
+#endif
connman_network_set_index(pan->network, index);
connman_network_set_connected(pan->network, true);
+#if defined TIZEN_EXT
+ }
+#endif
return true;
}
@@ -211,6 +217,18 @@ static void pan_connect_cb(DBusMessage *message, void *user_data)
return;
}
+#ifdef TIZEN_EXT
+ /*
+ * Network could be removed because of BT adapter power off
+ * This is to handle the scenario where network is removed
+ * before the connect_cb is called
+ */
+ if (!pan->network) {
+ DBG("network already removed");
+ return;
+ }
+#endif
+
if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_ERROR) {
const char *dbus_error = dbus_message_get_error_name(message);
@@ -262,6 +280,9 @@ static int bluetooth_pan_connect(struct connman_network *network)
g_strdup(path), g_free))
return -EIO;
+#if defined TIZEN_EXT
+ if (pan->network)
+#endif
connman_network_set_associating(pan->network, true);
return -EINPROGRESS;
@@ -286,6 +307,9 @@ static void pan_disconnect_cb(DBusMessage *message, void *user_data)
DBG("network %p", pan->network);
+#if defined TIZEN_EXT
+ if (pan->network)
+#endif
connman_network_set_connected(pan->network, false);
}
@@ -299,6 +323,11 @@ static int bluetooth_pan_disconnect(struct connman_network *network)
if (!pan)
return -EINVAL;
+#if defined TIZEN_EXT
+ if (connman_network_get_associating(network) == TRUE)
+ connman_network_clear_associating(network);
+#endif
+
path = g_dbus_proxy_get_path(pan->btnetwork_proxy);
if (!g_dbus_proxy_method_call(pan->btnetwork_proxy, "Disconnect",
@@ -524,7 +553,10 @@ static void device_enable_cb(const DBusError *error, void *user_data)
goto out;
}
+#if !defined TIZEN_EXT
enable_device(device, path);
+#endif
+
out:
g_free(path);
}
@@ -591,7 +623,9 @@ static void device_disable_cb(const DBusError *error, void *user_data)
goto out;
}
+#if !defined TIZEN_EXT
disable_device(device, path);
+#endif
out:
g_free(path);
@@ -883,7 +917,7 @@ static void bluetooth_tech_remove(struct connman_technology *technology)
static int bluetooth_tech_set_tethering(struct connman_technology *technology,
const char *identifier, const char *passphrase,
- const char *bridge, bool enabled)
+ const char *bridge, bool enabled, bool hidden)
{
GHashTableIter hash_iter;
gpointer key, value;
diff --git a/plugins/connman-nmcompat.conf b/plugins/connman-nmcompat.conf
index 5887a345..a051d927 100644..100755
--- a/plugins/connman-nmcompat.conf
+++ b/plugins/connman-nmcompat.conf
@@ -5,6 +5,10 @@
<allow own="org.freedesktop.NetworkManager"/>
<allow send_destination="org.freedesktop.NetworkManager"/>
</policy>
+ <policy user="network_fw">
+ <allow own="org.freedesktop.NetworkManager"/>
+ <allow send_destination="org.freedesktop.NetworkManager"/>
+ </policy>
<policy at_console="true">
<allow send_destination="org.freedesktop.NetworkManager"/>
</policy>
diff --git a/plugins/dundee.c b/plugins/dundee.c
index b5420acf..b5420acf 100644..100755
--- a/plugins/dundee.c
+++ b/plugins/dundee.c
diff --git a/plugins/ethernet.c b/plugins/ethernet.c
index 9a4d7413..9a4d7413 100644..100755
--- a/plugins/ethernet.c
+++ b/plugins/ethernet.c
diff --git a/plugins/gadget.c b/plugins/gadget.c
index 94f66487..cce51e26 100644..100755
--- a/plugins/gadget.c
+++ b/plugins/gadget.c
@@ -25,6 +25,8 @@
#include <errno.h>
#include <net/if.h>
+#include <stdio.h>
+#include <string.h>
#ifndef IFF_LOWER_UP
#define IFF_LOWER_UP 0x10000
@@ -226,6 +228,71 @@ static struct connman_device_driver gadget_dev_driver = {
};
static GList *cdc_interface_list = NULL;
+static GHashTable *cdc_mac_hash = NULL;
+
+static void add_station(int index)
+{
+ char *path, line[128] = {'\0'};
+ char *ifname = connman_inet_ifname(index);
+ char *mac;
+ FILE *f;
+
+ if (ifname == NULL)
+ return;
+
+ path = g_strdup_printf("/sys/class/usb_mode/%s/f_rndis/ethaddr",
+ ifname);
+
+ f = fopen(path, "re");
+
+ g_free(ifname);
+ g_free(path);
+
+ if (f == NULL)
+ return;
+
+ if (fgets(line, sizeof(line), f) == NULL) {
+ fclose(f);
+ return;
+ }
+
+ fclose(f);
+
+ mac = g_ascii_strdown(line, strlen(line) - 1);
+ DBG("Add station %s in Technology %d", mac,
+ CONNMAN_SERVICE_TYPE_GADGET);
+
+ g_hash_table_insert(cdc_mac_hash, GINT_TO_POINTER(index),
+ mac);
+
+ connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_GADGET,
+ mac);
+}
+
+static void remove_station(int index)
+{
+ char *mac;
+ mac = g_hash_table_lookup(cdc_mac_hash, GINT_TO_POINTER(index));
+ if (mac == NULL)
+ return;
+
+ connman_technology_tethering_remove_station(mac);
+
+ g_hash_table_remove(cdc_mac_hash, GINT_TO_POINTER(index));
+}
+
+static gboolean remove_all_station(gpointer key, gpointer value, gpointer user_data)
+{
+ char *mac;
+ mac = value;
+ if (mac == NULL)
+ return TRUE;
+
+ connman_technology_tethering_remove_station(mac);
+
+ return TRUE;
+}
+
static void gadget_tech_add_interface(struct connman_technology *technology,
int index, const char *name, const char *ident)
@@ -246,6 +313,8 @@ static void gadget_tech_remove_interface(struct connman_technology *technology,
cdc_interface_list = g_list_remove(cdc_interface_list,
GINT_TO_POINTER((int) index));
+
+ remove_station(index);
}
static void gadget_tech_enable_tethering(struct connman_technology *technology,
@@ -270,6 +339,8 @@ static void gadget_tech_enable_tethering(struct connman_technology *technology,
connman_inet_ifup(index);
connman_inet_add_to_bridge(index, bridge);
+
+ add_station(index);
}
}
@@ -283,6 +354,8 @@ static void gadget_tech_disable_tethering(struct connman_technology *technology,
connman_inet_remove_from_bridge(index, bridge);
+ remove_station(index);
+
connman_inet_ifdown(index);
connman_technology_tethering_notify(technology, false);
@@ -305,14 +378,28 @@ static int gadget_tech_set_tethering(struct connman_technology *technology,
static int gadget_tech_probe(struct connman_technology *technology)
{
+ DBG("tech probe %p", technology);
+
+ cdc_mac_hash = g_hash_table_new_full(g_direct_hash,
+ g_direct_equal, NULL, g_free);
+
return 0;
}
static void gadget_tech_remove(struct connman_technology *technology)
{
+ DBG("tech remove %p", technology);
+
g_list_free(cdc_interface_list);
cdc_interface_list = NULL;
+
+ if (cdc_mac_hash) {
+ g_hash_table_foreach_remove(cdc_mac_hash, remove_all_station,
+ NULL);
+ g_hash_table_destroy(cdc_mac_hash);
+ cdc_mac_hash = NULL;
+ }
}
static struct connman_technology_driver gadget_tech_driver = {
diff --git a/plugins/hh2serial-gps.c b/plugins/hh2serial-gps.c
index 99394e1c..99394e1c 100644..100755
--- a/plugins/hh2serial-gps.c
+++ b/plugins/hh2serial-gps.c
diff --git a/plugins/iospm.c b/plugins/iospm.c
index fcb4cea1..fcb4cea1 100644..100755
--- a/plugins/iospm.c
+++ b/plugins/iospm.c
diff --git a/plugins/loopback.c b/plugins/loopback.c
index e113887d..44100c64 100644..100755
--- a/plugins/loopback.c
+++ b/plugins/loopback.c
@@ -23,6 +23,8 @@
#include <config.h>
#endif
+#include <stdio.h>
+
#include <errno.h>
#include <unistd.h>
#include <limits.h>
@@ -34,6 +36,8 @@
#include <net/if.h>
#include <glib.h>
+#include <glib/gprintf.h>
+
#define CONNMAN_API_SUBJECT_TO_CHANGE
#include <connman/plugin.h>
@@ -62,16 +66,47 @@ static int setup_hostname(void)
memset(system_hostname, 0, sizeof(system_hostname));
- if (gethostname(system_hostname, HOST_NAME_MAX) < 0) {
- connman_error("Failed to get current hostname");
- return -EIO;
- }
+#if defined TIZEN_EXT
+ FILE *fp = NULL;
+#define WIFI_MAC "/opt/etc/.mac.info"
+ {
+ char* rv = 0;
+ gchar* dev_id = "TIZEN";
+ char wifi_mac[HOST_NAME_MAX + 1];
+
+ fp = fopen(WIFI_MAC, "r");
+ if(!fp){
+ connman_error("Failed to get current hostname");
+ strncpy(system_hostname, dev_id, strlen(dev_id));
+ goto host_name_end;
+ }
+
+ rv = fgets(wifi_mac, HOST_NAME_MAX, fp);
+ if(!rv){
+ connman_error("Failed to get current hostname");
+ strncpy(system_hostname, dev_id, strlen(dev_id));
+ fclose(fp);
+ goto host_name_end;
+ }
+
+ dev_id = g_base64_encode((const guchar *)wifi_mac, strlen(wifi_mac));
+ g_sprintf(system_hostname, "TIZEN-%s", dev_id);
+ g_free(dev_id);
+ fclose(fp);
+ }
- if (strlen(system_hostname) > 0 &&
- strcmp(system_hostname, "(none)") != 0)
- connman_info("System hostname is %s", system_hostname);
- else
- create_hostname();
+ host_name_end :
+#else
+ if (gethostname(system_hostname, HOST_NAME_MAX) < 0) {
+ connman_error("Failed to get current hostname");
+ return -EIO;
+ }
+#endif
+ if (strlen(system_hostname) > 0 &&
+ strcmp(system_hostname, "(none)") != 0)
+ connman_info("System hostname is %s", system_hostname);
+ else
+ create_hostname();
memset(name, 0, sizeof(name));
diff --git a/plugins/mcc.h b/plugins/mcc.h
index 0e0407c9..0e0407c9 100644..100755
--- a/plugins/mcc.h
+++ b/plugins/mcc.h
diff --git a/plugins/neard.c b/plugins/neard.c
index 69586df6..69586df6 100644..100755
--- a/plugins/neard.c
+++ b/plugins/neard.c
diff --git a/plugins/nmcompat.c b/plugins/nmcompat.c
index 883ce9bd..883ce9bd 100644..100755
--- a/plugins/nmcompat.c
+++ b/plugins/nmcompat.c
diff --git a/plugins/ofono.c b/plugins/ofono.c
index 78f8f196..78f8f196 100644..100755
--- a/plugins/ofono.c
+++ b/plugins/ofono.c
diff --git a/plugins/pacrunner.c b/plugins/pacrunner.c
index d2464a5e..d2464a5e 100644..100755
--- a/plugins/pacrunner.c
+++ b/plugins/pacrunner.c
diff --git a/plugins/polkit.c b/plugins/polkit.c
index ae38364a..ae38364a 100644..100755
--- a/plugins/polkit.c
+++ b/plugins/polkit.c
diff --git a/plugins/polkit.policy b/plugins/polkit.policy
index 0de152ce..0de152ce 100644..100755
--- a/plugins/polkit.policy
+++ b/plugins/polkit.policy
diff --git a/plugins/session_policy_local.c b/plugins/session_policy_local.c
index f003c0e1..f003c0e1 100644..100755
--- a/plugins/session_policy_local.c
+++ b/plugins/session_policy_local.c
diff --git a/plugins/telephony.c b/plugins/telephony.c
new file mode 100755
index 00000000..2b4c5a4a
--- /dev/null
+++ b/plugins/telephony.c
@@ -0,0 +1,1934 @@
+/*
+ *
+ * Connection Manager
+ *
+ * Copyright (C) 2007-2012 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <gdbus.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define CONNMAN_API_SUBJECT_TO_CHANGE
+#include <connman/dbus.h>
+#include <connman/inet.h>
+#include <connman/plugin.h>
+#include <connman/network.h>
+#include <connman/setting.h>
+#include <connman/technology.h>
+
+#include <connman.h>
+
+#define PS_DBUS_SERVICE "com.tcore.ps"
+
+#define PS_MASTER_INTERFACE PS_DBUS_SERVICE ".master"
+#define PS_MODEM_INTERFACE PS_DBUS_SERVICE ".modem"
+#define PS_SERVICE_INTERFACE PS_DBUS_SERVICE ".service"
+#define PS_CONTEXT_INTERFACE PS_DBUS_SERVICE ".context"
+
+/* methods */
+#define GET_MODEMS "GetModems"
+#define GET_SERVICES "GetServices"
+#define GET_CONTEXTS "GetContexts"
+#define ACTIVATE_CONTEXT "Activate"
+#define DEACTIVATE_CONTEXT "Deactivate"
+#define GET_PROPERTIES "GetProperties"
+#define SET_PROPERTY "SetProperties"
+
+/* signals */
+#define MODEM_ADDED "ModemAdded"
+#define MODEM_REMOVED "ModemRemoved"
+#define SERVICE_ADDED "ServiceAdded"
+#define SERVICE_REMOVED "ServiceRemoved"
+#define CONTEXT_ADDED "ContextAdded"
+#define CONTEXT_REMOVED "ContextRemoved"
+#define PROPERTY_CHANGED "PropertyChanged"
+
+#define TIMEOUT 130000
+
+#define STRING2BOOL(a) (!(g_strcmp0(a, "TRUE")) ? (TRUE):(FALSE))
+
+static DBusConnection *connection;
+static GHashTable *modem_hash;
+static GHashTable *service_hash;
+static GHashTable *network_hash;
+
+struct telephony_service {
+ char *path;
+
+ gpointer p_modem;
+ char *act;
+ gboolean roaming; /* global roaming state */
+ gboolean ps_attached; /* packet service is available */
+};
+
+struct telephony_modem {
+ char *path;
+
+ char *operator;
+ gboolean powered;
+ gboolean sim_init;
+ gboolean flight_mode;
+ gboolean data_allowed;
+ gboolean roaming_allowed;
+
+ struct connman_device *device;
+ struct telephony_service *s_service;
+};
+
+struct telephony_network {
+ char *path;
+ int if_index;
+ gboolean routing_only;
+ gboolean ipv6_link_only;
+
+ struct connman_network *network;
+
+ enum connman_ipconfig_method ipv4_method;
+ struct connman_ipaddress *ipv4_address;
+
+ enum connman_ipconfig_method ipv6_method;
+ struct connman_ipaddress *ipv6_address;
+};
+
+static int telephony_default_subscription_id = 0;
+
+/* function prototype */
+static void telephony_connect(DBusConnection *connection, void *user_data);
+static void telephony_disconnect(DBusConnection *connection, void *user_data);
+static void __remove_modem(gpointer data);
+static void __remove_service(gpointer data);
+static void __remove_network(gpointer data);
+
+static int __modem_probe(struct connman_device *device);
+static void __modem_remove(struct connman_device *device);
+static int __modem_enable(struct connman_device *device);
+static int __modem_disable(struct connman_device *device);
+
+static int __network_probe(struct connman_network *network);
+static void __network_remove(struct connman_network *network);
+static int __network_connect(struct connman_network *network);
+static int __network_disconnect(struct connman_network *network);
+
+
+/* dbus request and reply */
+static int __dbus_request(const char *path, const char *interface,
+ const char *method,
+ DBusPendingCallNotifyFunction notify, void *user_data,
+ DBusFreeFunction free_function, int type, ...);
+
+static int __request_get_modems(void);
+static void __response_get_modems(DBusPendingCall *call, void *user_data);
+static int __request_get_services(const char *path);
+static void __response_get_services(DBusPendingCall *call, void *user_data);
+static int __request_get_contexts(struct telephony_modem *modem);
+static void __response_get_contexts(DBusPendingCall *call, void *user_data);
+static int __request_network_activate(struct connman_network *network);
+static void __response_network_activate(DBusPendingCall *call, void *user_data);
+static int __request_network_deactivate(struct connman_network *network);
+
+/* telephony internal function */
+static void __add_modem(const char *path, DBusMessageIter *prop);
+static void __add_service(struct telephony_modem *modem,
+ const char *service_path, DBusMessageIter *prop);
+static void __add_connman_device(const char *modem_path, const char *operator);
+static void __remove_connman_device(struct telephony_modem *modem);
+static void __remove_connman_networks(struct connman_device *device);
+static int __add_context(struct connman_device *device, const char *path,
+ DBusMessageIter *prop);
+
+/* signal handler */
+static gboolean __changed_modem(DBusConnection *connection,
+ DBusMessage *message, void *user_data);
+static gboolean __added_modem(DBusConnection *connection,
+ DBusMessage *message, void *user_data);
+static gboolean __removed_modem(DBusConnection *connection,
+ DBusMessage *message, void *user_data);
+static gboolean __changed_service(DBusConnection *connection,
+ DBusMessage *message, void *user_data);
+static gboolean __added_service(DBusConnection *connection,
+ DBusMessage *message, void *user_data);
+static gboolean __removed_service(DBusConnection *connection,
+ DBusMessage *message, void *user_data);
+static gboolean __changed_context(DBusConnection *connection,
+ DBusMessage *message, void *user_data);
+static gboolean __added_context(DBusConnection *connection,
+ DBusMessage *message, void *user_data);
+static gboolean __removed_context(DBusConnection *connection,
+ DBusMessage *message, void *user_data);
+
+/* device driver */
+static struct connman_device_driver modem_driver = {
+ .name = "device",
+ .type = CONNMAN_DEVICE_TYPE_CELLULAR,
+ .probe = __modem_probe,
+ .remove = __modem_remove,
+ .enable = __modem_enable,
+ .disable = __modem_disable,
+};
+
+/* network driver */
+static struct connman_network_driver network_driver = {
+ .name = "network",
+ .type = CONNMAN_NETWORK_TYPE_CELLULAR,
+ .probe = __network_probe,
+ .remove = __network_remove,
+ .connect = __network_connect,
+ .disconnect = __network_disconnect,
+};
+
+static int tech_probe(struct connman_technology *technology)
+{
+ return 0;
+}
+
+static void tech_remove(struct connman_technology *technology)
+{
+ return;
+}
+
+static struct connman_technology_driver tech_driver = {
+ .name = "cellular",
+ .type = CONNMAN_SERVICE_TYPE_CELLULAR,
+ .probe = tech_probe,
+ .remove = tech_remove,
+};
+
+/* local function */
+static void telephony_connect(DBusConnection *connection, void *user_data)
+{
+ DBG("connection %p", connection);
+ modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, __remove_modem);
+ service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, __remove_service);
+ network_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, __remove_network);
+
+ __request_get_modems();
+}
+
+static void telephony_disconnect(DBusConnection *connection, void *user_data)
+{
+ DBG("connection %p", connection);
+
+ if (modem_hash != NULL) {
+ g_hash_table_destroy(modem_hash);
+ modem_hash = NULL;
+ }
+
+ if (network_hash != NULL) {
+ g_hash_table_destroy(network_hash);
+ network_hash = NULL;
+ }
+}
+
+static void __remove_modem(gpointer data)
+{
+ struct telephony_modem *modem = data;
+
+ __remove_connman_device(modem);
+
+ g_free(modem->path);
+ g_free(modem->operator);
+ g_free(modem);
+}
+
+static void __remove_service(gpointer data)
+{
+ struct telephony_service *service = data;
+
+ g_free(service->path);
+ g_free(service->act);
+ g_free(service);
+}
+
+static void __remove_network(gpointer data)
+{
+ struct telephony_network *info = data;
+ struct connman_device *device;
+
+ device = connman_network_get_device(info->network);
+ if (device != NULL)
+ connman_device_remove_network(device, info->network);
+
+ connman_network_unref(info->network);
+
+ g_free(info->path);
+
+ connman_ipaddress_free(info->ipv4_address);
+ connman_ipaddress_free(info->ipv6_address);
+
+ g_free(info);
+}
+
+static void __set_device_powered(struct telephony_modem *modem,
+ gboolean powered)
+{
+ DBG("set modem(%s) powered(%d)", modem->path, powered);
+
+ if (modem->device)
+ connman_device_set_powered(modem->device, powered);
+}
+
+static int __check_device_powered(const char *path, gboolean powered)
+{
+ struct telephony_modem *modem = g_hash_table_lookup(modem_hash, path);
+
+ if (modem == NULL)
+ return -ENODEV;
+
+ DBG("check modem (%s) powered (%d)", modem->path, modem->powered);
+
+ if (modem->powered == powered)
+ return -EALREADY;
+
+ return 0;
+}
+
+static int __modem_probe(struct connman_device *device)
+{
+ DBG("device %p", device);
+ return 0;
+}
+
+static void __modem_remove(struct connman_device *device)
+{
+ DBG("device %p", device);
+}
+
+static int __modem_enable(struct connman_device *device)
+{
+ const char *path = connman_device_get_string(device, "Path");
+ DBG("device %p, path, %s", device, path);
+
+ return __check_device_powered(path, TRUE);
+}
+
+static int __modem_disable(struct connman_device *device)
+{
+ const char *path = connman_device_get_string(device, "Path");
+ DBG("device %p, path, %s", device, path);
+
+ return __check_device_powered(path, FALSE);
+}
+
+static int __network_probe(struct connman_network *network)
+{
+ DBG("network_prove network(%p)", network);
+ return 0;
+}
+
+static int __network_connect(struct connman_network *network)
+{
+ DBG("network %p", network);
+
+ return __request_network_activate(network);
+}
+
+static int __network_disconnect(struct connman_network *network)
+{
+ DBG("network %p", network);
+
+ if (connman_network_get_associating(network) == TRUE)
+ connman_network_clear_associating(network);
+
+ connman_network_set_associating(network, FALSE);
+
+ return __request_network_deactivate(network);
+}
+
+static void __network_remove(struct connman_network *network)
+{
+ char const *path = connman_network_get_string(network, "Path");
+ DBG("network %p path %s", network, path);
+
+ g_hash_table_remove(network_hash, path);
+}
+
+static int __dbus_request(const char *path, const char *interface,
+ const char *method,
+ DBusPendingCallNotifyFunction notify, void *user_data,
+ DBusFreeFunction free_function, int type, ...)
+{
+ DBusMessage *message;
+ DBusPendingCall *call;
+ dbus_bool_t ok;
+ va_list va;
+
+ DBG("path %s %s.%s", path, interface, method);
+
+ if (path == NULL)
+ return -EINVAL;
+
+ message = dbus_message_new_method_call(PS_DBUS_SERVICE, path, interface, method);
+ if (message == NULL)
+ return -ENOMEM;
+
+ dbus_message_set_auto_start(message, FALSE);
+
+ va_start(va, type);
+ ok = dbus_message_append_args_valist(message, type, va);
+ va_end(va);
+
+ if (!ok)
+ return -ENOMEM;
+
+ if (dbus_connection_send_with_reply(connection, message,
+ &call, TIMEOUT) == FALSE) {
+ connman_error("Failed to call %s.%s", interface, method);
+ dbus_message_unref(message);
+ return -EINVAL;
+ }
+
+ if (call == NULL) {
+ connman_error("D-Bus connection not available");
+ dbus_message_unref(message);
+ return -EINVAL;
+ }
+
+ dbus_pending_call_set_notify(call, notify, user_data, free_function);
+
+ dbus_message_unref(message);
+
+ return -EINPROGRESS;
+}
+
+static int __request_get_modems(void)
+{
+ DBG("request get modem");
+ /* call connect master */
+ return __dbus_request("/", PS_MASTER_INTERFACE, GET_MODEMS,
+ __response_get_modems, NULL, NULL, DBUS_TYPE_INVALID);
+}
+
+static void __response_get_modems(DBusPendingCall *call, void *user_data)
+{
+ DBusMessage *reply;
+ DBusError error;
+ DBusMessageIter args, dict;
+
+ DBG("");
+
+ reply = dbus_pending_call_steal_reply(call);
+
+ dbus_error_init(&error);
+
+ if (dbus_set_error_from_message(&error, reply)) {
+ connman_error("GetModems() %s %s", error.name, error.message);
+ dbus_error_free(&error);
+ goto done;
+ }
+
+ DBG("message signature (%s)", dbus_message_get_signature(reply));
+
+ if (dbus_message_iter_init(reply, &args) == FALSE)
+ goto done;
+
+ dbus_message_iter_recurse(&args, &dict);
+
+ /* DBG("message type (%d) dic(%d)",
+ * dbus_message_iter_get_arg_type(&dict), DBUS_TYPE_DICT_ENTRY);
+ */
+
+ while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
+ DBusMessageIter entry, property;
+ const char *modem_path;
+
+ dbus_message_iter_recurse(&dict, &entry);
+ dbus_message_iter_get_basic(&entry, &modem_path);
+ DBG("modem path (%s)", modem_path);
+
+ dbus_message_iter_next(&entry);
+ dbus_message_iter_recurse(&entry, &property);
+
+ __add_modem(modem_path, &property);
+
+ dbus_message_iter_next(&dict);
+ }
+
+done:
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(call);
+}
+
+static int __request_get_services(const char *path)
+{
+ DBG("request get service");
+ return __dbus_request(path, PS_MODEM_INTERFACE, GET_SERVICES,
+ __response_get_services, g_strdup(path),
+ g_free, DBUS_TYPE_INVALID);
+}
+
+static void __response_get_services(DBusPendingCall *call, void *user_data)
+{
+ DBusMessage *reply;
+ DBusError error;
+ DBusMessageIter args, dict;
+
+ const char *path = user_data;
+ struct telephony_modem *modem;
+
+ modem = g_hash_table_lookup(modem_hash, path);
+ if (modem == NULL)
+ return;
+ if (modem->device == NULL)
+ return;
+
+ DBG("");
+
+ reply = dbus_pending_call_steal_reply(call);
+
+ dbus_error_init(&error);
+
+ if (dbus_set_error_from_message(&error, reply)) {
+ connman_error("GetServices() %s %s", error.name, error.message);
+ dbus_error_free(&error);
+ goto done;
+ }
+
+ DBG("message signature (%s)", dbus_message_get_signature(reply));
+
+ if (dbus_message_iter_init(reply, &args) == FALSE)
+ goto done;
+
+ dbus_message_iter_recurse(&args, &dict);
+
+ /* DBG("message type (%d) dic(%d)",
+ * dbus_message_iter_get_arg_type(&dict), DBUS_TYPE_DICT_ENTRY);
+ */
+
+ while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
+ DBusMessageIter entry, property;
+ const char *service_path;
+
+ dbus_message_iter_recurse(&dict, &entry);
+ dbus_message_iter_get_basic(&entry, &service_path);
+ DBG("service path (%s)", service_path);
+
+ dbus_message_iter_next(&entry);
+ dbus_message_iter_recurse(&entry, &property);
+
+ __add_service(modem, service_path, &property);
+
+ dbus_message_iter_next(&dict);
+ }
+
+done:
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(call);
+}
+
+static int __request_get_contexts(struct telephony_modem *modem)
+{
+ DBG("request get contexts");
+ return __dbus_request(modem->s_service->path,
+ PS_SERVICE_INTERFACE, GET_CONTEXTS,
+ __response_get_contexts, g_strdup(modem->path),
+ g_free, DBUS_TYPE_INVALID);
+}
+
+static void __response_get_contexts(DBusPendingCall *call, void *user_data)
+{
+ DBusError error;
+ DBusMessage *reply;
+ DBusMessageIter args, dict;
+
+ const char *path = user_data;
+ struct telephony_modem *modem;
+
+ DBG("");
+
+ modem = g_hash_table_lookup(modem_hash, path);
+ if (modem == NULL)
+ return;
+ if (modem->s_service == NULL)
+ return;
+ if (modem->device == NULL)
+ return;
+
+ reply = dbus_pending_call_steal_reply(call);
+
+ dbus_error_init(&error);
+
+ if (dbus_set_error_from_message(&error, reply)) {
+ connman_error("GetContexts() %s %s", error.name, error.message);
+ dbus_error_free(&error);
+ goto done;
+ }
+
+ DBG("message signature (%s)", dbus_message_get_signature(reply));
+
+ if (dbus_message_iter_init(reply, &args) == FALSE)
+ goto done;
+
+ dbus_message_iter_recurse(&args, &dict);
+
+ while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
+ DBusMessageIter entry, property;
+ const char *context_path;
+
+ dbus_message_iter_recurse(&dict, &entry);
+ dbus_message_iter_get_basic(&entry, &context_path);
+ DBG("context path (%s)", context_path);
+
+ dbus_message_iter_next(&entry);
+ dbus_message_iter_recurse(&entry, &property);
+
+ __add_context(modem->device, context_path, &property);
+
+ dbus_message_iter_next(&dict);
+ }
+
+done:
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(call);
+}
+
+static int __request_network_activate(struct connman_network *network)
+{
+ int n_modems;
+ const char *path = NULL;
+ struct telephony_modem *modem = NULL;
+
+ n_modems = g_hash_table_size(modem_hash);
+ path = connman_network_get_string(network, "Path");
+ modem = connman_device_get_data(connman_network_get_device(network));
+ DBG("network %p, path %s, modem %s[%d]", network, path, modem->path,
+ telephony_default_subscription_id);
+
+ if (modem && n_modems > 1 && g_str_has_suffix(path, "_1") == TRUE) {
+ char *subscribe_id = g_strdup_printf("%d", telephony_default_subscription_id);
+
+ if (g_str_has_suffix(modem->path, subscribe_id) != TRUE) {
+ g_free(subscribe_id);
+ return -ENOLINK;
+ }
+ g_free(subscribe_id);
+ }
+
+ return __dbus_request(path, PS_CONTEXT_INTERFACE, ACTIVATE_CONTEXT,
+ __response_network_activate,
+ g_strdup(path), NULL, DBUS_TYPE_INVALID);
+}
+
+static gboolean __check_network_available(struct connman_network *network)
+{
+ if (network == NULL || connman_network_get_device(network) == NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void __response_network_activate(DBusPendingCall *call, void *user_data)
+{
+ DBG("network activation response");
+
+ DBusError error;
+ DBusMessage *reply;
+
+ struct telephony_network *info;
+ const char *path = user_data;
+
+ info = g_hash_table_lookup(network_hash, path);
+ reply = dbus_pending_call_steal_reply(call);
+
+ if (info == NULL)
+ goto done;
+
+ if (__check_network_available(info->network) == FALSE) {
+ g_hash_table_remove(network_hash, path);
+ goto done;
+ }
+
+ dbus_error_init(&error);
+ if (dbus_set_error_from_message(&error, reply)) {
+ connman_error("connection activate() %s %s",
+ error.name, error.message);
+
+ if (connman_network_get_associating(info->network) == TRUE)
+ connman_network_set_error(info->network,
+ CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
+
+ if (connman_network_get_connecting(info->network) == TRUE)
+ connman_network_set_error(info->network,
+ CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
+
+ if (connman_network_get_index(info->network) < 0)
+ connman_network_set_error(info->network,
+ CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
+
+ dbus_error_free(&error);
+ goto done;
+ }
+
+done:
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(call);
+}
+
+static int __request_network_deactivate(struct connman_network *network)
+{
+ const char *path = connman_network_get_string(network, "Path");
+ DBG("network %p, path %s", network, path);
+
+ return __dbus_request(path, PS_CONTEXT_INTERFACE, DEACTIVATE_CONTEXT,
+ NULL, NULL, NULL, DBUS_TYPE_INVALID);
+}
+
+static void __response_get_default_subscription_id(DBusPendingCall *call,
+ void *user_data)
+{
+ DBusMessage *reply;
+ DBusError error;
+ DBusMessageIter args;
+
+ DBG("");
+
+ reply = dbus_pending_call_steal_reply(call);
+
+ dbus_error_init(&error);
+ if (dbus_set_error_from_message(&error, reply)) {
+ connman_error("GetDefaultDataSubscription() %s %s", error.name, error.message);
+ dbus_error_free(&error);
+ goto done;
+ }
+
+ DBG("message signature (%s)", dbus_message_get_signature(reply));
+
+ if (dbus_message_iter_init(reply, &args) == FALSE)
+ goto done;
+
+ dbus_message_iter_get_basic(&args, &telephony_default_subscription_id);
+ DBG("default subscription: %d", telephony_default_subscription_id);
+
+done:
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(call);
+}
+
+static int __request_get_default_subscription_id(const char *path)
+{
+ int ret;
+ char *telephony_modem_path = NULL;
+
+ telephony_modem_path = g_strdup_printf("/org/tizen/telephony%s", path);
+ DBG("request get default subscription id %s", telephony_modem_path);
+
+ ret = __dbus_request(telephony_modem_path,
+ "org.tizen.telephony.Network", "GetDefaultDataSubscription",
+ __response_get_default_subscription_id, NULL, NULL, DBUS_TYPE_INVALID);
+
+ g_free(telephony_modem_path);
+ return ret;
+}
+
+static void __add_modem(const char *path, DBusMessageIter *prop)
+{
+ struct telephony_modem *modem;
+
+ modem = g_hash_table_lookup(modem_hash, path);
+ if (modem != NULL)
+ return;
+
+ modem = g_try_new0(struct telephony_modem, 1);
+ if (modem == NULL)
+ return;
+
+ modem->path = g_strdup(path);
+ modem->device = NULL;
+ modem->s_service = NULL;
+
+ g_hash_table_insert(modem_hash, g_strdup(path), modem);
+
+ while (dbus_message_iter_get_arg_type(prop) != DBUS_TYPE_INVALID) {
+ DBusMessageIter entry;
+ const char *key, *tmp;
+
+ dbus_message_iter_recurse(prop, &entry);
+ dbus_message_iter_get_basic(&entry, &key);
+
+ dbus_message_iter_next(&entry);
+ dbus_message_iter_get_basic(&entry, &tmp);
+
+ DBG("key (%s) value(%s)", key, tmp);
+
+ if (g_strcmp0(key, "powered") == 0) {
+ modem->powered = STRING2BOOL(tmp);
+ } else if (g_strcmp0(key, "operator") == 0) {
+ modem->operator = g_strdup(tmp);
+ } else if (g_strcmp0(key, "sim_init") == 0) {
+ modem->sim_init = STRING2BOOL(tmp);
+ } else if (g_strcmp0(key, "flight_mode") == 0) {
+ modem->flight_mode = STRING2BOOL(tmp);
+ } else if (g_strcmp0(key, "roaming_allowed") == 0) {
+ modem->roaming_allowed = STRING2BOOL(tmp);
+ } else if (g_strcmp0(key, "data_allowed") == 0) {
+ modem->data_allowed = STRING2BOOL(tmp);
+ }
+ dbus_message_iter_next(prop);
+ }
+
+ __add_connman_device(path, modem->operator);
+ __set_device_powered(modem, modem->powered);
+
+ if (g_hash_table_size(modem_hash) > 1)
+ __request_get_default_subscription_id(modem->path);
+
+ if (modem->powered != TRUE) {
+ DBG("modem is not powered");
+ return;
+ }
+
+ __request_get_services(modem->path);
+}
+
+static void __add_service(struct telephony_modem *modem,
+ const char *service_path, DBusMessageIter *prop)
+{
+ struct telephony_service *service;
+
+ if (modem->s_service != NULL)
+ return;
+
+ service = g_try_new0(struct telephony_service, 1);
+ if (service == NULL)
+ return;
+
+ service->path = g_strdup(service_path);
+ service->p_modem = modem;
+ g_hash_table_insert(service_hash, g_strdup(service_path), service);
+
+ while (dbus_message_iter_get_arg_type(prop) != DBUS_TYPE_INVALID) {
+ DBusMessageIter entry;
+ const char *key, *tmp;
+
+ dbus_message_iter_recurse(prop, &entry);
+ dbus_message_iter_get_basic(&entry, &key);
+
+ dbus_message_iter_next(&entry);
+ dbus_message_iter_get_basic(&entry, &tmp);
+
+ DBG("key (%s) value(%s)", key, tmp);
+
+ if (g_strcmp0(key, "roaming") == 0) {
+ service->roaming = STRING2BOOL(tmp);
+ } else if (g_strcmp0(key, "act") == 0) {
+ service->act = g_strdup(tmp);
+ } else if (g_strcmp0(key, "ps_attached") == 0) {
+ service->ps_attached = STRING2BOOL(tmp);
+ }
+
+ dbus_message_iter_next(prop);
+ }
+
+ modem->s_service = service;
+ __request_get_contexts(modem);
+}
+
+static char *__get_ident(const char *path)
+{
+ char *pos;
+
+ if (*path != '/')
+ return NULL;
+
+ pos = strrchr(path, '/');
+ if (pos == NULL)
+ return NULL;
+
+ return pos + 1;
+}
+
+static void __add_connman_device(const char *modem_path, const char *operator)
+{
+ char* ident = NULL;
+ struct telephony_modem *modem;
+ struct connman_device *device;
+
+ DBG("path %s operator %s", modem_path, operator);
+
+ if (modem_path == NULL)
+ return;
+
+ if (operator == NULL)
+ return;
+
+ modem = g_hash_table_lookup(modem_hash, modem_path);
+ if (modem == NULL)
+ return;
+
+ if (modem->device) {
+ if (!g_strcmp0(operator,
+ connman_device_get_ident(modem->device)))
+ return;
+
+ __remove_connman_device(modem);
+ }
+
+ if (strlen(operator) == 0)
+ return;
+
+ device = connman_device_create(operator, CONNMAN_DEVICE_TYPE_CELLULAR);
+ if (device == NULL)
+ return;
+
+ ident = g_strdup_printf("%s_%s", __get_ident(modem_path), operator);
+ connman_device_set_ident(device, ident);
+ g_free(ident);
+
+ connman_device_set_string(device, "Path", modem_path);
+ connman_device_set_data(device, modem);
+
+ if (connman_device_register(device) < 0) {
+ connman_error("Failed to register cellular device");
+ connman_device_unref(device);
+ return;
+ }
+
+ modem->device = device;
+}
+
+static void __remove_connman_device(struct telephony_modem *modem)
+{
+ DBG("modem %p path %s device %p", modem, modem->path, modem->device);
+
+ if (modem->device == NULL)
+ return;
+
+ __remove_connman_networks(modem->device);
+
+ connman_device_unregister(modem->device);
+ connman_device_unref(modem->device);
+
+ modem->device = NULL;
+}
+
+static void __remove_connman_networks(struct connman_device *device)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+ GSList *info_list = NULL;
+ GSList *list;
+
+ if (network_hash == NULL)
+ return;
+
+ g_hash_table_iter_init(&iter, network_hash);
+
+ while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+ struct telephony_network *info = value;
+
+ if (connman_network_get_device(info->network) != device)
+ continue;
+
+ info_list = g_slist_append(info_list, info);
+ }
+
+ for (list = info_list; list != NULL; list = list->next) {
+ struct telephony_network *info = list->data;
+ connman_device_remove_network(device, info->network);
+ }
+
+ g_slist_free(info_list);
+}
+
+static gboolean connman_ipaddress_updated(struct connman_ipaddress *ipaddress,
+ const char *address, const char *gateway)
+{
+ if (ipaddress == NULL || address == NULL)
+ return FALSE;
+
+ if (g_strcmp0(ipaddress->local, address) != 0)
+ return TRUE;
+
+ if (g_strcmp0(ipaddress->gateway, gateway) != 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+static void __set_network_connected(struct telephony_network *network,
+ gboolean connected)
+{
+ gboolean setip = FALSE;
+
+ DBG("network %p connected %d", network, connected);
+
+ connman_network_set_index(network->network, network->if_index);
+ if (connman_network_get_connected(network->network) == connected)
+ return;
+
+ switch (network->ipv4_method) {
+ case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
+ case CONNMAN_IPCONFIG_METHOD_DHCP:
+ case CONNMAN_IPCONFIG_METHOD_AUTO:
+ case CONNMAN_IPCONFIG_METHOD_OFF:
+ connman_network_set_ipv4_method(network->network,
+ network->ipv4_method);
+ break;
+ case CONNMAN_IPCONFIG_METHOD_MANUAL:
+ case CONNMAN_IPCONFIG_METHOD_FIXED:
+ connman_network_set_ipv4_method(network->network,
+ network->ipv4_method);
+ connman_network_set_ipaddress(network->network,
+ network->ipv4_address);
+ setip = TRUE;
+ break;
+ }
+
+ switch (network->ipv6_method) {
+ case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
+ case CONNMAN_IPCONFIG_METHOD_OFF:
+ case CONNMAN_IPCONFIG_METHOD_DHCP:
+ break;
+ case CONNMAN_IPCONFIG_METHOD_AUTO:
+ connman_network_set_ipv6_method(network->network,
+ network->ipv6_method);
+ setip = TRUE;
+ break;
+ case CONNMAN_IPCONFIG_METHOD_MANUAL:
+ case CONNMAN_IPCONFIG_METHOD_FIXED:
+ connman_network_set_ipv6_method(network->network,
+ network->ipv6_method);
+ connman_network_set_ipaddress(network->network,
+ network->ipv6_address);
+ setip = TRUE;
+ break;
+ }
+
+ if (setip == TRUE)
+ connman_network_set_connected(network->network, connected);
+}
+
+static gboolean __set_network_context(
+ struct telephony_network *network,
+ DBusMessageIter *dict)
+{
+ int index = 0;
+ gboolean active = FALSE;
+ gboolean routing_only = FALSE;
+ gboolean ipv4_updated = FALSE;
+ gboolean ipv6_updated = FALSE;
+ gboolean ipv6_link_only = FALSE;
+ gboolean default_internet = FALSE;
+ gboolean active_proxy = FALSE;
+ char **proxies = NULL;
+ const char *dev_name = NULL;
+ const char *proxy_addr = NULL;
+ char *ipv4_addr = NULL, *ipv4_gw = NULL, *ipv4_netmask = NULL,
+ *ipv4_dns1 = NULL, *ipv4_dns2 = NULL;
+ char *ipv6_addr = NULL, *ipv6_gw = NULL, *ipv6_netmask = NULL,
+ *ipv6_dns1 = NULL, *ipv6_dns2 = NULL;
+ struct connman_service *service;
+
+ while (dbus_message_iter_get_arg_type(dict) != DBUS_TYPE_INVALID) {
+ DBusMessageIter entry;
+ const char *key, *value;
+
+ dbus_message_iter_recurse(dict, &entry);
+ dbus_message_iter_get_basic(&entry, &key);
+
+ dbus_message_iter_next(&entry);
+
+ if (g_strcmp0(key, "dev_name") == 0) {
+ dbus_message_iter_get_basic(&entry, &dev_name);
+ DBG("dev_name (%s)", dev_name);
+ } else if (g_strcmp0(key, "proxy") == 0) {
+ dbus_message_iter_get_basic(&entry, &proxy_addr);
+ DBG("proxy_addr (%s)", proxy_addr);
+ } else if (g_strcmp0(key, "ipv4_address") == 0) {
+ dbus_message_iter_get_basic(&entry, &ipv4_addr);
+ DBG("ipv4_addr (%s)", ipv4_addr);
+ } else if (g_strcmp0(key, "ipv4_gateway") == 0) {
+ dbus_message_iter_get_basic(&entry, &ipv4_gw);
+ DBG("ipv4_gw (%s)", ipv4_gw);
+ } else if (g_strcmp0(key, "ipv4_netmask") == 0) {
+ dbus_message_iter_get_basic(&entry, &ipv4_netmask);
+ DBG("ipv4_netmask (%s)", ipv4_netmask);
+ } else if (g_strcmp0(key, "ipv4_dns1") == 0) {
+ dbus_message_iter_get_basic(&entry, &ipv4_dns1);
+ DBG("ipv4_dns1 (%s)", ipv4_dns1);
+ } else if (g_strcmp0(key, "ipv4_dns2") == 0) {
+ dbus_message_iter_get_basic(&entry, &ipv4_dns2);
+ DBG("ipv4_dns2 (%s)", ipv4_dns2);
+ } else if (g_strcmp0(key, "ipv6_address") == 0) {
+ dbus_message_iter_get_basic(&entry, &ipv6_addr);
+ DBG("ipv6 address (%s)", ipv6_addr);
+ } else if (g_strcmp0(key, "ipv6_gateway") == 0) {
+ dbus_message_iter_get_basic(&entry, &ipv6_gw);
+ DBG("ipv6_gw (%s)", ipv6_gw);
+ } else if (g_strcmp0(key, "ipv6_netmask") == 0) {
+ dbus_message_iter_get_basic(&entry, &ipv6_netmask);
+ DBG("ipv6_netmask (%s)", ipv6_netmask);
+ } else if (g_strcmp0(key, "ipv6_dns1") == 0) {
+ dbus_message_iter_get_basic(&entry, &ipv6_dns1);
+ DBG("ipv6_dns1 (%s)", ipv6_dns1);
+ } else if (g_strcmp0(key, "ipv6_dns2") == 0) {
+ dbus_message_iter_get_basic(&entry, &ipv6_dns2);
+ DBG("ipv6_dns2 (%s)", ipv6_dns2);
+ } else if (g_strcmp0(key, "active") == 0) {
+ dbus_message_iter_get_basic(&entry, &value);
+ DBG("active (%s)", value);
+ active = STRING2BOOL(value);
+ } else if (g_strcmp0(key, "routing_only") == 0) {
+ dbus_message_iter_get_basic(&entry, &value);
+ DBG("routing_only (%s)", value);
+ routing_only = STRING2BOOL(value);
+ network->routing_only = routing_only;
+ } else if (g_strcmp0(key, "ipv6_link_only") == 0) {
+ dbus_message_iter_get_basic(&entry, &value);
+ DBG("ipv6_link_only (%s)", value);
+ ipv6_link_only = STRING2BOOL(value);
+ network->ipv6_link_only = ipv6_link_only;
+ }
+ else if (g_strcmp0(key, "default_internet_conn") == 0) {
+ dbus_message_iter_get_basic(&entry, &value);
+ DBG("default_internet (%s)", value);
+ default_internet = STRING2BOOL(value);
+ }
+
+ dbus_message_iter_next(dict);
+ }
+
+ if(routing_only){
+ //context active does not effect the connman service status.
+ //it only for setting the routing path.
+ DBG("routing_only(%d), active(%d)", routing_only, active);
+ return active;
+ }
+
+ if (g_strcmp0(proxy_addr, ":") == 0)
+ proxy_addr = NULL;
+ if (g_strcmp0(ipv4_addr, "0.0.0.0") == 0)
+ ipv4_addr = NULL;
+ if (g_strcmp0(ipv4_gw, "0.0.0.0") == 0)
+ ipv4_gw = NULL;
+ if (g_strcmp0(ipv4_netmask, "0.0.0.0") == 0)
+ ipv4_netmask = NULL;
+ if (g_strcmp0(ipv4_dns1, "0.0.0.0") == 0)
+ ipv4_dns1 = NULL;
+ if (g_strcmp0(ipv4_dns2, "0.0.0.0") == 0)
+ ipv4_dns2 = NULL;
+ if (g_strcmp0(ipv6_addr, "::") == 0)
+ ipv6_addr = NULL;
+ if (g_strcmp0(ipv6_gw, "::") == 0)
+ ipv6_gw = NULL;
+ if (g_strcmp0(ipv6_netmask, "::") == 0)
+ ipv6_netmask = NULL;
+ if (g_strcmp0(ipv6_dns1, "::") == 0)
+ ipv6_dns1 = NULL;
+ if (g_strcmp0(ipv6_dns2, "::") == 0)
+ ipv6_dns2 = NULL;
+
+ connman_network_set_bool(network->network, "DefaultInternet",
+ (bool)default_internet);
+
+ service = connman_service_lookup_from_network(network->network);
+ if (service == NULL)
+ return FALSE;
+
+ if (connman_setting_get_bool("SingleConnectedTechnology") == TRUE) {
+ /* Wi-Fi technology is always a top priority */
+ if (active == TRUE &&
+ connman_service_is_no_ref_user_pdn_connection(service) == TRUE &&
+ connman_service_get_type(connman_service_get_default_connection())
+ == CONNMAN_SERVICE_TYPE_WIFI) {
+ __request_network_deactivate(network->network);
+
+ return FALSE;
+ }
+ }
+
+ /* interface index set */
+ if (dev_name != NULL) {
+ index = connman_inet_ifindex(dev_name);
+ network->if_index = index;
+ DBG("interface index %d", index);
+ }
+
+ /* proxy set */
+ if (active == TRUE &&
+ connman_network_get_connected(network->network) == TRUE)
+ active_proxy = TRUE;
+
+ proxies = connman_service_get_proxy_servers(service);
+ if (proxies != NULL) {
+ if (proxy_addr == NULL)
+ connman_service_set_proxy(service, proxy_addr, active_proxy);
+ else if (g_strcmp0(proxy_addr, proxies[0]) != 0)
+ connman_service_set_proxy(service, proxy_addr, active_proxy);
+ } else if (proxy_addr != NULL)
+ connman_service_set_proxy(service, proxy_addr, active_proxy);
+
+ if (proxies != NULL)
+ g_strfreev(proxies);
+
+ __connman_service_nameserver_clear(service);
+
+ /* ipv4 set */
+ if (network->ipv4_address == NULL)
+ network->ipv4_address =
+ connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4);
+
+ if (network->ipv4_address == NULL)
+ return FALSE;
+
+ if (ipv4_addr == NULL && active == TRUE)
+ network->ipv4_method = CONNMAN_IPCONFIG_METHOD_OFF;
+ else
+ network->ipv4_method = CONNMAN_IPCONFIG_METHOD_FIXED;
+
+ connman_network_set_ipv4_method(network->network, network->ipv4_method);
+
+ ipv4_updated = connman_ipaddress_updated(network->ipv4_address,
+ ipv4_addr, ipv4_gw);
+ if (ipv4_updated == TRUE)
+ connman_ipaddress_set_ipv4(network->ipv4_address, ipv4_addr,
+ ipv4_netmask, ipv4_gw);
+
+ if (ipv4_dns1)
+#if defined TIZEN_EXT
+ __connman_service_nameserver_append(service, ipv4_dns1, FALSE,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
+#else
+ __connman_service_nameserver_append(service, ipv4_dns1, FALSE);
+#endif
+ //if (ipv4_dns2)
+ if (ipv4_dns2 && !ipv4_dns1)
+#if defined TIZEN_EXT
+ __connman_service_nameserver_append(service, ipv4_dns2, FALSE,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
+#else
+ __connman_service_nameserver_append(service, ipv4_dns2, FALSE);
+#endif
+ /* ipv6 set */
+ if (network->ipv6_address == NULL)
+ network->ipv6_address =
+ connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6);
+
+ if (network->ipv6_address == NULL)
+ return FALSE;
+
+ if(ipv6_link_only)
+ network->ipv6_method = CONNMAN_IPCONFIG_METHOD_AUTO;
+ else
+ network->ipv6_method = CONNMAN_IPCONFIG_METHOD_FIXED;
+
+ if (ipv6_addr == NULL)
+ network->ipv6_method = CONNMAN_IPCONFIG_METHOD_OFF;
+
+ connman_network_set_ipv6_method(network->network, network->ipv6_method);
+
+ ipv6_updated = connman_ipaddress_updated(network->ipv6_address,
+ ipv6_addr, ipv6_gw);
+ if (ipv6_updated == TRUE)
+ connman_ipaddress_set_ipv6(network->ipv6_address, ipv6_addr,
+ 64, ipv6_gw);
+
+ if (ipv6_dns1)
+#if defined TIZEN_EXT
+ __connman_service_nameserver_append(service, ipv6_dns1, FALSE,
+ CONNMAN_IPCONFIG_TYPE_IPV6);
+#else
+ __connman_service_nameserver_append(service, ipv6_dns1, FALSE);
+#endif
+ //if (ipv6_dns2)
+ if (ipv6_dns2 && !ipv6_dns1)
+#if defined TIZEN_EXT
+ __connman_service_nameserver_append(service, ipv6_dns2, FALSE,
+ CONNMAN_IPCONFIG_TYPE_IPV6);
+#else
+ __connman_service_nameserver_append(service, ipv6_dns2, FALSE);
+#endif
+
+ if (active == TRUE &&
+ connman_network_get_connected(network->network) == TRUE) {
+ if (ipv4_updated == TRUE || ipv6_updated == TRUE) {
+ DBG("IPv4 updated %d, IPv6 updated %d", ipv4_updated, ipv6_updated);
+
+ __set_network_connected(network, FALSE);
+ } else {
+ DBG("Already connected");
+
+ return active;
+ }
+ }
+
+ if (active == TRUE)
+ connman_network_set_associating(network->network, TRUE);
+
+ return active;
+}
+
+static int __add_context(struct connman_device *device, const char *path,
+ DBusMessageIter *prop)
+{
+ char *ident;
+ gboolean active = FALSE;
+
+ struct telephony_modem *modem = connman_device_get_data(device);
+ struct connman_network *network;
+ struct telephony_network *info;
+
+ DBG("modem %p device %p path %s", modem, device, path);
+
+ ident = __get_ident(path);
+
+ network = connman_device_get_network(device, ident);
+ if (network != NULL)
+ return -EALREADY;
+
+ info = g_hash_table_lookup(network_hash, path);
+ if (info != NULL) {
+ DBG("path %p already exists with device %p", path,
+ connman_network_get_device(info->network));
+
+ if (connman_network_get_device(info->network))
+ return -EALREADY;
+
+ g_hash_table_remove(network_hash, path);
+ }
+
+ network = connman_network_create(ident, CONNMAN_NETWORK_TYPE_CELLULAR);
+ if (network == NULL)
+ return -ENOMEM;
+
+ info = g_try_new0(struct telephony_network, 1);
+ if (info == NULL) {
+ connman_network_unref(network);
+ return -ENOMEM;
+ }
+
+ info->path = g_strdup(path);
+
+ connman_ipaddress_clear(info->ipv4_address);
+ connman_ipaddress_clear(info->ipv6_address);
+
+ info->network = network;
+
+ connman_network_set_string(network, "Path", path);
+ connman_network_set_name(network, path);
+
+ connman_network_set_group(network, ident);
+
+ g_hash_table_insert(network_hash, g_strdup(path), info);
+
+ connman_network_set_available(network, TRUE);
+ connman_network_set_bool(network, "Roaming", (bool)modem->s_service->roaming);
+
+ if (connman_device_add_network(device, network) != 0) {
+ g_hash_table_remove(network_hash, path);
+ return -EIO;
+ }
+
+ active = __set_network_context(info, prop);
+ if(info->routing_only){
+ int err = 0;
+ struct connman_service *routing_service;
+ struct connman_ipconfig *routing_ipconfig;
+
+ if(!active)
+ return TRUE;
+
+ routing_service = connman_service_lookup_from_network(info->network);
+ routing_ipconfig = __connman_service_get_ip4config(routing_service);
+ err = __connman_ipconfig_gateway_add(routing_ipconfig, routing_service);
+
+ DBG("set gateway rv(%d)", err);
+ return TRUE;
+ }
+
+ if (active == TRUE && (connman_network_get_associating(network) == TRUE ||
+ connman_network_get_connecting(network) == TRUE))
+ __set_network_connected(info, active);
+
+ return 0;
+}
+
+static gboolean __changed_modem(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ gboolean old_powered;
+ DBusMessageIter args, dict;
+ struct telephony_modem *modem;
+ const char *path = dbus_message_get_path(message);
+
+ DBG("modem changed signal %s", path);
+
+ modem = g_hash_table_lookup(modem_hash, path);
+ if (modem == NULL) {
+ DBG("modem object does not exists");
+ return TRUE;
+ }
+
+ old_powered = modem->powered;
+
+ DBG("message signature (%s)", dbus_message_get_signature(message));
+
+ if (dbus_message_iter_init(message, &args) == FALSE) {
+ DBG("error to read message");
+ return TRUE;
+ }
+
+ dbus_message_iter_recurse(&args, &dict);
+
+ while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
+ DBusMessageIter entry;
+ const char *key, *tmp;
+
+ dbus_message_iter_recurse(&dict, &entry);
+ dbus_message_iter_get_basic(&entry, &key);
+
+ dbus_message_iter_next(&entry);
+ dbus_message_iter_get_basic(&entry, &tmp);
+
+ DBG("key(%s), value(%s)", key, tmp);
+
+ if (g_strcmp0(key, "powered") == 0) {
+ modem->powered = STRING2BOOL(tmp);
+ } else if (g_strcmp0(key, "operator") == 0) {
+ modem->operator = g_strdup(tmp);
+ } else if (g_strcmp0(key, "sim_init") == 0) {
+ modem->sim_init = STRING2BOOL(tmp);
+ } else if (g_strcmp0(key, "flight_mode") == 0) {
+ modem->flight_mode = STRING2BOOL(tmp);
+ } else if (g_strcmp0(key, "roaming_allowed") == 0) {
+ modem->roaming_allowed = STRING2BOOL(tmp);
+ } else if (g_strcmp0(key, "data_allowed") == 0) {
+ modem->data_allowed = STRING2BOOL(tmp);
+ }
+
+ dbus_message_iter_next(&dict);
+ }
+
+ if (modem->device == NULL)
+ __add_connman_device(path, modem->operator);
+
+ if (old_powered != modem->powered)
+ __set_device_powered(modem, modem->powered);
+
+ if (modem->powered != TRUE) {
+ DBG("modem is not powered");
+ return TRUE;
+ }
+
+ if (modem->s_service == NULL) {
+ __request_get_services(modem->path);
+ return TRUE;
+ }
+
+ DBG("modem(%s) flight mode(%d) data allowed(%d)",
+ modem->path, modem->flight_mode, modem->data_allowed);
+
+ return TRUE;
+}
+
+static gboolean __added_modem(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ const char *modem_path = NULL;
+ DBusMessageIter args, dict, tmp;
+
+ DBG("modem added signal (%s)", dbus_message_get_signature(message));
+
+ if (dbus_message_iter_init(message, &args) == FALSE) {
+ DBG("error to read message");
+ return TRUE;
+ }
+
+ dbus_message_iter_recurse(&args, &dict);
+ memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
+
+ while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
+ DBusMessageIter entry;
+ const char *key, *value;
+
+ dbus_message_iter_recurse(&tmp, &entry);
+ dbus_message_iter_get_basic(&entry, &key);
+
+ dbus_message_iter_next(&entry);
+ dbus_message_iter_get_basic(&entry, &value);
+
+ DBG("key (%s) value(%s)", key, value);
+
+ if (g_strcmp0(key, "path") == 0)
+ modem_path = g_strdup(value);
+
+ dbus_message_iter_next(&tmp);
+ }
+
+ if (modem_path != NULL)
+ __add_modem(modem_path, &dict);
+
+ return TRUE;
+}
+
+static gboolean __removed_modem(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ DBusMessageIter iter;
+ const char *modem_path;
+
+ DBG("modem removed signal");
+
+ if (dbus_message_iter_init(message, &iter) == FALSE) {
+ DBG("error to read message");
+ return TRUE;
+ }
+
+ dbus_message_iter_get_basic(&iter, &modem_path);
+ g_hash_table_remove(modem_hash, modem_path);
+
+ return TRUE;
+}
+
+static gboolean __changed_service(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ DBusMessageIter args, dict;
+ struct telephony_modem *modem;
+ gboolean roaming_option = TRUE;
+ struct telephony_service *s_service;
+ const char *service_path = dbus_message_get_path(message);
+
+ DBG("service changed signal %s", service_path);
+
+ s_service = g_hash_table_lookup(service_hash, service_path);
+ if (s_service == NULL) {
+ DBG("service object does not exists");
+ return TRUE;
+ }
+
+ modem = s_service->p_modem;
+ if (modem == NULL) {
+ DBG("modem object does not exists");
+ return TRUE;
+ }
+
+ DBG("message signature (%s)", dbus_message_get_signature(message));
+
+ if (dbus_message_iter_init(message, &args) == FALSE) {
+ DBG("error to read message");
+ return TRUE;
+ }
+
+ dbus_message_iter_recurse(&args, &dict);
+
+ while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
+ DBusMessageIter entry;
+ const char *key, *tmp;
+
+ dbus_message_iter_recurse(&dict, &entry);
+ dbus_message_iter_get_basic(&entry, &key);
+
+ dbus_message_iter_next(&entry);
+ dbus_message_iter_get_basic(&entry, &tmp);
+
+ DBG("key(%s), value(%s)", key, tmp);
+
+ if (g_strcmp0(key, "roaming") == 0) {
+ s_service->roaming = STRING2BOOL(tmp);
+ } else if (g_strcmp0(key, "act") == 0) {
+ s_service->act = g_strdup(tmp);
+ } else if (g_strcmp0(key, "ps_attached") == 0) {
+ s_service->ps_attached = STRING2BOOL(tmp);
+ }
+
+ dbus_message_iter_next(&dict);
+ }
+
+ roaming_option &= (!s_service->roaming && !modem->roaming_allowed)
+ || modem->roaming_allowed;
+
+ return TRUE;
+}
+
+static gboolean __added_service(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ struct telephony_modem *modem;
+ const char *service_path = NULL;
+ DBusMessageIter args, dict, tmp;
+ const char *path = dbus_message_get_path(message);
+
+ DBG("service added signal %s", path);
+
+ modem = g_hash_table_lookup(modem_hash, path);
+ if (modem == NULL || modem->device == NULL)
+ return TRUE;
+
+ DBG("message signature (%s)", dbus_message_get_signature(message));
+ if (dbus_message_iter_init(message, &args) == FALSE) {
+ DBG("error to read message");
+ return TRUE;
+ }
+
+ dbus_message_iter_recurse(&args, &dict);
+ memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
+
+ while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
+ DBusMessageIter entry;
+ const char *key, *value;
+
+ dbus_message_iter_recurse(&tmp, &entry);
+ dbus_message_iter_get_basic(&entry, &key);
+
+ dbus_message_iter_next(&entry);
+ dbus_message_iter_get_basic(&entry, &value);
+
+ DBG("key (%s) value(%s)", key, value);
+
+ if (g_strcmp0(key, "path") == 0)
+ service_path = value;
+
+ dbus_message_iter_next(&tmp);
+ }
+
+ if (service_path != NULL)
+ __add_service(modem, service_path, &dict);
+
+ return TRUE;
+}
+
+static gboolean __removed_service(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ DBusMessageIter iter;
+ const char *service_path;
+
+ DBG("service removed signal");
+
+ if (dbus_message_iter_init(message, &iter) == FALSE) {
+ DBG("error to read message");
+ return TRUE;
+ }
+
+ dbus_message_iter_get_basic(&iter, &service_path);
+ g_hash_table_remove(service_hash, service_path);
+
+ return TRUE;
+}
+
+static gboolean __changed_context(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ gboolean active = FALSE;
+ DBusMessageIter args, dict;
+ struct telephony_network *info;
+ const char *path = dbus_message_get_path(message);
+
+ DBG("network changed signal %s", path);
+
+ info = g_hash_table_lookup(network_hash, path);
+ if (info == NULL)
+ return TRUE;
+
+ if (__check_network_available(info->network) == FALSE) {
+ g_hash_table_remove(network_hash, path);
+ return TRUE;
+ }
+
+ if (dbus_message_iter_init(message, &args) == FALSE) {
+ DBG("error to read message");
+ return TRUE;
+ }
+
+ dbus_message_iter_recurse(&args, &dict);
+
+ active = __set_network_context(info, &dict);
+ if(info->routing_only){
+ int err = 0;
+ struct connman_service *routing_service;
+ struct connman_ipconfig *routing_ipconfig;
+
+ if(!active)
+ return TRUE;
+
+ routing_service = connman_service_lookup_from_network(info->network);
+ routing_ipconfig = __connman_service_get_ip4config(routing_service);
+ err = __connman_ipconfig_gateway_add(routing_ipconfig, routing_service);
+
+ DBG("set gateway rv(%d)", err);
+ return TRUE;
+ }
+
+ __set_network_connected(info, active);
+
+ if (active == FALSE &&
+ connman_network_get_connecting(info->network) == TRUE)
+ connman_network_set_connected(info->network, FALSE);
+
+ return TRUE;
+}
+
+static gboolean __added_context(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ const char *network_path = NULL;
+ DBusMessageIter args, dict, tmp;
+ struct telephony_modem *modem = NULL;
+ struct telephony_service *service = NULL;
+ const char *path = dbus_message_get_path(message);
+
+ DBG("network added signal %s", path);
+
+ service = g_hash_table_lookup(service_hash, path);
+ if (service == NULL || service->p_modem == NULL)
+ return TRUE;
+
+ modem = service->p_modem;
+ if (modem == NULL || modem->device == NULL)
+ return TRUE;
+
+ DBG("message signature (%s)", dbus_message_get_signature(message));
+ if (dbus_message_iter_init(message, &args) == FALSE) {
+ DBG("error to read message");
+ return TRUE;
+ }
+
+ dbus_message_iter_recurse(&args, &dict);
+ memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
+
+ while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
+ DBusMessageIter entry;
+ const char *key, *value;
+
+ dbus_message_iter_recurse(&tmp, &entry);
+ dbus_message_iter_get_basic(&entry, &key);
+
+ dbus_message_iter_next(&entry);
+ dbus_message_iter_get_basic(&entry, &value);
+
+ DBG("key (%s) value(%s)", key, value);
+
+ if (g_strcmp0(key, "path") == 0)
+ network_path = g_strdup(value);
+
+ dbus_message_iter_next(&tmp);
+ }
+
+ if (network_path != NULL)
+ __add_context(modem->device, network_path, &dict);
+
+ return TRUE;
+}
+
+static gboolean __removed_context(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ DBusMessageIter iter;
+ const char *network_path = NULL;
+ struct telephony_service *service = NULL;
+ const char *path = dbus_message_get_path(message);
+
+ DBG("network removed signal %s", path);
+
+ service = g_hash_table_lookup(service_hash, path);
+ if (service == NULL || service->p_modem == NULL)
+ return TRUE;
+
+ if (dbus_message_iter_init(message, &iter) == FALSE) {
+ DBG("error to read message");
+ return TRUE;
+ }
+
+ dbus_message_iter_get_basic(&iter, &network_path);
+ g_hash_table_remove(network_hash, network_path);
+
+ return TRUE;
+}
+
+static gboolean __changed_default_subscription(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ DBusMessageIter args;
+
+ DBG("message signature (%s)", dbus_message_get_signature(message));
+ if (dbus_message_iter_init(message, &args) == FALSE)
+ return TRUE;
+
+ dbus_message_iter_get_basic(&args, &telephony_default_subscription_id);
+ DBG("default subscription: %d", telephony_default_subscription_id);
+
+ return TRUE;
+}
+
+/* telephony initialization */
+static guint watch = 0;
+static guint modem_watch = 0;
+static guint modem_added_watch = 0;
+static guint modem_removed_watch = 0;
+static guint service_watch = 0;
+static guint service_added_watch = 0;
+static guint service_removed_watch = 0;
+static guint context_watch = 0;
+static guint context_added_watch = 0;
+static guint context_removed_watch = 0;
+static guint default_subscription_watch = 0;
+
+static int telephony_init(void)
+{
+ int err;
+
+ DBG("telephony plugin");
+
+ connection = connman_dbus_get_connection();
+ if (connection == NULL)
+ return -EIO;
+
+ /* telephony watch */
+ watch = g_dbus_add_service_watch(connection, PS_DBUS_SERVICE,
+ telephony_connect, telephony_disconnect,
+ NULL, NULL);
+
+ modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+ PS_MODEM_INTERFACE,
+ PROPERTY_CHANGED,
+ __changed_modem,
+ NULL, NULL);
+
+ modem_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+ PS_MASTER_INTERFACE,
+ MODEM_ADDED,
+ __added_modem,
+ NULL, NULL);
+
+ modem_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+ PS_MASTER_INTERFACE,
+ MODEM_REMOVED,
+ __removed_modem,
+ NULL, NULL);
+
+ service_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+ PS_SERVICE_INTERFACE,
+ PROPERTY_CHANGED,
+ __changed_service,
+ NULL, NULL);
+
+ service_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+ PS_MODEM_INTERFACE,
+ SERVICE_ADDED,
+ __added_service,
+ NULL, NULL);
+
+ service_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+ PS_MODEM_INTERFACE,
+ SERVICE_REMOVED,
+ __removed_service,
+ NULL, NULL);
+
+ context_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+ PS_CONTEXT_INTERFACE,
+ PROPERTY_CHANGED,
+ __changed_context,
+ NULL, NULL);
+
+ context_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+ PS_SERVICE_INTERFACE,
+ CONTEXT_ADDED,
+ __added_context,
+ NULL, NULL);
+
+ context_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+ PS_SERVICE_INTERFACE,
+ CONTEXT_REMOVED,
+ __removed_context,
+ NULL, NULL);
+
+ default_subscription_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+ "org.tizen.telephony.Network",
+ "DefaultDataSubscription",
+ __changed_default_subscription,
+ NULL, NULL);
+
+ if (watch == 0 || modem_watch == 0 || modem_added_watch == 0
+ || modem_removed_watch == 0 || service_watch == 0
+ || service_added_watch == 0 || context_watch == 0
+ || service_removed_watch == 0
+ || context_added_watch == 0
+ || context_removed_watch == 0
+ || default_subscription_watch == 0) {
+ err = -EIO;
+ goto remove;
+ }
+
+ err = connman_network_driver_register(&network_driver);
+ if (err < 0)
+ goto remove;
+
+ err = connman_device_driver_register(&modem_driver);
+ if (err < 0) {
+ connman_network_driver_unregister(&network_driver);
+ goto remove;
+ }
+
+ err = connman_technology_driver_register(&tech_driver);
+ if (err < 0) {
+ connman_device_driver_unregister(&modem_driver);
+ connman_network_driver_unregister(&network_driver);
+ goto remove;
+ }
+
+ return 0;
+
+remove:
+ g_dbus_remove_watch(connection, watch);
+ g_dbus_remove_watch(connection, modem_watch);
+ g_dbus_remove_watch(connection, modem_added_watch);
+ g_dbus_remove_watch(connection, modem_removed_watch);
+ g_dbus_remove_watch(connection, service_watch);
+ g_dbus_remove_watch(connection, service_added_watch);
+ g_dbus_remove_watch(connection, service_removed_watch);
+ g_dbus_remove_watch(connection, context_watch);
+ g_dbus_remove_watch(connection, context_added_watch);
+ g_dbus_remove_watch(connection, context_removed_watch);
+ g_dbus_remove_watch(connection, default_subscription_watch);
+
+ dbus_connection_unref(connection);
+ return err;
+}
+
+static void telephony_exit(void)
+{
+ g_dbus_remove_watch(connection, watch);
+ g_dbus_remove_watch(connection, modem_watch);
+ g_dbus_remove_watch(connection, modem_added_watch);
+ g_dbus_remove_watch(connection, modem_removed_watch);
+ g_dbus_remove_watch(connection, service_watch);
+ g_dbus_remove_watch(connection, service_added_watch);
+ g_dbus_remove_watch(connection, service_removed_watch);
+ g_dbus_remove_watch(connection, context_watch);
+ g_dbus_remove_watch(connection, context_added_watch);
+ g_dbus_remove_watch(connection, context_removed_watch);
+ g_dbus_remove_watch(connection, default_subscription_watch);
+
+ telephony_disconnect(connection, NULL);
+
+ connman_device_driver_unregister(&modem_driver);
+ connman_network_driver_unregister(&network_driver);
+
+ dbus_connection_unref(connection);
+}
+
+CONNMAN_PLUGIN_DEFINE(telephony, "Samsung Telephony Framework plug-in", VERSION,
+ CONNMAN_PLUGIN_PRIORITY_DEFAULT, telephony_init, telephony_exit)
diff --git a/plugins/tist.c b/plugins/tist.c
index ad5ef79e..ad5ef79e 100644..100755
--- a/plugins/tist.c
+++ b/plugins/tist.c
diff --git a/plugins/vpn.c b/plugins/vpn.c
index c2a332ba..d3d75b81 100644..100755
--- a/plugins/vpn.c
+++ b/plugins/vpn.c
@@ -1726,7 +1726,7 @@ static gboolean property_changed(DBusConnection *conn,
struct connection_data *data = NULL;
DBusMessageIter iter, value;
bool ip_set = false;
- int err;
+ int err = 0;
char *str;
const char *key;
const char *signature = DBUS_TYPE_STRING_AS_STRING
diff --git a/plugins/wifi.c b/plugins/wifi.c
index 34c16dfd..8bc6307b 100644..100755
--- a/plugins/wifi.c
+++ b/plugins/wifi.c
@@ -152,10 +152,27 @@ struct wifi_data {
bool p2p_connecting;
bool p2p_device;
int servicing;
+#if defined TIZEN_EXT
+ int assoc_retry_count;
+ struct connman_network *scan_pending_network;
+ bool allow_full_scan;
+#endif
int disconnect_code;
int assoc_code;
};
+#if defined TIZEN_EXT
+#include "connman.h"
+#include "dbus.h"
+
+#define TIZEN_ASSOC_RETRY_COUNT 4
+
+static gboolean wifi_first_scan = false;
+static gboolean found_with_first_scan = false;
+static gboolean is_wifi_notifier_registered = false;
+#endif
+
+
static GList *iface_list = NULL;
static GList *pending_wifi_device = NULL;
@@ -163,10 +180,128 @@ static GList *p2p_iface_list = NULL;
bool wfd_service_registered = false;
static void start_autoscan(struct connman_device *device);
+
static int tech_set_tethering(struct connman_technology *technology,
const char *identifier, const char *passphrase,
const char *bridge, bool enabled);
+#if defined TIZEN_EXT
+#define NETCONFIG_SERVICE "net.netconfig"
+#define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
+#define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
+
+struct enc_method_call_data {
+ DBusConnection *connection;
+ struct connman_network *network;
+};
+
+static struct enc_method_call_data encrypt_request_data;
+
+static void encryption_request_reply(DBusPendingCall *call,
+ void *user_data)
+{
+ DBusMessage *reply;
+ DBusError error;
+ DBusMessageIter args;
+ char *out_data;
+ struct connman_service *service;
+ gchar* encrypted_value = NULL;
+ struct connman_network *network = encrypt_request_data.network;
+
+ DBG("");
+
+ reply = dbus_pending_call_steal_reply(call);
+
+ dbus_error_init(&error);
+ if (dbus_set_error_from_message(&error, reply)) {
+ DBG("send_encryption_request() %s %s", error.name, error.message);
+ dbus_error_free(&error);
+ goto done;
+ }
+
+ if (dbus_message_iter_init(reply, &args) == FALSE)
+ goto done;
+
+ dbus_message_iter_get_basic(&args, &out_data);
+
+ encrypted_value = g_strdup((const gchar *)out_data);
+ service = connman_service_lookup_from_network(network);
+
+ if (!service) {
+ DBG("encryption result: no service");
+ goto done;
+ }
+
+ if (connman_service_get_favorite(service)) {
+ __connman_service_set_passphrase(service, encrypted_value);
+ __connman_service_save(service);
+ } else
+ connman_network_set_string(network, "WiFi.Passphrase",
+ encrypted_value);
+
+ DBG("encryption result: succeeded");
+
+done:
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(call);
+ dbus_connection_unref(encrypt_request_data.connection);
+ g_free(encrypted_value);
+
+ encrypt_request_data.connection = NULL;
+ encrypt_request_data.network = NULL;
+}
+
+static int send_encryption_request(const char *passphrase,
+ struct connman_network *network)
+{
+ DBusConnection *connection = NULL;
+ DBusMessage *msg = NULL;
+ DBusPendingCall *call;
+
+ if (!passphrase) {
+ DBG("Invalid parameter");
+ return -EINVAL;
+ }
+
+ connection = connman_dbus_get_connection();
+ if (!connection) {
+ DBG("dbus connection does not exist");
+ return -EINVAL;
+ }
+
+ msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
+ NETCONFIG_WIFI_INTERFACE, "EncryptPassphrase");
+ if (!msg) {
+ dbus_connection_unref(connection);
+ return -EINVAL;
+ }
+
+ dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
+ DBUS_TYPE_INVALID);
+
+ if (!dbus_connection_send_with_reply(connection, msg,
+ &call, DBUS_TIMEOUT_USE_DEFAULT)) {
+ dbus_message_unref(msg);
+ dbus_connection_unref(connection);
+ return -EIO;
+ }
+
+ if (!call) {
+ dbus_message_unref(msg);
+ dbus_connection_unref(connection);
+ return -EIO;
+ }
+
+ encrypt_request_data.connection = connection;
+ encrypt_request_data.network = network;
+
+ dbus_pending_call_set_notify(call, encryption_request_reply, NULL, NULL);
+ dbus_message_unref(msg);
+
+ return 0;
+}
+#endif
+
static int p2p_tech_probe(struct connman_technology *technology)
{
p2p_technology = technology;
@@ -545,6 +680,11 @@ static void register_peer_service_cb(int result,
struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
struct peer_service_registration *reg_data = user_data;
+#if defined TIZEN_EXT
+ if (!wifi)
+ return;
+#endif
+
DBG("");
if (result == 0)
@@ -1069,6 +1209,15 @@ static int get_hidden_connections(GSupplicantScanParams *scan_data)
continue;
}
+#if defined TIZEN_EXT
+ value = g_key_file_get_boolean(keyfile,
+ services[i], "AutoConnect", NULL);
+ if (!value) {
+ g_key_file_free(keyfile);
+ continue;
+ }
+#endif
+
ssid = g_key_file_get_string(keyfile,
services[i], "SSID", NULL);
@@ -1208,8 +1357,11 @@ static int throw_wifi_scan(struct connman_device *device,
if (wifi->tethering)
return -EBUSY;
-
+#if defined TIZEN_EXT
+ if (connman_device_get_scanning(device) && !wifi->allow_full_scan)
+#else
if (connman_device_get_scanning(device))
+#endif
return -EALREADY;
connman_device_ref(device);
@@ -1238,6 +1390,45 @@ static void hidden_free(struct hidden_params *hidden)
g_free(hidden);
}
+#if defined TIZEN_EXT
+static void service_state_changed(struct connman_service *service,
+ enum connman_service_state state);
+
+static int network_connect(struct connman_network *network);
+
+static struct connman_notifier notifier = {
+ .name = "wifi",
+ .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
+ .service_state_changed = service_state_changed,
+};
+
+static void service_state_changed(struct connman_service *service,
+ enum connman_service_state state)
+{
+ enum connman_service_type type;
+
+ type = connman_service_get_type(service);
+ if (type != CONNMAN_SERVICE_TYPE_WIFI)
+ return;
+
+ DBG("service %p state %d", service, state);
+
+ switch (state) {
+ case CONNMAN_SERVICE_STATE_READY:
+ case CONNMAN_SERVICE_STATE_ONLINE:
+ case CONNMAN_SERVICE_STATE_FAILURE:
+ connman_notifier_unregister(&notifier);
+ is_wifi_notifier_registered = FALSE;
+
+ __connman_device_request_scan(type);
+ break;
+
+ default:
+ break;
+ }
+}
+#endif
+
static void scan_callback(int result, GSupplicantInterface *interface,
void *user_data)
{
@@ -1283,14 +1474,31 @@ static void scan_callback(int result, GSupplicantInterface *interface,
return scan_callback(ret, interface, user_data);
}
- scanning = connman_device_get_scanning(device);
+#if defined TIZEN_EXT
+ if (wifi && wifi->allow_full_scan) {
+ int ret;
+ DBG("Trigger Full Channel Scan");
+ wifi->allow_full_scan = FALSE;
- if (scanning) {
+ ret = g_supplicant_interface_scan(wifi->interface, NULL,
+ scan_callback, device);
+ if (ret == 0)
+ return;
+
+ /* On error, let's recall scan_callback, which will cleanup */
+ return scan_callback(ret, interface, user_data);
+ }
+#endif
+
+ scanning = connman_device_get_scanning(device);
+ if (scanning)
connman_device_set_scanning(device,
CONNMAN_SERVICE_TYPE_WIFI, false);
- }
if (result != -ENOLINK)
+#if defined TIZEN_EXT
+ if (result != -EIO)
+#endif
start_autoscan(device);
/*
@@ -1302,6 +1510,23 @@ static void scan_callback(int result, GSupplicantInterface *interface,
if (scanning)
connman_device_unref(device);
+
+#if defined TIZEN_EXT
+ if (wifi && wifi->scan_pending_network && result != -EIO) {
+ network_connect(wifi->scan_pending_network);
+ wifi->scan_pending_network = NULL;
+ connman_network_set_connecting(wifi->network);
+ }
+
+ if (is_wifi_notifier_registered != true &&
+ wifi_first_scan == true && found_with_first_scan == true) {
+ wifi_first_scan = false;
+ found_with_first_scan = false;
+
+ connman_notifier_register(&notifier);
+ is_wifi_notifier_registered = true;
+ }
+#endif
}
static void scan_callback_hidden(int result,
@@ -1358,7 +1583,11 @@ static gboolean autoscan_timeout(gpointer data)
} else
interval = autoscan->interval * autoscan->base;
+#if defined TIZEN_EXT
+ if (autoscan->interval >= autoscan->limit)
+#else
if (interval > autoscan->limit)
+#endif
interval = autoscan->limit;
throw_wifi_scan(wifi->device, scan_callback_hidden);
@@ -1552,6 +1781,15 @@ static int wifi_disable(struct connman_device *device)
remove_networks(device, wifi);
remove_peers(wifi);
+#if defined TIZEN_EXT
+ wifi->scan_pending_network = NULL;
+
+ if (is_wifi_notifier_registered == true) {
+ connman_notifier_unregister(&notifier);
+ is_wifi_notifier_registered = false;
+ }
+#endif
+
ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
if (ret < 0)
return ret;
@@ -1779,6 +2017,137 @@ static int p2p_find(struct connman_device *device)
return ret;
}
+#if defined TIZEN_EXT
+static void specific_scan_callback(int result, GSupplicantInterface *interface,
+ void *user_data)
+{
+ struct connman_device *device = user_data;
+ struct wifi_data *wifi = connman_device_get_data(device);
+ bool scanning;
+
+ DBG("result %d wifi %p", result, wifi);
+
+ if (wifi && wifi->scan_params) {
+ g_supplicant_free_scan_params(wifi->scan_params);
+ wifi->scan_params = NULL;
+ }
+
+ scanning = connman_device_get_scanning(device);
+ if (scanning) {
+ connman_device_set_scanning(device,
+ CONNMAN_SERVICE_TYPE_WIFI, false);
+ connman_device_unref(device);
+ }
+}
+
+static int wifi_specific_scan(enum connman_service_type type,
+ struct connman_device *device, int scan_type,
+ GSList *specific_scan_list, void *user_data)
+{
+ GSList *list = NULL;
+ char *ssid = NULL;
+ struct wifi_data *wifi = connman_device_get_data(device);
+ GSupplicantScanParams *scan_params = NULL;
+ struct scan_ssid *scan_ssid = NULL;
+ bool scanning;
+ int ret;
+ int freq;
+ int count = 0;
+
+ if (!wifi)
+ return -ENODEV;
+
+ if (wifi->p2p_device)
+ return 0;
+
+ if (type == CONNMAN_SERVICE_TYPE_P2P)
+ return p2p_find(device);
+
+ if (wifi->tethering)
+ return 0;
+
+ scanning = connman_device_get_scanning(device);
+ if (scanning)
+ return -EALREADY;
+
+ DBG("scan_type: %d", scan_type);
+ if (scan_type == 1) { /* ssid based scan */
+ scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
+ if (!scan_params) {
+ DBG("Failed to allocate memory.");
+ return -ENOMEM;
+ }
+
+ for (list = specific_scan_list; list; list = list->next) {
+ ssid = (char *)list->data;
+ int ssid_len = strlen(ssid);
+
+ scan_ssid = g_try_new0(struct scan_ssid, 1);
+ if (!scan_ssid) {
+ DBG("Failed to allocate memory.");
+ g_supplicant_free_scan_params(scan_params);
+ return -ENOMEM;
+ }
+
+ memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
+ DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len);
+ scan_ssid->ssid_len = ssid_len;
+ scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
+ count++;
+ }
+ scan_params->num_ssids = count;
+
+ } else if (scan_type == 2) { /* frequency based scan */
+
+ scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
+ if (!scan_params) {
+ DBG("Failed to allocate memory.");
+ return -ENOMEM;
+ }
+
+ guint num_freqs = g_slist_length(specific_scan_list);
+ DBG("num_freqs: %d", num_freqs);
+
+ scan_params->freqs = g_try_new0(uint16_t, num_freqs);
+ if (!scan_params->freqs) {
+ DBG("Failed to allocate memory.");
+ g_free(scan_params);
+ return -ENOMEM;
+ }
+
+ count = 0;
+ for (list = specific_scan_list; list; list = list->next) {
+ freq = (int)list->data;
+
+ scan_params->freqs[count] = freq;
+ DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
+ count++;
+ }
+ scan_params->num_freqs = count;
+
+ } else {
+ DBG("Invalid scan");
+ return -EINVAL;
+ }
+
+ reset_autoscan(device);
+ connman_device_ref(device);
+
+ ret = g_supplicant_interface_scan(wifi->interface, scan_params,
+ specific_scan_callback, device);
+
+ if (ret == 0) {
+ connman_device_set_scanning(device,
+ CONNMAN_SERVICE_TYPE_WIFI, true);
+ } else {
+ g_supplicant_free_scan_params(scan_params);
+ connman_device_unref(device);
+ }
+
+ return ret;
+}
+#endif
+
/*
* Note that the hidden scan is only used when connecting to this specific
* hidden AP first time. It is not used when system autoconnects to hidden AP.
@@ -1893,9 +2262,18 @@ static int wifi_scan(enum connman_service_type type,
ret = g_supplicant_interface_scan(wifi->interface, scan_params,
scan_callback, device);
+
if (ret == 0) {
connman_device_set_scanning(device,
CONNMAN_SERVICE_TYPE_WIFI, true);
+#if defined TIZEN_EXT
+ /*To allow the Full Scan after ssid based scan, set the flag here
+ It is required because Tizen does not use the ConnMan specific
+ backgroung Scan feature.Tizen has added the BG Scan feature in
+ net-config. To sync with up ConnMan, we need to issue the Full Scan
+ after SSID specific scan.*/
+ wifi->allow_full_scan = TRUE;
+#endif
} else {
g_supplicant_free_scan_params(scan_params);
connman_device_unref(device);
@@ -1949,6 +2327,9 @@ static struct connman_device_driver wifi_ng_driver = {
.disable = wifi_disable,
.scan = wifi_scan,
.set_regdom = wifi_set_regdom,
+#if defined TIZEN_EXT
+ .specific_scan = wifi_specific_scan,
+#endif
};
static void system_ready(void)
@@ -1988,15 +2369,42 @@ static void network_remove(struct connman_network *network)
return;
wifi->network = NULL;
+
+#if defined TIZEN_EXT
+ wifi->disconnecting = false;
+
+ if (wifi->pending_network == network)
+ wifi->pending_network = NULL;
+
+ if (wifi->scan_pending_network == network)
+ wifi->scan_pending_network = NULL;
+#endif
}
static void connect_callback(int result, GSupplicantInterface *interface,
void *user_data)
{
+#if defined TIZEN_EXT
+ GList *list;
+ struct wifi_data *wifi;
+#endif
struct connman_network *network = user_data;
DBG("network %p result %d", network, result);
+#if defined TIZEN_EXT
+ for (list = iface_list; list; list = list->next) {
+ wifi = list->data;
+
+ if (wifi && wifi->network == network)
+ goto found;
+ }
+
+ /* wifi_data may be invalid because wifi is already disabled */
+ return;
+
+found:
+#endif
if (result == -ENOKEY) {
connman_network_set_error(network,
CONNMAN_NETWORK_ERROR_INVALID_KEY);
@@ -2022,6 +2430,12 @@ static GSupplicantSecurity network_security(const char *security)
return G_SUPPLICANT_SECURITY_PSK;
else if (g_str_equal(security, "ieee8021x"))
return G_SUPPLICANT_SECURITY_IEEE8021X;
+#if defined TIZEN_EXT
+ else if (g_str_equal(security, "ft_psk") == TRUE)
+ return G_SUPPLICANT_SECURITY_FT_PSK;
+ else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
+ return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
+#endif
return G_SUPPLICANT_SECURITY_UNKNOWN;
}
@@ -2039,7 +2453,6 @@ static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
ssid->security = network_security(security);
ssid->passphrase = connman_network_get_string(network,
"WiFi.Passphrase");
-
ssid->eap = connman_network_get_string(network, "WiFi.EAP");
/*
@@ -2083,6 +2496,13 @@ static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
+#if defined TIZEN_EXT
+ ssid->bssid = connman_network_get_bssid(network);
+#endif
+#if defined TIZEN_EXT
+ ssid->freq = connman_network_get_frequency(network);
+#endif
+
if (connman_setting_get_bool("BackgroundScanning"))
ssid->bgscan = BGSCAN_DEFAULT;
}
@@ -2117,6 +2537,9 @@ static int network_connect(struct connman_network *network)
} else {
wifi->network = connman_network_ref(network);
wifi->retries = 0;
+#if defined TIZEN_EXT
+ wifi->scan_pending_network = NULL;
+#endif
return g_supplicant_interface_connect(interface, ssid,
connect_callback, network);
@@ -2128,7 +2551,30 @@ static int network_connect(struct connman_network *network)
static void disconnect_callback(int result, GSupplicantInterface *interface,
void *user_data)
{
+#if defined TIZEN_EXT
+ GList *list;
+ struct wifi_data *wifi;
+ struct connman_network *network = user_data;
+
+ DBG("network %p result %d", network, result);
+
+ for (list = iface_list; list; list = list->next) {
+ wifi = list->data;
+
+ if (wifi->network == NULL && wifi->disconnecting == true)
+ wifi->disconnecting = false;
+
+ if (wifi->network == network)
+ goto found;
+ }
+
+ /* wifi_data may be invalid because wifi is already disabled */
+ return;
+
+found:
+#else
struct wifi_data *wifi = user_data;
+#endif
DBG("result %d supplicant interface %p wifi %p",
result, interface, wifi);
@@ -2159,6 +2605,9 @@ static int network_disconnect(struct connman_network *network)
struct connman_device *device = connman_network_get_device(network);
struct wifi_data *wifi;
int err;
+#if defined TIZEN_EXT
+ struct connman_service *service;
+#endif
DBG("network %p", network);
@@ -2166,6 +2615,29 @@ static int network_disconnect(struct connman_network *network)
if (!wifi || !wifi->interface)
return -ENODEV;
+#if defined TIZEN_EXT
+ if (connman_network_get_associating(network) == true) {
+ connman_network_clear_associating(network);
+ connman_network_set_bool(network, "WiFi.UseWPS", false);
+ } else {
+ service = connman_service_lookup_from_network(network);
+
+ if (service != NULL &&
+ (__connman_service_is_connected_state(service,
+ CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
+ __connman_service_is_connected_state(service,
+ CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
+ (connman_service_get_favorite(service) == false))
+ __connman_service_set_passphrase(service, NULL);
+ }
+
+ if (wifi->pending_network == network)
+ wifi->pending_network = NULL;
+
+ if (wifi->scan_pending_network == network)
+ wifi->scan_pending_network = NULL;
+
+#endif
connman_network_set_associating(network, false);
if (wifi->disconnecting)
@@ -2173,8 +2645,14 @@ static int network_disconnect(struct connman_network *network)
wifi->disconnecting = true;
+#if defined TIZEN_EXT
+ err = g_supplicant_interface_disconnect(wifi->interface,
+ disconnect_callback, network);
+#else
err = g_supplicant_interface_disconnect(wifi->interface,
disconnect_callback, wifi);
+#endif
+
if (err < 0)
wifi->disconnecting = false;
@@ -2297,16 +2775,49 @@ static bool handle_wps_completion(GSupplicantInterface *interface,
if (!wps_ssid || wps_ssid_len != ssid_len ||
memcmp(ssid, wps_ssid, ssid_len) != 0) {
connman_network_set_associating(network, false);
+#if defined TIZEN_EXT
+ g_supplicant_interface_disconnect(wifi->interface,
+ disconnect_callback, wifi->network);
+
+ connman_network_set_bool(network, "WiFi.UseWPS", false);
+ connman_network_set_string(network, "WiFi.PinWPS", NULL);
+#else
g_supplicant_interface_disconnect(wifi->interface,
disconnect_callback, wifi);
+#endif
return false;
}
wps_key = g_supplicant_interface_get_wps_key(interface);
+#if defined TIZEN_EXT
+ /* Check the passphrase and encrypt it
+ */
+ int ret;
+ gchar *passphrase = g_strdup(wps_key);
+
+ connman_network_set_string(network, "WiFi.PinWPS", NULL);
+
+ if (check_passphrase_ext(network, passphrase) < 0) {
+ DBG("[WPS] Invalid passphrase");
+ g_free(passphrase);
+ return true;
+ }
+
+ ret = send_encryption_request(passphrase, passphrase);
+
+ g_free(passphrase);
+
+ if (!ret)
+ DBG("[WPS] Encryption request succeeded");
+ else
+ DBG("[WPS] Encryption request failed %d", ret);
+
+#else
connman_network_set_string(network, "WiFi.Passphrase",
wps_key);
connman_network_set_string(network, "WiFi.PinWPS", NULL);
+#endif
}
return true;
@@ -2329,6 +2840,26 @@ static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
struct connman_network *network,
struct wifi_data *wifi)
{
+#if defined TIZEN_EXT
+ const char *security;
+ struct connman_service *service;
+
+ if (wifi->connected)
+ return false;
+
+ security = connman_network_get_string(network, "WiFi.Security");
+
+ if (security && g_str_equal(security, "ieee8021x") == true &&
+ wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
+ wifi->retries = 0;
+ connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
+
+ return false;
+ }
+
+ if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
+ return false;
+#else
struct connman_service *service;
if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
@@ -2336,6 +2867,7 @@ static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
if (wifi->connected)
return false;
+#endif
service = connman_service_lookup_from_network(network);
if (!service)
@@ -2354,6 +2886,47 @@ static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
return false;
}
+#if defined TIZEN_EXT
+static bool handle_wifi_assoc_retry(struct connman_network *network,
+ struct wifi_data *wifi)
+{
+ const char *security;
+
+ if (!wifi->network || wifi->connected || wifi->disconnecting ||
+ connman_network_get_connecting(network) != true) {
+ wifi->assoc_retry_count = 0;
+ return false;
+ }
+
+ if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
+ wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
+ wifi->assoc_retry_count = 0;
+ return false;
+ }
+
+ security = connman_network_get_string(network, "WiFi.Security");
+ if (security && g_str_equal(security, "ieee8021x") == true &&
+ wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
+ wifi->assoc_retry_count = 0;
+ return false;
+ }
+
+ if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
+ wifi->assoc_retry_count = 0;
+
+ /* Honestly it's not an invalid-key error,
+ * however QA team recommends that the invalid-key error
+ * might be better to display for user experience.
+ */
+ connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
+
+ return false;
+ }
+
+ return true;
+}
+#endif
+
static void interface_state(GSupplicantInterface *interface)
{
struct connman_network *network;
@@ -2401,7 +2974,11 @@ static void interface_state(GSupplicantInterface *interface)
case G_SUPPLICANT_STATE_AUTHENTICATING:
case G_SUPPLICANT_STATE_ASSOCIATING:
+#if defined TIZEN_EXT
+ reset_autoscan(device);
+#else
stop_autoscan(device);
+#endif
if (!wifi->connected)
connman_network_set_associating(network, true);
@@ -2409,8 +2986,25 @@ static void interface_state(GSupplicantInterface *interface)
break;
case G_SUPPLICANT_STATE_COMPLETED:
+#if defined TIZEN_EXT
+ /* though it should be already reset: */
+ reset_autoscan(device);
+
+ wifi->assoc_retry_count = 0;
+
+ wifi->scan_pending_network = NULL;
+
+ /* should be cleared scanning flag */
+ bool scanning = connman_device_get_scanning(device);
+ if (scanning){
+ connman_device_set_scanning(device,
+ CONNMAN_SERVICE_TYPE_WIFI, false);
+ connman_device_unref(device);
+ }
+#else
/* though it should be already stopped: */
stop_autoscan(device);
+#endif
if (!handle_wps_completion(interface, network, device, wifi))
break;
@@ -2461,6 +3055,46 @@ static void interface_state(GSupplicantInterface *interface)
default:
break;
}
+
+#if defined TIZEN_EXT
+ int err;
+
+ err = g_supplicant_interface_remove_network(wifi->interface);
+ if (err < 0)
+ DBG("Failed to remove network(%d)", err);
+
+
+ /* Some of Wi-Fi networks are not comply Wi-Fi specification.
+ * Retry association until its retry count is expired */
+ if (handle_wifi_assoc_retry(network, wifi) == true) {
+ throw_wifi_scan(wifi->device, scan_callback);
+ wifi->scan_pending_network = wifi->network;
+ break;
+ }
+
+ if(wifi->disconnect_code > 0){
+ DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
+ connman_network_set_disconnect_reason(network, wifi->disconnect_code);
+ }
+
+ /* To avoid unnecessary repeated association in wpa_supplicant,
+ * "RemoveNetwork" should be made when Wi-Fi is disconnected */
+ if (wps != true && wifi->network && wifi->disconnecting == false) {
+ wifi->disconnecting = true;
+ err = g_supplicant_interface_disconnect(wifi->interface,
+ disconnect_callback, wifi->network);
+ if (err < 0)
+ wifi->disconnecting = false;
+
+ connman_network_set_connected(network, false);
+ connman_network_set_associating(network, false);
+
+ start_autoscan(device);
+
+ break;
+ }
+#endif
+
connman_network_set_connected(network, false);
connman_network_set_associating(network, false);
wifi->disconnecting = false;
@@ -2470,6 +3104,10 @@ static void interface_state(GSupplicantInterface *interface)
break;
case G_SUPPLICANT_STATE_INACTIVE:
+#if defined TIZEN_EXT
+ if (handle_wps_completion(interface, network, device, wifi) == false)
+ break;
+#endif
connman_network_set_associating(network, false);
start_autoscan(device);
@@ -2606,7 +3244,38 @@ static void scan_started(GSupplicantInterface *interface)
static void scan_finished(GSupplicantInterface *interface)
{
+#if defined TIZEN_EXT
+ struct wifi_data *wifi;
+ bool is_associating = false;
+ static bool is_scanning = true;
+#endif
+
DBG("");
+
+#if defined TIZEN_EXT
+ wifi = g_supplicant_interface_get_data(interface);
+ if (wifi && wifi->scan_pending_network) {
+ network_connect(wifi->scan_pending_network);
+ wifi->scan_pending_network = NULL;
+ }
+
+ //service state - associating
+ if(!wifi || !wifi->network)
+ return;
+
+ is_associating = connman_network_get_associating(wifi->network);
+ if(is_associating && is_scanning){
+ is_scanning = false;
+ DBG("send scan for connecting");
+ throw_wifi_scan(wifi->device, scan_callback);
+
+ return;
+ }
+ is_scanning = true;
+
+ //go scan
+
+#endif
}
static void ap_create_fail(GSupplicantInterface *interface)
@@ -2644,9 +3313,11 @@ static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
unsigned char strength;
strength = 120 + g_supplicant_network_get_signal(supplicant_network);
+
+#if !defined TIZEN_EXT
if (strength > 100)
strength = 100;
-
+#endif
return strength;
}
@@ -2663,6 +3334,11 @@ static void network_added(GSupplicantNetwork *supplicant_network)
bool wps_ready;
bool wps_advertizing;
+#if defined TIZEN_EXT
+ const char *wifi_vsie;
+ unsigned int wifi_vsie_len;
+#endif
+
mode = g_supplicant_network_get_mode(supplicant_network);
identifier = g_supplicant_network_get_identifier(supplicant_network);
@@ -2687,6 +3363,9 @@ static void network_added(GSupplicantNetwork *supplicant_network)
ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
+#if defined TIZEN_EXT
+ wifi_vsie = g_supplicant_network_get_wifi_vsie(supplicant_network, &wifi_vsie_len);
+#endif
network = connman_device_get_network(wifi->device, identifier);
if (!network) {
@@ -2710,6 +3389,11 @@ static void network_added(GSupplicantNetwork *supplicant_network)
connman_network_set_blob(network, "WiFi.SSID",
ssid, ssid_len);
+#if defined TIZEN_EXT
+ if(wifi_vsie_len > 0 && wifi_vsie)
+ connman_network_set_blob(network, "WiFi.Vsie",
+ wifi_vsie, wifi_vsie_len);
+#endif
connman_network_set_string(network, "WiFi.Security", security);
connman_network_set_strength(network,
calculate_strength(supplicant_network));
@@ -2719,21 +3403,53 @@ static void network_added(GSupplicantNetwork *supplicant_network)
/* Is AP advertizing for WPS association?
* If so, we decide to use WPS by default */
if (wps_ready && wps_pbc &&
- wps_advertizing)
+ wps_advertizing) {
+#if !defined TIZEN_EXT
connman_network_set_bool(network, "WiFi.UseWPS", true);
+#else
+ DBG("wps is activating by ap but ignore it.");
+#endif
+ }
}
connman_network_set_frequency(network,
g_supplicant_network_get_frequency(supplicant_network));
-
+#if defined TIZEN_EXT
+ connman_network_set_bssid(network,
+ g_supplicant_network_get_bssid(supplicant_network));
+ connman_network_set_maxrate(network,
+ g_supplicant_network_get_maxrate(supplicant_network));
+ connman_network_set_enc_mode(network,
+ g_supplicant_network_get_enc_mode(supplicant_network));
+ connman_network_set_rsn_mode(network,
+ g_supplicant_network_get_rsn_mode(supplicant_network));
+ connman_network_set_keymgmt(network,
+ g_supplicant_network_get_keymgmt(supplicant_network));
+ connman_network_set_bool(network, "WiFi.HS20AP",
+ g_supplicant_network_is_hs20AP(supplicant_network));
+#endif
connman_network_set_available(network, true);
connman_network_set_string(network, "WiFi.Mode", mode);
+#if defined TIZEN_EXT
+ if (group)
+#else
if (ssid)
+#endif
connman_network_set_group(network, group);
+#if defined TIZEN_EXT
+ if (wifi_first_scan == true)
+ found_with_first_scan = true;
+#endif
+
if (wifi->hidden && ssid) {
+#if defined TIZEN_EXT
+ if (network_security(wifi->hidden->security) ==
+ network_security(security) &&
+#else
if (!g_strcmp0(wifi->hidden->security, security) &&
+#endif
wifi->hidden->ssid_len == ssid_len &&
!memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
connman_network_connect_hidden(network,
@@ -2768,6 +3484,18 @@ static void network_removed(GSupplicantNetwork *network)
if (!connman_network)
return;
+#if defined TIZEN_EXT
+ if (connman_network == wifi->scan_pending_network)
+ wifi->scan_pending_network = NULL;
+
+ if (connman_network == wifi->pending_network)
+ wifi->pending_network = NULL;
+
+ if(connman_network_get_connecting(connman_network) == true){
+ connman_network_set_connected(connman_network, false);
+ }
+#endif
+
wifi->networks = g_slist_remove(wifi->networks, connman_network);
connman_device_remove_network(wifi->device, connman_network);
@@ -2781,6 +3509,13 @@ static void network_changed(GSupplicantNetwork *network, const char *property)
const char *name, *identifier;
struct connman_network *connman_network;
+#if defined TIZEN_EXT
+ const unsigned char *bssid;
+ unsigned int maxrate;
+ uint16_t frequency;
+ bool wps;
+#endif
+
interface = g_supplicant_network_get_interface(network);
wifi = g_supplicant_interface_get_data(interface);
identifier = g_supplicant_network_get_identifier(network);
@@ -2800,6 +3535,18 @@ static void network_changed(GSupplicantNetwork *network, const char *property)
calculate_strength(network));
connman_network_update(connman_network);
}
+
+#if defined TIZEN_EXT
+ bssid = g_supplicant_network_get_bssid(network);
+ maxrate = g_supplicant_network_get_maxrate(network);
+ frequency = g_supplicant_network_get_frequency(network);
+ wps = g_supplicant_network_get_wps(network);
+
+ connman_network_set_bssid(connman_network, bssid);
+ connman_network_set_maxrate(connman_network, maxrate);
+ connman_network_set_frequency(connman_network, frequency);
+ connman_network_set_bool(connman_network, "WiFi.WPS", wps);
+#endif
}
static void network_associated(GSupplicantNetwork *network)
@@ -2870,6 +3617,17 @@ static void apply_peer_services(GSupplicantPeer *peer,
}
}
+static void add_station(const char *mac)
+{
+ connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
+ mac);
+}
+
+static void remove_station(const char *mac)
+{
+ connman_technology_tethering_remove_station(mac);
+}
+
static void peer_found(GSupplicantPeer *peer)
{
GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
@@ -2877,7 +3635,10 @@ static void peer_found(GSupplicantPeer *peer)
struct connman_peer *connman_peer;
const char *identifier, *name;
int ret;
-
+#if defined TIZEN_EXT
+ if (!wifi)
+ return;
+#endif
identifier = g_supplicant_peer_get_identifier(peer);
name = g_supplicant_peer_get_name(peer);
@@ -2934,6 +3695,11 @@ static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
struct connman_peer *connman_peer;
const char *identifier;
+#if defined TIZEN_EXT
+ if (!wifi)
+ return;
+#endif
+
identifier = g_supplicant_peer_get_identifier(peer);
DBG("ident: %s", identifier);
@@ -3023,6 +3789,11 @@ static void peer_request(GSupplicantPeer *peer)
struct connman_peer *connman_peer;
const char *identifier;
+#if defined TIZEN_EXT
+ if (!wifi)
+ return;
+#endif
+
identifier = g_supplicant_peer_get_identifier(peer);
DBG("ident: %s", identifier);
@@ -3034,6 +3805,100 @@ static void peer_request(GSupplicantPeer *peer)
connman_peer_request_connection(connman_peer);
}
+#if defined TIZEN_EXT
+static void system_power_off(void)
+{
+ GList *list;
+ struct wifi_data *wifi;
+ struct connman_service *service;
+ struct connman_ipconfig *ipconfig_ipv4;
+
+ if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
+ for (list = iface_list; list; list = list->next) {
+ wifi = list->data;
+
+ if (wifi->network != NULL) {
+ service = connman_service_lookup_from_network(wifi->network);
+ ipconfig_ipv4 = __connman_service_get_ip4config(service);
+ __connman_dhcp_stop(ipconfig_ipv4);
+ }
+ }
+ }
+}
+
+static void network_merged(GSupplicantNetwork *network)
+{
+ GSupplicantInterface *interface;
+ GSupplicantState state;
+ struct wifi_data *wifi;
+ const char *identifier;
+ struct connman_network *connman_network;
+ bool ishs20AP = 0;
+ char *temp = NULL;
+
+ interface = g_supplicant_network_get_interface(network);
+ if (!interface)
+ return;
+
+ state = g_supplicant_interface_get_state(interface);
+ if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
+ return;
+
+ wifi = g_supplicant_interface_get_data(interface);
+ if (!wifi)
+ return;
+
+ identifier = g_supplicant_network_get_identifier(network);
+
+ connman_network = connman_device_get_network(wifi->device, identifier);
+ if (!connman_network)
+ return;
+
+ DBG("merged identifier %s", identifier);
+
+ if (wifi->connected == FALSE) {
+ switch (state) {
+ case G_SUPPLICANT_STATE_AUTHENTICATING:
+ case G_SUPPLICANT_STATE_ASSOCIATING:
+ case G_SUPPLICANT_STATE_ASSOCIATED:
+ case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
+ case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
+ connman_network_set_associating(connman_network, TRUE);
+ break;
+ case G_SUPPLICANT_STATE_COMPLETED:
+ connman_network_set_connected(connman_network, TRUE);
+ break;
+ default:
+ DBG("Not handled the state : %d", state);
+ break;
+ }
+ }
+
+ ishs20AP = g_supplicant_network_is_hs20AP(network);
+
+ if (ishs20AP &&
+ g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
+ temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
+ connman_network_set_string(connman_network, "WiFi.EAP",
+ temp);
+ connman_network_set_string(connman_network, "WiFi.Identity",
+ g_supplicant_network_get_identity(network));
+ connman_network_set_string(connman_network, "WiFi.Phase2",
+ g_supplicant_network_get_phase2(network));
+
+ g_free(temp);
+ }
+
+ wifi->network = connman_network;
+}
+
+static void assoc_failed(void *user_data)
+{
+ struct connman_network *network = user_data;
+ connman_network_set_associating(network, false);
+}
+#endif
+
static void debug(const char *str)
{
if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
@@ -3073,10 +3938,17 @@ static const GSupplicantCallbacks callbacks = {
.network_removed = network_removed,
.network_changed = network_changed,
.network_associated = network_associated,
+ .add_station = add_station,
+ .remove_station = remove_station,
.peer_found = peer_found,
.peer_lost = peer_lost,
.peer_changed = peer_changed,
.peer_request = peer_request,
+#if defined TIZEN_EXT
+ .system_power_off = system_power_off,
+ .network_merged = network_merged,
+ .assoc_failed = assoc_failed,
+#endif
.debug = debug,
.disconnect_reasoncode = disconnect_reasoncode,
.assoc_status_code = assoc_status_code,
@@ -3095,7 +3967,8 @@ static void tech_remove(struct connman_technology *technology)
wifi_technology = NULL;
}
-static GSupplicantSSID *ssid_ap_init(const char *ssid, const char *passphrase)
+static GSupplicantSSID *ssid_ap_init(const char *ssid,
+ const char *passphrase)
{
GSupplicantSSID *ap;
@@ -3193,7 +4066,7 @@ static void sta_remove_callback(int result,
DBG("ifname %s result %d ", info->ifname, result);
- if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
+ if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
info->wifi->tethering = false;
connman_technology_tethering_notify(info->technology, false);
@@ -3239,10 +4112,11 @@ static int enable_wifi_tethering(struct connman_technology *technology,
if (!interface)
continue;
- ifname = g_supplicant_interface_get_ifname(wifi->interface);
- if (!ifname)
+ if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
continue;
+ ifname = g_supplicant_interface_get_ifname(wifi->interface);
+
if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
DBG("%s does not support AP mode (detected)", ifname);
continue;
@@ -3276,6 +4150,8 @@ static int enable_wifi_tethering(struct connman_technology *technology,
goto failed;
info->ifname = g_strdup(ifname);
+ if (!info->ifname)
+ goto failed;
wifi->tethering_param->technology = technology;
wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);