[WCNCR00165271] misc: Support Android AOSP priv command

[Description]
Add priv command parsing format for wpa_supplicant w/o priv lib


Change-Id: Icc1d41f59059e50fce1cbe5451e1bb9967c393fa
Signed-off-by: Allan Wang <Allan.Wang@mediatek.com>
CR-Id: WCNCR00165271
Feature: misc
(cherry picked from commit cd0fbbe3f1ecbf8474d0401f58e278970d91d35c)
diff --git a/Makefile.ce b/Makefile.ce
index 5738d2e..c301ebb 100644
--- a/Makefile.ce
+++ b/Makefile.ce
@@ -136,6 +136,10 @@
 # Define to enable Android wake_lock
 CFG_ENABLE_WAKE_LOCK=0
 
+# For wpa_supplicant w/o MTK priv lib
+# y: enable, n: disable
+CFG_ANDROID_AOSP_PRIV_CMD=n
+
 CFG_DEFAULT_DBG_LEVEL=0xF
 
 CFG_TX_DIRECT_USB=1
@@ -229,6 +233,10 @@
 PLATFORM_FLAGS += -DCFG_DRIVER_INF_NAME_CHANGE
 endif
 
+ifeq ($(CFG_ANDROID_AOSP_PRIV_CMD), y)
+PLATFORM_FLAGS += -DCFG_ANDROID_AOSP_PRIV_CMD
+endif
+
 ifneq ($(CFG_SUPPORT_SINGLE_SKU_LOCAL_DB),)
 PLATFORM_FLAGS += -DCFG_SUPPORT_SINGLE_SKU_LOCAL_DB=$(CFG_SUPPORT_SINGLE_SKU_LOCAL_DB)
 endif
diff --git a/Makefile.x86 b/Makefile.x86
index ad95c45..d279330 100644
--- a/Makefile.x86
+++ b/Makefile.x86
@@ -54,6 +54,10 @@
 # Define to enable Android wake_lock
 #CFG_ENABLE_WAKE_LOCK=0
 
+# For wpa_supplicant w/o MTK priv lib
+# y: enable, n: disable
+CFG_ANDROID_AOSP_PRIV_CMD=n
+
 #CFG_DEFAULT_DBG_LEVEL=0xF
 
 CFG_TX_DIRECT_USB=1
@@ -154,6 +158,10 @@
 PLATFORM_FLAGS += -DCFG_CHIP_RESET_SUPPORT=$(CFG_CHIP_RESET_SUPPORT)
 endif
 
+ifeq ($(CFG_ANDROID_AOSP_PRIV_CMD), y)
+PLATFORM_FLAGS += -DCFG_ANDROID_AOSP_PRIV_CMD
+endif
+
 all: driver
 
 driver:
diff --git a/os/linux/gl_init.c b/os/linux/gl_init.c
index 3ef9884..8ebd1b2 100644
--- a/os/linux/gl_init.c
+++ b/os/linux/gl_init.c
@@ -785,7 +785,11 @@
 		/* 0x8BE0 ~ 0x8BFF, private ioctl region */
 		ret = priv_support_ioctl(prDev, prIfReq, i4Cmd);
 	} else if (i4Cmd == SIOCDEVPRIVATE + 1) {
+#ifdef CFG_ANDROID_AOSP_PRIV_CMD
+		ret = android_private_support_driver_cmd(prDev, prIfReq, i4Cmd);
+#else
 		ret = priv_support_driver_cmd(prDev, prIfReq, i4Cmd);
+#endif /* CFG_ANDROID_AOSP_PRIV_CMD */
 	} else {
 		DBGLOG(INIT, WARN, "Unexpected ioctl command: 0x%04x\n", i4Cmd);
 		ret = -EOPNOTSUPP;
diff --git a/os/linux/gl_p2p.c b/os/linux/gl_p2p.c
index c021b55..c3e6f23 100644
--- a/os/linux/gl_p2p.c
+++ b/os/linux/gl_p2p.c
@@ -1645,6 +1645,10 @@
 		ret = priv_support_driver_cmd(prDev, prIfReq, i4Cmd);
 	else if (i4Cmd == SIOCGIWPRIV)
 		ret = mtk_p2p_wext_get_priv(prDev, &rIwReqInfo, &(prIwReq->u), NULL);
+#ifdef CFG_ANDROID_AOSP_PRIV_CMD
+	else if (i4Cmd == SIOCDEVPRIVATE + 1)
+		ret = android_private_support_driver_cmd(prDev, prIfReq, i4Cmd);
+#endif
 	else {
 		DBGLOG(INIT, WARN, "Unexpected ioctl command: 0x%04x\n", i4Cmd);
 		ret = -1;
diff --git a/os/linux/gl_wext_priv.c b/os/linux/gl_wext_priv.c
index d9a7080..10d9c8f 100644
--- a/os/linux/gl_wext_priv.c
+++ b/os/linux/gl_wext_priv.c
@@ -2398,6 +2398,13 @@
 	int total_len;
 } priv_driver_cmd_t;
 
+#ifdef CFG_ANDROID_AOSP_PRIV_CMD
+struct android_wifi_priv_cmd {
+	char *buf;
+	int used_len;
+	int total_len;
+};
+#endif /* CFG_ANDROID_AOSP_PRIV_CMD */
 
 int priv_driver_get_dbg_level(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen)
 {
@@ -10036,7 +10043,13 @@
 	i4BytesWritten = (INT_32)u4Offset;
 
 	return i4BytesWritten;
+}
 
+static int priv_cmd_not_support(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen)
+{
+	DBGLOG(REQ, WARN, "not support priv command: %s\n", pcCommand);
+
+	return -EOPNOTSUPP;
 }
 
 static int priv_driver_set_maxrfgain(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen)
@@ -10447,7 +10460,6 @@
 {
 	P_GLUE_INFO_T prGlueInfo = NULL;
 	INT_32 i4BytesWritten = 0;
-	INT_32 i4CmdFound = 0;
 
 	if (g_u4HaltFlag) {
 		DBGLOG(REQ, WARN, "wlan is halt, skip priv_driver_cmds\n");
@@ -10458,8 +10470,6 @@
 		return -1;
 	prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
 
-	if (i4CmdFound == 0) {
-		i4CmdFound = 1;
 		if (strnicmp(pcCommand, CMD_RSSI, strlen(CMD_RSSI)) == 0) {
 			/* i4BytesWritten =
 			 *  wl_android_get_rssi(net, command, i4TotalLen);
@@ -10725,11 +10735,7 @@
 			i4BytesWritten = priv_driver_noise_histogram(prNetDev, pcCommand, i4TotalLen);
 #endif
 		else
-			i4CmdFound = 0;
-	}
-	/* i4CmdFound */
-	if (i4CmdFound == 0)
-		DBGLOG(REQ, INFO, "Unknown driver command %s - ignored\n", pcCommand);
+		i4BytesWritten = priv_cmd_not_support(prNetDev, pcCommand, i4TotalLen);
 
 	if (i4BytesWritten >= 0) {
 		if ((i4BytesWritten == 0) && (i4TotalLen > 0)) {
@@ -10835,3 +10841,54 @@
 
 	return ret;
 }				/* priv_support_driver_cmd */
+
+#ifdef CFG_ANDROID_AOSP_PRIV_CMD
+int android_private_support_driver_cmd(IN struct net_device *prNetDev,
+									IN OUT struct ifreq *prReq, IN int i4Cmd)
+{
+	struct android_wifi_priv_cmd priv_cmd;
+	char *command = NULL;
+	int ret = 0, bytes_written = 0;
+
+	if (!prReq->ifr_data)
+		return -EINVAL;
+
+	if (copy_from_user(&priv_cmd, prReq->ifr_data, sizeof(priv_cmd)))
+		return -EFAULT;
+
+	command = kzalloc(priv_cmd.total_len, GFP_KERNEL);
+	if (!command) {
+		DBGLOG(REQ, WARN, "%s, alloc mem failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) {
+		ret = -EFAULT;
+		goto FREE;
+	}
+
+	bytes_written = priv_driver_cmds(prNetDev, command, priv_cmd.total_len);
+
+	if (bytes_written >= 0) {
+		/* priv_cmd in but no response */
+		if ((bytes_written == 0) && (priv_cmd.total_len > 0))
+			command[0] = '\0';
+
+		if (bytes_written >= priv_cmd.total_len)
+			bytes_written = priv_cmd.total_len;
+		else
+			bytes_written++;
+
+		priv_cmd.used_len = bytes_written;
+
+		if (copy_to_user(priv_cmd.buf, command, bytes_written))
+			ret = -EFAULT;
+	} else
+		ret = bytes_written;
+
+FREE:
+		kfree(command);
+
+	return ret;
+}
+#endif /* CFG_ANDROID_AOSP_PRIV_CMD */
diff --git a/os/linux/include/gl_wext_priv.h b/os/linux/include/gl_wext_priv.h
index 7f305f7..9243a0f 100644
--- a/os/linux/include/gl_wext_priv.h
+++ b/os/linux/include/gl_wext_priv.h
@@ -318,6 +318,10 @@
 
 int priv_support_driver_cmd(IN struct net_device *prDev, IN OUT struct ifreq *prReq, IN int i4Cmd);
 
+#ifdef CFG_ANDROID_AOSP_PRIV_CMD
+int android_private_support_driver_cmd(IN struct net_device *prDev, IN OUT struct ifreq *prReq, IN int i4Cmd);
+#endif /* CFG_ANDROID_AOSP_PRIV_CMD */
+
 INT_32 priv_driver_cmds(IN struct net_device *prNetDev, IN PCHAR pcCommand, IN INT_32 i4TotalLen);
 
 int priv_driver_set_cfg(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen);