P2P: Disable periodic NoA when non-P2P STA is connected
authorJouni Malinen <jouni.malinen@atheros.com>
Fri, 9 Jul 2010 00:14:24 +0000 (17:14 -0700)
committerJouni Malinen <j@w1.fi>
Thu, 9 Sep 2010 14:17:20 +0000 (07:17 -0700)
For now, this applies to the test command that can be used to set
periodic NoA (p2p_set noa). The value are stored and periodic NoA
is enabled whenever there are no non-P2P STAs connected to the GO.

12 files changed:
src/ap/ap_drv_ops.c
src/ap/ap_drv_ops.h
src/ap/hostapd.c
src/ap/hostapd.h
src/ap/p2p_hostapd.c
src/ap/p2p_hostapd.h
src/ap/sta_info.c
src/ap/sta_info.h
wpa_supplicant/ctrl_iface.c
wpa_supplicant/driver_i.h
wpa_supplicant/p2p_supplicant.c
wpa_supplicant/p2p_supplicant.h

index 2f6932b..17c024c 100644 (file)
@@ -659,3 +659,13 @@ struct wpa_scan_results * hostapd_driver_get_scan_results(
                return hapd->driver->get_scan_results2(hapd->drv_priv);
        return NULL;
 }
+
+
+int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
+                          int duration)
+{
+       if (hapd->driver && hapd->driver->set_noa)
+               return hapd->driver->set_noa(hapd->drv_priv, count, start,
+                                            duration);
+       return -1;
+}
index 9b75d09..d8f9ddc 100644 (file)
@@ -63,5 +63,7 @@ int hostapd_driver_scan(struct hostapd_data *hapd,
                        struct wpa_driver_scan_params *params);
 struct wpa_scan_results * hostapd_driver_get_scan_results(
        struct hostapd_data *hapd);
+int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
+                          int duration);
 
 #endif /* AP_DRV_OPS */
index 2d50a51..cd9e87b 100644 (file)
@@ -35,6 +35,7 @@
 #include "wpa_auth_glue.h"
 #include "ap_drv_ops.h"
 #include "ap_config.h"
+#include "p2p_hostapd.h"
 
 
 static int hostapd_flush_old_stations(struct hostapd_data *hapd);
@@ -877,6 +878,15 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
        if (hapd->conf->ieee802_11f)
                iapp_new_station(hapd->iapp, sta);
 
+#ifdef CONFIG_P2P
+       if (sta->p2p_ie == NULL && !sta->no_p2p_set) {
+               sta->no_p2p_set = 1;
+               hapd->num_sta_no_p2p++;
+               if (hapd->num_sta_no_p2p == 1)
+                       hostapd_p2p_non_p2p_sta_connected(hapd);
+       }
+#endif /* CONFIG_P2P */
+
        /* Start accounting here, if IEEE 802.1X and WPA are not used.
         * IEEE 802.1X/WPA code will start accounting after the station has
         * been authorized. */
index 3efcdfa..021d2e8 100644 (file)
@@ -190,6 +190,14 @@ struct hostapd_data {
        struct p2p_group *p2p_group;
        struct wpabuf *p2p_beacon_ie;
        struct wpabuf *p2p_probe_resp_ie;
+
+       /* Number of non-P2P association stations */
+       int num_sta_no_p2p;
+
+       /* Periodic NoA (used only when no non-P2P clients in the group) */
+       int noa_enabled;
+       int noa_start;
+       int noa_duration;
 #endif /* CONFIG_P2P */
 };
 
index 7f99830..ffe16bb 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * hostapd / P2P integration
- * Copyright (c) 2009, Atheros Communications
+ * Copyright (c) 2009-2010, Atheros Communications
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -16,6 +16,8 @@
 
 #include "utils/common.h"
 #include "p2p/p2p.h"
+#include "hostapd.h"
+#include "ap_drv_ops.h"
 #include "sta_info.h"
 #include "p2p_hostapd.h"
 
@@ -28,3 +30,61 @@ int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
 
        return p2p_ie_text(sta->p2p_ie, buf, buf + buflen);
 }
+
+
+int hostapd_p2p_set_noa(struct hostapd_data *hapd, u8 count, int start,
+                       int duration)
+{
+       wpa_printf(MSG_DEBUG, "P2P: Set NoA parameters: count=%u start=%d "
+                  "duration=%d", count, start, duration);
+
+       if (count == 0) {
+               hapd->noa_enabled = 0;
+               hapd->noa_start = 0;
+               hapd->noa_duration = 0;
+       }
+
+       if (count != 255) {
+               wpa_printf(MSG_DEBUG, "P2P: Non-periodic NoA - set "
+                          "NoA parameters");
+               return hostapd_driver_set_noa(hapd, count, start, duration);
+       }
+
+       hapd->noa_enabled = 1;
+       hapd->noa_start = start;
+       hapd->noa_duration = duration;
+
+       if (hapd->num_sta_no_p2p == 0) {
+               wpa_printf(MSG_DEBUG, "P2P: No legacy STAs connected - update "
+                          "periodic NoA parameters");
+               return hostapd_driver_set_noa(hapd, count, start, duration);
+       }
+
+       wpa_printf(MSG_DEBUG, "P2P: Legacy STA(s) connected - do not enable "
+                  "periodic NoA");
+
+       return 0;
+}
+
+
+void hostapd_p2p_non_p2p_sta_connected(struct hostapd_data *hapd)
+{
+       wpa_printf(MSG_DEBUG, "P2P: First non-P2P device connected");
+
+       if (hapd->noa_enabled) {
+               wpa_printf(MSG_DEBUG, "P2P: Disable periodic NoA");
+               hostapd_driver_set_noa(hapd, 0, 0, 0);
+       }
+}
+
+
+void hostapd_p2p_non_p2p_sta_disconnected(struct hostapd_data *hapd)
+{
+       wpa_printf(MSG_DEBUG, "P2P: Last non-P2P device disconnected");
+
+       if (hapd->noa_enabled) {
+               wpa_printf(MSG_DEBUG, "P2P: Enable periodic NoA");
+               hostapd_driver_set_noa(hapd, 255, hapd->noa_start,
+                                      hapd->noa_duration);
+       }
+}
index 31aed15..643ad6c 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * hostapd / P2P integration
- * Copyright (c) 2009, Atheros Communications
+ * Copyright (c) 2009-2010, Atheros Communications
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
 
 int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
                            char *buf, size_t buflen);
