Add P2P support for BRCM CFG80211 driver

Change-Id: Iafec4bedbd33836d0a64e7ea054d8a46ef8ec204
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/hostapd/.config b/hostapd/.config
index e57aafe..8341d4b 100644
--- a/hostapd/.config
+++ b/hostapd/.config
@@ -40,13 +40,13 @@
 #CONFIG_DRIVER_NONE=y
 
 # IEEE 802.11F/IAPP
-CONFIG_IAPP=y
+#CONFIG_IAPP=y
 
 # WPA2/IEEE 802.11i RSN pre-authentication
-CONFIG_RSN_PREAUTH=y
+#CONFIG_RSN_PREAUTH=y
 
 # PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
-CONFIG_PEERKEY=y
+#CONFIG_PEERKEY=y
 
 # IEEE 802.11w (management frame protection)
 # This version is an experimental implementation based on IEEE 802.11w/D1.0
@@ -55,25 +55,25 @@
 #CONFIG_IEEE80211W=y
 
 # Integrated EAP server
-CONFIG_EAP=y
+#CONFIG_EAP=y
 
 # EAP-MD5 for the integrated EAP server
-CONFIG_EAP_MD5=y
+#CONFIG_EAP_MD5=y
 
 # EAP-TLS for the integrated EAP server
-CONFIG_EAP_TLS=y
+#CONFIG_EAP_TLS=y
 
 # EAP-MSCHAPv2 for the integrated EAP server
-CONFIG_EAP_MSCHAPV2=y
+#CONFIG_EAP_MSCHAPV2=y
 
 # EAP-PEAP for the integrated EAP server
-CONFIG_EAP_PEAP=y
+#CONFIG_EAP_PEAP=y
 
 # EAP-GTC for the integrated EAP server
-CONFIG_EAP_GTC=y
+#CONFIG_EAP_GTC=y
 
 # EAP-TTLS for the integrated EAP server
-CONFIG_EAP_TTLS=y
+#CONFIG_EAP_TTLS=y
 
 # EAP-SIM for the integrated EAP server
 #CONFIG_EAP_SIM=y
@@ -109,7 +109,7 @@
 # Wi-Fi Protected Setup (WPS)
 CONFIG_WPS=y
 # Enable WSC 2.0 support
-#CONFIG_WPS2=y
+CONFIG_WPS2=y
 # Enable UPnP support for external WPS Registrars
 #CONFIG_WPS_UPNP=y
 
@@ -152,7 +152,7 @@
 #CONFIG_NO_ACCOUNTING=y
 
 # Remove support for RADIUS
-#CONFIG_NO_RADIUS=y
+CONFIG_NO_RADIUS=y
 
 # Remove support for VLANs
 #CONFIG_NO_VLAN=y
@@ -185,3 +185,6 @@
 #LIBS += -lbfd -liberty -lz
 #LIBS_p += -lbfd -liberty -lz
 #LIBS_c += -lbfd -liberty -lz
+
+# Enable AP
+CONFIG_AP=y
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index 51c1488..2dbd67d 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -13,6 +13,10 @@
 # To ignore possible wrong network configurations
 L_CFLAGS = -DWPA_IGNORE_CONFIG_ERRORS
 
+ifdef CONFIG_DRIVER_NL80211
+L_CFLAGS += -DANDROID_BRCM_P2P_PATCH
+endif
+
 # To force sizeof(enum) = 4
 ifeq ($(TARGET_ARCH),arm)
 L_CFLAGS += -mabi=aapcs-linux
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 5544925..0091064 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -215,11 +215,12 @@
 		return;
 	ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
 
+#ifndef ANDROID_BRCM_P2P_PATCH
 	for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++)
 		if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
 					    mgmt->sa, ie, ie_len) > 0)
 			return;
-
+#endif
 	if (!hapd->iconf->send_probe_response)
 		return;
 
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index fc4bc31..10e3af9 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -227,6 +227,11 @@
 	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
 	wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
 		MAC2STR(sta->addr));
+#ifdef ANDROID_BRCM_P2P_PATCH
+	if(hapd->msg_ctx_parent)
+		wpa_msg(hapd->msg_ctx_parent, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
+			MAC2STR(sta->addr));
+#endif /* ANDROID_BRCM_P2P_PATCH */
 	wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
 	sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
 	ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index d4501a1..3764be4 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -81,6 +81,10 @@
 				 struct sta_info *sta, int reassoc);
 
 	void *msg_ctx; /* ctx for wpa_msg() calls */
+#ifdef ANDROID_BRCM_P2P_PATCH
+	/* Sending the event to parent is required as SSL listens on parent ctrl iface */
+	void *msg_ctx_parent; /* ctx for wpa_msg() calls */
+#endif /*ANDROID_BRCM_P2P_PATCH*/
 
 	struct radius_client_data *radius;
 	u32 acct_session_id_hi, acct_session_id_lo;
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 4d8dd25..e0a3a36 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -1163,6 +1163,12 @@
 	sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
 	wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
 		MAC2STR(sta->addr));
+#ifdef ANDROID_BRCM_P2P_PATCH
+	if(hapd->msg_ctx_parent)
+		wpa_msg(hapd->msg_ctx_parent, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
+			MAC2STR(sta->addr));
+#endif /* ANDROID_BRCM_P2P_PATCH */
+
 	wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
 	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 		       HOSTAPD_LEVEL_INFO, "disassociated");
