/* INT32 WMT_ioctl(struct inode *inode, struct file *filp, UINT32 cmd, unsigned long arg) */
long WMT_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
#define WMT_IOC_MAGIC        0xa0
#define WMT_IOCTL_SET_PATCH_NAME		_IOW(WMT_IOC_MAGIC, 4, char*)
#define WMT_IOCTL_SET_STP_MODE			_IOW(WMT_IOC_MAGIC, 5, int)
#define WMT_IOCTL_FUNC_ONOFF_CTRL		_IOW(WMT_IOC_MAGIC, 6, int)
#define WMT_IOCTL_LPBK_POWER_CTRL		_IOW(WMT_IOC_MAGIC, 7, int)
#define WMT_IOCTL_LPBK_TEST				_IOWR(WMT_IOC_MAGIC, 8, char*)
#define WMT_IOCTL_GET_CHIP_INFO			_IOR(WMT_IOC_MAGIC, 12, int)
#define WMT_IOCTL_SET_LAUNCHER_KILL		_IOW(WMT_IOC_MAGIC, 13, int)
#define WMT_IOCTL_SET_PATCH_NUM			_IOW(WMT_IOC_MAGIC, 14, int)
#define WMT_IOCTL_SET_PATCH_INFO		_IOW(WMT_IOC_MAGIC, 15, char*)
#define WMT_IOCTL_PORT_NAME			_IOWR(WMT_IOC_MAGIC, 20, char*)
#define WMT_IOCTL_WMT_CFG_NAME			_IOWR(WMT_IOC_MAGIC, 21, char*)
#define WMT_IOCTL_WMT_QUERY_CHIPID	_IOR(WMT_IOC_MAGIC, 22, int)
#define WMT_IOCTL_WMT_TELL_CHIPID	_IOW(WMT_IOC_MAGIC, 23, int)
#define WMT_IOCTL_WMT_COREDUMP_CTRL     _IOW(WMT_IOC_MAGIC, 24, int)
#define WMT_IOCTL_WMT_STP_ASSERT_CTRL   _IOW(WMT_IOC_MAGIC, 27, int)



	INT32 iRet = 0;
	UINT8 pBuffer[NAME_MAX + 1];
	WMT_DBG_FUNC("cmd (%u), arg (0x%lx)\n", cmd, arg);
	switch (cmd) {
	case WMT_IOCTL_SET_PATCH_NAME:	/* patch location */
		{

			if (copy_from_user(pBuffer, (void *)arg, NAME_MAX)) {
				iRet = -EFAULT;
				break;
			}
			pBuffer[NAME_MAX] = '\0';
			wmt_lib_set_patch_name(pBuffer);
		}
		break;

	case WMT_IOCTL_SET_STP_MODE:	/* stp/hif/fm mode */

		/* set hif conf */
		do {
			P_OSAL_OP pOp;
			MTK_WCN_BOOL bRet;
			P_OSAL_SIGNAL pSignal = NULL;
			P_WMT_HIF_CONF pHif = NULL;

			iRet = wmt_lib_set_hif(arg);
			if (0 != iRet) {
				WMT_INFO_FUNC("wmt_lib_set_hif fail (%lu)\n", arg);
				break;
			}

			pOp = wmt_lib_get_free_op();
			if (!pOp) {
				WMT_INFO_FUNC("get_free_lxop fail\n");
				break;
			}
			pSignal = &pOp->signal;
			pOp->op.opId = WMT_OPID_HIF_CONF;

			pHif = wmt_lib_get_hif();

			osal_memcpy(&pOp->op.au4OpData[0], pHif, sizeof(WMT_HIF_CONF));
			pOp->op.u4InfoBit = WMT_OP_HIF_BIT;
			pSignal->timeoutValue = 0;

			bRet = wmt_lib_put_act_op(pOp);
			WMT_DBG_FUNC("WMT_OPID_HIF_CONF result(%d)\n", bRet);
			iRet = (MTK_WCN_BOOL_FALSE == bRet) ? -EFAULT : 0;
		} while (0);

		break;

	case WMT_IOCTL_FUNC_ONOFF_CTRL:	/* test turn on/off func */

		do {
			MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE;
			if (arg & 0x80000000) {
				bRet = mtk_wcn_wmt_func_on(arg & 0xF);
			} else {
				bRet = mtk_wcn_wmt_func_off(arg & 0xF);
			}
			iRet = (MTK_WCN_BOOL_FALSE == bRet) ? -EFAULT : 0;
		} while (0);

		break;

	case WMT_IOCTL_LPBK_POWER_CTRL:
		/*switch Loopback function on/off
		   arg:     bit0 = 1:turn loopback function on
		   bit0 = 0:turn loopback function off
		 */
		do {
			MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE;
			if (arg & 0x01) {
				bRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_LPBK);
			} else {
				bRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_LPBK);
			}
			iRet = (MTK_WCN_BOOL_FALSE == bRet) ? -EFAULT : 0;
		} while (0);


		break;


	case WMT_IOCTL_LPBK_TEST:
		do {
			P_OSAL_OP pOp;
			MTK_WCN_BOOL bRet;
			UINT32 u4Wait;
			/* UINT8 lpbk_buf[1024] = {0}; */
			UINT32 effectiveLen = 0;
			P_OSAL_SIGNAL pSignal = NULL;

			if (copy_from_user(&effectiveLen, (void *)arg, sizeof(effectiveLen))) {
				iRet = -EFAULT;
				WMT_ERR_FUNC("copy_from_user failed at %d\n", __LINE__);
				break;
			}
			if (effectiveLen > sizeof(gLpbkBuf)) {
				iRet = -EFAULT;
				WMT_ERR_FUNC("length is too long\n");
				break;
			}
			WMT_DBG_FUNC("len = %d\n", effectiveLen);

			pOp = wmt_lib_get_free_op();
			if (!pOp) {
				WMT_WARN_FUNC("get_free_lxop fail\n");
				iRet = -EFAULT;
				break;
			}
			u4Wait = 2000;
			if (copy_from_user
			    (&gLpbkBuf[0], (void *)arg + sizeof(unsigned long), effectiveLen)) {
				WMT_ERR_FUNC("copy_from_user failed at %d\n", __LINE__);
				iRet = -EFAULT;
				break;
			}
			pSignal = &pOp->signal;
			pOp->op.opId = WMT_OPID_LPBK;
			pOp->op.au4OpData[0] = effectiveLen;	/* packet length */
			pOp->op.au4OpData[1] = (size_t) &gLpbkBuf[0];
			memcpy(&gLpbkBufLog,
			       &gLpbkBuf[((effectiveLen >= 4) ? effectiveLen - 4 : 0)], 4);
			pSignal->timeoutValue = MAX_EACH_WMT_CMD;
			WMT_INFO_FUNC("OPID(%d) type(%d) start\n",
				      pOp->op.opId, pOp->op.au4OpData[0]);
			if (DISABLE_PSM_MONITOR()) {
				WMT_ERR_FUNC("wake up failed\n");
				wmt_lib_put_op_to_free_queue(pOp);
				return -1;
			}

			bRet = wmt_lib_put_act_op(pOp);
			ENABLE_PSM_MONITOR();
			if (MTK_WCN_BOOL_FALSE == bRet) {
				WMT_WARN_FUNC("OPID(%d) type(%d) buf tail(0x%08x) fail\n",
					      pOp->op.opId, pOp->op.au4OpData[0], gLpbkBufLog);
				iRet = -1;
				break;
			} else {
				WMT_INFO_FUNC("OPID(%d) length(%d) ok\n",
					      pOp->op.opId, pOp->op.au4OpData[0]);
				iRet = pOp->op.au4OpData[0];
				if (copy_to_user
				    ((void *)arg + sizeof(unsigned long) + sizeof(UINT8[2048]), gLpbkBuf,
				     iRet)) {
					iRet = -EFAULT;
					break;
				}
			}
		} while (0);

		break;
