service: Add frequency support to service
[platform/upstream/connman.git] / plugins / wifi.c
index edea4e7..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;
@@ -239,10 +254,10 @@ static int wifi_disable(struct connman_device *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;
-       }
+
+       remove_networks(device, wifi);
 
        ret = g_supplicant_interface_remove(wifi->interface,
                                                interface_remove_callback,
@@ -264,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)
@@ -276,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;
 }
@@ -319,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,
@@ -358,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;
@@ -369,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");
@@ -389,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,
@@ -429,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);
@@ -455,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;
@@ -465,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;
        }
 
@@ -727,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)
@@ -799,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')
@@ -811,6 +841,9 @@ static void network_added(GSupplicantNetwork *supplicant_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)
@@ -838,10 +871,40 @@ static void network_removed(GSupplicantNetwork *network)
        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)
 {
        if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
@@ -858,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,
 };