@@ -1214,6 +1220,11 @@
 			WLAN_STA_ASSOC_REQ_OK);
 	wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
 		MAC2STR(sta->addr));
+#ifdef ANDROID_BRCM_P2P_PATCH
+	if(hapd->msg_ctx_parent)
+		wpa_msg(hapd->msg_ctx_parent, MSG_INFO, AP_STA_DISCONNECTED MACSTR,
+			MAC2STR(sta->addr));
+#endif /* ANDROID_BRCM_P2P_PATCH */
 	wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
 	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
 		       HOSTAPD_LEVEL_DEBUG, "deauthenticated");
@@ -1679,6 +1690,12 @@
 		ap_sta_set_authorized(hapd, sta, 1);
 		wpa_msg(hapd->msg_ctx, MSG_INFO,
 			AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr));
+#ifdef ANDROID_BRCM_P2P_PATCH
+		/* Sending the event to parent is required as SSL listens on parent ctrl iface */
+		if(hapd->msg_ctx_parent)
+			wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
+				AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr));
+#endif /* ANDROID_BRCM_P2P_PATCH */
 	}
 
 	if (reassoc)
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index 6b6fd4b..8737455 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -89,18 +89,32 @@
 		return;
 
 	if (authorized) {
-		if (!ap_sta_is_authorized(sta))
+		if (!ap_sta_is_authorized(sta)) {
 			wpa_msg(hapd->msg_ctx, MSG_INFO,
 				AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr));
+#ifdef ANDROID_BRCM_P2P_PATCH
+			/* Sending the event to parent is required as SSL listens on parent ctrl iface */
+			if(hapd->msg_ctx_parent)
+				wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
+					AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr));
+#endif /* ANDROID_BRCM_P2P_PATCH */
+		}
 		ap_sta_set_authorized(hapd, sta, 1);
 		res = hostapd_set_authorized(hapd, sta, 1);
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
 			       HOSTAPD_LEVEL_DEBUG, "authorizing port");
 	} else {
-		if (ap_sta_is_authorized(sta) && (sta->flags & WLAN_STA_ASSOC))
+		if (ap_sta_is_authorized(sta) && (sta->flags & WLAN_STA_ASSOC)) {
 			wpa_msg(hapd->msg_ctx, MSG_INFO,
 				AP_STA_DISCONNECTED MACSTR,
 				MAC2STR(sta->addr));
+#ifdef ANDROID_BRCM_P2P_PATCH
+			if(hapd->msg_ctx_parent)
+				wpa_msg(hapd->msg_ctx_parent, MSG_INFO,
+					AP_STA_DISCONNECTED MACSTR,
+					MAC2STR(sta->addr));
+#endif /* ANDROID_BRCM_P2P_PATCH */
+		}
 		ap_sta_set_authorized(hapd, sta, 0);
 		res = hostapd_set_authorized(hapd, sta, 0);
 		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c
index 5e8d134..9d4aa67 100644
--- a/src/ap/wpa_auth_ie.c
+++ b/src/ap/wpa_auth_ie.c
@@ -253,10 +253,19 @@
 		capab |= WPA_CAPABILITY_PREAUTH;
 	if (conf->peerkey)
 		capab |= WPA_CAPABILITY_PEERKEY_ENABLED;
+#ifdef ANDROID_BRCM_P2P_PATCH 
+    /* WAR: we should make an get_wpa_rsnie_cap() to get the cap of peer supp 
+	 * Temporally we force tp set replay counter tp 0x3 
+	 * as if wmm is enable in all of supp device
+     */
+    capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2); 
+#else
 	if (conf->wmm_enabled) {
 		/* 4 PTKSA replay counters when using WMM */
 		capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
 	}
+#endif /* ANDROID_BRCM_P2P_PATCH */
+
 #ifdef CONFIG_IEEE80211W
 	if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
 		capab |= WPA_CAPABILITY_MFPC;
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index 528cc16..35e5e3d 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -99,6 +99,12 @@
 
 /** P2P device found */
 #define P2P_EVENT_DEVICE_FOUND "P2P-DEVICE-FOUND "
+
+#ifdef ANDROID_BRCM_P2P_PATCH
+/** P2P device lost */
+#define P2P_EVENT_DEVICE_LOST "P2P-DEVICE-LOST "
+#endif
+
 /** A P2P device requested GO negotiation, but we were not ready to start the
  * negotiation */
 #define P2P_EVENT_GO_NEG_REQUEST "P2P-GO-NEG-REQUEST "
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index b183749..ab20e8a 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -40,7 +40,9 @@
 #include "radiotap_iter.h"
 #include "rfkill.h"
 #include "driver.h"
-
+#if defined(ANDROID_BRCM_P2P_PATCH) && !defined(HOSTAPD)
+#include "wpa_supplicant_i.h"
+#endif
 #ifdef CONFIG_LIBNL20
 /* libnl 2.0 compatibility code */
 #define nl_handle nl_sock
@@ -642,8 +644,25 @@
 	const struct ieee80211_mgmt *mgmt;
 	union wpa_event_data event;
 	u16 status;
+#ifdef ANDROID_BRCM_P2P_PATCH	
+	struct wpa_supplicant *wpa_s = drv->ctx;
+#endif
 
 	mgmt = (const struct ieee80211_mgmt *) frame;
