Updated connman to version 1.35
[platform/upstream/connman.git] / src / technology.c
old mode 100644 (file)
new mode 100755 (executable)
index d2f0ae2..5aea9f4
@@ -43,6 +43,16 @@ static GHashTable *rfkill_list;
 
 static bool global_offlinemode;
 
+#if defined TIZEN_EXT
+typedef enum {
+       CONNMAN_SCAN_TYPE_FULL_CHANNEL = 0x00,
+       CONNMAN_SCAN_TYPE_SPECIFIC_AP,
+       CONNMAN_SCAN_TYPE_MULTI_AP,
+} connman_scan_type_e;
+
+static connman_scan_type_e g_scan_type = -1;
+#endif
+
 struct connman_rfkill {
        unsigned int index;
        enum connman_service_type type;
@@ -66,6 +76,7 @@ struct connman_technology {
                                              */
        char *tethering_ident;
        char *tethering_passphrase;
+       bool tethering_hidden;
 
        bool enable_persistent; /* Save the tech state */
 
@@ -180,6 +191,9 @@ static void technology_save(struct connman_technology *technology)
        g_key_file_set_boolean(keyfile, identifier, "Tethering",
                                technology->tethering_persistent);
 
+       g_key_file_set_boolean(keyfile, identifier, "Hidden",
+                               technology->tethering_hidden);
+
        if (technology->tethering_ident)
                g_key_file_set_string(keyfile, identifier,
                                        "Tethering.Identifier",
@@ -253,8 +267,7 @@ static int set_tethering(struct connman_technology *technology,
        if (!bridge)
                return -EOPNOTSUPP;
 
-       if (technology->type == CONNMAN_SERVICE_TYPE_WIFI &&
-           (!ident || !passphrase))
+       if (technology->type == CONNMAN_SERVICE_TYPE_WIFI && (!ident))
                return -EINVAL;
 
        for (tech_drivers = technology->driver_list; tech_drivers;
@@ -546,6 +559,11 @@ static void append_properties(DBusMessageIter *iter,
                                        DBUS_TYPE_STRING,
                                        &technology->tethering_passphrase);
 
+       val = technology->tethering_hidden;
+       connman_dbus_dict_append_basic(&dict, "Hidden",
+                                       DBUS_TYPE_BOOLEAN,
+                                       &val);
+
        connman_dbus_dict_close(iter, &dict);
 }
 
@@ -682,6 +700,10 @@ static void powered_changed(struct connman_technology *technology)
 
        __sync_synchronize();
        enabled = technology->enabled;
+#if defined TIZEN_EXT
+       DBG("ConnMan, Powered : %s, %s",
+                       enabled ? "TRUE" : "FALSE",technology->path);
+#endif
        connman_dbus_property_changed_basic(technology->path,
                        CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
                        DBUS_TYPE_BOOLEAN, &enabled);
@@ -882,6 +904,21 @@ static DBusMessage *set_property(DBusConnection *conn,
 
        DBG("property %s", name);
 
+       if (technology->type == CONNMAN_SERVICE_TYPE_WIFI && technology->connected) {
+               uid_t uid;
+               if (connman_dbus_get_connection_unix_user_sync(conn,
+                                               dbus_message_get_sender(msg),
+                                               &uid) < 0) {
+                       DBG("Can not get unix user id!");
+                       return __connman_error_permission_denied(msg);
+               }
+
+               if (!__connman_service_is_user_allowed(CONNMAN_SERVICE_TYPE_WIFI, uid)) {
+                       DBG("Not allow this user to operate wifi technology now!");
+                       return __connman_error_permission_denied(msg);
+               }
+       }
+
        if (g_str_equal(name, "Tethering")) {
                dbus_bool_t tethering;
                int err;
@@ -958,6 +995,25 @@ static DBusMessage *set_property(DBusConnection *conn,
                                        DBUS_TYPE_STRING,
                                        &technology->tethering_passphrase);
                }
+       } else if (g_str_equal(name, "Hidden")) {
+               dbus_bool_t hidden;
+
+               if (type != DBUS_TYPE_BOOLEAN)
+                       return __connman_error_invalid_arguments(msg);
+
+               dbus_message_iter_get_basic(&value, &hidden);
+
+               if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
+                       return __connman_error_not_supported(msg);
+
+               technology->tethering_hidden = hidden;
+               technology_save(technology);
+
+               connman_dbus_property_changed_basic(technology->path,
+                                       CONNMAN_TECHNOLOGY_INTERFACE,
+                                       "Hidden",
+                                       DBUS_TYPE_BOOLEAN,
+                                       &hidden);
        } else if (g_str_equal(name, "Powered")) {
                dbus_bool_t enable;
 
@@ -997,9 +1053,38 @@ static void reply_scan_pending(struct connman_technology *technology, int err)
        }
 }
 
+#if defined TIZEN_EXT
+dbus_bool_t __connman_technology_notify_scan_changed(const char *key, void *val)
+{
+       DBG("key %s", key);
+       DBusMessage *signal;
+       DBusMessageIter iter;
+       dbus_bool_t result = FALSE;
+
+       signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
+                       CONNMAN_MANAGER_INTERFACE, "ScanChanged");
+       if (!signal)
+               return result;
+
+       dbus_message_iter_init_append(signal, &iter);
+       connman_dbus_property_append_basic(&iter, key, DBUS_TYPE_BOOLEAN, val);
+
+       result = dbus_connection_send(connection, signal, NULL);
+       dbus_message_unref(signal);
+
+       DBG("Successfuly sent signal");
+
+       return result;
+}
+#endif
+
 void __connman_technology_scan_started(struct connman_device *device)
 {
        DBG("device %p", device);
+#if defined TIZEN_EXT
+       dbus_bool_t status = 1;
+       __connman_technology_notify_scan_changed("scan_started", &status);
+#endif
 }
 
 void __connman_technology_scan_stopped(struct connman_device *device,
@@ -1029,8 +1114,32 @@ void __connman_technology_scan_stopped(struct connman_device *device,
                        count += 1;
        }
 
+#if defined TIZEN_EXT
+       if (count == 0) {
+               DBusMessage *signal;
+               DBusMessageIter iter;
+               dbus_bool_t status = 0;
+               __connman_technology_notify_scan_changed("scan_done", &status);
+
+               signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
+                               CONNMAN_MANAGER_INTERFACE, "ScanDone");
+               if (!signal)
+                       return;
+
+               dbus_message_iter_init_append(signal, &iter);
+               connman_dbus_property_append_basic(&iter, "Scantype",
+                               DBUS_TYPE_INT32, &g_scan_type);
+
+               dbus_connection_send(connection, signal, NULL);
+               dbus_message_unref(signal);
+               reply_scan_pending(technology, 0);
+
+               DBG("Successfuly sent ScanDone signal");
+       }
+#else
        if (count == 0)
                reply_scan_pending(technology, 0);
+#endif
 }
 
 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
@@ -1082,16 +1191,156 @@ static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
                return __connman_error_permission_denied(msg);
 
        dbus_message_ref(msg);
+#if !defined TIZEN_EXT
        technology->scan_pending =
                g_slist_prepend(technology->scan_pending, msg);
+#endif
 
        err = __connman_device_request_scan(technology->type);
+#if defined TIZEN_EXT
+       if (err < 0)
+               return __connman_error_failed(msg, -err);
+#else
        if (err < 0)
                reply_scan_pending(technology, err);
+#endif
 
+#if defined TIZEN_EXT
+       if (err == 0) {
+               g_scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
+               DBG("g_scan_type %d", g_scan_type);
+       }
+       technology->scan_pending =
+               g_slist_prepend(technology->scan_pending, msg);
+#endif
        return NULL;
 }
 
