DPP: QR Code display/scanner on Linux laptop

Use qr and zbarcam tools to handle ManualDPP case on a Linux laptop.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
diff --git a/dpp.c b/dpp.c
index 59e9027..109ae0e 100644
--- a/dpp.c
+++ b/dpp.c
@@ -6,10 +6,13 @@
  */
 
 #include "sigma_dut.h"
+#include <sys/wait.h>
 #include "wpa_ctrl.h"
 #include "wpa_helpers.h"
 
+#ifdef ANDROID
 char *dpp_qrcode_file = "/sdcard/wpadebug_qrdata.txt";
+#endif /* ANDROID */
 
 
 static int sigma_dut_is_ap(struct sigma_dut *dut)
@@ -530,6 +533,7 @@
 
 static int dpp_scan_peer_qrcode(struct sigma_dut *dut)
 {
+#ifdef ANDROID
 	char buf[100];
 	char *buf2 = NULL;
 	FILE *fp = NULL;
@@ -584,6 +588,81 @@
 	dut->dpp_peer_uri = strdup(buf2);
 	free(buf2);
 	return 0;
+#else /* ANDROID */
+	pid_t pid;
+	int pid_status;
+	int pipe_out[2];
+	char buf[4000], *pos;
+	ssize_t len;
+	int res = -1, ret;
+	struct timeval tv;
+	fd_set rfd;
+
+	if (pipe(pipe_out) != 0) {
+		perror("pipe");
+		return -1;
+	}
+
+	pid = fork();
+	if (pid < 0) {
+		perror("fork");
+		close(pipe_out[0]);
+		close(pipe_out[1]);
+		return -1;
+	}
+
+	if (pid == 0) {
+		char *argv[4] = { "zbarcam", "--raw", "--prescale=320x240",
+				  NULL };
+
+		dup2(pipe_out[1], STDOUT_FILENO);
+		close(pipe_out[0]);
+		close(pipe_out[1]);
+		execv("/usr/bin/zbarcam", argv);
+		perror("execv");
+		exit(0);
+		return -1;
+	}
+
+	close(pipe_out[1]);
+
+	FD_ZERO(&rfd);
+	FD_SET(pipe_out[0], &rfd);
+	tv.tv_sec = dut->default_timeout;
+	tv.tv_usec = 0;
+
+	ret = select(pipe_out[0] + 1, &rfd, NULL, NULL, &tv);
+	if (ret < 0) {
+		perror("select");
+		goto out;
+	}
+	if (ret == 0) {
+		sigma_dut_print(dut, DUT_MSG_DEBUG,
+				"QR Code scanning timed out");
+		goto out;
+	}
+
+	len = read(pipe_out[0], buf, sizeof(buf));
+	if (len <= 0)
+		goto out;
+	if (len == sizeof(buf))
+		len--;
+	buf[len] = '\0';
+	pos = strchr(buf, '\n');
+	if (pos)
+		*pos = '\0';
+	sigma_dut_print(dut, DUT_MSG_DEBUG, "URI from QR scanner: %s", buf);
+
+	free(dut->dpp_peer_uri);
+	dut->dpp_peer_uri = strdup(buf);
+	res = 0;
+out:
+	close(pipe_out[0]);
+	kill(pid, SIGTERM);
+	waitpid(pid, &pid_status, 0);
+
+	return res;
+#endif /* ANDROID */
 }
 
 
@@ -591,14 +670,21 @@
 {
 	char buf[200], resp[2000];
 	const char *ifname = get_station_ifname();
+#ifdef ANDROID
 	FILE *fp;
+#else /* ANDROID */
+	pid_t pid;
+	int pid_status;
+#endif /* ANDROID */
 
 	snprintf(buf, sizeof(buf), "DPP_BOOTSTRAP_GET_URI %d",
 		 dut->dpp_local_bootstrap);
 	if (wpa_command_resp(ifname, buf, resp, sizeof(resp)) < 0 ||
 	    strncmp(resp, "FAIL", 4) == 0)
 		return -2;
+	sigma_dut_print(dut, DUT_MSG_DEBUG, "Own bootstrap URI: %s", resp);
 
+#ifdef ANDROID
 	unlink(dpp_qrcode_file);
 
 	fp = fopen(dpp_qrcode_file, "w");
@@ -608,7 +694,6 @@
 		return -2;
 	}
 
-	sigma_dut_print(dut, DUT_MSG_DEBUG, "Own bootstrap URI: %s", resp);
 	fwrite(resp, 1, strlen(resp), fp);
 	fclose(fp);
 
@@ -618,6 +703,24 @@
 		sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to display QR Code");
 		return -1;
 	}
+#else /* ANDROID */
+	pid = fork();
+	if (pid < 0) {
+		perror("fork");
+		return -1;
+	}
+
+	if (pid == 0) {
+		char *argv[3] = { "qr", resp, NULL };
+
+		execv("/usr/bin/qr", argv);
+		perror("execv");
+		exit(0);
+		return -1;
+	}
+
+	waitpid(pid, &pid_status, 0);
+#endif /* ANDROID */
 
 	return 0;
 }
@@ -1495,8 +1598,12 @@
 
 	if (strcasecmp(auth_role, "Initiator") == 0) {
 		res = dpp_scan_peer_qrcode(dut);
-		if (res < 0)
+		if (res < 0) {
+			send_resp(dut, conn, SIGMA_ERROR,
+				  "errorCode,Failed to scan peer QR Code");
+			res = 0;
 			goto out;
+		}
 
 		res = dpp_automatic_dpp(dut, conn, cmd);
 		goto out;