service: Add frequency support to service
[platform/upstream/connman.git] / plugins / wifi.c
index 127b731..7ab38c5 100644 (file)
@@ -61,6 +61,7 @@ struct wifi_data {
        struct connman_device *device;
        struct connman_network *network;
        struct connman_network *pending_network;
+       GSList *networks;
        GSupplicantInterface *interface;
        GSupplicantState state;
        connman_bool_t connected;
@@ -154,6 +155,22 @@ static int wifi_probe(struct connman_device *device)
        return 0;
 }
 
+static void remove_networks(struct connman_device *device,
+                               struct wifi_data *wifi)
+{
+       GSList *list;
+
+       for (list = wifi->networks; list != NULL; list = list->next) {
+               struct connman_network *network = list->data;
+
+               connman_device_remove_network(device, network);
+               connman_network_unref(network);
+       }
+
+       g_slist_free(wifi->networks);
+       wifi->networks = NULL;
+}
+
 static void wifi_remove(struct connman_device *device)
 {
        struct wifi_data *wifi = connman_device_get_data(device);
@@ -165,10 +182,7 @@ static void wifi_remove(struct connman_device *device)
 
        iface_list = g_list_remove(iface_list, wifi);
 
-       if (wifi->pending_network != NULL) {
-               connman_network_unref(wifi->pending_network);
-               wifi->pending_network = NULL;
-       }
+       remove_networks(device, wifi);
 
        connman_device_set_data(device, NULL);
        connman_device_unref(wifi->device);
@@ -186,10 +200,11 @@ static void interface_create_callback(int result,
 {
        struct wifi_data *wifi = user_data;
 
-       DBG("result %d ifname %s", result,
-                               g_supplicant_interface_get_ifname(interface));
+       DBG("result %d ifname %s, wifi %p", result,
+                               g_supplicant_interface_get_ifname(interface),
+                               wifi);
 
-       if (result < 0)
+       if (result < 0 || wifi == NULL)
                return;
 
        wifi->interface = interface;
@@ -202,9 +217,9 @@ static void interface_remove_callback(int result,
 {
        struct wifi_data *wifi = user_data;
 
-       DBG("result %d", result);
+       DBG("result %d wifi %p", result, wifi);
 
-       if (result < 0)
+       if (result < 0 || wifi == NULL)
                return;
 
        wifi->interface = NULL;
@@ -216,31 +231,41 @@ static int wifi_enable(struct connman_device *device)
        struct wifi_data *wifi = connman_device_get_data(device);
        const char *interface = connman_device_get_string(device, "Interface");
        const char *driver = connman_option_get_string("wifi");
+       int ret;
 
        DBG("device %p %p", device, wifi);
 
-       return g_supplicant_interface_create(interface, driver, NULL,
+       ret = g_supplicant_interface_create(interface, driver, NULL,
                                                interface_create_callback,
                                                        wifi);
+       if (ret < 0)
+               return ret;
+
+       return -EINPROGRESS;
 }
 
 static int wifi_disable(struct connman_device *device)
 {
        struct wifi_data *wifi = connman_device_get_data(device);
+       int ret;
 
        DBG("device %p", device);
 
        wifi->connected = FALSE;
        wifi->disconnecting = FALSE;
 
-       if (wifi->pending_network != NULL) {
-               connman_network_unref(wifi->pending_network);
+       if (wifi->pending_network != NULL)
                wifi->pending_network = NULL;
-       }
 
-       return g_supplicant_interface_remove(wifi->interface,
+       remove_networks(device, wifi);
+
+       ret = g_supplicant_interface_remove(wifi->interface,
                                                interface_remove_callback,
                                                        wifi);
+       if (ret < 0)
+               return ret;
+
+       return -EINPROGRESS;
 }
 
 static void scan_callback(int result, GSupplicantInterface *interface,
@@ -254,6 +279,7 @@ static void scan_callback(int result, GSupplicantInterface *interface,
                connman_device_reset_scanning(device);
        else
                connman_device_set_scanning(device, FALSE);
+       connman_device_unref(device);
 }
 
 static int wifi_scan(struct connman_device *device)
@@ -266,10 +292,13 @@ static int wifi_scan(struct connman_device *device)
        if (wifi->tethering == TRUE)
                return 0;
 
+       connman_device_ref(device);
        ret = g_supplicant_interface_scan(wifi->interface, scan_callback,
                                                                device);
        if (ret == 0)
                connman_device_set_scanning(device, TRUE);
+       else
+               connman_device_unref(device);
 
        return ret;
 }
@@ -309,7 +338,19 @@ static int network_probe(struct connman_network *network)
 
 static void network_remove(struct connman_network *network)
 {
+       struct connman_device *device = connman_network_get_device(network);
+       struct wifi_data *wifi;
+
        DBG("network %p", network);
+
+       wifi = connman_device_get_data(device);
+       if (wifi == NULL)
+               return;
+
+       if (wifi->network != network)
+               return;
+
+       wifi->network = NULL;
 }
 
 static void connect_callback(int result, GSupplicantInterface *interface,
@@ -348,7 +389,7 @@ static GSupplicantSecurity network_security(const char *security)
 
 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
 {
-       const char *security, *passphrase;
+       const char *security, *passphrase, *agent_passphrase;
 
        memset(ssid, 0, sizeof(*ssid));
        ssid->mode = G_SUPPLICANT_MODE_INFRA;
@@ -359,9 +400,17 @@ static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
        ssid->security = network_security(security);
        passphrase = connman_network_get_string(network,
                                                "WiFi.Passphrase");
-       if (passphrase == NULL || strlen(passphrase) == 0)
-               ssid->passphrase = NULL;
-       else
+       if (passphrase == NULL || strlen(passphrase) == 0) {
+
+               /* Use agent provided passphrase as a fallback */
+               agent_passphrase = connman_network_get_string(network,
+                                               "WiFi.AgentPassphrase");
+
+               if (agent_passphrase == NULL || strlen(agent_passphrase) == 0)
+                       ssid->passphrase = NULL;
+               else
+                       ssid->passphrase = agent_passphrase;
+       } else
                ssid->passphrase = passphrase;
 
        ssid->eap = connman_network_get_string(network, "WiFi.EAP");
@@ -379,6 +428,12 @@ static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
                                                ssid->passphrase);
        /* We must have an identity for both PEAP and TLS */
        ssid->identity = connman_network_get_string(network, "WiFi.Identity");
+
+       /* Use agent provided identity as a fallback */
+       if (ssid->identity == NULL || strlen(ssid->identity) == 0)
+               ssid->identity = connman_network_get_string(network,
+                                                       "WiFi.AgentIdentity");
+
        ssid->ca_cert_path = connman_network_get_string(network,
                                                        "WiFi.CACertFile");
        ssid->client_cert_path = connman_network_get_string(network,
@@ -419,9 +474,9 @@ static int network_connect(struct connman_network *network)
        ssid_init(ssid, network);
 
        if (wifi->disconnecting == TRUE)
-               wifi->pending_network = connman_network_ref(network);
+               wifi->pending_network = network;
        else {
-               wifi->network = connman_network_ref(network);
+               wifi->network = network;
 
                return g_supplicant_interface_connect(interface, ssid,
                                                connect_callback, network);
@@ -445,8 +500,6 @@ static void disconnect_callback(int result, GSupplicantInterface *interface,
                 */
                if (result < 0)
                        connman_network_set_connected(wifi->network, FALSE);
-
-               connman_network_unref(wifi->network);
        }
 
        wifi->network = NULL;
@@ -455,7 +508,6 @@ static void disconnect_callback(int result, GSupplicantInterface *interface,
 
        if (wifi->pending_network != NULL) {
                network_connect(wifi->pending_network);
-               connman_network_unref(wifi->pending_network);
                wifi->pending_network = NULL;
        }
 
@@ -717,26 +769,12 @@ static void interface_removed(GSupplicantInterface *interface)
 
 static void scan_started(GSupplicantInterface *interface)
 {
-       struct wifi_data *wifi;
-
        DBG("");
-
-       wifi = g_supplicant_interface_get_data(interface);
-
-       if (wifi == NULL)
-               return;
 }
 
 static void scan_finished(GSupplicantInterface *interface)
 {
-       struct wifi_data *wifi;
-
        DBG("");
-
-       wifi = g_supplicant_interface_get_data(interface);
-
-       if (wifi == NULL)
-               return;
 }
 
 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
@@ -755,7 +793,7 @@ static void network_added(GSupplicantNetwork *supplicant_network)
        struct connman_network *network;
        GSupplicantInterface *interface;
        struct wifi_data *wifi;
-       const char *name, *identifier, *mode, *security, *group;
+       const char *name, *identifier, *security, *group;
        const unsigned char *ssid;
        unsigned int ssid_len;
        connman_bool_t wps;
@@ -766,7 +804,6 @@ static void network_added(GSupplicantNetwork *supplicant_network)
        wifi = g_supplicant_interface_get_data(interface);
        name = g_supplicant_network_get_name(supplicant_network);
        identifier = g_supplicant_network_get_identifier(supplicant_network);
-       mode = g_supplicant_network_get_mode(supplicant_network);
        security = g_supplicant_network_get_security(supplicant_network);
        group = g_supplicant_network_get_identifier(supplicant_network);
        wps = g_supplicant_network_get_wps(supplicant_network);
@@ -790,6 +827,8 @@ static void network_added(GSupplicantNetwork *supplicant_network)
                        connman_network_unref(network);
                        return;
                }
+
+               wifi->networks = g_slist_append(wifi->networks, network);
        }
 
        if (name != NULL && name[0] != '\0')
@@ -797,12 +836,14 @@ static void network_added(GSupplicantNetwork *supplicant_network)
 
        connman_network_set_blob(network, "WiFi.SSID",
                                                ssid, ssid_len);
-       connman_network_set_string(network, "WiFi.Mode", mode);
        connman_network_set_string(network, "WiFi.Security", security);
        connman_network_set_strength(network,
                                calculate_strength(supplicant_network));
        connman_network_set_bool(network, "WiFi.WPS", wps);
 
+       connman_network_set_frequency(network,
+                       g_supplicant_network_get_frequency(supplicant_network));
+
        connman_network_set_available(network, TRUE);
 
        if (ssid != NULL)
@@ -814,6 +855,7 @@ static void network_removed(GSupplicantNetwork *network)
        GSupplicantInterface *interface;
        struct wifi_data *wifi;
        const char *name, *identifier;
+       struct connman_network *connman_network;
 
        interface = g_supplicant_network_get_interface(network);
        wifi = g_supplicant_interface_get_data(interface);
@@ -822,8 +864,45 @@ static void network_removed(GSupplicantNetwork *network)
 
        DBG("name %s", name);
 
-       if (wifi != NULL)
-               connman_device_remove_network(wifi->device, identifier);
+       if (wifi == NULL)
+               return;
+
+       connman_network = connman_device_get_network(wifi->device, identifier);
+       if (connman_network == NULL)
+               return;
+
+       wifi->networks = g_slist_remove(wifi->networks, connman_network);
+
+       connman_device_remove_network(wifi->device, connman_network);
+       connman_network_unref(connman_network);
+}
+
+static void network_changed(GSupplicantNetwork *network, const char *property)
+{
+       GSupplicantInterface *interface;
+       struct wifi_data *wifi;
+       const char *name, *identifier;
+       struct connman_network *connman_network;
+
+       interface = g_supplicant_network_get_interface(network);
+       wifi = g_supplicant_interface_get_data(interface);
+       identifier = g_supplicant_network_get_identifier(network);
+       name = g_supplicant_network_get_name(network);
+
+       DBG("name %s", name);
+
+       if (wifi == NULL)
+               return;
+
+       connman_network = connman_device_get_network(wifi->device, identifier);
+       if (connman_network == NULL)
+               return;
+
+       if (g_str_equal(property, "Signal") == TRUE) {
+              connman_network_set_strength(connman_network,
+                                       calculate_strength(network));
+              connman_network_update(connman_network);
+       }
 }
 
 static void debug(const char *str)
@@ -842,6 +921,7 @@ static const GSupplicantCallbacks callbacks = {
        .scan_finished          = scan_finished,
        .network_added          = network_added,
        .network_removed        = network_removed,
+       .network_changed        = network_changed,
        .debug                  = debug,
 };