Implement dev_ble_action

dev_ble_action aims to interface sigma_dut with the BLE stack. This
commit implements this interface by having sigma_dut interact with a BLE
application. Also, this commit aims to enable NAN service discovery on
top of a successful BLE scan. Currently, this is implemented only for
Android platforms by having the NAN + BLE activity registered with
org.codeaurora.nanservicediscovery.MainActivity. sigma_dut invokes this
activity with the respective parameters.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
diff --git a/dev.c b/dev.c
index 5fe57db..2c8bfc9 100644
--- a/dev.c
+++ b/dev.c
@@ -8,6 +8,9 @@
 
 #include "sigma_dut.h"
 #include "miracast.h"
+#include <sys/wait.h>
+#include "wpa_ctrl.h"
+#include "wpa_helpers.h"
 
 
 static int cmd_dev_send_frame(struct sigma_dut *dut, struct sigma_conn *conn,
@@ -104,6 +107,97 @@
 }
 
 
+static int cmd_dev_ble_action(struct sigma_dut *dut, struct sigma_conn *conn,
+			      struct sigma_cmd *cmd)
+{
+#ifdef ANDROID
+	char buf[200];
+	const char *ble_op = get_param(cmd, "BLEOp");
+	const char *prog = get_param(cmd, "Prog");
+	const char *service_name = get_param(cmd, "ServiceName");
+	const char *ble_role = get_param(cmd, "BLERole");
+	const char *discovery_type = get_param(cmd, "DiscoveryType");
+	const char *msg_type = get_param(cmd, "messagetype");
+	const char *action = get_param(cmd, "action");
+	const char *M2Transmit = get_param(cmd, "M2Transmit");
+	char *argv[17];
+	pid_t pid;
+
+	if (prog && ble_role && action && msg_type) {
+		send_resp(dut, conn, SIGMA_COMPLETE,
+			  "OrgID,0x00,TransDataHeader,0x00,BloomFilterElement,NULL");
+		return 0;
+	}
+	if (!ble_op || !prog || !service_name || !ble_role || !discovery_type) {
+		sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid arguments");
+		return -1;
+	}
+
+	if ((strcasecmp(prog, "NAN") != 0)) {
+		sigma_dut_print(dut, DUT_MSG_ERROR, "Program %s not supported",
+				prog);
+		return -1;
+	}
+
+	if (strcasecmp(ble_role, "seeker") != 0 &&
+	    strcasecmp(ble_role, "provider") != 0 &&
+	    strcasecmp(ble_role, "browser") != 0) {
+		sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid BLERole: %s",
+				ble_role);
+		return -1;
+	}
+
+	if (strcasecmp(discovery_type, "active") != 0 &&
+	    strcasecmp(discovery_type, "passive") != 0) {
+		sigma_dut_print(dut, DUT_MSG_ERROR, "Invalid DiscoveryType: %s",
+				discovery_type);
+		return -1;
+	}
+
+	if (!M2Transmit)
+		M2Transmit = "disable";
+
+	argv[0] = "am";
+	argv[1] = "start";
+	argv[2] = "-n";
+	argv[3] = "org.codeaurora.nanservicediscovery/org.codeaurora.nanservicediscovery.MainActivity";
+	argv[4] = "--es";
+	argv[5] = "service";
+	argv[6] = (char *) service_name;
+	argv[7] = "--es";
+	argv[8] = "role";
+	argv[9] = (char *) ble_role;
+	argv[10] = "--es";
+	argv[11] = "scantype";
+	argv[12] = (char *) discovery_type;
+	argv[13] = "--es";
+	argv[14] = "M2Transmit";
+	argv[15] = (char *) M2Transmit;
+	argv[16] = NULL;
+
+	pid = fork();
+	if (pid == -1) {
+		sigma_dut_print(dut, DUT_MSG_ERROR, "fork: %s",
+				strerror(errno));
+		return -1;
+	}
+
+	if (pid == 0) {
+		execv("/system/bin/am", argv);
+		sigma_dut_print(dut, DUT_MSG_ERROR, "execv: %s",
+				strerror(errno));
+		exit(0);
+		return -1;
+	}
+
+	dut->nanservicediscoveryinprogress = 1;
+#endif /* ANDROID */
+
+	return 1;
+}
+
+
+
 static int cmd_dev_start_test(struct sigma_dut *dut, struct sigma_conn *conn,
 			      struct sigma_cmd *cmd)
 {
@@ -131,6 +225,16 @@
 }
 
 