+#if (defined (CONFIG_AP) || defined (HOSTAPD) ) && defined (ANDROID_BRCM_P2P_PATCH)	
+	if (drv->nlmode == NL80211_IFTYPE_AP || drv->nlmode == NL80211_IFTYPE_P2P_GO) {
+		if (len < 24 + sizeof(mgmt->u.assoc_req)) {
+			wpa_printf(MSG_DEBUG, "nl80211: Too short association event "
+			   "frame");
+			return;
+		}
+		os_memset(&event, 0, sizeof(event));
+		event.assoc_info.freq = drv->assoc_freq;
+		event.assoc_info.req_ies = (u8 *) mgmt->u.assoc_req.variable;
+		event.assoc_info.req_ies_len = len - 24 - sizeof(mgmt->u.assoc_req);
+		event.assoc_info.addr = mgmt->sa;
+	} else {
+#endif	
 	if (len < 24 + sizeof(mgmt->u.assoc_resp)) {
 		wpa_printf(MSG_DEBUG, "nl80211: Too short association event "
 			   "frame");
@@ -677,7 +696,9 @@
 	}
 
 	event.assoc_info.freq = drv->assoc_freq;
-
+#if (defined (CONFIG_AP) || defined(HOSTAPD)) && defined (ANDROID_BRCM_P2P_PATCH)	
+	}
+#endif
 	wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
 }
 
@@ -865,6 +886,12 @@
 		reason_code = le_to_host16(mgmt->u.deauth.reason_code);
 
 	if (type == EVENT_DISASSOC) {
+#ifdef ANDROID_BRCM_P2P_PATCH 
+		if (drv->nlmode == NL80211_IFTYPE_AP ||
+			drv->nlmode == NL80211_IFTYPE_P2P_GO) {
+			event.disassoc_info.addr = mgmt->sa;
+		} else
+#endif
 		event.disassoc_info.addr = bssid;
 		event.disassoc_info.reason_code = reason_code;
 		if (frame + len > mgmt->u.disassoc.variable) {
@@ -873,6 +900,12 @@
 				mgmt->u.disassoc.variable;
 		}
 	} else {
+#ifdef ANDROID_BRCM_P2P_PATCH 		
+		if (drv->nlmode == NL80211_IFTYPE_AP ||
+			drv->nlmode == NL80211_IFTYPE_P2P_GO) {
+		event.deauth_info.addr = mgmt->sa;
+		} else
+#endif
 		event.deauth_info.addr = bssid;
 		event.deauth_info.reason_code = reason_code;
 		if (frame + len > mgmt->u.deauth.variable) {
@@ -3688,8 +3721,11 @@
 
 	mgmt = (struct ieee80211_mgmt *) data;
 	fc = le_to_host16(mgmt->frame_control);
-
+#ifndef ANDROID_BRCM_P2P_PATCH
 	if (drv->nlmode == NL80211_IFTYPE_STATION &&
+#else
+	if (
+#endif
 	    WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
 	    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) {
 		/*
@@ -3731,8 +3767,11 @@
 	int ret;
 	int beacon_set;
 	int ifindex = if_nametoindex(bss->ifname);
-
-	beacon_set = bss->beacon_set;
+#ifdef ANDROID_BRCM_P2P_PATCH 		
+		beacon_set = 1;
+#else
+		beacon_set = bss->beacon_set;
+#endif
 
 	msg = nlmsg_alloc();
 	if (!msg)
@@ -3758,6 +3797,9 @@
 	} else {
 		bss->beacon_set = 1;
 	}
+#if defined(ANDROID_BRCM_P2P_PATCH) && defined(HOSTAPD)
+	wpa_driver_nl80211_probe_req_report(priv, 1);
+#endif
 	return ret;
  nla_put_failure:
 	return -ENOBUFS;
@@ -3791,8 +3833,14 @@
 				    NL80211_CHAN_HT40PLUS);
 			break;
 		default:
+#ifndef ANDROID_BRCM_P2P_PATCH 
+/* Should be change to HT20 as a default value because P2P firmware does not support 11n for BCM4329 */
 			NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
 				    NL80211_CHAN_HT20);
+#else
+			NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
+				    NL80211_CHAN_NO_HT);
+#endif
 			break;
 		}
 	}
@@ -5961,6 +6009,15 @@
 			}
 			os_memcpy(if_addr, new_addr, ETH_ALEN);
 		}
+#ifdef ANDROID_BRCM_P2P_PATCH
+		 else {
+			/* P2P_ADDR: Driver uses a different mac address than the primary mac */
+			wpa_printf(MSG_DEBUG, "nl80211: Driver uses a "
+				   "different mac address for the Virtual I/F. Get that and store it locally");
+			os_memcpy(if_addr, new_addr, ETH_ALEN);
+
+		}
+#endif
 	}
 #endif /* CONFIG_P2P */
 
@@ -6081,7 +6138,9 @@
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
 	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
+#ifndef ANDROID_BRCM_P2P_PATCH	
 	NLA_PUT_U32(msg, NL80211_ATTR_DURATION, wait);
+#endif	
 	NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK);
 	NLA_PUT(msg, NL80211_ATTR_FRAME, buf_len, buf);
 
