/* SPDX-License-Identifier: GPL-2.0 */
/******************************************************************************
 *
 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
 *
 *
 ******************************************************************************/

#include <drv_types.h>
#include <rtw_mp.h>
#include <rtw_mp_ioctl.h>
#include "../../hal/phydm/phydm_precomp.h"

/*
 * Input Format: %s,%d,%d
 *	%s is width, could be
 *		"b" for 1 byte
 *		"w" for WORD (2 bytes)
 *		"dw" for DWORD (4 bytes)
 *	1st %d is address(offset)
 *	2st %d is data to write
 */
int rtw_mp_write_reg(struct net_device *dev,
		     struct iw_request_info *info,
		     struct iw_point *wrqu, char *extra)
{
	char *pch, *pnext;
	char *width_str;
	char width;
	u32 addr, data;
	int ret;
	PADAPTER padapter = rtw_netdev_priv(dev);
	char *input;
	int rc = 0;

	input = kmalloc(sizeof(char) * wrqu->length, GFP_KERNEL);
	if (!input)
		return -ENOMEM;

	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
		rc = -EFAULT;
		goto out;
	}

	_rtw_memset(extra, 0, wrqu->length);

	pch = input;

	pnext = strpbrk(pch, " ,.-");
	if (pnext == NULL) {
		rc = -EINVAL;
		goto out;
	}
	*pnext = 0;
	width_str = pch;

	pch = pnext + 1;
	pnext = strpbrk(pch, " ,.-");
	if (pnext == NULL) {
		rc = -EINVAL;
		goto out;
	}
	*pnext = 0;
	/*addr = simple_strtoul(pch, &ptmp, 16);
	_rtw_memset(buf, '\0', sizeof(buf));
	_rtw_memcpy(buf, pch, pnext-pch);
	ret = kstrtoul(buf, 16, &addr);*/
	ret = sscanf(pch, "%x", &addr);
	if (addr > 0x3FFF) {
		rc = -EINVAL;
		goto out;
	}

	pch = pnext + 1;
	pnext = strpbrk(pch, " ,.-");
	if ((pch - input) >= wrqu->length) {
		rc = -EINVAL;
		goto out;
	}
	/*data = simple_strtoul(pch, &ptmp, 16);*/
	ret = sscanf(pch, "%x", &data);
	RTW_INFO("data=%x,addr=%x\n", (u32)data, (u32)addr);
	ret = 0;
	width = width_str[0];
	switch (width) {
	case 'b':
		/* 1 byte*/
		if (data > 0xFF) {
			rc = -EINVAL;
			break;
		}
		rtw_write8(padapter, addr, data);
		break;
	case 'w':
		/* 2 bytes*/
		if (data > 0xFFFF) {
			rc = -EINVAL;
			break;
		}
		rtw_write16(padapter, addr, data);
		break;
	case 'd':
		/* 4 bytes*/
		rtw_write32(padapter, addr, data);
		break;
	default:
		rc = -EINVAL;
		break;
	}

out:
	kfree(input);

	return rc;
}

/*
 * Input Format: %s,%d
 *	%s is width, could be
 *		"b" for 1 byte
 *		"w" for WORD (2 bytes)
 *		"dw" for DWORD (4 bytes)
 *	%d is address(offset)
 *
 * Return:
 *	%d for data readed
 */
int rtw_mp_read_reg(struct net_device *dev,
		    struct iw_request_info *info,
		    struct iw_point *wrqu, char *extra)
{
	char *input;
	char *pch, *pnext;
	char *width_str;
	char width;
	char data[20], tmp[20];
	u32 addr = 0, strtout = 0;
	u32 i = 0, j = 0, ret = 0, data32 = 0;
	PADAPTER padapter = rtw_netdev_priv(dev);
	int rc = 0;

	if (wrqu->length > 128)
		return -EFAULT;

	input = kmalloc(sizeof(char) * wrqu->length, GFP_KERNEL);
	if (!input)
		return -ENOMEM;

	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
		rc = -EFAULT;
		goto out;
	}

	_rtw_memset(extra, 0, wrqu->length);
	_rtw_memset(data, '\0', sizeof(data));
	_rtw_memset(tmp, '\0', sizeof(tmp));
	pch = input;
	pnext = strpbrk(pch, " ,.-");
	if (pnext == NULL) {
		rc = -EINVAL;
		goto out;
	}
	*pnext = 0;
	width_str = pch;

	pch = pnext + 1;

	ret = sscanf(pch, "%x", &addr);
	if (addr > 0x3FFF) {
		rc = -EINVAL;
		goto out;
	}

	ret = 0;
	width = width_str[0];

	switch (width) {
	case 'b':
		data32 = rtw_read8(padapter, addr);
		RTW_INFO("%x\n", data32);
		sprintf(extra, "%d", data32);
		wrqu->length = strlen(extra);
		break;
	case 'w':
		/* 2 bytes*/
		sprintf(data, "%04x\n", rtw_read16(padapter, addr));

		for (i = 0 ; i <= strlen(data) ; i++) {
			if (i % 2 == 0) {
				tmp[j] = ' ';
				j++;
			}
			if (data[i] != '\0')
				tmp[j] = data[i];

			j++;
		}
		pch = tmp;
		RTW_INFO("pch=%s", pch);

		while (*pch != '\0') {
			pnext = strpbrk(pch, " ");
			if (!pnext || ((pnext - tmp) > 4))
				break;

			pnext++;
			if (*pnext != '\0') {
				/*strtout = simple_strtoul(pnext , &ptmp, 16);*/
				ret = sscanf(pnext, "%x", &strtout);
				sprintf(extra, "%s %d" , extra , strtout);
			} else
				break;
			pch = pnext;
		}
		wrqu->length = strlen(extra);
		break;
	case 'd':
		/* 4 bytes */
		sprintf(data, "%08x", rtw_read32(padapter, addr));
		/*add read data format blank*/
		for (i = 0 ; i <= strlen(data) ; i++) {
			if (i % 2 == 0) {
				tmp[j] = ' ';
				j++;
			}
			if (data[i] != '\0')
				tmp[j] = data[i];

			j++;
		}
		pch = tmp;
		RTW_INFO("pch=%s", pch);

		while (*pch != '\0') {
			pnext = strpbrk(pch, " ");
			if (!pnext)
				break;

			pnext++;
			if (*pnext != '\0') {
				ret = sscanf(pnext, "%x", &strtout);
				sprintf(extra, "%s %d" , extra , strtout);
			} else
				break;
			pch = pnext;
		}
		wrqu->length = strlen(extra);
		break;

	default:
		wrqu->length = 0;
		rc = -EINVAL;
		break;
	}

out:
	kfree(input);

	return ret;
}

/*
 * Input Format: %d,%x,%x
 *	%d is RF path, should be smaller than MAX_RF_PATH_NUMS
 *	1st %x is address(offset)
 *	2st %x is data to write
 */
int rtw_mp_write_rf(struct net_device *dev,
		    struct iw_request_info *info,
		    struct iw_point *wrqu, char *extra)
{

	u32 path, addr, data;
	int ret = 0;
	PADAPTER padapter = rtw_netdev_priv(dev);
	char *input;
	int rc = 0;

	input = kmalloc(sizeof(char) * wrqu->length, GFP_KERNEL);
	if (!input)
		return -ENOMEM;

	_rtw_memset(input, 0, wrqu->length);
	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
		rc = -EFAULT;
		goto out;
	}

	ret = sscanf(input, "%d,%x,%x", &path, &addr, &data);
	if (ret < 3) {
		rc = -EINVAL;
		goto out;
	}

	if (path >= GET_HAL_RFPATH_NUM(padapter)) {
		rc = -EINVAL;
		goto out;
	}
	if (addr > 0xFF) {
		rc = -EINVAL;
		goto out;
	}
	if (data > 0xFFFFF) {
		rc = -EINVAL;
		goto out;
	}

	_rtw_memset(extra, 0, wrqu->length);

	write_rfreg(padapter, path, addr, data);

	sprintf(extra, "write_rf completed\n");
	wrqu->length = strlen(extra);

out:
	kfree(input);

	return rc;
}

/*
 * Input Format: %d,%x
 *	%d is RF path, should be smaller than MAX_RF_PATH_NUMS
 *	%x is address(offset)
 *
 * Return:
 *	%d for data readed
 */
int rtw_mp_read_rf(struct net_device *dev,
		   struct iw_request_info *info,
		   struct iw_point *wrqu, char *extra)
{
	char *input;
	char *pch, *pnext;
	char data[20], tmp[20];
	u32 path, addr, strtou;
	u32 ret = 0, i = 0, j = 0;
	PADAPTER padapter = rtw_netdev_priv(dev);
	int rc = 0;

	if (wrqu->length > 128)
		return -EFAULT;

	input = kmalloc(sizeof(char) * wrqu->length, GFP_KERNEL);
	if (!input)
		return -ENOMEM;

