diff options
author | Benjamin Berg <bberg@redhat.com> | 2018-10-10 23:32:22 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2019-01-27 23:45:12 +0100 |
commit | 959886892aa35d159d886cfddbbc856bf07bce6d (patch) | |
tree | d41d6dfd8f77ed89167b96ba241f38abbccb0a05 | |
parent | 00e64d13320f5848a757765c8541e8160aa8e3e2 (diff) | |
download | NetworkManager-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.c | 86 | ||||
-rw-r--r-- | src/devices/wifi/nm-device-wifi.h | 1 | ||||
-rw-r--r-- | src/devices/wifi/nm-wifi-factory.c | 23 |
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")) |