[PATCH 3/4 v2] platform: wifi: add support for wake-on-wlan



---
 src/platform/nm-linux-platform.c       |  8 +++++++
 src/platform/nm-platform.c             | 10 +++++++++
 src/platform/nm-platform.h             |  3 +++
 src/platform/wifi/wifi-utils-nl80211.c | 40 ++++++++++++++++++++++++++++++++++
 src/platform/wifi/wifi-utils-private.h |  3 +++
 src/platform/wifi/wifi-utils.c         |  8 +++++++
 src/platform/wifi/wifi-utils.h         |  2 ++
 7 files changed, 74 insertions(+)

diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 2c5f089..5be1a65 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -5575,6 +5575,13 @@ wifi_indicate_addressing_running (NMPlatform *platform, int ifindex, gboolean ru
        wifi_utils_indicate_addressing_running (wifi_data, running);
 }
 
+static gboolean
+wifi_set_wake_on_wlan (NMPlatform *platform, int ifindex, NMSettingWirelessWakeOnWLan wowl, const char 
*password)
+{
+       WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, FALSE);
+       return wifi_utils_set_wake_on_wlan (wifi_data, wowl, password);
+}
+
 /*****************************************************************************/
 
 static gboolean
@@ -6783,6 +6790,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
        platform_class->wifi_set_powersave = wifi_set_powersave;
        platform_class->wifi_find_frequency = wifi_find_frequency;
        platform_class->wifi_indicate_addressing_running = wifi_indicate_addressing_running;
+       platform_class->wifi_set_wake_on_wlan = wifi_set_wake_on_wlan;
 
        platform_class->mesh_get_channel = mesh_get_channel;
        platform_class->mesh_set_channel = mesh_set_channel;
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 8b22ced..a748526 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -2474,6 +2474,16 @@ nm_platform_wifi_indicate_addressing_running (NMPlatform *self, int ifindex, gbo
        klass->wifi_indicate_addressing_running (self, ifindex, running);
 }
 
+gboolean
+nm_platform_wifi_set_wake_on_wlan (NMPlatform *self, int ifindex, NMSettingWirelessWakeOnWLan wowl, const 
char *password)
+{
+       _CHECK_SELF (self, klass, FALSE);
+
+       g_return_val_if_fail (ifindex > 0, FALSE);
+
+       return klass->wifi_set_wake_on_wlan (self, ifindex, wowl, password);
+}
+
 guint32
 nm_platform_mesh_get_channel (NMPlatform *self, int ifindex)
 {
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 63dbe5a..f1ce0e6 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -32,6 +32,7 @@
 #include "nm-core-utils.h"
 #include "nm-setting-vlan.h"
 #include "nm-setting-wired.h"
+#include "nm-setting-wireless.h"
 
 #define NM_TYPE_PLATFORM            (nm_platform_get_type ())
 #define NM_PLATFORM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_PLATFORM, NMPlatform))
@@ -636,6 +637,7 @@ typedef struct {
        void        (*wifi_set_powersave)    (NMPlatform *, int ifindex, guint32 powersave);
        guint32     (*wifi_find_frequency)   (NMPlatform *, int ifindex, const guint32 *freqs);
        void        (*wifi_indicate_addressing_running) (NMPlatform *, int ifindex, gboolean running);
+       gboolean    (*wifi_set_wake_on_wlan) (NMPlatform *, int ifindex, NMSettingWirelessWakeOnWLan wowl, 
const char *password);
 
        guint32     (*mesh_get_channel)      (NMPlatform *, int ifindex);
        gboolean    (*mesh_set_channel)      (NMPlatform *, int ifindex, guint32 channel);
@@ -902,6 +904,7 @@ void        nm_platform_wifi_set_mode         (NMPlatform *self, int ifindex, NM
 void        nm_platform_wifi_set_powersave    (NMPlatform *self, int ifindex, guint32 powersave);
 guint32     nm_platform_wifi_find_frequency   (NMPlatform *self, int ifindex, const guint32 *freqs);
 void        nm_platform_wifi_indicate_addressing_running (NMPlatform *self, int ifindex, gboolean running);
+gboolean    nm_platform_wifi_set_wake_on_wlan (NMPlatform *self, int ifindex, NMSettingWirelessWakeOnWLan 
wowl, const char *password);
 
 guint32     nm_platform_mesh_get_channel      (NMPlatform *self, int ifindex);
 gboolean    nm_platform_mesh_set_channel      (NMPlatform *self, int ifindex, guint32 channel);
diff --git a/src/platform/wifi/wifi-utils-nl80211.c b/src/platform/wifi/wifi-utils-nl80211.c
index ac51678..a985225 100644
--- a/src/platform/wifi/wifi-utils-nl80211.c
+++ b/src/platform/wifi/wifi-utils-nl80211.c
@@ -469,6 +469,45 @@ nla_put_failure:
        return FALSE;
 }
 
+static gboolean
+wifi_nl80211_set_wake_on_wlan (WifiData *data, NMSettingWirelessWakeOnWLan wowl, const char *password)
+{
+       WifiDataNl80211 *nl80211 = (WifiDataNl80211 *) data;
+       struct nl_msg *msg;
+       struct nlattr *triggers;
+       int err;
+
+       msg = nl80211_alloc_msg(nl80211, NL80211_CMD_SET_WOWLAN, 0);
+       if (!msg)
+               return FALSE;
+
+       triggers = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS);
+
+       if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY))
+               NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_ANY);
+       if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_DISCONNECT))
+               NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_DISCONNECT);
+       if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_MAGIC))
+               NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_MAGIC_PKT);
+       if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_GTK_REKEY_FAILURE))
+               NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE);
+       if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_EAP_IDENTITY_REQUEST))
+               NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST);
+       if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_4WAY_HANDSHAKE))
+               NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE);
+       if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_RFKILL_RELEASE))
+               NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE);
+
+       nla_nest_end(msg, triggers);
+
+       err = nl80211_send_and_recv (nl80211, msg, NULL, NULL);
+       return err ? FALSE : TRUE;
+
+nla_put_failure:
+       nlmsg_free (msg);
+       return FALSE;
+}
+
 /* @divisor: pass what value @xbm should be divided by to get dBm */
 static guint32
 nl80211_xbm_to_percent (gint32 xbm, guint32 divisor)
