Accumulative patch from commit f8361e3d681e55efead2aac79fedf4b232d533fb

TDLS: Pass peer's VHT Capability information during sta_add
WPS: Clear sent_carrier to avoid errors in python script
WPS: Fix OOB Device Password use in PSK1,PSK1 derivation
WPS: Add AP mode NFC connection handover with wpa_supplicant/nfcpy
WPS NFC: Add connection handover support for ER
WPS: Add wps-er-config command for writing config token from ER

Change-Id: I8934dcffb9f66bd3a2f840b78d72c9dd6cecf61d
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index dbe9153..940cd74 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -910,12 +910,12 @@
 
 static int wpas_ctrl_nfc_get_handover_sel_wps(struct wpa_supplicant *wpa_s,
 					      char *reply, size_t max_len,
-					      int ndef, int cr)
+					      int ndef, int cr, char *uuid)
 {
 	struct wpabuf *buf;
 	int res;
 
-	buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr);
+	buf = wpas_wps_nfc_handover_sel(wpa_s, ndef, cr, uuid);
 	if (buf == NULL)
 		return -1;
 
@@ -934,7 +934,7 @@
 					  char *cmd, char *reply,
 					  size_t max_len)
 {
-	char *pos;
+	char *pos, *pos2;
 	int ndef;
 
 	pos = os_strchr(cmd, ' ');
@@ -949,10 +949,13 @@
 	else
 		return -1;
 
+	pos2 = os_strchr(pos, ' ');
+	if (pos2)
+		*pos2++ = '\0';
 	if (os_strcmp(pos, "WPS") == 0 || os_strcmp(pos, "WPS-CR") == 0) {
 		return wpas_ctrl_nfc_get_handover_sel_wps(
 			wpa_s, reply, max_len, ndef,
-			os_strcmp(pos, "WPS-CR") == 0);
+			os_strcmp(pos, "WPS-CR") == 0, pos2);
 	}
 
 	return -1;
diff --git a/wpa_supplicant/examples/wps-nfc.py b/wpa_supplicant/examples/wps-nfc.py
index 14acc5b..9a6da5f 100755
--- a/wpa_supplicant/examples/wps-nfc.py
+++ b/wpa_supplicant/examples/wps-nfc.py
@@ -61,6 +61,13 @@
     return wpas.request("WPS_NFC_CONFIG_TOKEN NDEF").rstrip().decode("hex")
 
 
+def wpas_get_er_config_token(uuid):
+    wpas = wpas_connect()
+    if (wpas == None):
+        return None
+    return wpas.request("WPS_ER_NFC_CONFIG_TOKEN NDEF " + uuid).rstrip().decode("hex")
+
+
 def wpas_get_password_token():
     wpas = wpas_connect()
     if (wpas == None):
@@ -75,15 +82,91 @@
     return wpas.request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip().decode("hex")
 
 
-def wpas_report_handover(req, sel):
+def wpas_get_handover_sel(uuid):
     wpas = wpas_connect()
     if (wpas == None):
         return None