+static int req_role_svcname(struct sigma_cmd *cmd)
+{
+	if (!get_param(cmd, "BLERole"))
+		 return -1;
+	if (get_param(cmd, "BLEOp") && !get_param(cmd, "ServiceName"))
+		return -1;
+	return 0;
+}
+
+
 static int req_intf_prog(struct sigma_cmd *cmd)
 {
 	if (get_param(cmd, "interface") == NULL)
@@ -160,4 +264,6 @@
 	sigma_dut_reg_cmd("dev_start_test", NULL, cmd_dev_start_test);
 	sigma_dut_reg_cmd("dev_stop_test", NULL, cmd_dev_stop_test);
 	sigma_dut_reg_cmd("dev_get_log", NULL, cmd_dev_get_log);
+	sigma_dut_reg_cmd("dev_ble_action", req_role_svcname,
+			  cmd_dev_ble_action);
 }
diff --git a/nan.c b/nan.c
index 4a7d0b9..18f23c6 100644
--- a/nan.c
+++ b/nan.c
@@ -1889,6 +1889,31 @@
 {
 	sigma_dut_print(dut, DUT_MSG_INFO, "NAN sta_reset_default");
 
+#ifdef ANDROID
+	if (dut->nanservicediscoveryinprogress) {
+		char *argv[5];
+		pid_t pid;
+
+		argv[0] = "am";
+		argv[1] = "broadcast";
+		argv[2] = "-a";
+		argv[3] = "org.codeaurora.nanservicediscovery.close";
+		argv[4] = NULL;
+
+		pid = fork();
+		if (pid == -1) {
+			sigma_dut_print(dut, DUT_MSG_ERROR, "fork: %s",
+					strerror(errno));
+		} else if (pid == 0) {
+			execv("/system/bin/am", argv);
+			sigma_dut_print(dut, DUT_MSG_ERROR, "execv: %s",
+					strerror(errno));
+			exit(0);
+		}
+		dut->nanservicediscoveryinprogress = 0;
+	}
+#endif /* ANDROID */
+
 	if (nan_state == 0) {
 		nan_init(dut);
 		nan_state = 1;
@@ -1922,6 +1947,7 @@
 	const char *nan_op = get_param(cmd, "NANOp");
 	const char *method_type = get_param(cmd, "MethodType");
 	const char *band = get_param(cmd, "band");
+	const char *disc_mac_addr = get_param(cmd, "DiscoveryMacAddress");
 	char resp_buf[100];
 	wifi_error ret;
 
@@ -2055,6 +2081,12 @@
 				sigma_nan_schedule_update(dut, cmd);
 				send_resp(dut, conn, SIGMA_COMPLETE, "NULL");
 			}
+		} else if (disc_mac_addr &&
+			   strcasecmp(disc_mac_addr, "GET") == 0) {
+			snprintf(resp_buf, sizeof(resp_buf), "mac,"
+				 MAC_ADDR_STR,
+				 MAC_ADDR_ARRAY(global_nan_mac_addr));
+			send_resp(dut, conn, SIGMA_COMPLETE, resp_buf);
 		} else {
 			sigma_nan_config_enable(dut, conn, cmd);
 			snprintf(resp_buf, sizeof(resp_buf), "mac,"
diff --git a/sigma_dut.h b/sigma_dut.h
index 07b385d..8537725 100644
--- a/sigma_dut.h
+++ b/sigma_dut.h
@@ -744,6 +744,10 @@
 #endif /* NL80211_SUPPORT */
 
 	int sta_nss;
+
+#ifdef ANDROID
+	int nanservicediscoveryinprogress;
+#endif /* ANDROID */
 };