@@ -6249,14 +6308,14 @@
 {
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
-
+#ifndef ANDROID_BRCM_P2P_PATCH
 	if (drv->nlmode != NL80211_IFTYPE_STATION) {
 		wpa_printf(MSG_DEBUG, "nl80211: probe_req_report control only "
 			   "allowed in station mode (iftype=%d)",
 			   drv->nlmode);
 		return -1;
 	}
-
+#endif
 	if (!report) {
 		if (drv->nl_handle_preq) {
 			eloop_unregister_read_sock(
@@ -6311,6 +6370,45 @@
 		goto out_err3;
 	}
 
+#ifdef ANDROID_BRCM_P2P_PATCH 
+	if (drv->nlmode != NL80211_IFTYPE_AP &&
+		drv->nlmode != NL80211_IFTYPE_P2P_GO) {
+		wpa_printf(MSG_DEBUG, "nl80211: probe_req_report control only "
+			   "allowed in AP or P2P GO mode (iftype=%d)",
+			   drv->nlmode);
+		goto done;
+	}
+	
+	if (nl80211_register_frame(drv, drv->nl_handle_preq,
+			   (WLAN_FC_TYPE_MGMT << 2) |
+			   (WLAN_FC_STYPE_ASSOC_REQ << 4),
+			   NULL, 0) < 0) {
+		goto out_err3;
+	}
+
+	if (nl80211_register_frame(drv, drv->nl_handle_preq,
+			   (WLAN_FC_TYPE_MGMT << 2) |
+			   (WLAN_FC_STYPE_REASSOC_REQ << 4),
+			   NULL, 0) < 0) {
+		goto out_err3;
+	}
+
+	if (nl80211_register_frame(drv, drv->nl_handle_preq,
+			   (WLAN_FC_TYPE_MGMT << 2) |
+			   (WLAN_FC_STYPE_DISASSOC << 4),
+			   NULL, 0) < 0) {
+		goto out_err3;
+	}
+	
+	if (nl80211_register_frame(drv, drv->nl_handle_preq,
+					   (WLAN_FC_TYPE_MGMT << 2) |
+					   (WLAN_FC_STYPE_DEAUTH << 4),
+					   NULL, 0) < 0) {
+		goto out_err3;
+	}
+
+done:
+#endif
 	eloop_register_read_sock(nl_socket_get_fd(drv->nl_handle_preq),
 				 wpa_driver_nl80211_event_receive, drv,
 				 drv->nl_handle_preq);
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index d4fac56..7147e5c 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -464,6 +464,10 @@
 
 	if (msg->capability) {
 		dev->info.dev_capab = msg->capability[0];
+#ifdef ANDROID_BRCM_P2P_PATCH
+	if( dev->info.group_capab != msg->capability[1])
+		dev->flags &= ~P2P_DEV_REPORTED;
+#endif	
 		dev->info.group_capab = msg->capability[1];
 	}
 
@@ -574,6 +578,11 @@
 			freq, msg.ds_params ? *msg.ds_params : -1);
 	}
 	dev->listen_freq = freq;
+#ifdef ANDROID_BRCM_P2P_PATCH	
+	if(msg.group_info)
+		dev->go_state = REMOTE_GO;
+#endif
+
 	if (msg.group_info)
 		dev->oper_freq = freq;
 	dev->info.level = level;
@@ -625,8 +634,12 @@
 {
 	int i;
 
-	if (p2p->go_neg_peer == dev)
+	if (p2p->go_neg_peer == dev) {
+#ifdef ANDROID_BRCM_P2P_PATCH
+		p2p_go_neg_failed(p2p, dev, -1);
+#endif
 		p2p->go_neg_peer = NULL;
+	}
 	if (p2p->invite_peer == dev)
 		p2p->invite_peer = NULL;
 	if (p2p->sd_peer == dev)
@@ -2665,7 +2678,15 @@
 	 * state once per second to give other uses a chance to use the radio.
 	 */
 	p2p_set_state(p2p, P2P_WAIT_PEER_IDLE);
+#ifdef ANDROID_BRCM_P2P_PATCH
+	/*
+	 * We need to be back in Listen state soon enough so that we don't miss
+	 * the GO Nego req from the peer.
+	*/
+	p2p_set_timeout(p2p, 0, 0);
+#else
 	p2p_set_timeout(p2p, 1, 0);
+#endif
 }
 
 
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index db816a6..81ebe9b 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -292,6 +292,17 @@
 	 */
 	u8 dev_addr[ETH_ALEN];
 
+#ifdef ANDROID_BRCM_P2P_PATCH
+	/**
+	 * p2p_dev_addr - P2P Device Address
+	 *
+	 * Holds the p2p device address. If the driver uses primary mac address
+	 * for p2p operations, then this will hold the same value as that of 
+	 * dev_addr.
+	 */
+	u8 p2p_dev_addr[ETH_ALEN];
+#endif
+
 	/**
 	 * dev_name - Device Name
 	 */
diff --git a/src/p2p/p2p_build.c b/src/p2p/p2p_build.c
index c34db91..d59e54b 100644
--- a/src/p2p/p2p_build.c
+++ b/src/p2p/p2p_build.c
@@ -164,7 +164,16 @@
 	len = wpabuf_put(buf, 2); /* IE length to be filled */
 
 	/* P2P Device address */
+#ifdef ANDROID_BRCM_P2P_PATCH
+	/* 
+	* P2P_ADDR: Supplicant uses primary mac addr for p2p and hence advertises that. To
+	* to make it compatible with solution using virtual interface for P2P, a new variable
+	* is added to hold the actual p2p device address.
+	*/
+	wpabuf_put_data(buf, p2p->cfg->p2p_dev_addr, ETH_ALEN);
+#else
 	wpabuf_put_data(buf, p2p->cfg->dev_addr, ETH_ALEN);
+#endif
 
 	/* Config Methods */
 	methods = 0;
diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c
index 1c96486..f5937b9 100644
--- a/src/p2p/p2p_go_neg.c
+++ b/src/p2p/p2p_go_neg.c
@@ -491,7 +491,15 @@
 		}
 
 		if (dev->go_neg_req_sent &&
+#ifdef ANDROID_BRCM_P2P_PATCH 
+		/* P2P_ADDR: compare against the p2p device address. The own mac 
+		address may not not be the actual p2p device address, if you 
+		are using a virtual interface.
+		*/
+		    os_memcmp(sa, p2p->cfg->p2p_dev_addr, ETH_ALEN) > 0) {
+#else
 		    os_memcmp(sa, p2p->cfg->dev_addr, ETH_ALEN) > 0) {
+#endif
 			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
 				"P2P: Do not reply since peer has higher "
 				"address and GO Neg Request already sent");
diff --git a/src/p2p/p2p_group.c b/src/p2p/p2p_group.c
index 14a475d..169985f 100644
--- a/src/p2p/p2p_group.c
+++ b/src/p2p/p2p_group.c
@@ -183,7 +183,12 @@
 
 	len = p2p_buf_add_ie_hdr(ie);
 	p2p_group_add_common_ies(group, ie);
+#ifdef ANDROID_BRCM_P2P_PATCH
+	/* P2P_ADDR: Use p2p_dev_addr instead of own mac addr*/
+	p2p_buf_add_device_id(ie, group->p2p->cfg->p2p_dev_addr);
+#else
 	p2p_buf_add_device_id(ie, group->p2p->cfg->dev_addr);
+#endif
 	p2p_group_add_noa(ie, group->noa);
 	p2p_buf_update_ie_hdr(ie, len);
 
diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c
index bb2767d..42015ad 100644
--- a/src/p2p/p2p_invitation.c
+++ b/src/p2p/p2p_invitation.c
@@ -55,7 +55,11 @@
 	else if (p2p->inv_role == P2P_INVITE_ROLE_CLIENT)
 		dev_addr = peer->info.p2p_device_addr;
 	else
+#ifdef ANDROID_BRCM_P2P_PATCH
+		dev_addr = p2p->cfg->p2p_dev_addr;
+#else
 		dev_addr = p2p->cfg->dev_addr;
+#endif
 	p2p_buf_add_group_id(buf, dev_addr, p2p->inv_ssid, p2p->inv_ssid_len);
 	p2p_buf_add_device_info(buf, p2p, peer);
 	p2p_buf_update_ie_hdr(buf, len);
diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c
index f7ff06c..32d82f6 100644
--- a/src/p2p/p2p_pd.c
+++ b/src/p2p/p2p_pd.c
@@ -283,8 +283,21 @@
 {
 	struct wpabuf *req;
 	int freq;
-
+#ifdef ANDROID_BRCM_P2P_PATCH
+	if(dev->go_state == REMOTE_GO) {
+		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
+			"P2P: GO Sending it to oper_freq %d", dev->oper_freq);
+		freq= dev->oper_freq;
+	}
+	else {
+		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
+			"P2P: NOT GO oper_freq %d listen_freq %d", dev->oper_freq, dev->listen_freq);
+		freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq;
+	}
+#else
 	freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq;
+#endif
+
 	if (freq <= 0) {
 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
 			"P2P: No Listen/Operating frequency known for the "
diff --git a/wpa_supplicant/.config b/wpa_supplicant/.config
index 1b0ee97..b234de8 100644
--- a/wpa_supplicant/.config
+++ b/wpa_supplicant/.config
@@ -393,3 +393,7 @@
 # Enable mitigation against certain attacks against TKIP by delaying Michael
 # MIC error reports by a random amount of time between 0 and 60 seconds
 #CONFIG_DELAYED_MIC_ERROR_REPORT=y
+
+# Enable P2P
+CONFIG_P2P=y
+CONFIG_AP=y
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index b97c9a3..a59652d 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -31,6 +31,10 @@
 # To ignore possible wrong network configurations
 L_CFLAGS = -DWPA_IGNORE_CONFIG_ERRORS
 
+ifdef CONFIG_DRIVER_NL80211
+L_CFLAGS += -DANDROID_BRCM_P2P_PATCH
+endif
+
 # Use Android specific directory for control interface sockets
 L_CFLAGS += -DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/misc/wifi/sockets\"
 L_CFLAGS += -DCONFIG_CTRL_IFACE_DIR=\"/data/system/wpa_supplicant\"
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index 41dbe23..6d9037a 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -23,7 +23,7 @@
 #include "ap/hostapd.h"
 #include "ap/ap_config.h"
 #include "ap/ap_drv_ops.h"
-#ifdef NEED_AP_MLME
+#if  defined (NEED_AP_MLME) || defined (ANDROID_BRCM_P2P_PATCH)
 #include "ap/ieee802_11.h"
 #endif /* NEED_AP_MLME */
 #include "ap/beacon.h"
@@ -451,6 +451,10 @@
 		}
 
 		hapd_iface->bss[i]->msg_ctx = wpa_s;