	_rtw_memset(input, 0, wrqu->length);
	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
		rc = -EFAULT;
		goto out;
	}

	ret = sscanf(input, "%d,%x", &path, &addr);
	if (ret < 2) {
		rc = -EINVAL;
		goto out;
	}

	if (path >= GET_HAL_RFPATH_NUM(padapter)) {
		rc = -EINVAL;
		goto out;
	}
	if (addr > 0xFF) {
		rc = -EINVAL;
		goto out;
	}

	_rtw_memset(extra, 0, wrqu->length);

	sprintf(data, "%08x", read_rfreg(padapter, path, addr));
	/*add read data format blank*/
	for (i = 0 ; i <= strlen(data) ; i++) {
		if (i % 2 == 0) {
			tmp[j] = ' ';
			j++;
		}
		tmp[j] = data[i];
		j++;
	}
	pch = tmp;
	RTW_INFO("pch=%s", pch);

	while (*pch != '\0') {
		pnext = strpbrk(pch, " ");
		if (!pnext)
			break;
		pnext++;
		if (*pnext != '\0') {
			/*strtou =simple_strtoul(pnext , &ptmp, 16);*/
			ret = sscanf(pnext, "%x", &strtou);
			sprintf(extra, "%s %d" , extra , strtou);
		} else
			break;
		pch = pnext;
	}
	wrqu->length = strlen(extra);

out:
	kfree(input);

	return rc;
}

int rtw_mp_start(struct net_device *dev,
		 struct iw_request_info *info,
		 struct iw_point *wrqu, char *extra)
{
	int ret = 0;
	PADAPTER padapter = rtw_netdev_priv(dev);

	rtw_pm_set_ips(padapter, IPS_NONE);
	LeaveAllPowerSaveMode(padapter);

	if (rtw_mi_check_fwstate(padapter, _FW_UNDER_SURVEY))
		rtw_mi_scan_abort(padapter, _FALSE);

	if (rtw_mp_cmd(padapter, MP_START, RTW_CMDF_WAIT_ACK) != _SUCCESS)
		ret = -EPERM;

	_rtw_memset(extra, 0, wrqu->length);
	sprintf(extra, "mp_start %s\n", ret == 0 ? "ok" : "fail");
	wrqu->length = strlen(extra);

	return ret;
}

int rtw_mp_stop(struct net_device *dev,
		struct iw_request_info *info,
		struct iw_point *wrqu, char *extra)
{
	int ret = 0;
	PADAPTER padapter = rtw_netdev_priv(dev);

	if (rtw_mp_cmd(padapter, MP_STOP, RTW_CMDF_WAIT_ACK) != _SUCCESS)
		ret = -EPERM;

	_rtw_memset(extra, 0, wrqu->length);
	sprintf(extra, "mp_stop %s\n", ret == 0 ? "ok" : "fail");
	wrqu->length = strlen(extra);

	return ret;
}

int rtw_mp_rate(struct net_device *dev,
		struct iw_request_info *info,
		struct iw_point *wrqu, char *extra)
{
	u32 rate = MPT_RATE_1M;
	char *input;
	PADAPTER padapter = rtw_netdev_priv(dev);
	PMPT_CONTEXT		pMptCtx = &(padapter->mppriv.mpt_ctx);
	int rc = 0;

	input = kmalloc(sizeof(char) * wrqu->length, GFP_KERNEL);
	if (!input)
		return -ENOMEM;

	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
		rc = -EFAULT;
		goto out;
	}

	rate = rtw_mpRateParseFunc(padapter, input);
	padapter->mppriv.rateidx = rate;

	if (rate == 0 && strcmp(input, "1M") != 0) {
		rate = rtw_atoi(input);
		padapter->mppriv.rateidx = MRateToHwRate(rate);
		/*if (rate <= 0x7f)
			rate = wifirate2_ratetbl_inx((u8)rate);
		else if (rate < 0xC8)
			rate = (rate - 0x79 + MPT_RATE_MCS0);
		HT  rate 0x80(MCS0)  ~ 0x8F(MCS15) ~ 0x9F(MCS31) 128~159
		VHT1SS~2SS rate 0xA0 (VHT1SS_MCS0 44) ~ 0xB3 (VHT2SS_MCS9 #63) 160~179
		VHT rate 0xB4 (VHT3SS_MCS0 64) ~ 0xC7 (VHT2SS_MCS9 #83) 180~199
		else
		VHT rate 0x90(VHT1SS_MCS0) ~ 0x99(VHT1SS_MCS9) 144~153
		rate =(rate - MPT_RATE_VHT1SS_MCS0);
		*/
	}
	_rtw_memset(extra, 0, wrqu->length);

	sprintf(extra, "Set data rate to %s index %d" , input, padapter->mppriv.rateidx);
	RTW_INFO("%s: %s rate index=%d\n", __func__, input, padapter->mppriv.rateidx);

	if (padapter->mppriv.rateidx >= DESC_RATEVHTSS4MCS9) {
		rc = -EINVAL;
		goto out;
	}

	pMptCtx->mpt_rate_index = HwRateToMPTRate(padapter->mppriv.rateidx);
	SetDataRate(padapter);

	wrqu->length = strlen(extra);
out:
	kfree(input);

	return rc;
}

int rtw_mp_channel(struct net_device *dev,
		   struct iw_request_info *info,
		   struct iw_point *wrqu, char *extra)
{

	PADAPTER padapter = rtw_netdev_priv(dev);
	HAL_DATA_TYPE	*pHalData	= GET_HAL_DATA(padapter);
	char *input;
	u32	channel = 1;
	int rc = 0;

	input = kmalloc(sizeof(char) * wrqu->length, GFP_KERNEL);
	if (!input)
		return -ENOMEM;

	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
		rc = -EFAULT;
		goto out;
	}

	channel = rtw_atoi(input);
	/*RTW_INFO("%s: channel=%d\n", __func__, channel);*/
	_rtw_memset(extra, 0, wrqu->length);
	sprintf(extra, "Change channel %d to channel %d", padapter->mppriv.channel , channel);
	padapter->mppriv.channel = channel;
	SetChannel(padapter);
	pHalData->current_channel = channel;

	wrqu->length = strlen(extra);

out:
	kfree(input);
	return rc;
}

int rtw_mp_bandwidth(struct net_device *dev,
		     struct iw_request_info *info,
		     struct iw_point *wrqu, char *extra)
{
	u32 bandwidth = 0, sg = 0;
	PADAPTER padapter = rtw_netdev_priv(dev);
	HAL_DATA_TYPE	*pHalData	= GET_HAL_DATA(padapter);
	char *input;
	int rc = 0;

	input = kmalloc(sizeof(char) * wrqu->length, GFP_KERNEL);
	if (!input)
		return -ENOMEM;

	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
		rc = -EFAULT;
		goto out;
	}

	if (sscanf(input, "40M=%d,shortGI=%d", &bandwidth, &sg) > 0)
		RTW_INFO("%s: bw=%d sg=%d\n", __func__, bandwidth , sg);

	if (bandwidth == 1)
		bandwidth = CHANNEL_WIDTH_40;
	else if (bandwidth == 2)
		bandwidth = CHANNEL_WIDTH_80;

	padapter->mppriv.bandwidth = (u8)bandwidth;
	padapter->mppriv.preamble = sg;
	_rtw_memset(extra, 0, wrqu->length);
	sprintf(extra, "Change BW %d to BW %d\n", pHalData->current_channel_bw , bandwidth);

	SetBandwidth(padapter);
	pHalData->current_channel_bw = bandwidth;
	/*cur_ch_offset =  rtw_get_offset_by_ch(padapter->mppriv.channel);*/
	/*set_channel_bwmode(padapter, padapter->mppriv.channel, cur_ch_offset, bandwidth);*/
	wrqu->length = strlen(extra);

out:
	kfree(input);

	return rc;
}

int rtw_mp_txpower_index(struct net_device *dev,
			 struct iw_request_info *info,
			 struct iw_point *wrqu, char *extra)
{
	PADAPTER padapter = rtw_netdev_priv(dev);
	char *input;
	u32 rfpath;
	u32 txpower_inx;
	int rc = 0;

	input = kmalloc(sizeof(char) * wrqu->length, GFP_KERNEL);
	if (!input)
		return -ENOMEM;

	if (wrqu->length > 128) {
		rc = -EFAULT;
		goto out;
	}

	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
		rc = -EFAULT;
		goto out;
	}

	rfpath = rtw_atoi(input);
	txpower_inx = mpt_ProQueryCalTxPower(padapter, rfpath);
	sprintf(extra, " %d", txpower_inx);
	wrqu->length = strlen(extra);

out:
	kfree(input);

	return rc;
}

int rtw_mp_txpower(struct net_device *dev,
		   struct iw_request_info *info,
		   struct iw_point *wrqu, char *extra)
{
	u32 idx_a = 0, idx_b = 0, idx_c = 0, idx_d = 0;
	int MsetPower = 1;
	char *input;
	PADAPTER padapter = rtw_netdev_priv(dev);
	PMPT_CONTEXT		pMptCtx = &(padapter->mppriv.mpt_ctx);
	int rc = 0;

