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.
This commit is contained in:
Benjamin Berg 2018-10-10 23:32:22 +02:00 committed by Thomas Haller
parent 00e64d1332
commit 959886892a
3 changed files with 109 additions and 1 deletions

View file

@ -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);
}

View file

@ -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;

View file

@ -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"))