#if 0
	case 9:
		{
#define LOG_BUF_SZ 300
			UINT8 buf[LOG_BUF_SZ];
			INT32 len = 0;
			INT32 remaining = 0;

			remaining = mtk_wcn_stp_btm_get_dmp(buf, &len);

			if (remaining == 0) {
				WMT_DBG_FUNC("waiting dmp\n");
				wait_event_interruptible(dmp_wq, dmp_flag != 0);
				dmp_flag = 0;
				remaining = mtk_wcn_stp_btm_get_dmp(buf, &len);

				/* WMT_INFO_FUNC("len = %d ###%s#\n", len, buf); */
			} else {
				WMT_LOUD_FUNC("no waiting dmp\n");
			}

			if (unlikely((len + sizeof(INT32)) >= LOG_BUF_SZ)) {
				WMT_ERR_FUNC("len is larger buffer\n");
				iRet = -EFAULT;
				goto fail_exit;
			}

			buf[sizeof(INT32) + len] = '\0';

			if (copy_to_user((void *)arg, (PUINT8)&len, sizeof(INT32))) {
				iRet = -EFAULT;
				goto fail_exit;
			}

			if (copy_to_user((void *)arg + sizeof(INT32), buf, len)) {
				iRet = -EFAULT;
				goto fail_exit;
			}
		}
		break;

	case 10:
		{
			WMT_INFO_FUNC("Enable combo trace32 dump\n");
			wmt_cdev_t32dmp_enable();
			WMT_INFO_FUNC("Enable STP debugging mode\n");
			mtk_wcn_stp_dbg_enable();
		}
		break;

	case 11:
		{
			WMT_INFO_FUNC("Disable combo trace32 dump\n");
			wmt_cdev_t32dmp_disable();
			WMT_INFO_FUNC("Disable STP debugging mode\n");
			mtk_wcn_stp_dbg_disable();
		}
		break;
