]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
AOSP: P2P frequency conflict
authorJouni Malinen <j@w1.fi>
Fri, 1 Nov 2013 09:21:28 +0000 (11:21 +0200)
committerJouni Malinen <j@w1.fi>
Fri, 1 Nov 2013 14:34:53 +0000 (16:34 +0200)
src/common/wpa_ctrl.h
wpa_supplicant/p2p_supplicant.c
wpa_supplicant/p2p_supplicant.h
wpa_supplicant/wpa_supplicant.c

index 81c4c2709daab9d447eda524e77095e4388fc652..fd7f686cbdfc057819f1b57c44405a5909481747 100644 (file)
@@ -62,6 +62,10 @@ extern "C" {
 #define WPA_EVENT_BSS_ADDED "CTRL-EVENT-BSS-ADDED "
 /** A BSS entry was removed (followed by BSS entry id and BSSID) */
 #define WPA_EVENT_BSS_REMOVED "CTRL-EVENT-BSS-REMOVED "
+#ifdef ANDROID_P2P
+/** Notify the Userspace about the freq conflict */
+#define WPA_EVENT_FREQ_CONFLICT "CTRL-EVENT-FREQ-CONFLICT "
+#endif
 
 /** RSN IBSS 4-way handshakes completed with specified peer */
 #define IBSS_RSN_COMPLETED "IBSS-RSN-COMPLETED "
index 9338ad5b0c3a52a3f627abed6dd1332043d98f20..9479cfc2387bbb2e282ec1cfa41019d76224b8fa 100644 (file)
@@ -83,7 +83,10 @@ enum p2p_group_removal_reason {
        P2P_GROUP_REMOVAL_IDLE_TIMEOUT,
        P2P_GROUP_REMOVAL_UNAVAILABLE,
        P2P_GROUP_REMOVAL_GO_ENDING_SESSION,
-       P2P_GROUP_REMOVAL_PSK_FAILURE
+       P2P_GROUP_REMOVAL_PSK_FAILURE,
+#ifdef ANDROID_P2P
+       P2P_GROUP_REMOVAL_FREQ_CONFLICT
+#endif
 };
 
 
@@ -103,6 +106,9 @@ static void wpas_p2p_group_idle_timeout(void *eloop_ctx, void *timeout_ctx);
 static void wpas_p2p_set_group_idle_timeout(struct wpa_supplicant *wpa_s);
 static void wpas_p2p_group_formation_timeout(void *eloop_ctx,
                                             void *timeout_ctx);
+#ifdef ANDROID_P2P
+static void wpas_p2p_group_freq_conflict(void *eloop_ctx, void *timeout_ctx);
+#endif
 static void wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
                                        int group_added);
 static int wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s);
@@ -395,6 +401,11 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s,
        case P2P_GROUP_REMOVAL_PSK_FAILURE:
                reason = " reason=PSK_FAILURE";
                break;
+#ifdef ANDROID_P2P
+       case P2P_GROUP_REMOVAL_FREQ_CONFLICT:
+               reason = " reason=FREQ_CONFLICT";
+               break;
+#endif
        default:
                reason = "";
                break;
@@ -405,6 +416,9 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s,
                               wpa_s->ifname, gtype, reason);
        }
 
+#ifdef ANDROID_P2P
+       eloop_cancel_timeout(wpas_p2p_group_freq_conflict, wpa_s, NULL);
+#endif
        if (eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL) > 0)
                wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group idle timeout");
        if (eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
@@ -3361,6 +3375,9 @@ void wpas_p2p_deinit(struct wpa_supplicant *wpa_s)
 
        os_free(wpa_s->go_params);
        wpa_s->go_params = NULL;
+#ifdef ANDROID_P2P
+       eloop_cancel_timeout(wpas_p2p_group_freq_conflict, wpa_s, NULL);
+#endif
        eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s, NULL);
        eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
        wpa_s->p2p_long_listen = 0;
@@ -3768,7 +3785,17 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq)
        struct wpabuf *wps_ie, *ies;
        size_t ielen;
        int freqs[2] = { 0, 0 };
+#ifdef ANDROID_P2P
+       int oper_freq;
 
+       /* If freq is not provided, check the operating freq of the GO and do a
+        * a directed scan to save time
+        */
+       if(!freq) {
+               freq = (oper_freq = p2p_get_oper_freq(wpa_s->global->p2p,
+                        wpa_s->pending_join_iface_addr) == -1) ? 0 : oper_freq; 
+       }
+#endif
        os_memset(&params, 0, sizeof(params));
 
        /* P2P Wildcard SSID */
@@ -6320,3 +6347,73 @@ int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s)
        wpa_s->p2p_last_4way_hs_fail = ssid;
        return 0;
 }
