Cumulative patch from commit 2cebdee66de6a1c6befe327c2348610478e06032

2cebdee Fix MinGW build
e4fa8b1 wpa_supplicant: Add Wake-on-WLAN configuration support
959214b Android: Use extended P2P functionality (ANDROID_P2P) for all vendors
9a41232 TDLS: Fully tear down existing link before setup
c04b465 TDLS: Disable links during AP deauth in external flow
b19719a TDLS: Make wpa_tdls_send_teardown() static
52f5877 nl80211: Take ownership of dynamically added interfaces
e390df0 nl80211: Cancel rfkill timeout on deinit
fa258a3 HS 2.0 R2: Fix writing of domain_suffix_match cred parameter
bb24229 TDLS: Pass peer's capability info to the driver in open mode

Change-Id: I20b4dba96c07a85cf7b9c9c4ae51bbf9f6f88540
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index f56267c..ca9d82d 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -27,24 +27,21 @@
 # Disable unused parameter warnings
 L_CFLAGS += -Wno-unused-parameter
 
+# Set Android extended P2P functionality
+L_CFLAGS += -DANDROID_P2P
+ifeq ($(BOARD_WPA_SUPPLICANT_PRIVATE_LIB),)
+L_CFLAGS += -DANDROID_P2P_STUB
+endif
+
 # Disable roaming in wpa_supplicant
 ifdef CONFIG_NO_ROAMING
 L_CFLAGS += -DCONFIG_NO_ROAMING
 endif
 
 ifeq ($(BOARD_WLAN_DEVICE), bcmdhd)
-L_CFLAGS += -DANDROID_P2P
 L_CFLAGS += -DP2P_CONCURRENT_SEARCH_DELAY=0
 endif
 
-ifeq ($(BOARD_WLAN_DEVICE), qcwcn)
-L_CFLAGS += -DANDROID_P2P
-endif
-
-ifeq ($(BOARD_WLAN_DEVICE), mrvl)
-L_CFLAGS += -DANDROID_P2P
-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/config.c b/wpa_supplicant/config.c
index 698b459..b5a5d78 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2022,6 +2022,7 @@
 	os_free(config->sae_groups);
 	wpabuf_free(config->ap_vendor_elements);
 	os_free(config->osu_dir);
+	os_free(config->wowlan_triggers);
 	os_free(config);
 }
 
@@ -3875,6 +3876,7 @@
 	{ INT(sched_scan_interval), 0 },
 	{ INT(tdls_external_control), 0},
 	{ STR(osu_dir), 0 },
+	{ STR(wowlan_triggers), 0 },
 };
 
 #undef FUNC
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 26b1233..bf3f3f7 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -1022,6 +1022,13 @@
 	 * directory.
 	 */
 	char *osu_dir;
+
+	/**
+	 * wowlan_triggers - Wake-on-WLAN triggers
+	 *
+	 * If set, these wowlan triggers will be configured.
+	 */
+	char *wowlan_triggers;
 };
 
 
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 3842946..3cfe5ba 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -775,7 +775,7 @@
 	for (i = 0; i < cred->num_domain; i++)
 		fprintf(f, "\tdomain=\"%s\"\n", cred->domain[i]);
 	if (cred->domain_suffix_match)