+#ifdef ANDROID_BRCM_P2P_PATCH
+		/* Sending the event to parent is required as SSL listens on parent ctrl iface */
+		hapd_iface->bss[i]->msg_ctx_parent = wpa_s->parent;
+#endif
 		hapd_iface->bss[i]->public_action_cb = ap_public_action_rx;
 		hapd_iface->bss[i]->public_action_cb_ctx = wpa_s;
 		hapd_iface->bss[i]->vendor_action_cb = ap_vendor_action_rx;
@@ -486,6 +490,14 @@
 		wpa_supplicant_ap_deinit(wpa_s);
 		return -1;
 	}
+	
+#ifdef ANDROID_BRCM_P2P_PATCH
+	if (wpa_drv_probe_req_report(wpa_s, 1) < 0) {
+		wpa_printf(MSG_DEBUG, "P2P: Failed to request the driver to "
+			   "report received Probe Request frames");
+		return -1;
+	}
+#endif
 
 	return 0;
 }
@@ -541,7 +553,7 @@
 
 void ap_mgmt_rx(void *ctx, struct rx_mgmt *rx_mgmt)
 {
-#ifdef NEED_AP_MLME
+#if  defined (NEED_AP_MLME) || defined (ANDROID_BRCM_P2P_PATCH)
 	struct wpa_supplicant *wpa_s = ctx;
 	struct hostapd_frame_info fi;
 	os_memset(&fi, 0, sizeof(fi));
@@ -549,7 +561,7 @@
 	fi.ssi_signal = rx_mgmt->ssi_signal;
 	ieee802_11_mgmt(wpa_s->ap_iface->bss[0], rx_mgmt->frame,
 			rx_mgmt->frame_len, &fi);
-#endif /* NEED_AP_MLME */
+#endif /* defined (NEED_AP_MLME) || defined (ANDROID_BRCM_P2P_PATCH) */
 }
 
 
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index b071f76..1ad7d80 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -303,7 +303,9 @@
 #ifdef CONFIG_AP
 	u8 *_p2p_dev_addr = NULL;
 #endif /* CONFIG_AP */
-
+#ifdef ANDROID_BRCM_P2P_PATCH	
+	struct wpa_supplicant *iface;
+#endif
 	if (cmd == NULL || os_strcmp(cmd, "any") == 0) {
 		_bssid = NULL;
 #ifdef CONFIG_P2P
@@ -322,7 +324,17 @@
 		return -1;
 	}
 
-#ifdef CONFIG_AP
+#if defined(ANDROID_BRCM_P2P_PATCH) && defined(CONFIG_AP)
+	for (iface = wpa_s->global->ifaces; iface; iface = iface->next)	{
+		if (iface->ap_iface){
+			wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: iface 0x%08x wpa_s->ap_iface %p", iface, iface->ap_iface);
+			wpa_supplicant_ap_wps_pbc(iface, _bssid, _p2p_dev_addr);
+			return 0;
+		}
+		else
+			wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: ap_iface is not set iface 0x%08x", iface);
+	}
+#elif defined CONFIG_AP
 	if (wpa_s->ap_iface)
 		return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr);
 #endif /* CONFIG_AP */
@@ -339,6 +351,10 @@
 	char *pin;
 	int ret;
 
+#if defined ANDROID_BRCM_P2P_PATCH && defined CONFIG_AP
+	struct wpa_supplicant *iface;
+#endif
+
 	pin = os_strchr(cmd, ' ');
 	if (pin)
 		*pin++ = '\0';
@@ -351,7 +367,19 @@
 		return -1;
 	}
 
-#ifdef CONFIG_AP
+#if defined ANDROID_BRCM_P2P_PATCH && defined CONFIG_AP
+	for (iface = wpa_s->global->ifaces; iface; iface = iface->next)	{
+		if (iface->ap_iface){
+			wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: iface 0x%08x wpa_s->ap_iface %p", iface, iface->ap_iface);
+			/* Call the wps registrar for the main interface */
+			wpa_supplicant_ap_wps_pin(iface, _bssid, pin,
+							 buf, buflen);
+			return 0;
+		}
+		else
+			wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: ap_iface is not set iface 0x%08x", iface);
+	}
+#elif defined CONFIG_AP
 	if (wpa_s->ap_iface)
 		return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
 						 buf, buflen);
@@ -2335,6 +2363,16 @@
 {
 	struct wpa_ssid *ssid = wpa_s->current_ssid;
 
+#ifdef ANDROID_BRCM_P2P_PATCH
+	struct wpa_supplicant *ifs = NULL;
+	
+	for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
+		if((ifs->ap_iface) && 
+			(ifs->p2p_group_interface == P2P_GROUP_INTERFACE_GO)) {
+			ssid = ifs->current_ssid;
+		}
+	}
+#endif
 	if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
 	    ssid->passphrase == NULL)
 		return -1;
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 8bccb6b..812cd52 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -724,7 +724,12 @@
 	 * reassociation is requested. If we are in process of associating with
 	 * the selected BSSID, do not trigger new attempt.
 	 */