	input = kmalloc(sizeof(char) * wrqu->length, GFP_KERNEL);
	if (!input)
		return -ENOMEM;

	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
		rc = -EFAULT;
		goto out;
	}

	MsetPower = strncmp(input, "off", 3);
	if (MsetPower == 0) {
		padapter->mppriv.bSetTxPower = 0;
		sprintf(extra, "MP Set power off");
	} else {
		if (sscanf(input, "patha=%d,pathb=%d,pathc=%d,pathd=%d", &idx_a, &idx_b, &idx_c, &idx_d) < 3)
			RTW_INFO("Invalid format on line %s ,patha=%d,pathb=%d,pathc=%d,pathd=%d\n", input , idx_a , idx_b , idx_c , idx_d);

		sprintf(extra, "Set power level path_A:%d path_B:%d path_C:%d path_D:%d", idx_a , idx_b , idx_c , idx_d);
		padapter->mppriv.txpoweridx = (u8)idx_a;

		pMptCtx->TxPwrLevel[ODM_RF_PATH_A] = (u8)idx_a;
		pMptCtx->TxPwrLevel[ODM_RF_PATH_B] = (u8)idx_b;
		pMptCtx->TxPwrLevel[ODM_RF_PATH_C] = (u8)idx_c;
		pMptCtx->TxPwrLevel[ODM_RF_PATH_D]  = (u8)idx_d;
		padapter->mppriv.bSetTxPower = 1;

		SetTxPower(padapter);
	}

	wrqu->length = strlen(extra);

out:
	kfree(input);
	return rc;
}

int rtw_mp_ant_tx(struct net_device *dev,
		  struct iw_request_info *info,
		  struct iw_point *wrqu, char *extra)
{
	u8 i;
	char *input;
	u16 antenna = 0;
	PADAPTER padapter = rtw_netdev_priv(dev);
	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
	int rc = 0;

	input = kmalloc(sizeof(char) * wrqu->length, GFP_KERNEL);
	if (!input)
		return -ENOMEM;

	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
		rc = -EFAULT;
		goto out;
	}

	sprintf(extra, "switch Tx antenna to %s", input);

	for (i = 0; i < strlen(input); i++) {
		switch (input[i]) {
		case 'a':
			antenna |= ANTENNA_A;
			break;
		case 'b':
			antenna |= ANTENNA_B;
			break;
		case 'c':
			antenna |= ANTENNA_C;
			break;
		case 'd':
			antenna |= ANTENNA_D;
			break;
		}
	}
	/*antenna |= BIT(extra[i]-'a');*/
	RTW_INFO("%s: antenna=0x%x\n", __func__, antenna);
	padapter->mppriv.antenna_tx = antenna;
	padapter->mppriv.antenna_rx = antenna;
	/*RTW_INFO("%s:mppriv.antenna_rx=%d\n", __func__, padapter->mppriv.antenna_tx);*/
	pHalData->antenna_tx_path = antenna;

	SetAntenna(padapter);

	wrqu->length = strlen(extra);
out:
	kfree(input);

	return rc;
}

int rtw_mp_ant_rx(struct net_device *dev,
		  struct iw_request_info *info,
		  struct iw_point *wrqu, char *extra)
{
	u8 i;
	u16 antenna = 0;
	char		*input;
	PADAPTER padapter = rtw_netdev_priv(dev);
	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
	int rc = 0;

	input = kmalloc(sizeof(char) * wrqu->length, GFP_KERNEL);
	if (!input)
		return -ENOMEM;

	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
		rc = -EFAULT;
		goto out;
	}
	/*RTW_INFO("%s: input=%s\n", __func__, input);*/
	_rtw_memset(extra, 0, wrqu->length);

	sprintf(extra, "switch Rx antenna to %s", input);

	for (i = 0; i < strlen(input); i++) {
		switch (input[i]) {
		case 'a':
			antenna |= ANTENNA_A;
			break;
		case 'b':
			antenna |= ANTENNA_B;
			break;
		case 'c':
			antenna |= ANTENNA_C;
			break;
		case 'd':
			antenna |= ANTENNA_D;
			break;
		}
	}

	RTW_INFO("%s: antenna=0x%x\n", __func__, antenna);
	padapter->mppriv.antenna_tx = antenna;
	padapter->mppriv.antenna_rx = antenna;
	pHalData->AntennaRxPath = antenna;
	/*RTW_INFO("%s:mppriv.antenna_rx=%d\n", __func__, padapter->mppriv.antenna_rx);*/
	SetAntenna(padapter);
	wrqu->length = strlen(extra);

out:
	kfree(input);

	return rc;
}

int rtw_set_ctx_destAddr(struct net_device *dev,
			 struct iw_request_info *info,
			 struct iw_point *wrqu, char *extra)
{
	int jj, kk = 0;

	struct pkt_attrib *pattrib;
	struct mp_priv *pmp_priv;
	PADAPTER padapter = rtw_netdev_priv(dev);

	pmp_priv = &padapter->mppriv;
	pattrib = &pmp_priv->tx.attrib;

	if (strlen(extra) < 5)
		return _FAIL;

	RTW_INFO("%s: in=%s\n", __func__, extra);
	for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
		pattrib->dst[jj] = key_2char2num(extra[kk], extra[kk + 1]);

	RTW_INFO("pattrib->dst:%x %x %x %x %x %x\n", pattrib->dst[0], pattrib->dst[1], pattrib->dst[2], pattrib->dst[3], pattrib->dst[4], pattrib->dst[5]);
	return 0;
}

int rtw_mp_ctx(struct net_device *dev,
	       struct iw_request_info *info,
	       struct iw_point *wrqu, char *extra)
{
	u32 pkTx = 1;
	int countPkTx = 1, cotuTx = 1, CarrSprTx = 1, scTx = 1, sgleTx = 1, stop = 1;
	u32 bStartTest = 1;
	u32 count = 0, pktinterval = 0, pktlen = 0;
	u8 status;
	struct mp_priv *pmp_priv;
	struct pkt_attrib *pattrib;
	PADAPTER padapter = rtw_netdev_priv(dev);
	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);

	pmp_priv = &padapter->mppriv;
	pattrib = &pmp_priv->tx.attrib;

	if (copy_from_user(extra, wrqu->pointer, wrqu->length))
		return -EFAULT;

	RTW_INFO("%s: in=%s\n", __func__, extra);
	countPkTx = strncmp(extra, "count=", 5); /* strncmp TRUE is 0*/
	cotuTx = strncmp(extra, "background", 20);
	CarrSprTx = strncmp(extra, "background,cs", 20);
	scTx = strncmp(extra, "background,sc", 20);
	sgleTx = strncmp(extra, "background,stone", 20);
	pkTx = strncmp(extra, "background,pkt", 20);
	stop = strncmp(extra, "stop", 4);
	if (sscanf(extra, "count=%d,pkt", &count) > 0)
		RTW_INFO("count= %d\n", count);
	if (sscanf(extra, "pktinterval=%d", &pktinterval) > 0)
		RTW_INFO("pktinterval= %d\n", pktinterval);

	if (sscanf(extra, "pktlen=%d", &pktlen) > 0)
		RTW_INFO("pktlen= %d\n", pktlen);

	if (_rtw_memcmp(extra, "destmac=", 8)) {
		wrqu->length -= 8;
		rtw_set_ctx_destAddr(dev, info, wrqu, &extra[8]);
		sprintf(extra, "Set dest mac OK !\n");
		return 0;
	}

	/*RTW_INFO("%s: count=%d countPkTx=%d cotuTx=%d CarrSprTx=%d scTx=%d sgleTx=%d pkTx=%d stop=%d\n", __func__, count, countPkTx, cotuTx, CarrSprTx, pkTx, sgleTx, scTx, stop);*/
	_rtw_memset(extra, '\0', strlen(extra));

	if (pktinterval != 0) {
		sprintf(extra, "Pkt Interval = %d", pktinterval);
		padapter->mppriv.pktInterval = pktinterval;
		wrqu->length = strlen(extra);
		return 0;
	}
	if (pktlen != 0) {
		sprintf(extra, "Pkt len = %d", pktlen);
		pattrib->pktlen = pktlen;
		wrqu->length = strlen(extra);
		return 0;
	}
	if (stop == 0) {
		bStartTest = 0; /* To set Stop*/
		pmp_priv->tx.stop = 1;
		sprintf(extra, "Stop continuous Tx");
		odm_write_dig(&pHalData->odmpriv, 0x20);
	} else {
		bStartTest = 1;
		odm_write_dig(&pHalData->odmpriv, 0x7f);
		if (pmp_priv->mode != MP_ON) {
			if (pmp_priv->tx.stop != 1) {
				RTW_INFO("%s: MP_MODE != ON %d\n", __func__, pmp_priv->mode);
				return	-EFAULT;
			}
		}
	}

	pmp_priv->tx.count = count;

	if (pkTx == 0 || countPkTx == 0)
		pmp_priv->mode = MP_PACKET_TX;
	if (sgleTx == 0)
		pmp_priv->mode = MP_SINGLE_TONE_TX;
	if (cotuTx == 0)
		pmp_priv->mode = MP_CONTINUOUS_TX;
	if (CarrSprTx == 0)
		pmp_priv->mode = MP_CARRIER_SUPPRISSION_TX;
	if (scTx == 0)
		pmp_priv->mode = MP_SINGLE_CARRIER_TX;

	status = rtw_mp_pretx_proc(padapter, bStartTest, extra);

	wrqu->length = strlen(extra);
	return status;
}

int rtw_mp_disable_bt_coexist(struct net_device *dev,
			      struct iw_request_info *info,
			      union iwreq_data *wrqu, char *extra)
{
	PADAPTER padapter = (PADAPTER)rtw_netdev_priv(dev);
	char *input;
	u32 bt_coexist;
	int rc = 0;

	input = kmalloc(sizeof(char) * wrqu->data.length, GFP_KERNEL);
	if (!input)
		return -ENOMEM;

	if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length)) {
		rc = -EFAULT;
		goto out;
	}

	bt_coexist = rtw_atoi(input);

	if (bt_coexist == 0) {
		RTW_INFO("Set OID_RT_SET_DISABLE_BT_COEXIST: disable BT_COEXIST\n");
		rtw_btcoex_HaltNotify(padapter);
		rtw_btcoex_SetManualControl(padapter, _TRUE);
		/* Force to switch Antenna to WiFi*/
		rtw_write16(padapter, 0x870, 0x300);
		rtw_write16(padapter, 0x860, 0x110);
		/* CONFIG_BT_COEXIST */
	} else {
		rtw_btcoex_SetManualControl(padapter, _FALSE);
	}

out:
	kfree(input);

	return rc;
}

int rtw_mp_arx(struct net_device *dev,
	       struct iw_request_info *info,
	       struct iw_point *wrqu, char *extra)
{
	int bStartRx = 0, bStopRx = 0, bQueryPhy = 0, bQueryMac = 0, bSetBssid = 0;
	int bmac_filter = 0, bmon = 0, bSmpCfg = 0;
	char *input;
	char *pch, *token, *tmp[2] = {0x00, 0x00};
	u32 i = 0, jj = 0, kk = 0, cnts = 0, ret = 0;
	PADAPTER padapter = rtw_netdev_priv(dev);
	struct mp_priv *pmppriv = &padapter->mppriv;
	struct dbg_rx_counter rx_counter;
	int rc = 0;

	input = kmalloc(sizeof(char) * wrqu->length, GFP_KERNEL);
	if (!input)
		return -ENOMEM;

	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
		rc = -EFAULT;
		goto out;
	}

	RTW_INFO("%s: %s\n", __func__, input);
	bStartRx = (strncmp(input, "start", 5) == 0) ? 1 : 0; /* strncmp TRUE is 0*/
	bStopRx = (strncmp(input, "stop", 5) == 0) ? 1 : 0; /* strncmp TRUE is 0*/
	bQueryPhy = (strncmp(input, "phy", 3) == 0) ? 1 : 0; /* strncmp TRUE is 0*/
	bQueryMac = (strncmp(input, "mac", 3) == 0) ? 1 : 0; /* strncmp TRUE is 0*/
	bSetBssid = (strncmp(input, "setbssid=", 8) == 0) ? 1 : 0; /* strncmp TRUE is 0*/
	/*bfilter_init = (strncmp(input, "filter_init",11)==0)?1:0;*/
	bmac_filter = (strncmp(input, "accept_mac", 10) == 0) ? 1 : 0;
	bmon = (strncmp(input, "mon=", 4) == 0) ? 1 : 0;
	bSmpCfg = (strncmp(input , "smpcfg=" , 7) == 0) ? 1 : 0;
	pmppriv->bloopback = (strncmp(input, "loopbk", 6) == 0) ? 1 : 0; /* strncmp TRUE is 0*/

	if (bSetBssid == 1) {
		pch = input;
		while ((token = strsep(&pch, "=")) != NULL) {
			if (i > 1)
				break;
			tmp[i] = token;
			i++;
		}
		if ((tmp[0] != NULL) && (tmp[1] != NULL)) {
			cnts = strlen(tmp[1]) / 2;
			if (cnts < 1) {
				rc = -EFAULT;
				goto out;
			}
			RTW_INFO("%s: cnts=%d\n", __func__, cnts);
			RTW_INFO("%s: data=%s\n", __func__, tmp[1]);
			for (jj = 0, kk = 0; jj < cnts ; jj++, kk += 2) {
				pmppriv->network_macaddr[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
				RTW_INFO("network_macaddr[%d]=%x\n", jj, pmppriv->network_macaddr[jj]);
			}
		} else {
			rc = -EFAULT;
			goto out;
		}

		pmppriv->bSetRxBssid = _TRUE;
	}

	if (bmac_filter) {
		pmppriv->bmac_filter = bmac_filter;
		pch = input;
		while ((token = strsep(&pch, "=")) != NULL) {
			if (i > 1)
				break;
			tmp[i] = token;
			i++;
		}
		if ((tmp[0] != NULL) && (tmp[1] != NULL)) {
			cnts = strlen(tmp[1]) / 2;
			if (cnts < 1) {
				rc = -EFAULT;
				goto out;
			}
			RTW_INFO("%s: cnts=%d\n", __func__, cnts);
			RTW_INFO("%s: data=%s\n", __func__, tmp[1]);
			for (jj = 0, kk = 0; jj < cnts ; jj++, kk += 2) {
				pmppriv->mac_filter[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
				RTW_INFO("%s mac_filter[%d]=%x\n", __func__, jj, pmppriv->mac_filter[jj]);
			}
		} else {
			rc = -EFAULT;
			goto out;
		}

	}

	if (bStartRx) {
		sprintf(extra, "start");
		SetPacketRx(padapter, bStartRx, _FALSE);
	} else if (bStopRx) {
		SetPacketRx(padapter, bStartRx, _FALSE);
		pmppriv->bmac_filter = _FALSE;
		pmppriv->bSetRxBssid = _FALSE;
		sprintf(extra, "Received packet OK:%d CRC error:%d ,Filter out:%d", padapter->mppriv.rx_pktcount, padapter->mppriv.rx_crcerrpktcount, padapter->mppriv.rx_pktcount_filter_out);
	} else if (bQueryPhy) {
		_rtw_memset(&rx_counter, 0, sizeof(struct dbg_rx_counter));
		rtw_dump_phy_rx_counters(padapter, &rx_counter);

		RTW_INFO("%s: OFDM_FA =%d\n", __func__, rx_counter.rx_ofdm_fa);
		RTW_INFO("%s: CCK_FA =%d\n", __func__, rx_counter.rx_cck_fa);
		sprintf(extra, "Phy Received packet OK:%d CRC error:%d FA Counter: %d", rx_counter.rx_pkt_ok, rx_counter.rx_pkt_crc_error, rx_counter.rx_cck_fa + rx_counter.rx_ofdm_fa);

	} else if (bQueryMac) {
		_rtw_memset(&rx_counter, 0, sizeof(struct dbg_rx_counter));
		rtw_dump_mac_rx_counters(padapter, &rx_counter);
		sprintf(extra, "Mac Received packet OK: %d , CRC error: %d , Drop Packets: %d\n",
			rx_counter.rx_pkt_ok, rx_counter.rx_pkt_crc_error, rx_counter.rx_pkt_drop);

	}

	if (bmon == 1) {
		ret = sscanf(input, "mon=%d", &bmon);

		if (bmon == 1) {
			pmppriv->rx_bindicatePkt = _TRUE;
			sprintf(extra, "Indicating Receive Packet to network start\n");
		} else {
			pmppriv->rx_bindicatePkt = _FALSE;
			sprintf(extra, "Indicating Receive Packet to network Stop\n");
		}
	}
	if (bSmpCfg == 1) {
		ret = sscanf(input, "smpcfg=%d", &bSmpCfg);

		if (bSmpCfg == 1) {
			pmppriv->bRTWSmbCfg = _TRUE;
			sprintf(extra , "Indicate By Simple Config Format\n");
			SetPacketRx(padapter, _TRUE, _TRUE);
		} else {
			pmppriv->bRTWSmbCfg = _FALSE;
			sprintf(extra , "Indicate By Normal Format\n");
			SetPacketRx(padapter, _TRUE, _FALSE);
		}
	}

	if (pmppriv->bloopback == _TRUE) {
		sprintf(extra , "Enter MAC LoopBack mode\n");
		_rtw_write32(padapter, 0x100, 0xB0106FF);
		RTW_INFO("0x100 :0x%x" , _rtw_read32(padapter, 0x100));
		_rtw_write16(padapter, 0x608, 0x30c);
		RTW_INFO("0x100 :0x%x" , _rtw_read32(padapter, 0x608));
	}

	wrqu->length = strlen(extra) + 1;

out:
	kfree(input);

	return rc;
}

int rtw_mp_trx_query(struct net_device *dev,
		     struct iw_request_info *info,
		     struct iw_point *wrqu, char *extra)
{
	u32 txok, txfail, rxok, rxfail, rxfilterout;
	PADAPTER padapter = rtw_netdev_priv(dev);
	PMPT_CONTEXT	pMptCtx		=	&(padapter->mppriv.mpt_ctx);
	RT_PMAC_TX_INFO	PMacTxInfo	=	pMptCtx->PMacTxInfo;

	if (PMacTxInfo.bEnPMacTx == TRUE)
		txok = hal_mpt_query_phytxok(padapter);
	else
		txok = padapter->mppriv.tx.sended;

	txfail = 0;
	rxok = padapter->mppriv.rx_pktcount;
	rxfail = padapter->mppriv.rx_crcerrpktcount;
	rxfilterout = padapter->mppriv.rx_pktcount_filter_out;

	_rtw_memset(extra, '\0', 128);

	sprintf(extra, "Tx OK:%d, Tx Fail:%d, Rx OK:%d, CRC error:%d ,Rx Filter out:%d\n", txok, txfail, rxok, rxfail, rxfilterout);

	wrqu->length = strlen(extra) + 1;

	return 0;
}

int rtw_mp_pwrtrk(struct net_device *dev,
		  struct iw_request_info *info,
		  struct iw_point *wrqu, char *extra)
{
	u8 enable;
	u32 thermal;
	int ret = 0;
	PADAPTER padapter = rtw_netdev_priv(dev);
	char *input;
	int rc = 0;

	input = kmalloc(sizeof(char) * wrqu->length, GFP_KERNEL);
	if (!input)
		return -ENOMEM;

	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
		rc = -EFAULT;
		goto out;
	}

	_rtw_memset(extra, 0, wrqu->length);

	enable = 1;
	if (wrqu->length > 1) {
		/* not empty string*/
		if (strncmp(input, "stop", 4) == 0) {
			enable = 0;
			sprintf(extra, "mp tx power tracking stop");
		} else if (sscanf(input, "ther=%d", &thermal) == 1) {
			ret = SetThermalMeter(padapter, (u8)thermal);
			if (ret == _FAIL) {
				rc = -EPERM;
				goto out;
			}
			sprintf(extra, "mp tx power tracking start,target value=%d ok", thermal);
		} else {
			rc = -EINVAL;
			goto out;
		}
	}

	ret = SetPowerTracking(padapter, enable);
	if (ret == _FAIL) {
		rc = -EPERM;
		goto out;
	}

	wrqu->length = strlen(extra);

out:
	kfree(input);

	return rc;
}

int rtw_mp_psd(struct net_device *dev,
	       struct iw_request_info *info,
	       struct iw_point *wrqu, char *extra)
{
	PADAPTER padapter = rtw_netdev_priv(dev);
	char *input;
	int rc = 0;

	input = kmalloc(sizeof(char) * wrqu->length, GFP_KERNEL);
	if (!input)
		return -ENOMEM;

	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
		rc = -EFAULT;
		goto out;
	}

	strcpy(extra, input);

	wrqu->length = mp_query_psd(padapter, extra);

out:
	kfree(input);

	return rc;
}

int rtw_mp_thermal(struct net_device *dev,
		   struct iw_request_info *info,
		   struct iw_point *wrqu, char *extra)
{
	u8 val;
	int bwrite = 1;

	u16 addr = EEPROM_THERMAL_METER_8821C;
	u16 cnt = 1;
	u16 max_available_size = 0;
	PADAPTER padapter = rtw_netdev_priv(dev);

	if (copy_from_user(extra, wrqu->pointer, wrqu->length))
		return -EFAULT;

	bwrite = strncmp(extra, "write", 6);/* strncmp TRUE is 0*/

	GetThermalMeter(padapter, &val);

	if (bwrite == 0) {
		/*RTW_INFO("to write val:%d",val);*/
		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_available_size, _FALSE);
		if (2 > max_available_size) {
			RTW_INFO("no available efuse!\n");
			return -EFAULT;
		}
		if (rtw_efuse_map_write(padapter, addr, cnt, &val) == _FAIL) {
			RTW_INFO("rtw_efuse_map_write error\n");
			return -EFAULT;
		}
		sprintf(extra, " efuse write ok :%d", val);
	} else
		sprintf(extra, "%d", val);
	wrqu->length = strlen(extra);

	return 0;
}

int rtw_mp_reset_stats(struct net_device *dev,
		       struct iw_request_info *info,
		       struct iw_point *wrqu, char *extra)
{
	struct mp_priv *pmp_priv;
	PADAPTER padapter = rtw_netdev_priv(dev);

	pmp_priv = &padapter->mppriv;

	pmp_priv->tx.sended = 0;
	pmp_priv->tx_pktcount = 0;
	pmp_priv->rx_pktcount = 0;
	pmp_priv->rx_pktcount_filter_out = 0;
	pmp_priv->rx_crcerrpktcount = 0;

	rtw_reset_phy_rx_counters(padapter);
	rtw_reset_mac_rx_counters(padapter);

	_rtw_memset(extra, 0, wrqu->length);
	sprintf(extra, "mp_reset_stats ok\n");
	wrqu->length = strlen(extra);

	return 0;
}

int rtw_mp_dump(struct net_device *dev,
		struct iw_request_info *info,
		struct iw_point *wrqu, char *extra)
{
	struct mp_priv *pmp_priv;
	char *input;
	PADAPTER padapter = rtw_netdev_priv(dev);
	int rc = 0;

	input = kmalloc(sizeof(char) * wrqu->length, GFP_KERNEL);
	if (!input)
		return -ENOMEM;

	pmp_priv = &padapter->mppriv;

	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
		rc = -EFAULT;
		goto out;
	}

	if (strncmp(input, "all", 4) == 0) {
		mac_reg_dump(RTW_DBGDUMP, padapter);
		bb_reg_dump(RTW_DBGDUMP, padapter);
		rf_reg_dump(RTW_DBGDUMP, padapter);
	}

out:
	kfree(input);
	return rc;
}

int rtw_mp_phypara(struct net_device *dev,
		   struct iw_request_info *info,
		   struct iw_point *wrqu, char *extra)
{

	PADAPTER padapter = rtw_netdev_priv(dev);
	HAL_DATA_TYPE	*pHalData	= GET_HAL_DATA(padapter);
	char *input;
	u32		valxcap, ret;
	int rc = 0;

	input = kmalloc(sizeof(char) * wrqu->length, GFP_KERNEL);
	if (!input)
		return -ENOMEM;

	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
		rc = -EFAULT;
		goto out;
	}

	RTW_INFO("%s:iwpriv in=%s\n", __func__, input);

	ret = sscanf(input, "xcap=%d", &valxcap);

	pHalData->crystal_cap = (u8)valxcap;
	hal_set_crystal_cap(padapter , valxcap);

	sprintf(extra, "Set xcap=%d", valxcap);
	wrqu->length = strlen(extra) + 1;

out:
	kfree(input);

	return rc;
}

int rtw_mp_SetRFPath(struct net_device *dev,
		     struct iw_request_info *info,
		     struct iw_point *wrqu, char *extra)
{
	PADAPTER padapter = rtw_netdev_priv(dev);
	char *input;
	int		bMain = 1, bTurnoff = 1;
	int rc = 0;

	input = kmalloc(sizeof(char) * wrqu->length, GFP_KERNEL);
	if (!input)
		return -ENOMEM;

	RTW_INFO("%s:iwpriv in=%s\n", __func__, input);

	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
		rc = -EFAULT;
		goto out;
	}

	bMain = strncmp(input, "1", 2); /* strncmp TRUE is 0*/
	bTurnoff = strncmp(input, "0", 3); /* strncmp TRUE is 0*/

	_rtw_memset(extra, 0, wrqu->length);

	if (bMain == 0) {
		MP_PHY_SetRFPathSwitch(padapter, _TRUE);
		RTW_INFO("%s:PHY_SetRFPathSwitch=TRUE\n", __func__);
		sprintf(extra, "mp_setrfpath Main\n");

	} else if (bTurnoff == 0) {
		MP_PHY_SetRFPathSwitch(padapter, _FALSE);
		RTW_INFO("%s:PHY_SetRFPathSwitch=FALSE\n", __func__);
		sprintf(extra, "mp_setrfpath Aux\n");
	} else {
		bMain = MP_PHY_QueryRFPathSwitch(padapter);
		RTW_INFO("%s:PHY_SetRFPathSwitch = %s\n", __func__, (bMain ? "Main":"Aux"));
		sprintf(extra, "mp_setrfpath %s\n" , (bMain ? "Main":"Aux"));
	}

	wrqu->length = strlen(extra);

out:
	kfree(input);

	return rc;
}

int rtw_mp_QueryDrv(struct net_device *dev,
		    struct iw_request_info *info,
		    union iwreq_data *wrqu, char *extra)
{
	PADAPTER padapter = rtw_netdev_priv(dev);
	char *input;
	int	qAutoLoad = 1;
	int rc = 0;

	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);

	input = kmalloc(sizeof(char) * wrqu->data.length, GFP_KERNEL);
	if (!input)
		return -ENOMEM;

	if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length)) {
		rc = -EFAULT;
		goto out;
	}
	RTW_INFO("%s:iwpriv in=%s\n", __func__, input);

	qAutoLoad = strncmp(input, "autoload", 8); /* strncmp TRUE is 0*/

	if (qAutoLoad == 0) {
		RTW_INFO("%s:qAutoLoad\n", __func__);

		if (pHalData->bautoload_fail_flag)
			sprintf(extra, "fail");
		else
			sprintf(extra, "ok");
	}
	wrqu->data.length = strlen(extra) + 1;