-		fprintf(f, "\tdomain_suffix_match=\"%s\"",
+		fprintf(f, "\tdomain_suffix_match=\"%s\"\n",
 			cred->domain_suffix_match);
 	if (cred->roaming_consortium_len) {
 		fprintf(f, "\troaming_consortium=");
@@ -1155,6 +1155,10 @@
 		fprintf(f, "tdls_external_control=%d\n",
 			config->tdls_external_control);
 
+	if (config->wowlan_triggers)
+		fprintf(f, "wowlan_triggers=\"%s\"\n",
+			config->wowlan_triggers);
+
 	if (config->bgscan)
 		fprintf(f, "bgscan=\"%s\"\n", config->bgscan);
 }
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index b8b6d95..14664df 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -5534,7 +5534,7 @@
 		data_len /= 2;
 		data = os_malloc(data_len);
 		if (!data)
-			return -ENOBUFS;
+			return -1;
 
 		if (hexstr2bin(pos, data, data_len)) {
 			wpa_printf(MSG_DEBUG,
@@ -5547,7 +5547,7 @@
 	reply = wpabuf_alloc((buflen - 1) / 2);
 	if (!reply) {
 		os_free(data);
-		return -ENOBUFS;
+		return -1;
 	}
 
 	ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len,
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 938ece6..beeb059 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -614,6 +614,14 @@
 					  qos_map_set_len);
 }
 
+static inline int wpa_drv_wowlan(struct wpa_supplicant *wpa_s,
+				 const struct wowlan_triggers *triggers)
+{
+	if (!wpa_s->driver->set_wowlan)
+		return -1;
+	return wpa_s->driver->set_wowlan(wpa_s->drv_priv, triggers);
+}
+
 static inline int wpa_drv_vendor_cmd(struct wpa_supplicant *wpa_s,
 				     int vendor_id, int subcmd, const u8 *data,
 				     size_t data_len, struct wpabuf *buf)
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index af7b847..f56b198 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -3123,6 +3123,79 @@
 }
 
 
+static int wpas_check_wowlan_trigger(const char *start, const char *trigger,
+				     int capa_trigger, u8 *param_trigger)
+{
+	if (os_strcmp(start, trigger) != 0)
+		return 0;
+	if (!capa_trigger)
+		return 0;
+
+	*param_trigger = 1;
+	return 1;
+}
+
+
+int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
+			     struct wpa_driver_capa *capa)
+{
+	struct wowlan_triggers triggers;
+	char *start, *end, *buf;
+	int last, ret;
+
+	if (!wpa_s->conf->wowlan_triggers)
+		return 0;
+
+	buf = os_strdup(wpa_s->conf->wowlan_triggers);
+	if (buf == NULL)
+		return -1;
+
+	os_memset(&triggers, 0, sizeof(triggers));
+
+#define CHECK_TRIGGER(trigger) \
+	wpas_check_wowlan_trigger(start, #trigger,			\
+				  capa->wowlan_triggers.trigger,	\
+				  &triggers.trigger)
+
+	start = buf;
+	while (*start != '\0') {
+		while (isblank(*start))
+			start++;
+		if (*start == '\0')
+			break;
+		end = start;
+		while (!isblank(*end) && *end != '\0')
+			end++;
+		last = *end == '\0';
+		*end = '\0';
+
+		if (!CHECK_TRIGGER(any) &&
+		    !CHECK_TRIGGER(disconnect) &&
+		    !CHECK_TRIGGER(magic_pkt) &&
+		    !CHECK_TRIGGER(gtk_rekey_failure) &&
+		    !CHECK_TRIGGER(eap_identity_req) &&
+		    !CHECK_TRIGGER(four_way_handshake) &&
+		    !CHECK_TRIGGER(rfkill_release)) {
+			wpa_printf(MSG_DEBUG,
+				   "Unknown/unsupported wowlan trigger '%s'",
+				   start);
+			ret = -1;
+			goto out;
+		}
+
+		if (last)
+			break;
+		start = end + 1;
+	}
+#undef CHECK_TRIGGER
+
+	ret = wpa_drv_wowlan(wpa_s, &triggers);
+out:
+	os_free(buf);
+	return ret;
+}
+
+
 static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
 					      const char *rn)
 {
@@ -3650,6 +3723,14 @@
 	if (wpa_bss_init(wpa_s) < 0)
 		return -1;
 
+	/*
+	 * Set Wake-on-WLAN triggers, if configured.
+	 * Note: We don't restore/remove the triggers on shutdown (it doesn't
+	 * have effect anyway when the interface is down).
+	 */
+	if (wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
+		return -1;
+
 #ifdef CONFIG_EAP_PROXY
 {
 	size_t len;