-	if (wpa_s->reassociate ||
+	if ((wpa_s->reassociate
+#ifdef ANDROID_BRCM_P2P_PATCH
+		&& (os_memcmp(selected->bssid, wpa_s->bssid, ETH_ALEN) != 0)
+		&& (wpa_s->wpa_state != WPA_COMPLETED)
+#endif
+		)||
 	    (os_memcmp(selected->bssid, wpa_s->bssid, ETH_ALEN) != 0 &&
 	     ((wpa_s->wpa_state != WPA_ASSOCIATING &&
 	       wpa_s->wpa_state != WPA_AUTHENTICATING) ||
@@ -1851,6 +1856,11 @@
 		}
 #endif /* CONFIG_AP */
 		wpa_supplicant_event_disassoc(wpa_s, reason_code);
+
+#if defined(ANDROID_BRCM_P2P_PATCH) && defined(CONFIG_P2P)
+		wpas_p2p_group_remove_notif(wpa_s, reason_code);
+#endif
+
 		break;
 	case EVENT_MICHAEL_MIC_FAILURE:
 		wpa_supplicant_event_michael_mic_failure(wpa_s, data);
@@ -1988,6 +1998,25 @@
 				size_t ie_len = data->rx_mgmt.frame_len -
 					(mgmt->u.probe_req.variable -
 					 data->rx_mgmt.frame);
+			#ifdef ANDROID_BRCM_P2P_PATCH
+				wpa_printf(MSG_DEBUG, "Non-AP: Probe request frame ");
+			{
+				/* If we are Go or client, we need not reply the probe reqest on eth0 interface */
+				struct wpa_supplicant* ifs;
+				int ignore = 0;
+				for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
+					if ( (ifs->p2p_group_interface == P2P_GROUP_INTERFACE_GO ) ||(ifs->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT )) {
+						wpa_printf(MSG_DEBUG, "Non-AP: NEERAJKG Ignoring Probe request");
+						ignore = 1;
+						break;
+					}
+				}
+				if(ignore)
+					break;
+				else
+					wpa_printf(MSG_DEBUG, "Non-AP: Couln't Ignore Probe request %d", wpa_s->p2p_group_interface);
+			}
+			#endif
 				wpas_p2p_probe_req_rx(wpa_s, src, ie, ie_len);
 				break;
 			}
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index c34a28c..9a9194a 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -509,8 +509,15 @@
 		client = ssid->mode == WPAS_MODE_INFRA;
 		if (ssid->mode == WPAS_MODE_P2P_GO) {
 			persistent = ssid->p2p_persistent_group;
+#ifndef ANDROID_BRCM_P2P_PATCH
 			os_memcpy(go_dev_addr, wpa_s->parent->own_addr,
 				  ETH_ALEN);
+#else
+			/* P2P_ADDR: Use p2p_dev_addr instead of own mac addr */
+			os_memcpy(go_dev_addr, wpa_s->global->p2p_dev_addr,
+				  ETH_ALEN);
+
+#endif
 		} else
 			persistent = wpas_p2p_persistent_group(wpa_s,
 							       go_dev_addr,
@@ -880,13 +887,22 @@
 			wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
 			ssid->frequency,
 			params->passphrase ? params->passphrase : "",
+#ifndef ANDROID_BRCM_P2P_PATCH
 			MAC2STR(wpa_s->parent->own_addr),
+#else
+			/* P2P_ADDR: use p2p_dev_addr instead of own addr */
+			MAC2STR(wpa_s->global->p2p_dev_addr),
+#endif
 			params->persistent_group ? " [PERSISTENT]" : "");
-
 		if (params->persistent_group)
 			network_id = wpas_p2p_store_persistent_group(
 				wpa_s->parent, ssid,
+#ifndef ANDROID_BRCM_P2P_PATCH
 				wpa_s->parent->own_addr);
+#else
+				/* P2P_ADDR: Use p2p device address */
+				wpa_s->global->p2p_dev_addr);
+#endif
 		if (network_id < 0)
 			network_id = ssid->id;
 		wpas_notify_p2p_group_started(wpa_s, ssid, network_id, 0);
@@ -1204,7 +1220,10 @@
 static void wpas_dev_lost(void *ctx, const u8 *dev_addr)
 {
 	struct wpa_supplicant *wpa_s = ctx;
-
+#ifdef ANDROID_BRCM_P2P_PATCH
+	wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_DEVICE_LOST
+		"p2p_dev_addr=" MACSTR, MAC2STR(dev_addr));
+#endif
 	wpas_notify_p2p_device_lost(wpa_s, dev_addr);
 }
 
@@ -2353,6 +2372,9 @@
 	struct p2p_config p2p;
 	unsigned int r;
 	int i;
+#ifdef ANDROID_BRCM_P2P_PATCH
+	char buf[200];
+#endif
 
 	if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE))
 		return 0;
@@ -2414,7 +2436,19 @@
 	p2p.invitation_result = wpas_invitation_result;
 	p2p.get_noa = wpas_get_noa;
 
+#ifdef ANDROID_BRCM_P2P_PATCH
+	/* P2P_ADDR: Using p2p_dev_addr to hold the actual p2p device address incase if
+	 * we are not using the primary interface for p2p operations.
+	 */
+	wpa_drv_driver_cmd(wpa_s,  "P2P_DEV_ADDR", buf, sizeof(buf));	
+	os_memcpy(p2p.p2p_dev_addr, buf, ETH_ALEN);
+	os_memcpy(wpa_s->global->p2p_dev_addr, buf, ETH_ALEN);
+	os_memcpy(p2p.dev_addr, buf, ETH_ALEN);
+	wpa_printf(MSG_DEBUG, "P2P: Device address ("MACSTR")", MAC2STR(p2p.p2p_dev_addr));
+#else
 	os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN);