+#if defined TIZEN_EXT
+static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void *data)
+{
+       struct connman_technology *technology = data;
+       GSList *specific_scan_list = NULL;
+       int scan_type = 0;
+       const char *name = NULL;
+       unsigned int freq = 0;
+       DBusMessageIter iter, dict;
+       int err;
+
+       DBG("technology %p request from %s", technology,
+                       dbus_message_get_sender(msg));
+
+       if (!dbus_message_iter_init(msg, &iter))
+               return __connman_error_invalid_arguments(msg);
+
+       if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
+               return __connman_error_invalid_arguments(msg);
+
+       dbus_message_iter_recurse(&iter, &dict);
+       while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+               DBusMessageIter entry, value2;
+               const char *key;
+               int type;
+
+               dbus_message_iter_recurse(&dict, &entry);
+               if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) {
+                       g_slist_free_full(specific_scan_list, g_free);
+                       return __connman_error_invalid_arguments(msg);
+               }
+
+               dbus_message_iter_get_basic(&entry, &key);
+               dbus_message_iter_next(&entry);
+
+               if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) {
+                       g_slist_free_full(specific_scan_list, g_free);
+                       return __connman_error_invalid_arguments(msg);
+               }
+
+               dbus_message_iter_recurse(&entry, &value2);
+               type = dbus_message_iter_get_arg_type(&value2);
+               if (g_str_equal(key, "SSID")) {
+                       if (type != DBUS_TYPE_STRING) {
+                               g_slist_free_full(specific_scan_list, g_free);
+                               return __connman_error_invalid_arguments(msg);
+                       }
+
+                       scan_type = 1; /* SSID based scan */
+                       dbus_message_iter_get_basic(&value2, &name);
+                       DBG("name %s", name);
+                       specific_scan_list = g_slist_append(specific_scan_list, g_strdup(name));
+               } else if (g_str_equal(key, "Frequency")) {
+                       if (type != DBUS_TYPE_UINT16) {
+                               g_slist_free_full(specific_scan_list, g_free);
+                               return __connman_error_invalid_arguments(msg);
+                       }
+
+                       scan_type = 2; /* Frequency based scan */
+                       dbus_message_iter_get_basic(&value2, &freq);
+                       DBG("freq %d", freq);
+                       specific_scan_list = g_slist_append(specific_scan_list, GINT_TO_POINTER(freq));
+               }
+               dbus_message_iter_next(&dict);
+       }
+
+       dbus_message_ref(msg);
+
+       err = __connman_device_request_specific_scan(technology->type, scan_type, specific_scan_list);
+       if (err < 0)
+               return __connman_error_failed(msg, -err);
+
+       if (err == 0) {
+               guint list_size = g_slist_length(specific_scan_list);
+               if (list_size == 1)
+                       g_scan_type = CONNMAN_SCAN_TYPE_SPECIFIC_AP;
+               else
+                       g_scan_type = CONNMAN_SCAN_TYPE_MULTI_AP;
+               DBG("list_size %u g_scan_type %d", list_size, g_scan_type);
+       }
+       technology->scan_pending =
+               g_slist_prepend(technology->scan_pending, msg);
+
+       if (scan_type == 1) {
+               g_slist_free_full(specific_scan_list, g_free);
+               scan_type = 0;
+       }
+       return NULL;
+}
+
+static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void *data)
+{
+       DBusMessage *reply;
+       DBusMessageIter iter, dict;
+       GSList *list;
+       struct connman_technology *technology = data;
+       dbus_bool_t scanning = false;
+
+       DBG("technology %p", technology);
+
+       for (list = technology->device_list; list; list = list->next) {
+               struct connman_device *device = list->data;
+               scanning = connman_device_get_scanning(device);
+               if(scanning)
+                       break;
+       }
+
+       DBG("scanning : %d", scanning);
+       reply = dbus_message_new_method_return(msg);
+       if (!reply)
+               return NULL;
+
+       dbus_message_iter_init_append(reply, &iter);
+
+       connman_dbus_dict_open(&iter, &dict);
+       connman_dbus_dict_append_basic(&dict, "Scanstate",
+                                       DBUS_TYPE_BOOLEAN,
+                                       &scanning);
+
+       connman_dbus_dict_close(&iter, &dict);
+
+       return reply;
+}
+#endif
+
 static const GDBusMethodTable technology_methods[] = {
        { GDBUS_DEPRECATED_METHOD("GetProperties",
                        NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
@@ -1100,12 +1349,28 @@ static const GDBusMethodTable technology_methods[] = {
                        GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
                        NULL, set_property) },
        { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
+#if defined TIZEN_EXT
+       { GDBUS_ASYNC_METHOD("SpecificScan", GDBUS_ARGS({ "specificscan", "a{sv}" }),
+                       NULL, specific_scan) },
+       { GDBUS_METHOD("GetScanState", NULL, GDBUS_ARGS({ "scan_state", "a{sv}" }),
+                       get_scan_state) },
+#endif
        { },
 };
 
 static const GDBusSignalTable technology_signals[] = {
        { GDBUS_SIGNAL("PropertyChanged",
                        GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
+       { GDBUS_SIGNAL("DhcpConnected",
+                       GDBUS_ARGS({ "aptype", "s" },
+                               { "ipaddr", "s" },
+                               { "macaddr", "s" },
+                               { "hostname", "s" })) },
+       { GDBUS_SIGNAL("DhcpLeaseDeleted",
+                       GDBUS_ARGS({ "aptype", "s" },
+                               { "ipaddr", "s" },
+                               { "macaddr", "s" },
+                               { "hostname", "s" })) },
        { },
 };
 
@@ -1227,6 +1492,7 @@ static struct connman_technology *technology_get(enum connman_service_type type)
 
        technology->refcount = 1;
        technology->type = type;
+       technology->tethering_hidden = FALSE;
        technology->path = g_strdup_printf("%s/technology/%s",
                                                        CONNMAN_PATH, str);
 
@@ -1532,12 +1798,13 @@ int __connman_technology_enabled(enum connman_service_type type)
        DBG("technology %p type %s rfkill %d enabled %d", technology,
                get_name(type), technology->rfkill_driven,
                technology->enabled);
-
+#if !defined TIZEN_EXT
        if (technology->rfkill_driven) {
                if (technology->tethering_persistent)
                        enable_tethering(technology);
                return 0;
        }
+#endif
 
        return technology_enabled(technology);
 }
@@ -1550,10 +1817,10 @@ int __connman_technology_disabled(enum connman_service_type type)
        technology = technology_find(type);
        if (!technology)
                return -ENXIO;
-
+#if !defined TIZEN_EXT
        if (technology->rfkill_driven)
                return 0;
-
+#endif
        for (list = technology->device_list; list; list = list->next) {
                struct connman_device *device = list->data;
 
@@ -1732,6 +1999,10 @@ int __connman_technology_add_rfkill(unsigned int index,
        g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
 
 done:
+#if defined TIZEN_EXT
+       /* Fix Svace Issue [WGID: 1348]. */
+       g_free(rfkill);
+#endif
        technology = technology_get(type);
        /* If there is no driver for this type, ignore it. */
        if (!technology)
@@ -1739,11 +2010,12 @@ done:
 
        technology->rfkill_driven = true;
 
+#if !defined TIZEN_EXT
        /* If hardblocked, there is no need to handle softblocked state */
        if (technology_apply_rfkill_change(technology,
                                softblock, hardblock, true))
                return 0;
-
+#endif
        if (global_offlinemode)
                return 0;