When connecting with P2P, a new wifi device will be created and detected
by both connman and wpa_supplicant. This last one will automatically
create an interface out of it, thus the need to hold connman creating it
itself through the DBus API.
Instead, the device is put into a pending device list, and once the
InterfaceAdded signal has been handled, we manage the other pending
devices if any as usual.
---
 plugins/wifi.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 66 insertions(+), 10 deletions(-)

diff --git a/plugins/wifi.c b/plugins/wifi.c
index 037199a..c1b4cfd 100644
--- a/plugins/wifi.c
+++ b/plugins/wifi.c
@@ -121,10 +121,14 @@ struct wifi_data {
        unsigned int p2p_find_timeout;
        unsigned int p2p_connection_timeout;
        bool p2p_connecting;
+       bool p2p_device;
 };
 
 static GList *iface_list = NULL;
 
+static GList *pending_wifi_device = NULL;
+static GList *p2p_iface_list = NULL;
+
 static void start_autoscan(struct connman_device *device);
 
 static int p2p_tech_probe(struct connman_technology *technology)
@@ -146,6 +150,46 @@ static struct connman_technology_driver p2p_tech_driver = {
        .remove         = p2p_tech_remove,
 };
 
+static bool is_p2p_connecting(void)
+{
+       GList *list;
+
+       for (list = iface_list; list; list = list->next) {
+               struct wifi_data *wifi = list->data;
+
+               if (wifi->p2p_connecting)
+                       return true;
+       }
+
+       return false;
+}
+
+static void add_pending_wifi_device(struct wifi_data *wifi)
+{
+       if (g_list_find(pending_wifi_device, wifi))
+               return;
+
+       pending_wifi_device = g_list_append(pending_wifi_device, wifi);
+}
+
+static struct wifi_data *get_pending_wifi_data(const char *ifname)
+{
+       GList *list;
+
+       for (list = pending_wifi_device; list; list = list->next) {
+               struct wifi_data *wifi = list->data;
+               const char *dev_name = connman_device_get_string(wifi->device,
+                                                               "Interface");
+               if (!g_strcmp0(ifname, dev_name)) {
+                       pending_wifi_device = g_list_delete_link(
+                                               pending_wifi_device, list);
+                       return wifi;
+               }
+       }
+
+       return NULL;
+}
+
 static gboolean peer_connect_timeout(gpointer data)
 {
        struct wifi_data *wifi = data;
@@ -286,8 +330,10 @@ static int wifi_probe(struct connman_device *device)
 
        wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
                                                        wifi_newlink, device);
-
-       iface_list = g_list_append(iface_list, wifi);
+       if (is_p2p_connecting())
+               add_pending_wifi_device(wifi);
+       else
+               iface_list = g_list_append(iface_list, wifi);
 
        return 0;
 }
@@ -373,7 +419,10 @@ static void wifi_remove(struct connman_device *device)
 
        stop_autoscan(device);
 
-       iface_list = g_list_remove(iface_list, wifi);
+       if (wifi->p2p_device)
+               p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
+       else
+               iface_list = g_list_remove(iface_list, wifi);
 
        check_p2p_technology();
 
@@ -998,6 +1047,9 @@ static int wifi_enable(struct connman_device *device)
        if (!wifi || index < 0)
                return -ENODEV;
 
+       if (is_p2p_connecting())
+               return -EINPROGRESS;
+
        interface = connman_inet_ifname(index);
        ret = g_supplicant_interface_create(interface, driver, NULL,
                                                interface_create_callback,
@@ -1282,6 +1334,9 @@ static int wifi_scan(enum connman_service_type type,
        if (!wifi)
                return -ENODEV;
 
+       if (wifi->p2p_device)
+               return 0;
+
        if (type == CONNMAN_SERVICE_TYPE_P2P)
                return p2p_find(device);
 
@@ -1671,14 +1726,15 @@ static void interface_added(GSupplicantInterface 
*interface)
        struct wifi_data *wifi;
 
        wifi = g_supplicant_interface_get_data(interface);
+       if (!wifi) {
+               wifi = get_pending_wifi_data(ifname);
+               if (!wifi)
+                       return;
 
-       /*
-        * We can get here with a NULL wifi pointer when
-        * the interface added signal is sent before the
-        * interface creation callback is called.
-        */
-       if (!wifi)
-               return;
+               g_supplicant_interface_set_data(interface, wifi);
+               p2p_iface_list = g_list_append(p2p_iface_list, wifi);
+               wifi->p2p_device = true;
+       }
 
        DBG("ifname %s driver %s wifi %p tethering %d",
                        ifname, driver, wifi, wifi->tethering);
-- 
1.8.5.5

_______________________________________________
connman mailing list
[email protected]
https://lists.connman.net/mailman/listinfo/connman

Reply via email to