+int hostapd_p2p_set_noa(struct hostapd_data *hapd, u8 count, int start,
+                       int duration);
+void hostapd_p2p_non_p2p_sta_connected(struct hostapd_data *hapd);
+void hostapd_p2p_non_p2p_sta_disconnected(struct hostapd_data *hapd);
+
 
 #else /* CONFIG_P2P */
 
index 8cd6c3f..80cdb62 100644 (file)
@@ -31,6 +31,7 @@
 #include "beacon.h"
 #include "ap_mlme.h"
 #include "vlan_init.h"
+#include "p2p_hostapd.h"
 #include "sta_info.h"
 
 static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
@@ -174,6 +175,15 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
                hapd->iface->num_sta_ht_20mhz--;
        }
 
+#ifdef CONFIG_P2P
+       if (sta->no_p2p_set) {
+               sta->no_p2p_set = 0;
+               hapd->num_sta_no_p2p--;
+               if (hapd->num_sta_no_p2p == 0)
+                       hostapd_p2p_non_p2p_sta_disconnected(hapd);
+       }
+#endif /* CONFIG_P2P */
+
 #if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N)
        if (hostapd_ht_operation_update(hapd->iface) > 0)
                set_beacon++;
index e65ddef..51bd9d2 100644 (file)
@@ -55,6 +55,7 @@ struct sta_info {
        unsigned int no_ht_gf_set:1;
        unsigned int no_ht_set:1;
        unsigned int ht_20mhz_set:1;
+       unsigned int no_p2p_set:1;
 
        u16 auth_alg;
        u8 previous_ap[6];
index e82d31d..8355757 100644 (file)
@@ -2438,7 +2438,7 @@ static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
                        return -1;
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: P2P_SET GO NoA: count=%d "
                           "start=%d duration=%d", count, start, duration);
-               return wpa_drv_set_noa(wpa_s, count, start, duration);
+               return wpas_p2p_set_noa(wpa_s, count, start, duration);
        }
 
        if (os_strcmp(cmd, "ps") == 0)
index 0868fa8..2e404e9 100644 (file)
@@ -514,14 +514,6 @@ static inline int wpa_drv_get_noa(struct wpa_supplicant *wpa_s,
        return wpa_s->driver->get_noa(wpa_s->drv_priv, buf, buf_len);
 }
 
-static inline int wpa_drv_set_noa(struct wpa_supplicant *wpa_s, u8 count,
-                                 int start, int duration)
-{
-       if (!wpa_s->driver->set_noa)
-               return -1;
-       return wpa_s->driver->set_noa(wpa_s->drv_priv, count, start, duration);
-}
-
 static inline int wpa_drv_set_p2p_powersave(struct wpa_supplicant *wpa_s,
                                            int legacy_ps, int opp_ps,
                                            int ctwindow)
index 60a3c66..b257654 100644 (file)
@@ -22,6 +22,7 @@
 #include "wps/wps_i.h"
 #include "p2p/p2p.h"
 #include "ap/hostapd.h"
+#include "ap/p2p_hostapd.h"
 #include "wpa_supplicant_i.h"
 #include "driver_i.h"
 #include "ap.h"
@@ -3296,3 +3297,13 @@ void wpas_p2p_update_config(struct wpa_supplicant *wpa_s)
                                     0);
        }
 }
+
+
+int wpas_p2p_set_noa(struct wpa_supplicant *wpa_s, u8 count, int start,
+                    int duration)
+{
+       if (!wpa_s->ap_iface)
+               return -1;
+       return hostapd_p2p_set_noa(wpa_s->ap_iface->bss[0], count, start,
+                                  duration);
+}
index 075cda8..e1578fc 100644 (file)
@@ -106,5 +106,7 @@ void wpas_p2p_deauth_notif(struct wpa_supplicant *wpa_s, const u8 *bssid,
 void wpas_p2p_disassoc_notif(struct wpa_supplicant *wpa_s, const u8 *bssid,
                             u16 reason_code, const u8 *ie, size_t ie_len);
 void wpas_p2p_update_config(struct wpa_supplicant *wpa_s);
+int wpas_p2p_set_noa(struct wpa_supplicant *wpa_s, u8 count, int start,
+                    int duration);
 
 #endif /* P2P_SUPPLICANT_H */