+
+#ifdef ANDROID_P2P
+static void wpas_p2p_group_freq_conflict(void *eloop_ctx, void *timeout_ctx)
+{
+       struct wpa_supplicant *wpa_s = eloop_ctx;
+
+       wpa_printf(MSG_DEBUG, "P2P: Frequency conflict - terminate group");
+       wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_FREQ_CONFLICT);
+}
+
+int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s, int freq,
+       struct wpa_ssid *ssid)
+{
+       struct wpa_supplicant *iface = NULL;
+       struct p2p_data *p2p = wpa_s->global->p2p;
+
+       for (iface = wpa_s->global->ifaces; iface; iface = iface->next) {
+               if ((iface->current_ssid) &&
+                   (iface->current_ssid->frequency != freq) &&
+                   ((iface->p2p_group_interface) ||
+                    (iface->current_ssid->p2p_group))) {
+
+                       if ((iface->p2p_group_interface == P2P_GROUP_INTERFACE_GO)  ||
+                           (iface->current_ssid->mode == WPAS_MODE_P2P_GO)) {
+                               /* Try to see whether we can move the GO. If it
+                                * is not possible, remove the GO interface
+                                */
+                               if (wpa_drv_switch_channel(iface, freq) == 0) {
+                                       wpa_printf(MSG_ERROR, "P2P: GO Moved to freq(%d)", freq);
+                                       iface->current_ssid->frequency = freq;
+                                       continue;
+                               }
+                       }
+
+                       /* If GO cannot be moved or if the conflicting interface is a
+                        * P2P Client, remove the interface depending up on the connection
+                        * priority */
+                       if(!wpas_is_p2p_prioritized(iface)) {
+                               /* STA connection has priority over existing
+                                * P2P connection. So remove the interface */
+                               wpa_printf(MSG_DEBUG, "P2P: Removing P2P connection due to Single channel"
+                                               "concurrent mode frequency conflict");
+                               eloop_register_timeout(0, 0, wpas_p2p_group_freq_conflict,
+                                                      iface, NULL);
+                               /* If connection in progress is p2p connection, do not proceed for the connection */
+                               if (wpa_s == iface)
+                                       return -1;
+                               else
+                                       /* If connection in progress is STA connection, proceed for the connection */
+                                       return 0;
+                       } else {
+                               /* P2p connection has priority, disable the STA network*/
+                               wpa_supplicant_disable_network(wpa_s->global->ifaces, ssid);
+                               wpa_msg(wpa_s->global->ifaces, MSG_INFO, WPA_EVENT_FREQ_CONFLICT
+                                       " id=%d", ssid->id);
+                               os_memset(wpa_s->global->ifaces->pending_bssid, 0, ETH_ALEN);
+                               if (wpa_s == iface) {
+                                       /* p2p connection is in progress, continue connecting...*/
+                                       return 0;
+                               }
+                               else {
+                                       /* STA connection is in progress, do not allow to continue */
+                                       return -1;
+                               }
+                       }
+               }
+       }
+       return 0;
+}
+#endif
index 26f5def4ebcc737792556f2ba64644684533a9c7..65ccbf9877f0a4b75f1575e2aa3442f1d36d9989 100644 (file)
@@ -29,6 +29,10 @@ void wpas_p2p_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
                                   unsigned int freq, unsigned int duration);
 void wpas_p2p_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
                                          unsigned int freq);
+#ifdef ANDROID_P2P
+int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s,
+                                          int freq, struct wpa_ssid *ssid);
+#endif
 int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname);
 int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
                       int freq, int ht40);
index 334ccc93c63aae28d9cf0bef9c4e0ccdbfeacf67..8a1574efa5e1c2784b24e2f037efe9b9eb2c7a88 100644 (file)
@@ -1284,6 +1284,9 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
        ibss_rsn_deinit(wpa_s->ibss_rsn);
        wpa_s->ibss_rsn = NULL;
 #endif /* CONFIG_IBSS_RSN */
+#ifdef ANDROID_P2P
+       int freq = 0;
+#endif
 
        if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
            ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
@@ -1620,6 +1623,18 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
        wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
 #endif /* CONFIG_HT_OVERRIDES */
 
+#ifdef ANDROID_P2P
+       /* If multichannel concurrency is not supported, check for any frequency
+        * conflict and take appropriate action.
+        */
+       if ((wpa_s->num_multichan_concurrent < 2) &&
+               ((freq = wpa_drv_shared_freq(wpa_s)) > 0) && (freq != params.freq)) {
+               wpa_printf(MSG_DEBUG, "Shared interface with conflicting frequency found (%d != %d)"
+                                                                                                                               , freq, params.freq);
+               if (wpas_p2p_handle_frequency_conflicts(wpa_s, params.freq, ssid) < 0) 
+                       return;
+       }
+#endif
        ret = wpa_drv_associate(wpa_s, &params);
        if (ret < 0) {
                wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "