[WCNCR00148136] softap: add dfs master feature
[Description]
Add dfs master feature
1. Add commands and events for dfs master
2. Add dfs driver flow
Change-Id: I0701c8bc689ec21530b09b05922cd9e71622b0e8
Feature: softap
Signed-off-by: Chun Lee <chun.lee@mediatek.com>
CR-Id: WCNCR00148136
diff --git a/common/wlan_lib.c b/common/wlan_lib.c
index e74b4d0..cff2fc4 100644
--- a/common/wlan_lib.c
+++ b/common/wlan_lib.c
@@ -165,6 +165,9 @@
wlanoidRftestSetTestMode,
wlanoidRftestSetAbortTestMode,
wlanoidSetAcpiDevicePowerState,
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ wlanoidQuerySetRddReport,
+#endif
};
#if CFG_SUPPORT_COMPRESSION_FW_OPTION
#define COMPRESSION_OPTION_OFFSET 4
diff --git a/common/wlan_oid.c b/common/wlan_oid.c
index 4defa5a..40ef18b 100644
--- a/common/wlan_oid.c
+++ b/common/wlan_oid.c
@@ -11926,6 +11926,75 @@
return rWlanStatus;
}
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief This routine is called to set rdd report.
+*
+* \param[in] pvAdapter Pointer to the Adapter structure.
+* \param[out] pvQueryBuf A pointer to the buffer that holds the result of
+* the query.
+* \param[in] u4QueryBufLen The length of the query buffer.
+* \param[out] pu4QueryInfoLen If the call is successful, returns the number of
+* bytes written into the query buffer. If the call
+* failed due to invalid length of the query buffer,
+* returns the amount of storage needed.
+*
+* \retval WLAN_STATUS_SUCCESS
+* \retval WLAN_STATUS_INVALID_LENGTH
+*/
+/*----------------------------------------------------------------------------*/
+WLAN_STATUS
+wlanoidQuerySetRddReport(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen,
+ OUT PUINT_32 pu4SetInfoLen)
+{
+ P_PARAM_CUSTOM_SET_RDD_REPORT_T prSetRddReport;
+ P_CMD_RDD_ON_OFF_CTRL_T prCmdRddOnOffCtrl;
+ WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS;
+
+ DEBUGFUNC("wlanoidQuerySetRddReport");
+
+ ASSERT(prAdapter);
+ ASSERT(pu4SetInfoLen);
+
+ *pu4SetInfoLen = sizeof(P_PARAM_CUSTOM_SET_RDD_REPORT_T);
+
+ /*if (u4SetBufferLen < sizeof(P_PARAM_CUSTOM_SET_RDD_REPORT_T))*/
+ /*return WLAN_STATUS_INVALID_LENGTH;*/
+
+ ASSERT(pvSetBuffer);
+
+ prSetRddReport = (P_PARAM_CUSTOM_SET_RDD_REPORT_T) pvSetBuffer;
+
+ prCmdRddOnOffCtrl = (P_CMD_RDD_ON_OFF_CTRL_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG,
+ sizeof(P_CMD_RDD_ON_OFF_CTRL_T));
+
+ prCmdRddOnOffCtrl->ucDfsCtrl = RDD_RADAR_EMULATE;
+
+ prCmdRddOnOffCtrl->ucRddIdx = prSetRddReport->ucDbdcIdx;
+
+ if (prCmdRddOnOffCtrl->ucRddIdx)
+ prCmdRddOnOffCtrl->ucRddInSel = RDD_IN_SEL_1;
+ else
+ prCmdRddOnOffCtrl->ucRddInSel = RDD_IN_SEL_0;
+
+ DBGLOG(INIT, INFO, "MT6632 : wlanoidQuerySetRddReport - DFS ctrl: %.d, RDD index: %d\n",
+ prCmdRddOnOffCtrl->ucDfsCtrl, prCmdRddOnOffCtrl->ucRddIdx);
+
+ rWlanStatus = wlanSendSetQueryCmd(prAdapter,
+ CMD_ID_RDD_ON_OFF_CTRL,
+ TRUE, /* fgSetQuery Bit: True->write False->read*/
+ FALSE, /* fgNeedResp */
+ FALSE, /* fgIsOid*/
+ NULL,
+ NULL,
+ sizeof(CMD_RDD_ON_OFF_CTRL_T),
+ (PUINT_8) (prCmdRddOnOffCtrl), NULL, 0);
+
+ return rWlanStatus;
+}
+#endif
+
/*----------------------------------------------------------------------------*/
/*!
* \brief This routine is used to turn radio off.
diff --git a/include/config.h b/include/config.h
index b7b2581..a7cb895 100644
--- a/include/config.h
+++ b/include/config.h
@@ -154,6 +154,7 @@
#define CFG_SUPPORT_RRM 0 /* Radio Reasource Measurement (802.11k) */
#define CFG_SUPPORT_DFS 1 /* DFS (802.11h) */
+#define CFG_SUPPORT_DFS_MASTER 0
#if (CFG_SUPPORT_DFS == 1) /* Add by Enlai */
#define CFG_SUPPORT_QUIET 0 /* Quiet (802.11h) */
diff --git a/include/mgmt/cnm.h b/include/mgmt/cnm.h
index 2b92884..5695b9c 100644
--- a/include/mgmt/cnm.h
+++ b/include/mgmt/cnm.h
@@ -89,6 +89,9 @@
CH_REQ_TYPE_P2P_LISTEN,
CH_REQ_TYPE_OFFCHNL_TX,
CH_REQ_TYPE_GO_START_BSS,
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ CH_REQ_TYPE_DFS_CAC,
+#endif
CH_REQ_TYPE_NUM
} ENUM_CH_REQ_TYPE_T, *P_ENUM_CH_REQ_TYPE_T;
@@ -211,6 +214,12 @@
VOID cnmChMngrHandleChEvent(P_ADAPTER_T prAdapter, P_WIFI_EVENT_T prEvent);
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+VOID cnmRadarDetectEvent(P_ADAPTER_T prAdapter, P_WIFI_EVENT_T prEvent);
+
+VOID cnmCsaDoneEvent(P_ADAPTER_T prAdapter, P_WIFI_EVENT_T prEvent);
+#endif
+
BOOLEAN
cnmPreferredChannel(P_ADAPTER_T prAdapter, P_ENUM_BAND_T prBand, PUINT_8 pucPrimaryChannel, P_ENUM_CHNL_EXT_T prBssSCO);
diff --git a/include/mgmt/hem_mbox.h b/include/mgmt/hem_mbox.h
index 314995e..52a2f65 100644
--- a/include/mgmt/hem_mbox.h
+++ b/include/mgmt/hem_mbox.h
@@ -89,6 +89,10 @@
MID_CNM_P2P_CH_GRANT, /* CNM notify P2P for indicating channel granted */
MID_CNM_BOW_CH_GRANT, /* CNM notify BOW for indicating channel granted */
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ MID_CNM_P2P_RADAR_DETECT,
+ MID_CNM_P2P_CSA_DONE,
+#endif
/*--------------------------------------------------*/
/* SCN Module Mailbox Messages */
/*--------------------------------------------------*/
@@ -150,6 +154,10 @@
MID_MNY_P2P_START_AP,
MID_MNY_P2P_DEL_IFACE,
MID_MNY_P2P_MGMT_FRAME_UPDATE,
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ MID_MNY_P2P_DFS_CAC,
+ MID_MNY_P2P_SET_NEW_CHANNEL,
+#endif
#if CFG_SUPPORT_WFD
MID_MNY_P2P_WFD_CFG_UPDATE,
#endif
diff --git a/include/mgmt/p2p_func.h b/include/mgmt/p2p_func.h
index 3d25b38..81ae4a0 100644
--- a/include/mgmt/p2p_func.h
+++ b/include/mgmt/p2p_func.h
@@ -136,6 +136,12 @@
VOID p2pFuncReleaseCh(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo);
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+VOID p2pFuncStartRdd(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx);
+
+VOID p2pFuncDfsSwitchCh(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P2P_CHNL_REQ_INFO_T rP2pChnlReqInfo);
+#endif
+
VOID p2pFuncSetChannel(IN P_ADAPTER_T prAdapter, IN UINT_8 ucRoleIdx, IN P_RF_CHANNEL_INFO_T prRfChannelInfo);
BOOLEAN p2pFuncRetryJOIN(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_P2P_JOIN_INFO_T prJoinInfo);
diff --git a/include/mgmt/p2p_role.h b/include/mgmt/p2p_role.h
index 0a06eb7..ea224ba 100644
--- a/include/mgmt/p2p_role.h
+++ b/include/mgmt/p2p_role.h
@@ -166,6 +166,31 @@
INT_32 i4InactiveTimeout;
} MSG_P2P_START_AP_T, *P_MSG_P2P_START_AP_T;
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+typedef struct _MSG_P2P_DFS_CAC_T {
+ MSG_HDR_T rMsgHdr;
+ ENUM_CHANNEL_WIDTH_T eChannelWidth;
+ UINT_8 ucRoleIdx;
+} MSG_P2P_DFS_CAC_T, *P_MSG_P2P_DFS_CAC_T;
+
+typedef struct _MSG_P2P_RADAR_DETECT_T {
+ MSG_HDR_T rMsgHdr;
+ UINT_8 ucBssIndex;
+} MSG_P2P_RADAR_DETECT_T, *P_MSG_P2P_RADAR_DETECT_T;
+
+typedef struct _MSG_P2P_SET_NEW_CHANNEL_T {
+ MSG_HDR_T rMsgHdr;
+ ENUM_CHANNEL_WIDTH_T eChannelWidth;
+ UINT_8 ucRoleIdx;
+ UINT_8 ucBssIndex;
+} MSG_P2P_SET_NEW_CHANNEL_T, *P_MSG_P2P_SET_NEW_CHANNEL_T;
+
+typedef struct _MSG_P2P_CSA_DONE_T {
+ MSG_HDR_T rMsgHdr;
+ UINT_8 ucBssIndex;
+} MSG_P2P_CSA_DONE_T, *P_MSG_P2P_CSA_DONE_T;
+#endif
+
typedef struct _MSG_P2P_DEL_IFACE_T {
MSG_HDR_T rMsgHdr;
UINT_8 ucRoleIdx;
@@ -199,6 +224,10 @@
P2P_ROLE_STATE_REQING_CHANNEL,
P2P_ROLE_STATE_AP_CHNL_DETECTION, /* Requesting Channel to Send Specific Frame. */
P2P_ROLE_STATE_GC_JOIN,
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ P2P_ROLE_STATE_DFS_CAC,
+ P2P_ROLE_STATE_SWITCH_CHANNEL,
+#endif
P2P_ROLE_STATE_NUM
} ENUM_P2P_ROLE_STATE_T, *P_ENUM_P2P_ROLE_STATE_T;
@@ -285,6 +314,16 @@
VOID p2pRoleFsmRunEventStopAP(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr);
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+VOID p2pRoleFsmRunEventDfsCac(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr);
+
+VOID p2pRoleFsmRunEventRadarDet(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr);
+
+VOID p2pRoleFsmRunEventSetNewChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr);
+
+VOID p2pRoleFsmRunEventCsaDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr);
+#endif
+
VOID p2pRoleFsmRunEventScanRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr);
VOID
diff --git a/include/mgmt/p2p_role_state.h b/include/mgmt/p2p_role_state.h
index 2edf010..a6fad85 100644
--- a/include/mgmt/p2p_role_state.h
+++ b/include/mgmt/p2p_role_state.h
@@ -94,6 +94,32 @@
IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo,
IN P_P2P_JOIN_INFO_T prJoinInfo, IN ENUM_P2P_ROLE_STATE_T eNextState);
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+VOID
+p2pRoleStateInit_DFS_CAC(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo);
+
+VOID
+p2pRoleStateAbort_DFS_CAC(IN P_ADAPTER_T prAdapter,
+ IN P_BSS_INFO_T prP2pRoleBssInfo,
+ IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, IN ENUM_P2P_ROLE_STATE_T eNextState);
+
+VOID
+p2pRoleStateInit_SWITCH_CHANNEL(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo);
+
+VOID
+p2pRoleStateAbort_SWITCH_CHANNEL(IN P_ADAPTER_T prAdapter,
+ IN P_BSS_INFO_T prP2pRoleBssInfo,
+ IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, IN ENUM_P2P_ROLE_STATE_T eNextState);
+
+VOID
+p2pRoleStatePrepare_To_DFS_CAC_STATE(IN P_ADAPTER_T prAdapter,
+ IN P_BSS_INFO_T prBssInfo,
+ IN ENUM_CHANNEL_WIDTH_T rChannelWidth,
+ IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo,
+ OUT P_P2P_CHNL_REQ_INFO_T prChnlReqInfo);
+
+#endif
+
VOID
p2pRoleStatePrepare_To_REQING_CHANNEL_STATE(IN P_ADAPTER_T prAdapter,
IN P_BSS_INFO_T prBssInfo,
diff --git a/include/mgmt/rlm.h b/include/mgmt/rlm.h
index 3a374c1..eebb855 100644
--- a/include/mgmt/rlm.h
+++ b/include/mgmt/rlm.h
@@ -289,6 +289,10 @@
BOOLEAN rlmParseCheckMTKOuiIE(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, IN PUINT_32 pu4Cap);
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+VOID rlmGenerateCsaIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo);
+#endif
+
VOID rlmProcessBcn(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength);
VOID rlmProcessAssocRsp(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength);
diff --git a/include/nic/adapter.h b/include/nic/adapter.h
index faf317e..f00b541 100644
--- a/include/nic/adapter.h
+++ b/include/nic/adapter.h
@@ -243,6 +243,10 @@
ENUM_OP_MODE_T eIntendOPMode;
#endif
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ BOOLEAN fgIsDfsActive;
+#endif
+
BOOLEAN fgIsInUse; /* For CNM to assign BSS_INFO */
BOOLEAN fgIsNetActive; /* TRUE if this network has been activated */
@@ -744,6 +748,11 @@
UINT_8 aucMtkFeature[4];
#endif
+ BOOLEAN fgCsaInProgress;
+ UINT_8 ucChannelSwitchMode;
+ UINT_8 ucNewChannelNumber;
+ UINT_8 ucChannelSwitchCount;
+
UINT_32 u4HifIstLoopCount;
UINT_32 u4Rx2OsLoopCount;
UINT_32 u4HifTxloopCount;
diff --git a/include/nic/mac.h b/include/nic/mac.h
index fe90d83..4891f5f 100644
--- a/include/nic/mac.h
+++ b/include/nic/mac.h
@@ -1234,6 +1234,9 @@
#define MTK_SYNERGY_CAP2 0x0
#define MTK_SYNERGY_CAP3 0x0
+/* 802.11h CSA element */
+#define ELEM_MIN_LEN_CSA 3
+
/* 3 Management frame body components (III): 7.4 Action frame format details. */
/* 7.4.1 Spectrum Measurement Action frame details */
#define ACTION_MEASUREMENT_REQ 0 /* Spectrum measurement request */
@@ -2617,6 +2620,8 @@
#define MTK_OUI_IE(fp) ((P_IE_MTK_OUI_T) fp)
+#define CSA_IE(fp) ((P_IE_CHANNEL_SWITCH_T) fp)
+
#define SUPPORTED_CHANNELS_IE(fp) ((P_IE_SUPPORTED_CHANNELS_T)fp)
#define TIMEOUT_INTERVAL_IE(fp) ((IE_TIMEOUT_INTERVAL_T *)fp)
diff --git a/include/nic_cmd_event.h b/include/nic_cmd_event.h
index a30ca6b..077c143 100644
--- a/include/nic_cmd_event.h
+++ b/include/nic_cmd_event.h
@@ -123,6 +123,11 @@
#define RDD_PULSE_OFFSET6 6
#define RDD_PULSE_OFFSET7 7
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+#define RDD_IN_SEL_0 0
+#define RDD_IN_SEL_1 1
+#endif
+
#if CFG_SUPPORT_QA_TOOL
#define IQ_FILE_LINE_OFFSET 18
#define IQ_FILE_IQ_STR_LEN 8
@@ -505,6 +510,10 @@
CMD_ID_GET_BUG_REPORT = 0x89, /* 0x89 (Query) */
CMD_ID_GET_NIC_CAPABILITY_V2 = 0x8A,/* 0x8A (Query) */
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ CMD_ID_RDD_ON_OFF_CTRL = 0x8F, /* 0x8F(Set) */
+#endif
+
#if CFG_SUPPORT_CAL_RESULT_BACKUP_TO_HOST
CMD_ID_CAL_BACKUP_IN_HOST_V2 = 0xAE, /* 0xAE (Set / Query) */
#endif
@@ -611,6 +620,11 @@
EVENT_ID_MU_GET_LQ = 0x54,
#endif
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ EVENT_ID_RDD_REPORT = 0x60,
+ EVENT_ID_CSA_DONE = 0x61,
+#endif
+
EVENT_ID_TDLS = 0x80, /* TDLS event_id */
EVENT_ID_UPDATE_COEX_PHYRATE = 0x90, /* 0x90 (Unsolicited) */
@@ -1562,6 +1576,15 @@
UINT_8 ucReserved[1];
} CMD_BT_OVER_WIFI, *P_CMD_BT_OVER_WIFI;
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+typedef struct _CMD_RDD_ON_OFF_CTRL_T {
+ UINT_8 ucDfsCtrl;
+ UINT_8 ucRddIdx;
+ UINT_8 ucRddInSel;
+ UINT_8 ucReserve[1];
+} CMD_RDD_ON_OFF_CTRL_T, *P_CMD_RDD_ON_OFF_CTRL_T;
+#endif
+
/* EVENT_BT_OVER_WIFI */
typedef struct _EVENT_BT_OVER_WIFI {
UINT_8 ucLinkStatus;
@@ -1755,6 +1778,16 @@
TXS_IS_EXIST
} ENUM_TXS_CONTROL_FLAG_T, *P_ENUM_TXS_CONTROL_FLAG_T;
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+typedef enum _ENUM_DFS_CTRL_T {
+ RDD_STOP = 0,
+ RDD_START,
+ RDD_DET_MODE,
+ RDD_RADAR_EMULATE,
+ RDD_START_TXQ
+} ENUM_DFS_CTRL_T, *P_ENUM_DFS_CTRL_T;
+#endif
+
typedef struct _CMD_BSS_ACTIVATE_CTRL {
UINT_8 ucBssIndex;
UINT_8 ucActive;
diff --git a/include/wlan_oid.h b/include/wlan_oid.h
index 0f77fd9..7f3527e 100644
--- a/include/wlan_oid.h
+++ b/include/wlan_oid.h
@@ -719,6 +719,11 @@
INT_8 cTxPwr5GHT40_MCS7;
} PARAM_CUSTOM_SET_TX_TARGET_POWER_T, *P_PARAM_CUSTOM_SET_TX_TARGET_POWER_T;
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+typedef struct _PARAM_CUSTOM_SET_RDD_REPORT_T {
+ UINT_8 ucDbdcIdx; /* 0:Band 0, 1: Band1 */
+} PARAM_CUSTOM_SET_RDD_REPORT_T, *P_PARAM_CUSTOM_SET_RDD_REPORT_T;
+#endif
typedef struct _PARAM_CUSTOM_ACCESS_RX_STAT {
UINT_32 u4SeqNum;
@@ -2734,6 +2739,12 @@
wlanoidQuerySetTxTargetPower(IN P_ADAPTER_T prAdapter,
IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen);
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+WLAN_STATUS
+wlanoidQuerySetRddReport(IN P_ADAPTER_T prAdapter,
+ IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen);
+#endif
+
#if CFG_AUTO_CHANNEL_SEL_SUPPORT
WLAN_STATUS
wlanoidQueryLteSafeChannel(IN P_ADAPTER_T prAdapter,
diff --git a/mgmt/bss.c b/mgmt/bss.c
index 748d641..1e011db 100644
--- a/mgmt/bss.c
+++ b/mgmt/bss.c
@@ -133,6 +133,9 @@
#if CFG_SUPPORT_MTK_SYNERGY
, {(ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI), NULL, rlmGenerateMTKOuiIE} /* 221 */
#endif
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ , {(ELEM_HDR_LEN + ELEM_MIN_LEN_CSA), NULL, rlmGenerateCsaIE} /* 37 */
+#endif
};
diff --git a/mgmt/cnm.c b/mgmt/cnm.c
index e6243e2..3c47e49 100644
--- a/mgmt/cnm.c
+++ b/mgmt/cnm.c
@@ -409,6 +409,60 @@
prCnmInfo->fgChGranted = TRUE;
}
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+VOID cnmRadarDetectEvent(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent)
+{
+ P_BSS_INFO_T prBssInfo;
+ P_MSG_P2P_RADAR_DETECT_T prP2pRddDetMsg;
+ UINT_8 ucBssIndex;
+
+ DBGLOG(CNM, INFO, "cnmRadarDetectEvent.\n");
+
+ prP2pRddDetMsg = (P_MSG_P2P_RADAR_DETECT_T) cnmMemAlloc(prAdapter,
+ RAM_TYPE_MSG, sizeof(P_MSG_P2P_RADAR_DETECT_T));
+
+ prP2pRddDetMsg->rMsgHdr.eMsgId = MID_CNM_P2P_RADAR_DETECT;
+
+ for (ucBssIndex = 0; ucBssIndex < BSS_INFO_NUM; ucBssIndex++) {
+ prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex);
+
+ if (prBssInfo && prBssInfo->fgIsDfsActive) {
+ prP2pRddDetMsg->ucBssIndex = ucBssIndex;
+ break;
+ }
+ }
+
+ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T)prP2pRddDetMsg, MSG_SEND_METHOD_BUF);
+}
+
+VOID cnmCsaDoneEvent(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent)
+{
+ P_BSS_INFO_T prBssInfo;
+ P_MSG_P2P_CSA_DONE_T prP2pCsaDoneMsg;
+ UINT_8 ucBssIndex;
+
+ DBGLOG(CNM, INFO, "cnmCsaDoneEvent.\n");
+
+ prP2pCsaDoneMsg = (P_MSG_P2P_CSA_DONE_T) cnmMemAlloc(prAdapter,
+ RAM_TYPE_MSG, sizeof(P_MSG_P2P_CSA_DONE_T));
+
+ prAdapter->rWifiVar.fgCsaInProgress = FALSE;
+
+ prP2pCsaDoneMsg->rMsgHdr.eMsgId = MID_CNM_P2P_CSA_DONE;
+
+ for (ucBssIndex = 0; ucBssIndex < BSS_INFO_NUM; ucBssIndex++) {
+ prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex);
+
+ if (prBssInfo && prBssInfo->fgIsDfsActive) {
+ prP2pCsaDoneMsg->ucBssIndex = ucBssIndex;
+ break;
+ }
+ }
+
+ mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T)prP2pCsaDoneMsg, MSG_SEND_METHOD_BUF);
+}
+#endif
+
/*----------------------------------------------------------------------------*/
/*!
* @brief This function is invoked for P2P or BOW networks
diff --git a/mgmt/hem_mbox.c b/mgmt/hem_mbox.c
index d8acb48..af49380 100644
--- a/mgmt/hem_mbox.c
+++ b/mgmt/hem_mbox.c
@@ -146,6 +146,13 @@
(PUINT_8) DISP_STRING("MID_MNY_P2P_NET_DEV_REGISTER"),
(PUINT_8) DISP_STRING("MID_MNY_P2P_START_AP"),
(PUINT_8) DISP_STRING("MID_MNY_P2P_UPDATE_IE_BUF"),
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ (PUINT_8) DISP_STRING("MID_CNM_P2P_RADAR_DETECT"),
+ (PUINT_8) DISP_STRING("MID_CNM_P2P_CSA_DONE"),
+ (PUINT_8) DISP_STRING("MID_MNY_P2P_DFS_CAC"),
+ (PUINT_8) DISP_STRING("MID_MNY_P2P_SET_NEW_CHANNEL"),
+#endif
+
#endif
#if CFG_SUPPORT_ADHOC
@@ -179,6 +186,11 @@
{MID_CNM_P2P_CH_GRANT, mboxDummy},
#endif
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ {MID_CNM_P2P_RADAR_DETECT, p2pRoleFsmRunEventRadarDet},
+ {MID_CNM_P2P_CSA_DONE, p2pRoleFsmRunEventCsaDone},
+#endif
+
#if CFG_ENABLE_BT_OVER_WIFI
{MID_CNM_BOW_CH_GRANT, bowRunEventChGrant},
#else
@@ -252,6 +264,10 @@
{MID_MNY_P2P_START_AP, p2pRoleFsmRunEventStartAP},
{MID_MNY_P2P_DEL_IFACE, p2pRoleFsmRunEventDelIface},
{MID_MNY_P2P_MGMT_FRAME_UPDATE, p2pFsmRunEventUpdateMgmtFrame},
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ {MID_MNY_P2P_DFS_CAC, p2pRoleFsmRunEventDfsCac},
+ {MID_MNY_P2P_SET_NEW_CHANNEL, p2pRoleFsmRunEventSetNewChannel},
+#endif
#if CFG_SUPPORT_WFD
{MID_MNY_P2P_WFD_CFG_UPDATE, p2pFsmRunEventWfdSettingUpdate},
#endif
diff --git a/mgmt/p2p_func.c b/mgmt/p2p_func.c
index 162ce5c..4bbacee 100644
--- a/mgmt/p2p_func.c
+++ b/mgmt/p2p_func.c
@@ -963,6 +963,98 @@
} while (FALSE);
} /* p2pFuncAcquireCh */
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+VOID p2pFuncStartRdd(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx)
+{
+ P_CMD_RDD_ON_OFF_CTRL_T prCmdRddOnOffCtrl;
+
+ DEBUGFUNC("p2pFuncStartRdd()");
+
+ do {
+ ASSERT_BREAK((prAdapter != NULL));
+
+ prCmdRddOnOffCtrl = (P_CMD_RDD_ON_OFF_CTRL_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG,
+ sizeof(P_CMD_RDD_ON_OFF_CTRL_T));
+
+ prCmdRddOnOffCtrl->ucDfsCtrl = RDD_START;
+
+ prCmdRddOnOffCtrl->ucRddIdx = prAdapter->aprBssInfo[ucBssIdx]->eDBDCBand;
+
+ if (prCmdRddOnOffCtrl->ucRddIdx)
+ prCmdRddOnOffCtrl->ucRddInSel = RDD_IN_SEL_1;
+ else
+ prCmdRddOnOffCtrl->ucRddInSel = RDD_IN_SEL_0;
+
+ DBGLOG(P2P, INFO, "p2pFuncStartRdd: Start Radar detection - DFS ctrl: %.d, RDD index: %d\n",
+ prCmdRddOnOffCtrl->ucDfsCtrl, prCmdRddOnOffCtrl->ucRddIdx);
+
+ wlanSendSetQueryCmd(prAdapter,
+ CMD_ID_RDD_ON_OFF_CTRL,
+ TRUE,
+ FALSE,
+ FALSE,
+ NULL,
+ NULL,
+ sizeof(CMD_RDD_ON_OFF_CTRL_T), (PUINT_8) prCmdRddOnOffCtrl, NULL, 0);
+
+ } while (FALSE);
+} /* p2pFuncStartRdd */
+
+VOID p2pFuncDfsSwitchCh(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P2P_CHNL_REQ_INFO_T rP2pChnlReqInfo)
+{
+
+ P_GLUE_INFO_T prGlueInfo;
+ P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL;
+ P_CMD_RDD_ON_OFF_CTRL_T prCmdRddOnOffCtrl;
+
+ DEBUGFUNC("p2pFuncDfsSwitchCh()");
+
+ do {
+ ASSERT_BREAK((prAdapter != NULL) && (prBssInfo != NULL));
+
+ /* Setup Channel, Band */
+ prBssInfo->ucPrimaryChannel = rP2pChnlReqInfo.ucReqChnlNum;
+ prBssInfo->eBand = rP2pChnlReqInfo.eBand;
+ prBssInfo->eBssSCO = rP2pChnlReqInfo.eChnlSco;
+
+ /* Setup channel and bandwidth */
+ rlmBssInitForAPandIbss(prAdapter, prBssInfo);
+
+ /* Update Beacon again for network phy type confirmed. */
+ bssUpdateBeaconContent(prAdapter, prBssInfo->ucBssIndex);
+
+ /* Reset HW TSF Update Mode and Beacon Mode */
+ nicUpdateBss(prAdapter, prBssInfo->ucBssIndex);
+
+ prCmdRddOnOffCtrl = (P_CMD_RDD_ON_OFF_CTRL_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG,
+ sizeof(P_CMD_RDD_ON_OFF_CTRL_T));
+
+ prCmdRddOnOffCtrl->ucDfsCtrl = RDD_START_TXQ;
+
+ DBGLOG(P2P, INFO, "p2pFuncDfsSwitchCh: Start TXQ - DFS ctrl: %.d\n", prCmdRddOnOffCtrl->ucDfsCtrl);
+
+ wlanSendSetQueryCmd(prAdapter,
+ CMD_ID_RDD_ON_OFF_CTRL,
+ TRUE,
+ FALSE,
+ FALSE,
+ NULL,
+ NULL,
+ sizeof(CMD_RDD_ON_OFF_CTRL_T), (PUINT_8) prCmdRddOnOffCtrl, NULL, 0);
+
+ prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prBssInfo->u4PrivateData);
+
+ prGlueInfo = prAdapter->prGlueInfo;
+
+ DBGLOG(P2P, INFO, "p2pFuncDfsSwitchCh: Update to OS\n");
+ cfg80211_ch_switch_notify(prGlueInfo->prP2PInfo[prP2pRoleFsmInfo->ucRoleIndex]->prDevHandler,
+ prGlueInfo->prP2PInfo[prP2pRoleFsmInfo->ucRoleIndex]->chandef);
+ DBGLOG(P2P, INFO, "p2pFuncDfsSwitchCh: Update to OS Done\n");
+
+ } while (FALSE);
+} /* p2pFuncDfsSwitchCh */
+#endif
+
#if 0
WLAN_STATUS
p2pFuncBeaconUpdate(IN P_ADAPTER_T prAdapter,
diff --git a/mgmt/p2p_role_fsm.c b/mgmt/p2p_role_fsm.c
index 4d93803..74f7bce 100644
--- a/mgmt/p2p_role_fsm.c
+++ b/mgmt/p2p_role_fsm.c
@@ -60,7 +60,13 @@
(PUINT_8) DISP_STRING("P2P_ROLE_STATE_SCAN"),
(PUINT_8) DISP_STRING("P2P_ROLE_STATE_REQING_CHANNEL"),
(PUINT_8) DISP_STRING("P2P_ROLE_STATE_AP_CHNL_DETECTION"),
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ (PUINT_8) DISP_STRING("P2P_ROLE_STATE_GC_JOIN"),
+ (PUINT_8) DISP_STRING("P2P_ROLE_STATE_DFS_CAC"),
+ (PUINT_8) DISP_STRING("P2P_ROLE_STATE_SWITCH_CHANNEL")
+#else
(PUINT_8) DISP_STRING("P2P_ROLE_STATE_GC_JOIN")
+#endif
};
/*lint -restore */
@@ -372,6 +378,29 @@
prP2pRoleFsmInfo, &(prP2pRoleFsmInfo->rJoinInfo), eNextState);
}
break;
+
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ case P2P_ROLE_STATE_DFS_CAC:
+ if (!fgIsTransitionOut) {
+ p2pRoleStateInit_DFS_CAC(prAdapter,
+ prP2pRoleFsmInfo->ucBssIndex,
+ &(prP2pRoleFsmInfo->rChnlReqInfo));
+ } else {
+ p2pRoleStateAbort_DFS_CAC(prAdapter, prP2pRoleBssInfo,
+ prP2pRoleFsmInfo, eNextState);
+ }
+ break;
+ case P2P_ROLE_STATE_SWITCH_CHANNEL:
+ if (!fgIsTransitionOut) {
+ p2pRoleStateInit_SWITCH_CHANNEL(prAdapter,
+ prP2pRoleFsmInfo->ucBssIndex,
+ &(prP2pRoleFsmInfo->rChnlReqInfo));
+ } else {
+ p2pRoleStateAbort_SWITCH_CHANNEL(prAdapter, prP2pRoleBssInfo,
+ prP2pRoleFsmInfo, eNextState);
+ }
+ break;
+#endif
default:
ASSERT(FALSE);
break;
@@ -408,6 +437,12 @@
DBGLOG(P2P, ERROR,
"Current P2P Role State P2P_ROLE_STATE_GC_JOIN is unexpected for FSM timeout event.\n");
break;
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ case P2P_ROLE_STATE_DFS_CAC:
+ p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, P2P_ROLE_STATE_IDLE);
+ kalP2PCacFinishedUpdate(prAdapter->prGlueInfo, prP2pRoleFsmInfo->ucRoleIndex);
+ break;
+#endif
default:
DBGLOG(P2P, ERROR,
"Current P2P Role State %d is unexpected for FSM timeout event.\n",
@@ -1063,6 +1098,184 @@
} /* p2pRoleFsmRunEventStopAP */
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+VOID p2pRoleFsmRunEventDfsCac(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr)
+{
+ P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL;
+ P_MSG_P2P_DFS_CAC_T prP2pDfsCacMsg = (P_MSG_P2P_DFS_CAC_T) NULL;
+ P_P2P_CONNECTION_REQ_INFO_T prP2pConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T) NULL;
+ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL;
+ ENUM_CHANNEL_WIDTH_T rChannelWidth;
+#if CFG_SUPPORT_DBDC
+ CNM_DBDC_CAP_T rDbdcCap;
+#endif /*CFG_SUPPORT_DBDC*/
+
+ do {
+ ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL));
+
+ DBGLOG(P2P, INFO, "p2pRoleFsmRunEventDfsCac\n");
+
+ prP2pDfsCacMsg = (P_MSG_P2P_DFS_CAC_T) prMsgHdr;
+
+ rChannelWidth = prP2pDfsCacMsg->eChannelWidth;
+
+ prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prP2pDfsCacMsg->ucRoleIdx);
+
+ DBGLOG(P2P, INFO, "p2pRoleFsmRunEventDfsCac with Role(%d)\n", prP2pDfsCacMsg->ucRoleIdx);
+
+ if (!prP2pRoleFsmInfo) {
+ DBGLOG(P2P, ERROR,
+ "p2pRoleFsmRunEventDfsCac: Corresponding P2P Role FSM empty: %d.\n",
+ prP2pDfsCacMsg->ucRoleIdx);
+ break;
+ }
+
+ prP2pBssInfo = prAdapter->aprBssInfo[prP2pRoleFsmInfo->ucBssIndex];
+
+ prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo);
+
+ if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2PConnSettings[prP2pDfsCacMsg->ucRoleIdx]))
+ prP2pConnReqInfo->eConnRequest = P2P_CONNECTION_TYPE_PURE_AP;
+ else
+ prP2pConnReqInfo->eConnRequest = P2P_CONNECTION_TYPE_GO;
+
+#if CFG_SUPPORT_DBDC
+ cnmDbdcEnableDecision(prAdapter, prP2pBssInfo->ucBssIndex, prP2pConnReqInfo->rChannelInfo.eBand);
+ cnmGetDbdcCapability(prAdapter,
+ prP2pBssInfo->ucBssIndex,
+ prP2pConnReqInfo->rChannelInfo.eBand,
+ prP2pConnReqInfo->rChannelInfo.ucChannelNum,
+ prAdapter->rWifiVar.ucNSS,
+ &rDbdcCap);
+
+ DBGLOG(P2P, INFO,
+ "p2pRoleFsmRunEventDfsCac: Set channel at CH %u.\n",
+ prP2pConnReqInfo->rChannelInfo.ucChannelNum);
+
+ prP2pBssInfo->eDBDCBand = rDbdcCap.ucDbdcBandIndex;
+ prP2pBssInfo->ucNss = rDbdcCap.ucNss;
+ prP2pBssInfo->ucWmmQueSet = rDbdcCap.ucWmmSetIndex;
+#endif /*CFG_SUPPORT_DBDC*/
+
+ if (prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_IDLE) {
+ /* Make sure the state is in IDLE state. */
+ p2pRoleFsmRunEventAbort(prAdapter, prP2pRoleFsmInfo);
+ }
+
+ /* Leave IDLE state. */
+ SET_NET_PWR_STATE_ACTIVE(prAdapter, prP2pBssInfo->ucBssIndex);
+
+ prP2pBssInfo->eIntendOPMode = OP_MODE_ACCESS_POINT;
+ prP2pBssInfo->fgIsDfsActive = TRUE;
+
+ if (prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucChannelNum != 0) {
+ DBGLOG(P2P, INFO, "Role(%d) Set channel at CH(%d)\n",
+ prP2pDfsCacMsg->ucRoleIdx,
+ prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucChannelNum);
+
+ p2pRoleStatePrepare_To_DFS_CAC_STATE(prAdapter,
+ GET_BSS_INFO_BY_INDEX(prAdapter, prP2pRoleFsmInfo->ucBssIndex),
+ rChannelWidth,
+ &(prP2pRoleFsmInfo->rConnReqInfo),
+ &(prP2pRoleFsmInfo->rChnlReqInfo));
+ p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, P2P_ROLE_STATE_DFS_CAC);
+ } else
+ ASSERT(FALSE);
+
+
+ } while (FALSE);
+
+} /*p2pRoleFsmRunEventDfsCac*/
+
+VOID p2pRoleFsmRunEventRadarDet(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr)
+{
+ P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL;
+ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL;
+ P_MSG_P2P_RADAR_DETECT_T prMsgP2pRddDetMsg;
+
+ do {
+ ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL));
+
+ DBGLOG(P2P, INFO, "p2pRoleFsmRunEventRadarDet\n");
+
+ prMsgP2pRddDetMsg = (P_MSG_P2P_RADAR_DETECT_T) prMsgHdr;
+
+ prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsgP2pRddDetMsg->ucBssIndex);
+
+ prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prP2pBssInfo->u4PrivateData);
+
+ DBGLOG(P2P, INFO, "p2pRoleFsmRunEventRadarDet with Role(%d)\n", prP2pRoleFsmInfo->ucRoleIndex);
+
+ if (prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_DFS_CAC &&
+ prP2pRoleFsmInfo->eCurrentState != P2P_ROLE_STATE_IDLE)
+ ASSERT(FALSE);
+
+ if (prP2pRoleFsmInfo->eCurrentState == P2P_ROLE_STATE_DFS_CAC)
+ p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, P2P_ROLE_STATE_IDLE);
+
+ kalP2PRddDetectUpdate(prAdapter->prGlueInfo, prP2pRoleFsmInfo->ucRoleIndex);
+
+ } while (FALSE);
+
+} /*p2pRoleFsmRunEventRadarDet*/
+
+VOID p2pRoleFsmRunEventSetNewChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr)
+{
+ P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL;
+ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL;
+ P_MSG_P2P_SET_NEW_CHANNEL_T prMsgP2pSetNewChannelMsg;
+
+ do {
+ ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL));
+
+ DBGLOG(P2P, INFO, "p2pRoleFsmRunEventSetNewChannel\n");
+
+ prMsgP2pSetNewChannelMsg = (P_MSG_P2P_SET_NEW_CHANNEL_T) prMsgHdr;
+
+ prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsgP2pSetNewChannelMsg->ucBssIndex);
+
+ prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prMsgP2pSetNewChannelMsg->ucRoleIdx);
+
+ prP2pRoleFsmInfo->rChnlReqInfo.ucReqChnlNum = prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucChannelNum;
+ prP2pRoleFsmInfo->rChnlReqInfo.eBand = prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.eBand;
+ prP2pRoleFsmInfo->rChnlReqInfo.eChannelWidth = prMsgP2pSetNewChannelMsg->eChannelWidth;
+ prP2pBssInfo->ucPrimaryChannel = prP2pRoleFsmInfo->rConnReqInfo.rChannelInfo.ucChannelNum;
+
+ prP2pRoleFsmInfo->rChnlReqInfo.ucCenterFreqS1 =
+ nicGetVhtS1(prP2pBssInfo->ucPrimaryChannel, prP2pRoleFsmInfo->rChnlReqInfo.eChannelWidth);
+ prP2pRoleFsmInfo->rChnlReqInfo.ucCenterFreqS2 = 0;
+
+
+ } while (FALSE);
+
+} /*p2pRoleFsmRunEventCsaDone*/
+
+VOID p2pRoleFsmRunEventCsaDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr)
+{
+ P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL;
+ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL;
+ P_MSG_P2P_CSA_DONE_T prMsgP2pCsaDoneMsg;
+
+ do {
+ ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL));
+
+ DBGLOG(P2P, INFO, "p2pRoleFsmRunEventCsaDone\n");
+
+ prMsgP2pCsaDoneMsg = (P_MSG_P2P_CSA_DONE_T) prMsgHdr;
+
+ prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsgP2pCsaDoneMsg->ucBssIndex);
+
+ prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prP2pBssInfo->u4PrivateData);
+
+ p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, P2P_ROLE_STATE_SWITCH_CHANNEL);
+
+
+ } while (FALSE);
+
+} /*p2pRoleFsmRunEventCsaDone*/
+#endif
+
+
VOID p2pRoleFsmRunEventConnectionRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr)
{
P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL;
@@ -1707,6 +1920,9 @@
{
P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL;
P_MSG_CH_GRANT_T prMsgChGrant = (P_MSG_CH_GRANT_T) NULL;
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL;
+#endif
UINT_8 ucTokenID = 0;
do {
@@ -1717,6 +1933,10 @@
prMsgChGrant = (P_MSG_CH_GRANT_T) prMsgHdr;
ucTokenID = prMsgChGrant->ucTokenID;
prChnlReqInfo = &(prP2pRoleFsmInfo->rChnlReqInfo);
+
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsgChGrant->ucBssIndex);
+#endif
if (prChnlReqInfo->u4MaxInterval != prMsgChGrant->u4GrantInterval) {
DBGLOG(P2P, WARN,
"P2P Role:%d Request Channel Interval:%d, Grant Interval:%d\n",
@@ -1747,6 +1967,22 @@
p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, eNextState);
break;
+
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ case P2P_ROLE_STATE_DFS_CAC:
+ p2pFuncStartRdd(prAdapter, prMsgChGrant->ucBssIndex);
+ cnmTimerStartTimer(prAdapter, &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer),
+ prAdapter->prGlueInfo->prP2PInfo[prP2pRoleFsmInfo->ucRoleIndex]->cac_time_ms);
+
+ DBGLOG(P2P, INFO, "p2pRoleFsmRunEventChnlGrant: CAC time = %ds\n",
+ prAdapter->prGlueInfo->prP2PInfo[prP2pRoleFsmInfo->ucRoleIndex]->
+ cac_time_ms/1000);
+ break;
+ case P2P_ROLE_STATE_SWITCH_CHANNEL:
+ p2pFuncDfsSwitchCh(prAdapter, prP2pBssInfo, prP2pRoleFsmInfo->rChnlReqInfo);
+ p2pRoleFsmStateTransition(prAdapter, prP2pRoleFsmInfo, P2P_ROLE_STATE_IDLE);
+ break;
+#endif
default:
/* Channel is granted under unexpected state.
* Driver should cancel channel privileagea before leaving the states.
diff --git a/mgmt/p2p_role_state.c b/mgmt/p2p_role_state.c
index bb2a594..a2ca649 100644
--- a/mgmt/p2p_role_state.c
+++ b/mgmt/p2p_role_state.c
@@ -301,6 +301,54 @@
} while (FALSE);
}
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+VOID
+p2pRoleStateInit_DFS_CAC(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo)
+{
+
+ do {
+ ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL));
+
+ p2pFuncAcquireCh(prAdapter, ucBssIdx, prChnlReqInfo);
+ } while (FALSE);
+} /* p2pRoleStateInit_DFS_CAC */
+
+VOID
+p2pRoleStateAbort_DFS_CAC(IN P_ADAPTER_T prAdapter,
+ IN P_BSS_INFO_T prP2pRoleBssInfo,
+ IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, IN ENUM_P2P_ROLE_STATE_T eNextState)
+{
+ do {
+ cnmTimerStopTimer(prAdapter, &(prP2pRoleFsmInfo->rP2pRoleFsmTimeoutTimer));
+
+ p2pFuncReleaseCh(prAdapter, prP2pRoleFsmInfo->ucBssIndex,
+ &(prP2pRoleFsmInfo->rChnlReqInfo));
+ } while (FALSE);
+} /* p2pRoleStateAbort_DFS_CAC */
+
+VOID
+p2pRoleStateInit_SWITCH_CHANNEL(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBssIdx, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo)
+{
+
+ do {
+ ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL));
+
+ p2pFuncAcquireCh(prAdapter, ucBssIdx, prChnlReqInfo);
+ } while (FALSE);
+} /* p2pRoleStateInit_SWITCH_CHANNEL */
+
+VOID
+p2pRoleStateAbort_SWITCH_CHANNEL(IN P_ADAPTER_T prAdapter,
+ IN P_BSS_INFO_T prP2pRoleBssInfo,
+ IN P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo, IN ENUM_P2P_ROLE_STATE_T eNextState)
+{
+ do {
+ p2pFuncReleaseCh(prAdapter, prP2pRoleFsmInfo->ucBssIndex,
+ &(prP2pRoleFsmInfo->rChnlReqInfo));
+ } while (FALSE);
+} /* p2pRoleStateAbort_SWITCH_CHANNEL */
+#endif
+
VOID
p2pRoleStatePrepare_To_REQING_CHANNEL_STATE(IN P_ADAPTER_T prAdapter,
IN P_BSS_INFO_T prBssInfo,
@@ -373,3 +421,62 @@
prBssInfo->eBssSCO = eSCOBackup;
} while (FALSE);
}
+
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+VOID
+p2pRoleStatePrepare_To_DFS_CAC_STATE(IN P_ADAPTER_T prAdapter,
+ IN P_BSS_INFO_T prBssInfo,
+ IN ENUM_CHANNEL_WIDTH_T rChannelWidth,
+ IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo,
+ OUT P_P2P_CHNL_REQ_INFO_T prChnlReqInfo)
+{
+ ENUM_BAND_T eBand;
+ UINT_8 ucChannel;
+ ENUM_CHNL_EXT_T eSCO;
+ ENUM_BAND_T eBandBackup;
+ UINT_8 ucChannelBackup;
+ ENUM_CHNL_EXT_T eSCOBackup;
+ P_P2P_ROLE_FSM_INFO_T prP2pRoleFsmInfo = (P_P2P_ROLE_FSM_INFO_T) NULL;
+
+ do {
+
+ eBandBackup = prBssInfo->eBand;
+ ucChannelBackup = prBssInfo->ucPrimaryChannel;
+ eSCOBackup = prBssInfo->eBssSCO;
+
+ prBssInfo->ucPrimaryChannel = prConnReqInfo->rChannelInfo.ucChannelNum;
+ prBssInfo->eBand = prConnReqInfo->rChannelInfo.eBand;
+
+ if (cnmPreferredChannel(prAdapter, &eBand, &ucChannel, &eSCO) &&
+ eSCO != CHNL_EXT_SCN && ucChannel == prBssInfo->ucPrimaryChannel && eBand == prBssInfo->eBand) {
+ prBssInfo->eBssSCO = eSCO;
+ } else {
+ prBssInfo->eBssSCO = rlmDecideScoForAP(prAdapter, prBssInfo);
+ }
+
+ prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, prBssInfo->u4PrivateData);
+
+ ASSERT_BREAK((prAdapter != NULL) && (prConnReqInfo != NULL) && (prChnlReqInfo != NULL));
+ prChnlReqInfo->u8Cookie = 0;
+ prChnlReqInfo->ucReqChnlNum = prConnReqInfo->rChannelInfo.ucChannelNum;
+ prChnlReqInfo->eBand = prConnReqInfo->rChannelInfo.eBand;
+ prChnlReqInfo->eChnlSco = prBssInfo->eBssSCO;
+ prChnlReqInfo->u4MaxInterval =
+ prAdapter->prGlueInfo->prP2PInfo[prP2pRoleFsmInfo->ucRoleIndex]->cac_time_ms;
+ prChnlReqInfo->eChnlReqType = CH_REQ_TYPE_DFS_CAC;
+
+ prChnlReqInfo->eChannelWidth = rChannelWidth;
+
+ prChnlReqInfo->ucCenterFreqS1 =
+ nicGetVhtS1(prBssInfo->ucPrimaryChannel, prChnlReqInfo->eChannelWidth);
+ prChnlReqInfo->ucCenterFreqS2 = 0;
+
+ DBGLOG(P2P, TRACE, "p2pRoleStatePrepare_To_REQING_CHANNEL_STATE\n");
+
+ /* Reset */
+ prBssInfo->ucPrimaryChannel = ucChannelBackup;
+ prBssInfo->eBand = eBandBackup;
+ prBssInfo->eBssSCO = eSCOBackup;
+ } while (FALSE);
+}
+#endif
diff --git a/mgmt/rlm.c b/mgmt/rlm.c
index 626d5b5..173b007 100644
--- a/mgmt/rlm.c
+++ b/mgmt/rlm.c
@@ -530,6 +530,42 @@
* \return none
*/
/*----------------------------------------------------------------------------*/
+VOID rlmGenerateCsaIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo)
+{
+ P_BSS_INFO_T prBssInfo;
+ PUINT_8 pucBuffer;
+
+ ASSERT(prAdapter);
+ ASSERT(prMsduInfo);
+
+ if (prAdapter->rWifiVar.fgCsaInProgress) {
+ prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex];
+ if (!prBssInfo)
+ return;
+
+ pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) prMsduInfo->u2FrameLength);
+
+ CSA_IE(pucBuffer)->ucId = ELEM_ID_CH_SW_ANNOUNCEMENT;
+ CSA_IE(pucBuffer)->ucLength = ELEM_MIN_LEN_CSA;
+ CSA_IE(pucBuffer)->ucChannelSwitchMode = prAdapter->rWifiVar.ucChannelSwitchMode;
+ CSA_IE(pucBuffer)->ucNewChannelNum = prAdapter->rWifiVar.ucNewChannelNumber;
+ CSA_IE(pucBuffer)->ucChannelSwitchCount = prAdapter->rWifiVar.ucChannelSwitchCount;
+
+ prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer);
+ pucBuffer += IE_SIZE(pucBuffer);
+ }
+
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief
+*
+* \param[in]
+*
+* \return none
+*/
+/*----------------------------------------------------------------------------*/
static VOID rlmFillHtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo)
{
P_IE_HT_CAP_T prHtCap;
diff --git a/mgmt/rlm_domain.c b/mgmt/rlm_domain.c
index 2354990..5f917af 100644
--- a/mgmt/rlm_domain.c
+++ b/mgmt/rlm_domain.c
@@ -2614,11 +2614,12 @@
below_ch = primary_ch - CHNL_SPAN_20;
above_ch = primary_ch + CHNL_SPAN_20;
+ if (rlmDomainIsLegalChannel(prAdapter, band, above_ch))
+ return CHNL_EXT_SCA;
+
if (rlmDomainIsLegalChannel(prAdapter, band, below_ch))
return CHNL_EXT_SCB;
- if (rlmDomainIsLegalChannel(prAdapter, band, above_ch))
- return CHNL_EXT_SCA;
#endif
return CHNL_EXT_SCN;
diff --git a/nic/nic_rx.c b/nic/nic_rx.c
index 4291e75..e90de10 100644
--- a/nic/nic_rx.c
+++ b/nic/nic_rx.c
@@ -174,7 +174,13 @@
#endif
{EVENT_ID_HIF_CTRL, nicEventHifCtrl},
{EVENT_ID_RDD_SEND_PULSE, nicEventRddSendPulse},
- {EVENT_ID_UPDATE_COEX_PHYRATE, nicEventUpdateCoexPhyrate}
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ {EVENT_ID_UPDATE_COEX_PHYRATE, nicEventUpdateCoexPhyrate},
+ {EVENT_ID_RDD_REPORT, cnmRadarDetectEvent},
+ {EVENT_ID_CSA_DONE, cnmCsaDoneEvent},
+#else
+ {EVENT_ID_UPDATE_COEX_PHYRATE, nicEventUpdateCoexPhyrate},
+#endif
};
/*******************************************************************************
diff --git a/os/linux/gl_ate_agent.c b/os/linux/gl_ate_agent.c
index f042e5f..bd4596a 100644
--- a/os/linux/gl_ate_agent.c
+++ b/os/linux/gl_ate_agent.c
@@ -172,6 +172,9 @@
{"WriteEfuse", WriteEfuse},
{"TxPower", SetTxTargetPower},
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ {"RDDReport", SetRddReport},
+#endif
{NULL,}
};
@@ -2010,6 +2013,44 @@
return i4Status;
}
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief This routine is called to Set Tx Power.
+*
+* \param[in] prNetDev Pointer to the Net Device
+* \param[in] prInBuf A pointer to the command string buffer
+* \param[out] None
+*
+* \retval 0 On success.
+* \retval -EINVAL If invalid argument.
+*/
+/*----------------------------------------------------------------------------*/
+int SetRddReport(struct net_device *prNetDev, UINT_8 *prInBuf)
+{
+ INT_32 i4Status;
+ INT_32 rv;
+ int dbdcIdx;
+ UINT_8 ucDbdcIdx;
+
+ DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv Set RDD Report, buf: %s\n", prInBuf);
+
+ /* rv = sscanf(prInBuf, "%u", &addr);*/
+ rv = kstrtoint(prInBuf, 0, &dbdcIdx);
+
+ DBGLOG(REQ, INFO, "MT6632 : ATE_AGENT iwpriv Set RDD Report, prInBuf: %s\n", prInBuf);
+ DBGLOG(INIT, ERROR, "MT6632 : ATE_AGENT iwpriv Set RDD Report : Band %d\n", dbdcIdx);
+
+ ucDbdcIdx = (UINT_8) dbdcIdx;
+
+ if (rv == 0)
+ i4Status = MT_ATESetRddReport(prNetDev, ucDbdcIdx);
+ else
+ return -EINVAL;
+
+ return i4Status;
+}
+#endif
/*----------------------------------------------------------------------------*/
/*!
diff --git a/os/linux/gl_hook_api.c b/os/linux/gl_hook_api.c
index 16e0a29..77918c8 100644
--- a/os/linux/gl_hook_api.c
+++ b/os/linux/gl_hook_api.c
@@ -2572,7 +2572,45 @@
return i4Status;
}
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief Hook API for Set Rdd Report.
+*
+* \param[in] prNetDev Pointer to the Net Device
+* \param[in] ucDbdcIdx Dbdc Index
+* \param[out] None
+*
+* \retval 0 On success.
+* \retval -EFAULT If kalIoctl return nonzero.
+* \retval -EINVAL If invalid argument.
+*/
+/*----------------------------------------------------------------------------*/
+INT_32 MT_ATESetRddReport(struct net_device *prNetDev, UINT_8 ucDbdcIdx)
+{
+ UINT_32 u4BufLen = 0;
+ PARAM_CUSTOM_SET_RDD_REPORT_T rSetRddReport;
+ P_GLUE_INFO_T prGlueInfo = NULL;
+ WLAN_STATUS i4Status = WLAN_STATUS_SUCCESS;
+ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev));
+ kalMemSet(&rSetRddReport, 0, sizeof(PARAM_CUSTOM_SET_RDD_REPORT_T));
+
+ /* Set Rdd Report */
+ DBGLOG(INIT, INFO, "MT6632 : QA_AGENT Set RDD Report - Band: %d\n", ucDbdcIdx);
+ rSetRddReport.ucDbdcIdx = ucDbdcIdx;
+
+ i4Status = kalIoctl(prGlueInfo,
+ wlanoidQuerySetRddReport,
+ &rSetRddReport,
+ sizeof(PARAM_CUSTOM_SET_RDD_REPORT_T), FALSE, FALSE, TRUE, &u4BufLen);
+
+ if (i4Status != WLAN_STATUS_SUCCESS)
+ return -EFAULT;
+
+ return i4Status;
+}
+#endif
#if CFG_SUPPORT_TX_BF
INT_32 TxBfProfileTag_InValid(struct net_device *prNetDev, P_PFMU_PROFILE_TAG1 prPfmuTag1, UINT_8 ucInValid)
diff --git a/os/linux/gl_init.c b/os/linux/gl_init.c
index 71d7c81..ce8aea0 100644
--- a/os/linux/gl_init.c
+++ b/os/linux/gl_init.c
@@ -273,6 +273,15 @@
.tx_params = IEEE80211_HT_MCS_TX_DEFINED, \
}
+#define WLAN_VHT_MCS_INFO \
+{ \
+ .rx_mcs_map = 0xFFFA, \
+ .rx_highest = cpu_to_le16(867), \
+ .tx_mcs_map = 0xFFFA, \
+ .tx_highest = cpu_to_le16(867), \
+}
+
+
#define WLAN_HT_CAP \
{ \
.ht_supported = true, \
@@ -286,6 +295,20 @@
.mcs = WLAN_MCS_INFO, \
}
+#define WLAN_VHT_CAP \
+{ \
+ .vht_supported = true, \
+ .cap = IEEE80211_VHT_CAP_RXLDPC \
+ | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK \
+ | IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 \
+ | IEEE80211_VHT_CAP_RXLDPC \
+ | IEEE80211_VHT_CAP_SHORT_GI_80 \
+ | IEEE80211_VHT_CAP_TXSTBC \
+ | IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE \
+ | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE, \
+ .vht_mcs = WLAN_VHT_MCS_INFO, \
+}
+
/* public for both Legacy Wi-Fi / P2P access */
struct ieee80211_supported_band mtk_band_2ghz = {
.band = IEEE80211_BAND_2GHZ,
@@ -304,6 +327,7 @@
.bitrates = mtk_a_rates,
.n_bitrates = mtk_a_rates_size,
.ht_cap = WLAN_HT_CAP,
+ .vht_cap = WLAN_VHT_CAP,
};
const UINT_32 mtk_cipher_suites[5] = {
@@ -1458,7 +1482,11 @@
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)
prWiphy->flags = WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_SUPPORTS_FW_ROAM | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
#else
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ prWiphy->flags = WIPHY_FLAG_SUPPORTS_FW_ROAM | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+#else
prWiphy->flags = WIPHY_FLAG_SUPPORTS_FW_ROAM | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+#endif
prWiphy->regulatory_flags = REGULATORY_CUSTOM_REG;
#endif
diff --git a/os/linux/gl_p2p.c b/os/linux/gl_p2p.c
index 3d03dbb..fe42a5c 100644
--- a/os/linux/gl_p2p.c
+++ b/os/linux/gl_p2p.c
@@ -158,6 +158,10 @@
.set_tx_power = mtk_p2p_cfg80211_set_txpower,
.get_tx_power = mtk_p2p_cfg80211_get_txpower,
.set_power_mgmt = mtk_p2p_cfg80211_set_power_mgmt,
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ .start_radar_detection = mtk_p2p_cfg80211_start_radar_detection,
+ .channel_switch = mtk_p2p_cfg80211_channel_switch,
+#endif
#ifdef CONFIG_NL80211_TESTMODE
.testmode_cmd = mtk_p2p_cfg80211_testmode_cmd,
#endif
@@ -1029,7 +1033,11 @@
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)
prWiphy->flags = WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_HAVE_AP_SME;
#else
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ prWiphy->flags = WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+#else
prWiphy->flags = WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_HAVE_AP_SME;
+#endif
prWiphy->regulatory_flags = REGULATORY_CUSTOM_REG;
#endif
prWiphy->ap_sme_capa = 1;
@@ -1266,8 +1274,9 @@
#endif
/* 2. carrier on & start TX queue */
- netif_carrier_on(prDev);
- netif_tx_start_all_queues(prDev);
+ /*Chun todo 20161220_DFS*/
+ /*netif_carrier_on(prDev);*/
+ /*netif_tx_start_all_queues(prDev);*/
return 0; /* success */
} /* end of p2pOpen() */
diff --git a/os/linux/gl_p2p_cfg80211.c b/os/linux/gl_p2p_cfg80211.c
index 0d7f4e0..5faecf0 100644
--- a/os/linux/gl_p2p_cfg80211.c
+++ b/os/linux/gl_p2p_cfg80211.c
@@ -1090,6 +1090,10 @@
DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_start_ap.\n");
prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy));
+ /*Chun todo 20161220_DFS*/
+ netif_carrier_on(dev);
+ netif_tx_start_all_queues(dev);
+
chandef = &settings->chandef;
if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0)
@@ -1237,6 +1241,261 @@
return i4Rslt;
} /* mtk_p2p_cfg80211_start_ap */
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+int mtk_p2p_cfg80211_start_radar_detection(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_chan_def *chandef, unsigned int cac_time_ms)
+{
+ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL;
+ INT_32 i4Rslt = -EINVAL;
+ P_MSG_P2P_DFS_CAC_T prP2pDfsCacMsg = (P_MSG_P2P_DFS_CAC_T) NULL;
+ UINT_8 ucRoleIdx = 0;
+ RF_CHANNEL_INFO_T rRfChnlInfo;
+
+ do {
+ if ((wiphy == NULL) || (chandef == NULL))
+ break;
+
+ DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_start_radar_detection.\n");
+ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy));
+
+ if (prGlueInfo->prP2PInfo[ucRoleIdx]->chandef == NULL) {
+ prGlueInfo->prP2PInfo[ucRoleIdx]->chandef = (struct cfg80211_chan_def *)
+ cnmMemAlloc(prGlueInfo->prAdapter,
+ RAM_TYPE_BUF, sizeof(struct cfg80211_chan_def));
+
+ prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan = (struct ieee80211_channel *)
+ cnmMemAlloc(prGlueInfo->prAdapter,
+ RAM_TYPE_BUF, sizeof(struct ieee80211_channel));
+ }
+
+ if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0)
+ break;
+
+ /* Copy chan def to local buffer*/
+ prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->center_freq1 = chandef->center_freq1;
+ prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->center_freq2 = chandef->center_freq2;
+ prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->width = chandef->width;
+ memcpy(prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan, chandef->chan,
+ sizeof(struct ieee80211_channel));
+ prGlueInfo->prP2PInfo[ucRoleIdx]->cac_time_ms = cac_time_ms;
+
+
+ if (chandef) {
+ mtk_p2p_cfg80211func_channel_format_switch(chandef->chan, chandef->width, &rRfChnlInfo, NULL);
+
+ p2pFuncSetChannel(prGlueInfo->prAdapter, ucRoleIdx, &rRfChnlInfo);
+ } else
+ break;
+
+ DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_start_radar_detection.(role %d)\n", ucRoleIdx);
+
+ prP2pDfsCacMsg = (P_MSG_P2P_DFS_CAC_T) cnmMemAlloc(prGlueInfo->prAdapter,
+ RAM_TYPE_MSG, sizeof(MSG_P2P_DFS_CAC_T));
+
+ if (prP2pDfsCacMsg == NULL) {
+ ASSERT(FALSE);
+ i4Rslt = -ENOMEM;
+ break;
+ }
+
+ prP2pDfsCacMsg->rMsgHdr.eMsgId = MID_MNY_P2P_DFS_CAC;
+
+ switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ case NL80211_CHAN_WIDTH_20:
+ case NL80211_CHAN_WIDTH_40:
+ prP2pDfsCacMsg->eChannelWidth = CW_20_40MHZ;
+ break;
+
+ case NL80211_CHAN_WIDTH_80:
+ prP2pDfsCacMsg->eChannelWidth = CW_80MHZ;
+ break;
+
+ case NL80211_CHAN_WIDTH_80P80:
+ prP2pDfsCacMsg->eChannelWidth = CW_80P80MHZ;
+ break;
+
+ default:
+ DBGLOG(P2P, ERROR,
+ "mtk_p2p_cfg80211_start_radar_detection. !!!Bandwidth do not support!!!\n");
+ ASSERT(FALSE);
+ break;
+ }
+
+ prP2pDfsCacMsg->ucRoleIdx = ucRoleIdx;
+
+ mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pDfsCacMsg, MSG_SEND_METHOD_BUF);
+
+ i4Rslt = 0;
+
+ } while (FALSE);
+
+ return i4Rslt;
+}
+
+int mtk_p2p_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_csa_settings *params)
+{
+ P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL;
+ INT_32 i4Rslt = -EINVAL;
+ P_MSG_P2P_BEACON_UPDATE_T prP2pBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T) NULL;
+ P_MSG_P2P_SET_NEW_CHANNEL_T prP2pSetNewChannelMsg = (P_MSG_P2P_SET_NEW_CHANNEL_T) NULL;
+ PUINT_8 pucBuffer = (PUINT_8) NULL;
+ UINT_8 ucRoleIdx = 0;
+ RF_CHANNEL_INFO_T rRfChnlInfo;
+ P_BSS_INFO_T prBssInfo;
+ UINT_8 ucBssIndex;
+
+ do {
+ if ((wiphy == NULL) || (params == NULL))
+ break;
+
+ DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_channel_switch.\n");
+ prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy));
+
+ /* Todo: 20161220_DFS_Chun */
+ netif_carrier_on(dev);
+ netif_tx_start_all_queues(dev);
+
+ if (prGlueInfo->prP2PInfo[ucRoleIdx]->chandef == NULL) {
+ prGlueInfo->prP2PInfo[ucRoleIdx]->chandef = (struct cfg80211_chan_def *)
+ cnmMemAlloc(prGlueInfo->prAdapter,
+ RAM_TYPE_BUF, sizeof(struct cfg80211_chan_def));
+
+ prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan = (struct ieee80211_channel *)
+ cnmMemAlloc(prGlueInfo->prAdapter,
+ RAM_TYPE_BUF, sizeof(struct ieee80211_channel));
+ }
+ /* Copy chan def to local buffer*/
+ prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->center_freq1 = params->chandef.center_freq1;
+ prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->center_freq2 = params->chandef.center_freq2;
+ prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->width = params->chandef.width;
+ memcpy(prGlueInfo->prP2PInfo[ucRoleIdx]->chandef->chan, params->chandef.chan,
+ sizeof(struct ieee80211_channel));
+
+
+ if (mtk_Netdev_To_RoleIdx(prGlueInfo, dev, &ucRoleIdx) < 0)
+ break;
+
+ if (params) {
+ mtk_p2p_cfg80211func_channel_format_switch(params->chandef.chan,
+ params->chandef.width, &rRfChnlInfo, NULL);
+
+ p2pFuncSetChannel(prGlueInfo->prAdapter, ucRoleIdx, &rRfChnlInfo);
+ } else
+ break;
+
+ DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_channel_switch.(role %d)\n", ucRoleIdx);
+
+ /* Set CSA IE parameters */
+ prGlueInfo->prAdapter->rWifiVar.fgCsaInProgress = TRUE;
+ prGlueInfo->prAdapter->rWifiVar.ucChannelSwitchMode = 1;
+ prGlueInfo->prAdapter->rWifiVar.ucNewChannelNumber =
+ nicFreq2ChannelNum(params->chandef.chan->center_freq * 1000);
+ prGlueInfo->prAdapter->rWifiVar.ucChannelSwitchCount = params->count;
+
+ /* Set new channel parameters */
+ prP2pSetNewChannelMsg = (P_MSG_P2P_SET_NEW_CHANNEL_T) cnmMemAlloc(prGlueInfo->prAdapter,
+ RAM_TYPE_MSG, sizeof(P_MSG_P2P_SET_NEW_CHANNEL_T));
+
+ if (prP2pSetNewChannelMsg == NULL) {
+ ASSERT(FALSE);
+ i4Rslt = -ENOMEM;
+ break;
+ }
+
+ prP2pSetNewChannelMsg->rMsgHdr.eMsgId = MID_MNY_P2P_SET_NEW_CHANNEL;
+
+ switch (params->chandef.width) {
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ case NL80211_CHAN_WIDTH_20:
+ case NL80211_CHAN_WIDTH_40:
+ prP2pSetNewChannelMsg->eChannelWidth = CW_20_40MHZ;
+ break;
+
+ case NL80211_CHAN_WIDTH_80:
+ prP2pSetNewChannelMsg->eChannelWidth = CW_80MHZ;
+ break;
+
+ case NL80211_CHAN_WIDTH_80P80:
+ prP2pSetNewChannelMsg->eChannelWidth = CW_80P80MHZ;
+ break;
+
+ default:
+ DBGLOG(P2P, ERROR,
+ "mtk_p2p_cfg80211_channel_switch. !!!Bandwidth do not support!!!\n");
+ ASSERT(FALSE);
+ break;
+ }
+
+ prP2pSetNewChannelMsg->ucRoleIdx = ucRoleIdx;
+
+ for (ucBssIndex = 0; ucBssIndex < BSS_INFO_NUM; ucBssIndex++) {
+ prBssInfo = GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, ucBssIndex);
+
+ if (prBssInfo && prBssInfo->fgIsDfsActive) {
+ prP2pSetNewChannelMsg->ucBssIndex = ucBssIndex;
+ break;
+ }
+ }
+
+ mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pSetNewChannelMsg, MSG_SEND_METHOD_BUF);
+
+ /* Update beacon */
+ if ((params->beacon_csa.head_len != 0) || (params->beacon_csa.tail_len != 0)) {
+ prP2pBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T) cnmMemAlloc(prGlueInfo->prAdapter,
+ RAM_TYPE_MSG, (sizeof(MSG_P2P_BEACON_UPDATE_T)
+ + params->beacon_csa.head_len + params->beacon_csa.tail_len));
+
+ if (prP2pBcnUpdateMsg == NULL) {
+ ASSERT(FALSE);
+ i4Rslt = -ENOMEM;
+ break;
+ }
+
+ prP2pBcnUpdateMsg->ucRoleIndex = ucRoleIdx;
+ prP2pBcnUpdateMsg->rMsgHdr.eMsgId = MID_MNY_P2P_BEACON_UPDATE;
+ pucBuffer = prP2pBcnUpdateMsg->aucBuffer;
+
+ if (params->beacon_csa.head_len != 0) {
+ kalMemCopy(pucBuffer, params->beacon_csa.head, params->beacon_csa.head_len);
+
+ prP2pBcnUpdateMsg->u4BcnHdrLen = params->beacon_csa.head_len;
+
+ prP2pBcnUpdateMsg->pucBcnHdr = pucBuffer;
+
+ pucBuffer = (PUINT_8) ((ULONG) pucBuffer + (ULONG) params->beacon_csa.head_len);
+ } else {
+ prP2pBcnUpdateMsg->u4BcnHdrLen = 0;
+
+ prP2pBcnUpdateMsg->pucBcnHdr = NULL;
+ }
+
+ if (params->beacon_csa.tail_len != 0) {
+ UINT_8 ucLen = params->beacon_csa.tail_len;
+
+ prP2pBcnUpdateMsg->pucBcnBody = pucBuffer;
+ kalMemCopy(pucBuffer, params->beacon_csa.tail, params->beacon_csa.tail_len);
+
+ prP2pBcnUpdateMsg->u4BcnBodyLen = ucLen;
+ } else {
+ prP2pBcnUpdateMsg->u4BcnBodyLen = 0;
+ prP2pBcnUpdateMsg->pucBcnBody = NULL;
+ }
+
+ kalP2PSetRole(prGlueInfo, 2, ucRoleIdx);
+
+ mboxSendMsg(prGlueInfo->prAdapter,
+ MBOX_ID_0, (P_MSG_HDR_T) prP2pBcnUpdateMsg, MSG_SEND_METHOD_BUF);
+
+ i4Rslt = 0; /* Return Success */
+ }
+
+ } while (FALSE);
+
+ return i4Rslt;
+}
+#endif
+
#if 0
struct cfg80211_beacon_data {
const u8 *head, *tail;
diff --git a/os/linux/gl_p2p_kal.c b/os/linux/gl_p2p_kal.c
index 38f3b40..ecc8064 100644
--- a/os/linux/gl_p2p_kal.c
+++ b/os/linux/gl_p2p_kal.c
@@ -1278,6 +1278,59 @@
} /* kalP2PGOStationUpdate */
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+VOID kalP2PRddDetectUpdate(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRoleIndex)
+{
+ DBGLOG(INIT, INFO, "Radar Detection event\n");
+
+ do {
+ if (prGlueInfo == NULL) {
+ ASSERT(FALSE);
+ break;
+ }
+
+ if (prGlueInfo->prP2PInfo[ucRoleIndex]->chandef == NULL) {
+ ASSERT(FALSE);
+ break;
+ }
+
+ /* cac start disable for next cac slot if enable in dfs channel */
+ prGlueInfo->prP2PInfo[ucRoleIndex]->prWdev->cac_started = FALSE;
+ DBGLOG(INIT, INFO, "kalP2PRddDetectUpdate: Update to OS\n");
+ cfg80211_radar_event(prGlueInfo->prP2PInfo[ucRoleIndex]->prWdev->wiphy,
+ prGlueInfo->prP2PInfo[ucRoleIndex]->chandef, GFP_KERNEL);
+ DBGLOG(INIT, INFO, "kalP2PRddDetectUpdate: Update to OS Done\n");
+
+ netif_carrier_off(prGlueInfo->prP2PInfo[ucRoleIndex]->prDevHandler);
+ netif_tx_stop_all_queues(prGlueInfo->prP2PInfo[ucRoleIndex]->prDevHandler);
+
+ } while (FALSE);
+
+} /* kalP2PRddDetectUpdate */
+
+VOID kalP2PCacFinishedUpdate(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRoleIndex)
+{
+ DBGLOG(INIT, INFO, "CAC Finished event\n");
+
+ do {
+ if (prGlueInfo == NULL)
+ ASSERT(FALSE);
+
+ if (prGlueInfo->prP2PInfo[ucRoleIndex]->chandef == NULL) {
+ ASSERT(FALSE);
+ break;
+ }
+
+ DBGLOG(INIT, INFO, "kalP2PCacFinishedUpdate: Update to OS\n");
+ cfg80211_cac_event(prGlueInfo->prP2PInfo[ucRoleIndex]->prDevHandler,
+ prGlueInfo->prP2PInfo[ucRoleIndex]->chandef, NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
+ DBGLOG(INIT, INFO, "kalP2PCacFinishedUpdate: Update to OS Done\n");
+
+ } while (FALSE);
+
+} /* kalP2PRddDetectUpdate */
+#endif
+
BOOLEAN kalP2pFuncGetChannelType(IN ENUM_CHNL_EXT_T rChnlSco, OUT enum nl80211_channel_type *channel_type)
{
BOOLEAN fgIsValid = FALSE;
diff --git a/os/linux/include/gl_ate_agent.h b/os/linux/include/gl_ate_agent.h
index e90da51..560820f 100644
--- a/os/linux/include/gl_ate_agent.h
+++ b/os/linux/include/gl_ate_agent.h
@@ -187,6 +187,10 @@
int WriteEfuse(struct net_device *prNetDev, UINT_8 *prInBuf);
int SetTxTargetPower(struct net_device *prNetDev, UINT_8 *prInBuf);
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+int SetRddReport(struct net_device *prNetDev, UINT_8 *prInBuf);
+#endif
+
int AteCmdSetHandle(struct net_device *prNetDev, UINT_8 *prInBuf, UINT_32 u4InBufLen);
#endif /*CFG_SUPPORT_QA_TOOL */
diff --git a/os/linux/include/gl_hook_api.h b/os/linux/include/gl_hook_api.h
index a131d1d..b3387d9 100644
--- a/os/linux/include/gl_hook_api.h
+++ b/os/linux/include/gl_hook_api.h
@@ -146,6 +146,9 @@
INT_32 MT_ATEWriteEfuse(struct net_device *prNetDev, UINT_16 u2Offset, UINT_16 u2Content);
INT_32 MT_ATESetTxTargetPower(struct net_device *prNetDev, UINT_8 ucTxTargetPower);
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+INT_32 MT_ATESetRddReport(struct net_device *prNetDev, UINT_8 ucDbdcIdx);
+#endif
#if CFG_SUPPORT_TX_BF
diff --git a/os/linux/include/gl_p2p_ioctl.h b/os/linux/include/gl_p2p_ioctl.h
index 28e846b..04b8edf 100644
--- a/os/linux/include/gl_p2p_ioctl.h
+++ b/os/linux/include/gl_p2p_ioctl.h
@@ -436,6 +436,15 @@
int mtk_p2p_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, bool enabled, int timeout);
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+int mtk_p2p_cfg80211_start_radar_detection(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct cfg80211_chan_def *chandef,
+ unsigned int cac_time_ms);
+
+int mtk_p2p_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_csa_settings *params);
+#endif
+
int mtk_p2p_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev, struct bss_parameters *params);
int mtk_p2p_cfg80211_deauth(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_deauth_request *req);
diff --git a/os/linux/include/gl_p2p_kal.h b/os/linux/include/gl_p2p_kal.h
index 12080a0..ff8f5e3 100644
--- a/os/linux/include/gl_p2p_kal.h
+++ b/os/linux/include/gl_p2p_kal.h
@@ -249,6 +249,14 @@
kalP2PGOStationUpdate(IN P_GLUE_INFO_T prGlueInfo,
IN UINT_8 ucRoleIndex, IN P_STA_RECORD_T prCliStaRec, IN BOOLEAN fgIsNew);
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+VOID
+kalP2PRddDetectUpdate(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRoleIndex);
+
+VOID
+kalP2PCacFinishedUpdate(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRoleIndex);
+#endif
+
#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER
BOOLEAN kalP2PSetBlackList(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rbssid, IN BOOLEAN fgIsblock,
diff --git a/os/linux/include/gl_p2p_os.h b/os/linux/include/gl_p2p_os.h
index d219b04..e6cf890 100644
--- a/os/linux/include/gl_p2p_os.h
+++ b/os/linux/include/gl_p2p_os.h
@@ -195,6 +195,11 @@
/*UINT_8 aucSecCheckRsp[256];*//* TH3 multiple P2P */
#endif
+#if (CFG_SUPPORT_DFS_MASTER == 1)
+ struct cfg80211_chan_def *chandef;
+ UINT_32 cac_time_ms;
+#endif
+
#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER
/* Hotspot Client Management */
/* dependent with #define P2P_MAXIMUM_CLIENT_COUNT 10,