summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Berg <bberg@redhat.com>2018-10-10 23:32:22 +0200
committerThomas Haller <thaller@redhat.com>2019-01-27 23:45:12 +0100
commit959886892aa35d159d886cfddbbc856bf07bce6d (patch)
treed41d6dfd8f77ed89167b96ba241f38abbccb0a05
parent00e64d13320f5848a757765c8541e8160aa8e3e2 (diff)
downloadNetworkManager-959886892aa35d159d886cfddbbc856bf07bce6d.tar.gz
core/devices: Automatically create P2P device for wifi devices
If a wifi device supports P2P mode, then create a further P2P device for it automatically.
-rw-r--r--src/devices/wifi/nm-device-wifi.c86
-rw-r--r--src/devices/wifi/nm-device-wifi.h1
-rw-r--r--src/devices/wifi/nm-wifi-factory.c23
3 files changed, 109 insertions, 1 deletions
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
index e0be38c3f7..4ba14ac336 100644
--- a/src/devices/wifi/nm-device-wifi.c
+++ b/src/devices/wifi/nm-device-wifi.c
@@ -22,6 +22,7 @@
#include "nm-default.h"
#include "nm-device-wifi.h"
+#include "nm-device-p2p-wifi.h"
#include <netinet/in.h>
#include <string.h>
@@ -79,6 +80,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceWifi,
enum {
SCANNING_PROHIBITED,
+ P2P_DEVICE_CREATED,
LAST_SIGNAL
};
@@ -124,6 +126,8 @@ typedef struct {
guint wps_timeout_id;
NMSettingWirelessWakeOnWLan wowlan_restore;
+
+ NMDeviceP2PWifi *p2p_device;
} NMDeviceWifiPrivate;
struct _NMDeviceWifi
@@ -186,6 +190,10 @@ static void supplicant_iface_notify_current_bss (NMSupplicantInterface *iface,
GParamSpec *pspec,
NMDeviceWifi *self);
+static void supplicant_iface_notify_p2p_available (NMSupplicantInterface *iface,
+ GParamSpec *pspec,
+ NMDeviceWifi *self);
+
static void request_wireless_scan (NMDeviceWifi *self,
gboolean periodic,
gboolean force_if_scanning,
@@ -198,6 +206,8 @@ static void ap_add_remove (NMDeviceWifi *self,
static void _hw_addr_set_scanning (NMDeviceWifi *self, gboolean do_reset);
+static void recheck_p2p_availability (NMDeviceWifi *self);
+
/*****************************************************************************/
static void
@@ -291,6 +301,10 @@ supplicant_interface_acquire (NMDeviceWifi *self)
"notify::" NM_SUPPLICANT_INTERFACE_CURRENT_BSS,
G_CALLBACK (supplicant_iface_notify_current_bss),
self);
+ g_signal_connect (priv->sup_iface,
+ "notify::" NM_SUPPLICANT_INTERFACE_P2P_AVAILABLE,
+ G_CALLBACK (supplicant_iface_notify_p2p_available),
+ self);
_notify_scanning (self);
@@ -347,6 +361,11 @@ supplicant_interface_release (NMDeviceWifi *self)
g_clear_object (&priv->sup_iface);
}
+ if (priv->p2p_device) {
+ /* Signal to P2P device to also release its reference */
+ nm_device_p2p_wifi_set_mgmt_iface (priv->p2p_device, NULL);
+ }
+
_notify_scanning (self);
}
@@ -2028,6 +2047,10 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface,
&& new_state <= NM_SUPPLICANT_INTERFACE_STATE_COMPLETED)
priv->ssid_found = TRUE;
+ if (old_state < NM_SUPPLICANT_INTERFACE_STATE_READY &&
+ new_state >= NM_SUPPLICANT_INTERFACE_STATE_READY)
+ recheck_p2p_availability (self);
+
switch (new_state) {
case NM_SUPPLICANT_INTERFACE_STATE_READY:
_LOGD (LOGD_WIFI, "supplicant ready");
@@ -2204,6 +2227,61 @@ supplicant_iface_notify_current_bss (NMSupplicantInterface *iface,
}
}
+/* We bind the existance of the P2P device to a wifi device that is being
+ * managed by NetworkManager and is capable of P2P operation.
+ * Note that some care must be taken here, because we don't want to re-create
+ * the device every time the supplicant interface is destroyed (e.g. due to
+ * a suspend/resume cycle).
+ * Therefore, this function will be called when a change in the P2P capability
+ * is detected and the supplicant interface has been initialised.
+ */
+static void
+recheck_p2p_availability (NMDeviceWifi *self)
+{
+ NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+ NMDeviceP2PWifi *p2p_device;
+ gboolean p2p_available;
+
+ g_object_get (priv->sup_iface,
+ NM_SUPPLICANT_INTERFACE_P2P_AVAILABLE, &p2p_available,
+ NULL);
+
+ if (p2p_available && !priv->p2p_device) {
+ g_autofree char *iface_name = NULL;
+ /* Create a P2P device. "p2p-dev-" is the same prefix as chosen by
+ * wpa_supplicant internally.
+ */
+ iface_name = g_strconcat ("p2p-dev-", nm_device_get_iface (NM_DEVICE (self)), NULL);
+ p2p_device = NM_DEVICE_P2P_WIFI (nm_device_p2p_wifi_new (priv->sup_iface, iface_name));
+ priv->p2p_device = p2p_device;
+
+ g_signal_emit (self, signals[P2P_DEVICE_CREATED], 0, priv->p2p_device);
+ g_object_add_weak_pointer (G_OBJECT (p2p_device), (gpointer*) &priv->p2p_device);
+ g_object_unref (p2p_device);
+
+ } else if (p2p_available && priv->p2p_device) {
+ nm_device_p2p_wifi_set_mgmt_iface (priv->p2p_device, priv->sup_iface);
+
+ } else if (!p2p_available && priv->p2p_device) {
+ /* Destroy the P2P device. */
+ g_object_remove_weak_pointer (G_OBJECT (priv->p2p_device), (gpointer*) &priv->p2p_device);
+ nm_device_p2p_wifi_remove (priv->p2p_device);
+ priv->p2p_device = NULL;
+ }
+}
+
+static void
+supplicant_iface_notify_p2p_available (NMSupplicantInterface *iface,
+ GParamSpec *pspec,
+ NMDeviceWifi *self)
+{
+ /* Do not update when the interface is still initializing. */
+ if (nm_supplicant_interface_get_state (iface) < NM_SUPPLICANT_INTERFACE_STATE_READY)
+ return;
+
+ recheck_p2p_availability (self);
+}
+
static gboolean
handle_auth_or_fail (NMDeviceWifi *self,
NMActRequest *req,
@@ -3426,4 +3504,12 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
G_STRUCT_OFFSET (NMDeviceWifiClass, scanning_prohibited),
NULL, NULL, NULL,
G_TYPE_BOOLEAN, 1, G_TYPE_BOOLEAN);
+
+ signals[P2P_DEVICE_CREATED] =
+ g_signal_new (NM_DEVICE_WIFI_P2P_DEVICE_CREATED,
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 1, NM_TYPE_DEVICE);
}
diff --git a/src/devices/wifi/nm-device-wifi.h b/src/devices/wifi/nm-device-wifi.h
index 1c555f5fe1..116ad11e48 100644
--- a/src/devices/wifi/nm-device-wifi.h
+++ b/src/devices/wifi/nm-device-wifi.h
@@ -40,6 +40,7 @@
#define NM_DEVICE_WIFI_LAST_SCAN "last-scan"
#define NM_DEVICE_WIFI_SCANNING_PROHIBITED "scanning-prohibited"
+#define NM_DEVICE_WIFI_P2P_DEVICE_CREATED "p2p-device-created"
typedef struct _NMDeviceWifi NMDeviceWifi;
typedef struct _NMDeviceWifiClass NMDeviceWifiClass;
diff --git a/src/devices/wifi/nm-wifi-factory.c b/src/devices/wifi/nm-wifi-factory.c
index 4e9d1ecb20..e220c3a4cb 100644
--- a/src/devices/wifi/nm-wifi-factory.c
+++ b/src/devices/wifi/nm-wifi-factory.c
@@ -26,6 +26,7 @@
#include "nm-setting-wireless.h"
#include "nm-setting-olpc-mesh.h"
#include "nm-device-wifi.h"
+#include "nm-device-p2p-wifi.h"
#include "nm-device-olpc-mesh.h"
#include "nm-device-iwd.h"
#include "settings/nm-settings-connection.h"
@@ -68,6 +69,18 @@ nm_device_factory_create (GError **error)
/*****************************************************************************/
+static void
+p2p_device_created (NMDeviceWifi *device,
+ NMDeviceP2PWifi *p2p_device,
+ NMDeviceFactory *self)
+{
+ nm_log_info (LOGD_PLATFORM | LOGD_WIFI,
+ "P2P Wifi device controlled by wifi interface %s created",
+ nm_device_get_iface (NM_DEVICE (device)));
+
+ g_signal_emit_by_name (self, NM_DEVICE_FACTORY_DEVICE_ADDED, p2p_device);
+}
+
static NMDevice *
create_device (NMDeviceFactory *factory,
const char *iface,
@@ -98,6 +111,7 @@ create_device (NMDeviceFactory *factory,
NM_PRINT_FMT_QUOTE_STRING (backend),
WITH_IWD ? " (iwd support enabled)" : "");
if (!backend || !strcasecmp (backend, "wpa_supplicant")) {
+ NMDevice *device;
NMDeviceWifiCapabilities capabilities;
NM80211Mode mode;
@@ -120,7 +134,14 @@ create_device (NMDeviceFactory *factory,
return NULL;
}
- return nm_device_wifi_new (iface, capabilities);
+ device = nm_device_wifi_new (iface, capabilities);
+
+ g_signal_connect_object (device, NM_DEVICE_WIFI_P2P_DEVICE_CREATED,
+ G_CALLBACK (p2p_device_created),
+ factory,
+ 0);
+
+ return device;
}
#if WITH_IWD
else if (!strcasecmp (backend, "iwd"))