Add P2P support for BRCM CFG80211 driver

Change-Id: Iafec4bedbd33836d0a64e7ea054d8a46ef8ec204
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
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);