out:
	kfree(input);
	return rc;
}

int rtw_mp_PwrCtlDM(struct net_device *dev,
		    struct iw_request_info *info,
		    struct iw_point *wrqu, char *extra)
{
	PADAPTER padapter = rtw_netdev_priv(dev);
	char *input;
	int		bstart = 1;
	int rc = 0;

	input = kmalloc(sizeof(char) * wrqu->length, GFP_KERNEL);
	if (!input)
		return -ENOMEM;

	if (copy_from_user(input, wrqu->pointer, wrqu->length)) {
		rc = -EFAULT;
		goto out;
	}

	bstart = strncmp(input, "start", 5); /* strncmp TRUE is 0*/
	if (bstart == 0) {
		sprintf(extra, "PwrCtlDM start\n");
		MPT_PwrCtlDM(padapter, 1);
	} else {
		sprintf(extra, "PwrCtlDM stop\n");
		MPT_PwrCtlDM(padapter, 0);
	}
	wrqu->length = strlen(extra);

out:
	kfree(input);
	return rc;
}

int rtw_mp_iqk(struct net_device *dev,
		 struct iw_request_info *info,
		 struct iw_point *wrqu, char *extra)
{
	PADAPTER padapter = rtw_netdev_priv(dev);

	rtw_mp_trigger_iqk(padapter);

	return 0;
}

int rtw_mp_lck(struct net_device *dev,
		 struct iw_request_info *info,
		 struct iw_point *wrqu, char *extra)
{
	PADAPTER padapter = rtw_netdev_priv(dev);

	rtw_mp_trigger_lck(padapter);

	return 0;
}

int rtw_mp_getver(struct net_device *dev,
		  struct iw_request_info *info,
		  union iwreq_data *wrqu, char *extra)
{
	PADAPTER padapter = rtw_netdev_priv(dev);
	struct mp_priv *pmp_priv;

	pmp_priv = &padapter->mppriv;

	if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
		return -EFAULT;

	sprintf(extra, "rtwpriv=%d\n", RTWPRIV_VER_INFO);
	wrqu->data.length = strlen(extra);
	return 0;
}

int rtw_mp_mon(struct net_device *dev,
	       struct iw_request_info *info,
	       union iwreq_data *wrqu, char *extra)
{
	PADAPTER padapter = rtw_netdev_priv(dev);
	struct mp_priv *pmp_priv = &padapter->mppriv;
	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
	struct hal_ops *pHalFunc = &padapter->hal_func;
	NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
	int bstart = 1, bstop = 1;

	networkType = Ndis802_11Infrastructure;
	if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
		return -EFAULT;

	rtw_pm_set_ips(padapter, IPS_NONE);
	LeaveAllPowerSaveMode(padapter);

	if (init_mp_priv(padapter) == _FAIL)
		RTW_INFO("%s: initialize MP private data Fail!\n", __func__);
	padapter->mppriv.channel = 6;

	bstart = strncmp(extra, "start", 5); /* strncmp TRUE is 0*/
	bstop = strncmp(extra, "stop", 4); /* strncmp TRUE is 0*/
	if (bstart == 0) {
		mp_join(padapter, WIFI_FW_ADHOC_STATE);
		SetPacketRx(padapter, _TRUE, _FALSE);
		SetChannel(padapter);
		pmp_priv->rx_bindicatePkt = _TRUE;
		pmp_priv->bRTWSmbCfg = _TRUE;
		sprintf(extra, "monitor mode start\n");
	} else if (bstop == 0) {
		SetPacketRx(padapter, _FALSE, _FALSE);
		pmp_priv->rx_bindicatePkt = _FALSE;
		pmp_priv->bRTWSmbCfg = _FALSE;
		padapter->registrypriv.mp_mode = 1;
		pHalFunc->hal_deinit(padapter);
		padapter->registrypriv.mp_mode = 0;
		pHalFunc->hal_init(padapter);
		/*rtw_disassoc_cmd(padapter, 0, 0);*/
		if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
			rtw_disassoc_cmd(padapter, 500, 0);
			rtw_indicate_disconnect(padapter, 0, _FALSE);
			/*rtw_free_assoc_resources(padapter, 1);*/
		}
		rtw_pm_set_ips(padapter, IPS_NORMAL);
		sprintf(extra, "monitor mode Stop\n");
	}
	wrqu->data.length = strlen(extra);
	return 0;
}

int rtw_mp_pretx_proc(PADAPTER padapter, u8 bStartTest, char *extra)
{
	struct mp_priv *pmp_priv = &padapter->mppriv;

	switch (pmp_priv->mode) {

	case MP_PACKET_TX:
		if (bStartTest == 0) {
			pmp_priv->tx.stop = 1;
			pmp_priv->mode = MP_ON;
			sprintf(extra, "Stop continuous Tx");
		} else if (pmp_priv->tx.stop == 1) {
			sprintf(extra, "%s\nStart continuous DA=ffffffffffff len=1500 count=%u\n", extra, pmp_priv->tx.count);
			pmp_priv->tx.stop = 0;
			SetPacketTx(padapter);
		} else
			return -EFAULT;
		return 0;
	case MP_SINGLE_TONE_TX:
		if (bStartTest != 0)
			sprintf(extra, "%s\nStart continuous DA=ffffffffffff len=1500\n infinite=yes.", extra);
		SetSingleToneTx(padapter, (u8)bStartTest);
		break;
	case MP_CONTINUOUS_TX:
		if (bStartTest != 0)
			sprintf(extra, "%s\nStart continuous DA=ffffffffffff len=1500\n infinite=yes.", extra);
		SetContinuousTx(padapter, (u8)bStartTest);
		break;
	case MP_CARRIER_SUPPRISSION_TX:
		if (bStartTest != 0) {
			if (HwRateToMPTRate(pmp_priv->rateidx) <= MPT_RATE_11M)
				sprintf(extra, "%s\nStart continuous DA=ffffffffffff len=1500\n infinite=yes.", extra);
			else
				sprintf(extra, "%s\nSpecify carrier suppression but not CCK rate", extra);
		}
		SetCarrierSuppressionTx(padapter, (u8)bStartTest);
		break;
	case MP_SINGLE_CARRIER_TX:
		if (bStartTest != 0)
			sprintf(extra, "%s\nStart continuous DA=ffffffffffff len=1500\n infinite=yes.", extra);
		SetSingleCarrierTx(padapter, (u8)bStartTest);
		break;

	default:
		sprintf(extra, "Error! Continuous-Tx is not on-going.");
		return -EFAULT;
	}

	if (bStartTest == 1 && pmp_priv->mode != MP_ON) {
		struct mp_priv *pmp_priv = &padapter->mppriv;

		if (pmp_priv->tx.stop == 0) {
			pmp_priv->tx.stop = 1;
			rtw_msleep_os(5);
		}
		pmp_priv->tx.attrib.ht_en = 1;
		pmp_priv->tx.stop = 0;
		pmp_priv->tx.count = 1;
		SetPacketTx(padapter);
	} else
		pmp_priv->mode = MP_ON;

	return 0;
}

int rtw_mp_tx(struct net_device *dev,
	      struct iw_request_info *info,
	      union iwreq_data *wrqu, char *extra)
{
	PADAPTER padapter = rtw_netdev_priv(dev);
	HAL_DATA_TYPE	*pHalData	= GET_HAL_DATA(padapter);
	struct mp_priv *pmp_priv = &padapter->mppriv;
	PMPT_CONTEXT		pMptCtx = &(padapter->mppriv.mpt_ctx);

	u32 bandwidth = 0, sg = 0, channel = 6, txpower = 40, rate = 108, ant = 0, txmode = 1, count = 0;
	u8 bStartTest = 1, status = 0;
	u16 antenna = 0;

	if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
		return -EFAULT;
	RTW_INFO("extra = %s\n", extra);