#endif

	case 10:
		{
			wmt_lib_host_awake_get();
			mtk_wcn_stp_coredump_start_ctrl(1);
			osal_strcpy(pBuffer, "MT662x f/w coredump start-");
			if (copy_from_user
			    (pBuffer + osal_strlen(pBuffer), (void *)arg,
			     NAME_MAX - osal_strlen(pBuffer))) {
				/* osal_strcpy(pBuffer, "MT662x f/w assert core dump start"); */
				WMT_ERR_FUNC("copy assert string failed\n");
			}
			pBuffer[NAME_MAX] = '\0';
			osal_dbg_assert_aee(pBuffer, pBuffer);
		}
		break;
	case 11:
		{
			osal_dbg_assert_aee("MT662x f/w coredump end",
					    "MT662x firmware coredump ends");
			wmt_lib_host_awake_put();
		}
		break;


	case WMT_IOCTL_GET_CHIP_INFO:
		{
			if (0 == arg) {
				return wmt_lib_get_icinfo(WMTCHIN_CHIPID);
			} else if (1 == arg) {
				return wmt_lib_get_icinfo(WMTCHIN_HWVER);
			} else if (2 == arg) {
				return wmt_lib_get_icinfo(WMTCHIN_FWVER);
			}
		}
		break;

	case WMT_IOCTL_SET_LAUNCHER_KILL:{
			if (1 == arg) {
				WMT_INFO_FUNC("launcher may be killed,block abnormal stp tx.\n");
				wmt_lib_set_stp_wmt_last_close(1);
			} else {
				wmt_lib_set_stp_wmt_last_close(0);
			}

		}
		break;

	case WMT_IOCTL_SET_PATCH_NUM:{
			pAtchNum = arg;
			WMT_INFO_FUNC(" get patch num from launcher = %d\n", pAtchNum);
			wmt_lib_set_patch_num(pAtchNum);
			if (pAtchNum > 0)
				pPatchInfo = kzalloc(sizeof(WMT_PATCH_INFO) *pAtchNum, GFP_ATOMIC);
			else
				WMT_ERR_FUNC("patch num == 0!\n");
			if (!pPatchInfo) {
				WMT_ERR_FUNC("allocate memory fail!\n");
				break;
			}
		}
		break;

	case WMT_IOCTL_SET_PATCH_INFO:{
			WMT_PATCH_INFO wMtPatchInfo;
			P_WMT_PATCH_INFO pTemp = NULL;
			UINT32 dWloadSeq;
			static UINT32 counter = 0;

			if (!pPatchInfo) {
				WMT_ERR_FUNC("NULL patch info pointer\n");
				break;
			}

			if (copy_from_user(&wMtPatchInfo, (void *)arg, sizeof(WMT_PATCH_INFO))) {
				WMT_ERR_FUNC("copy_from_user failed at %d\n", __LINE__);
				iRet = -EFAULT;
				break;
			}

			dWloadSeq = wMtPatchInfo.dowloadSeq;
			WMT_DBG_FUNC
			    ("current download seq no is %d,patch name is %s,addres info is 0x%02x,0x%02x,0x%02x,0x%02x\n",
			     dWloadSeq, wMtPatchInfo.patchName, wMtPatchInfo.addRess[0],
			     wMtPatchInfo.addRess[1], wMtPatchInfo.addRess[2],
			     wMtPatchInfo.addRess[3]);
			osal_memcpy(pPatchInfo + dWloadSeq - 1, &wMtPatchInfo,
				    sizeof(WMT_PATCH_INFO));
			pTemp = pPatchInfo + dWloadSeq - 1;
			if (++counter == pAtchNum) {
				wmt_lib_set_patch_info(pPatchInfo);
				counter = 0;
			}
		}
		break;

	case WMT_IOCTL_PORT_NAME:{
			INT8 cUartName[NAME_MAX + 1];
			if (copy_from_user(cUartName, (void *)arg, NAME_MAX)) {
				iRet = -EFAULT;
				break;
			}
			cUartName[NAME_MAX] = '\0';
			wmt_lib_set_uart_name(cUartName);
		}
		break;

	case WMT_IOCTL_WMT_CFG_NAME:
		{
			INT8 cWmtCfgName[NAME_MAX + 1];
			if (copy_from_user(cWmtCfgName, (void *)arg, NAME_MAX)) {
				iRet = -EFAULT;
				break;
			}
			cWmtCfgName[NAME_MAX] = '\0';
			wmt_conf_set_cfg_file(cWmtCfgName);
		}
		break;
	case WMT_IOCTL_WMT_QUERY_CHIPID:
		{
#if !(DELETE_HIF_SDIO_CHRDEV)
			iRet = mtk_wcn_hif_sdio_query_chipid(1);
#else
			iRet = mtk_wcn_wmt_chipid_query();
#endif
		}
		break;
	case WMT_IOCTL_WMT_TELL_CHIPID:
		{
#if !(DELETE_HIF_SDIO_CHRDEV)
			iRet = mtk_wcn_hif_sdio_tell_chipid(arg);
#endif

			if (0x6628 == arg || 0x6630 == arg) {
				wmt_lib_merge_if_flag_ctrl(1);
			} else {
				wmt_lib_merge_if_flag_ctrl(0);
			}
		}
		break;
	case WMT_IOCTL_WMT_COREDUMP_CTRL:
		{
			if (0 == arg) {
				mtk_wcn_stp_coredump_flag_ctrl(0);
			} else {
				mtk_wcn_stp_coredump_flag_ctrl(1);
			}
		}
		break;
		case WMT_IOCTL_WMT_STP_ASSERT_CTRL:
			if (MTK_WCN_BOOL_TRUE == wmt_lib_btm_cb(BTM_TRIGGER_STP_ASSERT_OP))
			{
				WMT_INFO_FUNC("trigger stp assert succeed\n");
				iRet = 0;
			}
			else
			{
				WMT_INFO_FUNC("trigger stp assert failed\n");
				iRet = -1;
			}
		break;
	default:
		iRet = -EINVAL;
		WMT_WARN_FUNC("unknown cmd (%d)\n", cmd);
		break;
	}


	return iRet;
}
INT32 wmt_dbg_stp_trigger_assert(INT32 par1, INT32 par2, INT32 par3)
{
    wmt_lib_btm_cb(BTM_TRIGGER_STP_ASSERT_OP);
    return 0;
}