@@ -1040,6 +1079,7 @@ wifi_nl80211_init (const char *iface, int ifindex)
        nl80211->parent.get_mode = wifi_nl80211_get_mode;
        nl80211->parent.set_mode = wifi_nl80211_set_mode;
        nl80211->parent.set_powersave = wifi_nl80211_set_powersave;
+       nl80211->parent.set_wake_on_wlan = wifi_nl80211_set_wake_on_wlan;
        nl80211->parent.get_freq = wifi_nl80211_get_freq;
        nl80211->parent.find_freq = wifi_nl80211_find_freq;
        nl80211->parent.get_bssid = wifi_nl80211_get_bssid;
diff --git a/src/platform/wifi/wifi-utils-private.h b/src/platform/wifi/wifi-utils-private.h
index ebe76f1..c8c499f 100644
--- a/src/platform/wifi/wifi-utils-private.h
+++ b/src/platform/wifi/wifi-utils-private.h
@@ -36,6 +36,9 @@ struct WifiData {
        /* Set power saving mode on an interface */
        gboolean (*set_powersave) (WifiData *data, guint32 powersave);
 
+       /* Set WakeOnWLAN mode on an interface */
+       gboolean (*set_wake_on_wlan) (WifiData *data, NMSettingWirelessWakeOnWLan wowl, const char *password);
+
        /* Return current frequency in MHz (really associated BSS frequency) */
        guint32 (*get_freq) (WifiData *data);
 
diff --git a/src/platform/wifi/wifi-utils.c b/src/platform/wifi/wifi-utils.c
index b8da02c..2646951 100644
--- a/src/platform/wifi/wifi-utils.c
+++ b/src/platform/wifi/wifi-utils.c
@@ -126,6 +126,14 @@ wifi_utils_set_powersave (WifiData *data, guint32 powersave)
        return data->set_powersave ? data->set_powersave (data, powersave) : TRUE;
 }
 
+gboolean
+wifi_utils_set_wake_on_wlan (WifiData *data, NMSettingWirelessWakeOnWLan wowl, const char *password)
+{
+       g_return_val_if_fail (data != NULL, FALSE);
+
+       return data->set_wake_on_wlan ? data->set_wake_on_wlan (data, wowl, password) : TRUE;
+}
+
 guint32
 wifi_utils_get_freq (WifiData *data)
 {
diff --git a/src/platform/wifi/wifi-utils.h b/src/platform/wifi/wifi-utils.h
index 4fd5a80..9be589a 100644
--- a/src/platform/wifi/wifi-utils.h
+++ b/src/platform/wifi/wifi-utils.h
@@ -25,6 +25,7 @@
 #include <net/ethernet.h>
 
 #include "nm-dbus-interface.h"
+#include "nm-setting-wireless.h"
 
 typedef struct WifiData WifiData;
 
@@ -68,6 +69,7 @@ gboolean wifi_utils_get_wowlan (WifiData *data);
 
 gboolean wifi_utils_set_powersave (WifiData *data, guint32 powersave);
 
+gboolean wifi_utils_set_wake_on_wlan (WifiData *data, NMSettingWirelessWakeOnWLan wowl, const char 
*password);
 
 /* OLPC Mesh-only functions */
 guint32 wifi_utils_get_mesh_channel (WifiData *data);
-- 
2.7.4



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]