	if (strncmp(extra, "stop", 3) == 0) {
		bStartTest = 0; /* To set Stop*/
		pmp_priv->tx.stop = 1;
		sprintf(extra, "Stop continuous Tx");
		status = rtw_mp_pretx_proc(padapter, bStartTest, extra);
		wrqu->data.length = strlen(extra);
		return status;
	} else if (strncmp(extra, "count", 5) == 0) {
		if (sscanf(extra, "count=%d", &count) < 1)
			RTW_INFO("Got Count=%d]\n", count);
		pmp_priv->tx.count = count;
		return 0;
	} else if (strncmp(extra, "setting", 7) == 0) {
		_rtw_memset(extra, 0, wrqu->data.length);
		sprintf(extra, "Current Setting :\n Channel:%d", pmp_priv->channel);
		sprintf(extra, "%s\n Bandwidth:%d", extra, pmp_priv->bandwidth);
		sprintf(extra, "%s\n Rate index:%d", extra, pmp_priv->rateidx);
		sprintf(extra, "%s\n TxPower index:%d", extra, pmp_priv->txpoweridx);
		sprintf(extra, "%s\n Antenna TxPath:%d", extra, pmp_priv->antenna_tx);
		sprintf(extra, "%s\n Antenna RxPath:%d", extra, pmp_priv->antenna_rx);
		sprintf(extra, "%s\n MP Mode:%d", extra, pmp_priv->mode);
		wrqu->data.length = strlen(extra);
		return 0;
	} else {

		if (sscanf(extra, "ch=%d,bw=%d,rate=%d,pwr=%d,ant=%d,tx=%d", &channel, &bandwidth, &rate, &txpower, &ant, &txmode) < 6) {
			RTW_INFO("Invalid format [ch=%d,bw=%d,rate=%d,pwr=%d,ant=%d,tx=%d]\n", channel, bandwidth, rate, txpower, ant, txmode);
			_rtw_memset(extra, 0, wrqu->data.length);
			sprintf(extra, "\n Please input correct format as bleow:\n");
			sprintf(extra, "%s\t ch=%d,bw=%d,rate=%d,pwr=%d,ant=%d,tx=%d\n", extra, channel, bandwidth, rate, txpower, ant, txmode);
			sprintf(extra, "%s\n [ ch : BGN = <1~14> , A or AC = <36~165> ]", extra);
			sprintf(extra, "%s\n [ bw : Bandwidth: 0 = 20M, 1 = 40M, 2 = 80M ]", extra);
			sprintf(extra, "%s\n [ rate :	CCK: 1 2 5.5 11M X 2 = < 2 4 11 22 >]", extra);
			sprintf(extra, "%s\n [		OFDM: 6 9 12 18 24 36 48 54M X 2 = < 12 18 24 36 48 72 96 108>", extra);
			sprintf(extra, "%s\n [		HT 1S2SS MCS0 ~ MCS15 : < [MCS0]=128 ~ [MCS7]=135 ~ [MCS15]=143 >", extra);
			sprintf(extra, "%s\n [		HT 3SS MCS16 ~ MCS32 : < [MCS16]=144 ~ [MCS23]=151 ~ [MCS32]=159 >", extra);
			sprintf(extra, "%s\n [		VHT 1SS MCS0 ~ MCS9 : < [MCS0]=160 ~ [MCS9]=169 >", extra);
			sprintf(extra, "%s\n [ txpower : 1~63 power index", extra);
			sprintf(extra, "%s\n [ ant : <A = 1, B = 2, C = 4, D = 8> ,2T ex: AB=3 BC=6 CD=12", extra);
			sprintf(extra, "%s\n [ txmode : < 0 = CONTINUOUS_TX, 1 = PACKET_TX, 2 = SINGLE_TONE_TX, 3 = CARRIER_SUPPRISSION_TX, 4 = SINGLE_CARRIER_TX>\n", extra);
			wrqu->data.length = strlen(extra);
			return status;

		} else {
			RTW_INFO("Got format [ch=%d,bw=%d,rate=%d,pwr=%d,ant=%d,tx=%d]\n", channel, bandwidth, rate, txpower, ant, txmode);
			_rtw_memset(extra, 0, wrqu->data.length);
			sprintf(extra, "Change Current channel %d to channel %d", padapter->mppriv.channel , channel);
			padapter->mppriv.channel = channel;
			SetChannel(padapter);
			pHalData->current_channel = channel;

			if (bandwidth == 1)
				bandwidth = CHANNEL_WIDTH_40;
			else if (bandwidth == 2)
				bandwidth = CHANNEL_WIDTH_80;
			sprintf(extra, "%s\nChange Current Bandwidth %d to Bandwidth %d", extra, padapter->mppriv.bandwidth , bandwidth);
			padapter->mppriv.bandwidth = (u8)bandwidth;
			padapter->mppriv.preamble = sg;
			SetBandwidth(padapter);
			pHalData->current_channel_bw = bandwidth;

			sprintf(extra, "%s\nSet power level :%d", extra, txpower);
			padapter->mppriv.txpoweridx = (u8)txpower;
			pMptCtx->TxPwrLevel[ODM_RF_PATH_A] = (u8)txpower;
			pMptCtx->TxPwrLevel[ODM_RF_PATH_B] = (u8)txpower;
			pMptCtx->TxPwrLevel[ODM_RF_PATH_C] = (u8)txpower;
			pMptCtx->TxPwrLevel[ODM_RF_PATH_D]  = (u8)txpower;

			RTW_INFO("%s: bw=%d sg=%d\n", __func__, bandwidth, sg);

			if (rate <= 0x7f)
				rate = wifirate2_ratetbl_inx((u8)rate);
			else if (rate < 0xC8)
				rate = (rate - 0x80 + MPT_RATE_MCS0);
			/*HT  rate 0x80(MCS0)  ~ 0x8F(MCS15) ~ 0x9F(MCS31) 128~159
			VHT1SS~2SS rate 0xA0 (VHT1SS_MCS0 44) ~ 0xB3 (VHT2SS_MCS9 #63) 160~179
			VHT rate 0xB4 (VHT3SS_MCS0 64) ~ 0xC7 (VHT2SS_MCS9 #83) 180~199
			else
			VHT rate 0x90(VHT1SS_MCS0) ~ 0x99(VHT1SS_MCS9) 144~153
			rate =(rate - MPT_RATE_VHT1SS_MCS0);
			*/
			RTW_INFO("%s: rate index=%d\n", __func__, rate);
			if (rate >= MPT_RATE_LAST)
				return -EINVAL;
			sprintf(extra, "%s\nSet data rate to %d index %d", extra, padapter->mppriv.rateidx, rate);

			padapter->mppriv.rateidx = rate;
			pMptCtx->mpt_rate_index = rate;
			SetDataRate(padapter);

			sprintf(extra, "%s\nSet Antenna Path :%d",  extra, ant);
			switch (ant) {
			case 1:
				antenna = ANTENNA_A;
				break;
			case 2:
				antenna = ANTENNA_B;
				break;
			case 4:
				antenna = ANTENNA_C;
				break;
			case 8:
				antenna = ANTENNA_D;
				break;
			case 3:
				antenna = ANTENNA_AB;
				break;
			case 5:
				antenna = ANTENNA_AC;
				break;
			case 9:
				antenna = ANTENNA_AD;
				break;
			case 6:
				antenna = ANTENNA_BC;
				break;
			case 10:
				antenna = ANTENNA_BD;
				break;
			case 12:
				antenna = ANTENNA_CD;
				break;
			case 7:
				antenna = ANTENNA_ABC;
				break;
			case 14:
				antenna = ANTENNA_BCD;
				break;
			case 11:
				antenna = ANTENNA_ABD;
				break;
			case 15:
				antenna = ANTENNA_ABCD;
				break;
			}
			RTW_INFO("%s: antenna=0x%x\n", __func__, antenna);
			padapter->mppriv.antenna_tx = antenna;
			padapter->mppriv.antenna_rx = antenna;
			pHalData->antenna_tx_path = antenna;
			SetAntenna(padapter);

			if (txmode == 0)
				pmp_priv->mode = MP_CONTINUOUS_TX;
			else if (txmode == 1) {
				pmp_priv->mode = MP_PACKET_TX;
				pmp_priv->tx.count = count;
			} else if (txmode == 2)
				pmp_priv->mode = MP_SINGLE_TONE_TX;
			else if (txmode == 3)
				pmp_priv->mode = MP_CARRIER_SUPPRISSION_TX;
			else if (txmode == 4)
				pmp_priv->mode = MP_SINGLE_CARRIER_TX;

			status = rtw_mp_pretx_proc(padapter, bStartTest, extra);
		}

	}

	wrqu->data.length = strlen(extra);
	return status;
}

int rtw_mp_rx(struct net_device *dev,
	      struct iw_request_info *info,
	      union iwreq_data *wrqu, char *extra)
{
	PADAPTER padapter = rtw_netdev_priv(dev);
	HAL_DATA_TYPE	*pHalData	= GET_HAL_DATA(padapter);
	struct mp_priv *pmp_priv = &padapter->mppriv;

	u32 bandwidth = 0, sg = 0, channel = 6, ant = 0;
	u16 antenna = 0;
	u8 bStartRx = 0;

	if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
		return -EFAULT;