-    return wpas.request("NFC_REPORT_HANDOVER INIT WPS " +
+    if uuid is None:
+        return wpas.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR").rstrip().decode("hex")
+    return wpas.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR " + uuid).rstrip().decode("hex")
+
+
+def wpas_report_handover(req, sel, type):
+    wpas = wpas_connect()
+    if (wpas == None):
+        return None
+    return wpas.request("NFC_REPORT_HANDOVER " + type + " WPS " +
                         str(req).encode("hex") + " " +
                         str(sel).encode("hex"))
 
 
+class HandoverServer(nfc.handover.HandoverServer):
+    def __init__(self):
+        super(HandoverServer, self).__init__()
+
+    def process_request(self, request):
+        print "HandoverServer - request received"
+        print "Parsed handover request: " + request.pretty()
+
+        sel = nfc.ndef.HandoverSelectMessage(version="1.2")
+
+        for carrier in request.carriers:
+            print "Remote carrier type: " + carrier.type
+            if carrier.type == "application/vnd.wfa.wsc":
+                print "WPS carrier type match - add WPS carrier record"
+                self.received_carrier = carrier.record
+                data = wpas_get_handover_sel(self.uuid)
+                if data is None:
+                    print "Could not get handover select carrier record from wpa_supplicant"
+                    continue
+                print "Handover select carrier record from wpa_supplicant:"
+                print data.encode("hex")
+                self.sent_carrier = data
+
+                message = nfc.ndef.Message(data);
+                sel.add_carrier(message[0], "active", message[1:])
+
+        print "Handover select:"
+        print sel.pretty()
+        print str(sel).encode("hex")
+
+        print "Sending handover select"
+        return sel
+
+
+def wps_handover_resp(peer, uuid):
+    if uuid is None:
+        print "Trying to handle WPS handover"
+    else:
+        print "Trying to handle WPS handover with AP " + uuid
+
+    srv = HandoverServer()
+    srv.sent_carrier = None
+    srv.uuid = uuid
+
+    nfc.llcp.activate(peer);
+
+    try:
+        print "Trying handover";
+        srv.start()
+        print "Wait for disconnect"
+        while nfc.llcp.connected():
+            time.sleep(0.1)
+        print "Disconnected after handover"
+    except nfc.llcp.ConnectRefused:
+        print "Handover connection refused"
+        nfc.llcp.shutdown()
+        return
+
+    if srv.sent_carrier:
+        wpas_report_handover(srv.received_carrier, srv.sent_carrier, "RESP")
+
+    print "Remove peer"
+    nfc.llcp.shutdown()
+    print "Done with handover"
+    time.sleep(1)
+
+
 def wps_handover_init(peer):
     print "Trying to initiate WPS handover"
 
@@ -147,7 +230,7 @@
         print "Remote carrier type: " + carrier.type
         if carrier.type == "application/vnd.wfa.wsc":
             print "WPS carrier type match - send to wpa_supplicant"
-            wpas_report_handover(data, carrier.record)
+            wpas_report_handover(data, carrier.record, "INIT")
             wifi = nfc.ndef.WifiConfigRecord(carrier.record)
             print wifi.pretty()
 
@@ -198,6 +281,28 @@
         time.sleep(0.1)
 
 
+def wps_write_er_config_tag(clf, uuid):
+    print "Write WPS ER config token"
+    data = wpas_get_er_config_token(uuid)
+    if (data == None):
+        print "Could not get WPS config token from wpa_supplicant"
+        return
+
+    print "Touch an NFC tag"
+    while True:
+        tag = clf.poll()
+        if tag == None:
+            time.sleep(0.1)
+            continue
+        break
+
+    print "Tag found - writing"
+    tag.ndef.message = data
+    print "Done - remove tag"
+    while tag.is_present:
+        time.sleep(0.1)
+
+
 def wps_write_password_tag(clf):
     print "Write WPS password token"
     data = wpas_get_password_token()
@@ -252,10 +357,18 @@
     clf = nfc.ContactlessFrontend()
 
     try:
+        arg_uuid = None
+        if len(sys.argv) > 1:
+            arg_uuid = sys.argv[1]
+
         if len(sys.argv) > 1 and sys.argv[1] == "write-config":
             wps_write_config_tag(clf)
             raise SystemExit
 
+        if len(sys.argv) > 2 and sys.argv[1] == "write-er-config":
+            wps_write_er_config_tag(clf, sys.argv[2])
+            raise SystemExit
+
         if len(sys.argv) > 1 and sys.argv[1] == "write-password":
             wps_write_password_tag(clf)
             raise SystemExit
@@ -265,7 +378,12 @@
 
             tag = find_peer(clf)
             if isinstance(tag, nfc.DEP):
-                wps_handover_init(tag)
+                if arg_uuid is None:
+                    wps_handover_init(tag)
+                elif arg_uuid is "ap":
+                    wps_handover_resp(tag, None)
+                else:
+                    wps_handover_resp(tag, arg_uuid)
                 continue
 
             if tag.ndef:
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index dfc3b76..7585b86 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -554,6 +554,7 @@
 	void *ctx, const u8 *peer, int add, u16 capability,
 	const u8 *supp_rates, size_t supp_rates_len,
 	const struct ieee80211_ht_capabilities *ht_capab,
+	const struct ieee80211_vht_capabilities *vht_capab,
 	u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len)
 {
 	struct wpa_supplicant *wpa_s = ctx;
@@ -574,6 +575,7 @@
 		params.flags |= WPA_STA_WMM;
 
 	params.ht_capabilities = ht_capab;
+	params.vht_capabilities = vht_capab;
 	params.qosinfo = qosinfo;
 	params.listen_interval = 0;
 	params.supp_rates = supp_rates;
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index c89479f..509a7c0 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -2003,12 +2003,48 @@
 }
 
 
-struct wpabuf * wpas_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s,
-					  int ndef, int cr)
+#ifdef CONFIG_WPS_NFC
+struct wpabuf * wpas_wps_er_nfc_handover_sel(struct wpa_supplicant *wpa_s,
+					     int ndef, const char *uuid)
 {
+	struct wpabuf *ret;
+	u8 u[UUID_LEN];
+
+	if (!wpa_s->wps_er)
+		return NULL;
+
+	if (uuid == NULL || uuid_str2bin(uuid, u))
+		return NULL;
+
+	/*
+	 * Handover Select carrier record for WPS uses the same format as
+	 * configuration token.
+	 */
+	ret = wps_er_nfc_config_token(wpa_s->wps_er, u);
+	if (ndef && ret) {
+		struct wpabuf *tmp;
+		tmp = ndef_build_wifi(ret);
+		wpabuf_free(ret);
+		if (tmp == NULL)
+			return NULL;
+		ret = tmp;
+	}
+
+	return ret;
+}
+#endif /* CONFIG_WPS_NFC */
+
+
+struct wpabuf * wpas_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s,
+					  int ndef, int cr, const char *uuid)
+{
+	struct wpabuf *ret;
 	if (!cr)
 		return NULL;
-	return wpas_ap_wps_nfc_handover_sel(wpa_s, ndef);
+	ret = wpas_ap_wps_nfc_handover_sel(wpa_s, ndef);
+	if (ret)
+		return ret;
+	return wpas_wps_er_nfc_handover_sel(wpa_s, ndef, uuid);
 }
 
 
diff --git a/wpa_supplicant/wps_supplicant.h b/wpa_supplicant/wps_supplicant.h
index 5bc5ffa..8bb9546 100644
--- a/wpa_supplicant/wps_supplicant.h
+++ b/wpa_supplicant/wps_supplicant.h
@@ -70,7 +70,7 @@
 			  const struct wpabuf *data);
 struct wpabuf * wpas_wps_nfc_handover_req(struct wpa_supplicant *wpa_s, int cr);
 struct wpabuf * wpas_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s,
-					  int ndef, int cr);
+					  int ndef, int cr, const char *uuid);
 int wpas_wps_nfc_rx_handover_req(struct wpa_supplicant *wpa_s,
 				 const struct wpabuf *data);
 int wpas_wps_nfc_rx_handover_sel(struct wpa_supplicant *wpa_s,