+#endif
+
 	os_memcpy(p2p.dev_addr, wpa_s->own_addr, ETH_ALEN);
 	p2p.dev_name = wpa_s->conf->device_name;
 	p2p.manufacturer = wpa_s->conf->manufacturer;
@@ -3643,6 +3677,9 @@
 		return -1;
 
 	p2p_ie = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
+#ifdef ANDROID_BRCM_P2P_PATCH 
+	if (p2p_ie == NULL) return -1;
+#endif
 	ret = p2p_assoc_req_ie(wpa_s->global->p2p, bss->bssid, buf, len,
 			       p2p_group, p2p_ie);
 	wpabuf_free(p2p_ie);
@@ -3715,6 +3752,9 @@
 {
 	enum p2p_invite_role role;
 	u8 *bssid = NULL;
+#ifdef ANDROID_BRCM_P2P_PATCH
+	int go;
+#endif
 
 	if (ssid->mode == WPAS_MODE_P2P_GO) {
 		role = P2P_INVITE_ROLE_GO;
@@ -3723,6 +3763,19 @@
 				   "address in invitation command");
 			return -1;
 		}
+
+#ifdef ANDROID_BRCM_P2P_PATCH
+	wpa_printf(MSG_DEBUG, "P2P: Check to see if already runnig persistent wpa_s %p grp ssid %s ssid_len %d", wpa_s, ssid->ssid, ssid->ssid_len);
+	if(wpas_get_p2p_group(wpa_s, ssid->ssid, ssid->ssid_len, &go)) {
+		wpa_printf(MSG_DEBUG, "P2P: We are already running persistent group");
+		if (go)
+			bssid = wpa_s->own_addr;
+		else
+			wpa_printf(MSG_DEBUG, "P2P: We are running persistent group but go is not set");
+	} else {
+		wpa_printf(MSG_DEBUG, "P2P: We are NOT already running persistent group");
+#endif
+
 		if (wpas_p2p_create_iface(wpa_s)) {
 			if (wpas_p2p_add_group_interface(wpa_s,
 							 WPA_IF_P2P_GO) < 0) {
@@ -3734,6 +3787,9 @@
 			bssid = wpa_s->pending_interface_addr;
 		} else
 			bssid = wpa_s->own_addr;
+#ifdef ANDROID_BRCM_P2P_PATCH
+	}
+#endif
 	} else {
 		role = P2P_INVITE_ROLE_CLIENT;
 		peer_addr = ssid->bssid;
@@ -3841,14 +3897,22 @@
 		wpa_msg(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
 			"%s client ssid=\"%s\" freq=%d psk=%s go_dev_addr="
 			MACSTR "%s",
+		#ifdef ANDROID_BRCM_P2P_PATCH
+			wpa_s->ifname, ssid_txt, wpa_s->current_bss->freq, psk,
+		#else
 			wpa_s->ifname, ssid_txt, ssid->frequency, psk,
+		#endif
 			MAC2STR(go_dev_addr),
 			persistent ? " [PERSISTENT]" : "");
 	} else {
 		wpa_msg(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED
 			"%s client ssid=\"%s\" freq=%d passphrase=\"%s\" "
 			"go_dev_addr=" MACSTR "%s",
+		#ifdef ANDROID_BRCM_P2P_PATCH
+			wpa_s->ifname, ssid_txt, wpa_s->current_bss->freq,
+		#else
 			wpa_s->ifname, ssid_txt, ssid->frequency,
+		#endif
 			ssid->passphrase ? ssid->passphrase : "",
 			MAC2STR(go_dev_addr),
 			persistent ? " [PERSISTENT]" : "");
@@ -3939,6 +4003,22 @@
 	p2p_deauth_notif(wpa_s->global->p2p, bssid, reason_code, ie, ie_len);
 }
 
+#ifdef ANDROID_BRCM_P2P_PATCH
+void wpas_p2p_group_remove_notif(struct wpa_supplicant *wpa_s, u16 reason_code)
+{
+	if(wpa_s->global->p2p_disabled)
+		return;
+
+	/* If we are running a P2P Client and we received a Deauth/Disassoc from the Go, then remove 
+	   the virutal interface on which the client is running. */
+	if((wpa_s != wpa_s->parent) && (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT) && (wpa_s->key_mgmt != WPA_KEY_MGMT_WPS)) {
+
+		wpa_printf(MSG_DEBUG, "P2P: [EVENT_DEAUTH] Removing P2P_CLIENT virtual intf.");
+		wpa_supplicant_cancel_scan(wpa_s);
+		wpas_p2p_interface_unavailable(wpa_s);
+	}
+}
+#endif
 
 void wpas_p2p_disassoc_notif(struct wpa_supplicant *wpa_s, const u8 *bssid,
 			     u16 reason_code, const u8 *ie, size_t ie_len)
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index b1080a5..93a5afd 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -108,6 +108,10 @@
 			unsigned int interval);
 void wpas_p2p_deauth_notif(struct wpa_supplicant *wpa_s, const u8 *bssid,
 			   u16 reason_code, const u8 *ie, size_t ie_len);
+#ifdef ANDROID_BRCM_P2P_PATCH
+void wpas_p2p_group_remove_notif(struct wpa_supplicant *wpa_s,
+				u16 reason_code);
+#endif /* ANDROID_BRCM_P2P_PATCH */
 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);