	if (strncmp(extra, "stop", 4) == 0) {
		_rtw_memset(extra, 0, wrqu->data.length);
		SetPacketRx(padapter, bStartRx, _FALSE);
		pmp_priv->bmac_filter = _FALSE;
		sprintf(extra, "Received packet OK:%d CRC error:%d ,Filter out:%d", padapter->mppriv.rx_pktcount, padapter->mppriv.rx_crcerrpktcount, padapter->mppriv.rx_pktcount_filter_out);
		wrqu->data.length = strlen(extra);
		return 0;

	} else if (sscanf(extra, "ch=%d,bw=%d,ant=%d", &channel, &bandwidth, &ant) < 3) {
		RTW_INFO("Invalid format [ch=%d,bw=%d,ant=%d]\n", channel, bandwidth, ant);
		_rtw_memset(extra, 0, wrqu->data.length);
		sprintf(extra, "\n Please input correct format as bleow:\n");
		sprintf(extra, "%s\t ch=%d,bw=%d,ant=%d\n", extra, channel, bandwidth, ant);
		sprintf(extra, "%s\n [ ch : BGN = <1~14> , A or AC = <36~165> ]", extra);
		sprintf(extra, "%s\n [ bw : Bandwidth: 0 = 20M, 1 = 40M, 2 = 80M ]", extra);
		sprintf(extra, "%s\n [ ant : <A = 1, B = 2, C = 4, D = 8> ,2T ex: AB=3 BC=6 CD=12", extra);
		wrqu->data.length = strlen(extra);
		return 0;

	} else {
		bStartRx = 1;
		RTW_INFO("Got format [ch=%d,bw=%d,ant=%d]\n", channel, bandwidth, ant);
		_rtw_memset(extra, 0, wrqu->data.length);
		sprintf(extra, "Change Current channel %d to channel %d", padapter->mppriv.channel , channel);
		padapter->mppriv.channel = channel;
		SetChannel(padapter);
		pHalData->current_channel = channel;

		if (bandwidth == 1)
			bandwidth = CHANNEL_WIDTH_40;
		else if (bandwidth == 2)
			bandwidth = CHANNEL_WIDTH_80;
		sprintf(extra, "%s\nChange Current Bandwidth %d to Bandwidth %d", extra, padapter->mppriv.bandwidth , bandwidth);
		padapter->mppriv.bandwidth = (u8)bandwidth;
		padapter->mppriv.preamble = sg;
		SetBandwidth(padapter);
		pHalData->current_channel_bw = bandwidth;

		sprintf(extra, "%s\nSet Antenna Path :%d",  extra, ant);
		switch (ant) {
		case 1:
			antenna = ANTENNA_A;
			break;
		case 2:
			antenna = ANTENNA_B;
			break;
		case 4:
			antenna = ANTENNA_C;
			break;
		case 8:
			antenna = ANTENNA_D;
			break;
		case 3:
			antenna = ANTENNA_AB;
			break;
		case 5:
			antenna = ANTENNA_AC;
			break;
		case 9:
			antenna = ANTENNA_AD;
			break;
		case 6:
			antenna = ANTENNA_BC;
			break;
		case 10:
			antenna = ANTENNA_BD;
			break;
		case 12:
			antenna = ANTENNA_CD;
			break;
		case 7:
			antenna = ANTENNA_ABC;
			break;
		case 14:
			antenna = ANTENNA_BCD;
			break;
		case 11:
			antenna = ANTENNA_ABD;
			break;
		case 15:
			antenna = ANTENNA_ABCD;
			break;
		}
		RTW_INFO("%s: antenna=0x%x\n", __func__, antenna);
		padapter->mppriv.antenna_tx = antenna;
		padapter->mppriv.antenna_rx = antenna;
		pHalData->antenna_tx_path = antenna;
		SetAntenna(padapter);

		sprintf(extra, "%s\nstart Rx", extra);
		SetPacketRx(padapter, bStartRx, _FALSE);
	}
	wrqu->data.length = strlen(extra);
	return 0;
}

int rtw_mp_hwtx(struct net_device *dev,
		struct iw_request_info *info,
		union iwreq_data *wrqu, char *extra)
{
	PADAPTER padapter = rtw_netdev_priv(dev);
	PMPT_CONTEXT		pMptCtx = &(padapter->mppriv.mpt_ctx);
	char *input;
	int rc = 0;

	input = kmalloc(sizeof(char) * wrqu->data.length, GFP_KERNEL);
	if (!input)
		return -ENOMEM;

	if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length)) {
		rc = -EFAULT;
		goto out;
	}

	_rtw_memset(&pMptCtx->PMacTxInfo, 0, sizeof(RT_PMAC_TX_INFO));
	_rtw_memcpy((void *)&pMptCtx->PMacTxInfo, (void *)input, sizeof(RT_PMAC_TX_INFO));

	mpt_ProSetPMacTx(padapter);
	sprintf(extra, "Set PMac Tx Mode start\n");

	wrqu->data.length = strlen(extra);
out:
	kfree(input);

	return 0;
}

int rtw_efuse_mask_file(struct net_device *dev,
			struct iw_request_info *info,
			union iwreq_data *wrqu, char *extra)
{
	char *rtw_efuse_mask_file_path;
	u8 Status;
	PADAPTER padapter = rtw_netdev_priv(dev);

	_rtw_memset(maskfileBuffer, 0x00, sizeof(maskfileBuffer));

	if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
		return -EFAULT;

	if (strncmp(extra, "off", 3) == 0 && strlen(extra) < 4) {
		padapter->registrypriv.boffefusemask = 1;
		sprintf(extra, "Turn off Efuse Mask\n");
		wrqu->data.length = strlen(extra);
		return 0;
	}
	if (strncmp(extra, "on", 2) == 0 && strlen(extra) < 3) {
		padapter->registrypriv.boffefusemask = 0;
		sprintf(extra, "Turn on Efuse Mask\n");
		wrqu->data.length = strlen(extra);
		return 0;
	}
	if (strncmp(extra, "data,", 5) == 0) {
		u8	*pch;
		char	*ptmp, tmp;
		u8	count = 0;
		u8	i = 0;

		ptmp = extra;
		pch = strsep(&ptmp, ",");

		if ((pch == NULL) || (strlen(pch) == 0)) {
			RTW_INFO("%s: parameter error(no cmd)!\n", __func__);
			return -EFAULT;
		}

		do {
			pch = strsep(&ptmp, ":");
			if ((pch == NULL) || (strlen(pch) == 0))
				break;
			if (strlen(pch) != 2
				|| IsHexDigit(*pch) == _FALSE
				|| IsHexDigit(*(pch + 1)) == _FALSE
				|| sscanf(pch, "%hhx", &tmp) != 1
			) {
				RTW_INFO("%s: invalid 8-bit hex! input format: data,01:23:45:67:89:ab:cd:ef...\n", __func__);
				return -EFAULT;
			}
			maskfileBuffer[count++] = tmp;

		 } while (count < 64);

		for (i = 0; i < count; i++)
			sprintf(extra, "%s:%02x", extra, maskfileBuffer[i]);

		padapter->registrypriv.bFileMaskEfuse = _TRUE;

		sprintf(extra, "%s\nLoad Efuse Mask data %d hex ok\n", extra, count);
		wrqu->data.length = strlen(extra);
		return 0;
	}
	rtw_efuse_mask_file_path = extra;

	if (rtw_is_file_readable(rtw_efuse_mask_file_path) == _TRUE) {
		RTW_INFO("%s do rtw_efuse_mask_file_read = %s! ,sizeof maskfileBuffer %zu\n", __func__, rtw_efuse_mask_file_path, sizeof(maskfileBuffer));
		Status = rtw_efuse_file_read(padapter, rtw_efuse_mask_file_path, maskfileBuffer, sizeof(maskfileBuffer));
		if (Status == _TRUE)
			padapter->registrypriv.bFileMaskEfuse = _TRUE;
		sprintf(extra, "efuse mask file read OK\n");
	} else {
		padapter->registrypriv.bFileMaskEfuse = _FALSE;
		sprintf(extra, "efuse mask file readable FAIL\n");
		RTW_INFO("%s rtw_is_file_readable fail!\n", __func__);
	}
	wrqu->data.length = strlen(extra);
	return 0;
}

int rtw_efuse_file_map(struct net_device *dev,
		       struct iw_request_info *info,
		       union iwreq_data *wrqu, char *extra)
{
	char *rtw_efuse_file_map_path;
	u8 Status;
	PEFUSE_HAL pEfuseHal;
	PADAPTER padapter = rtw_netdev_priv(dev);
	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
	struct mp_priv *pmp_priv = &padapter->mppriv;

	pEfuseHal = &pHalData->EfuseHal;
	if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
		return -EFAULT;

	rtw_efuse_file_map_path = extra;

	_rtw_memset(pEfuseHal->fakeEfuseModifiedMap, 0xFF, EFUSE_MAX_MAP_LEN);

	if (rtw_is_file_readable(rtw_efuse_file_map_path) == _TRUE) {
		RTW_INFO("%s do rtw_efuse_mask_file_read = %s!\n", __func__, rtw_efuse_file_map_path);
		Status = rtw_efuse_file_read(padapter, rtw_efuse_file_map_path, pEfuseHal->fakeEfuseModifiedMap, sizeof(pEfuseHal->fakeEfuseModifiedMap));
		if (Status == _TRUE) {
			pmp_priv->bloadefusemap = _TRUE;
			sprintf(extra, "efuse file file_read OK\n");
		} else {
			pmp_priv->bloadefusemap = _FALSE;
			sprintf(extra, "efuse file file_read FAIL\n");
		}
	} else {
		sprintf(extra, "efuse file readable FAIL\n");
		RTW_INFO("%s rtw_is_file_readable fail!\n", __func__);
	}
	wrqu->data.length = strlen(extra);
	return 0;
}

