/**************************************************************************** * Ralink Tech Inc. * Taiwan, R.O.C. * * (c) Copyright 2002, Ralink Technology, Inc. * * All rights reserved. Ralink's source code is an unpublished work and the * use of a copyright notice does not imply otherwise. This source code * contains confidential trade secret material of Ralink Tech. Any attemp * or participation in deciphering, decoding, reverse engineering or in any * way altering the source code is stricitly prohibited, unless the prior * written consent of Ralink Technology, Inc. is obtained. ***************************************************************************/ /**************************************************************************** Abstract: All related CFG80211 function body. History: ***************************************************************************/ #ifdef RT_CFG80211_SUPPORT #include "rt_config.h" #define RT_CFG80211_DEBUG /* debug use */ #define CFG80211CB (pAd->pCfg80211_CB) #ifdef RT_CFG80211_DEBUG #define CFG80211DBG(__Flg, __pMsg) DBGPRINT(__Flg, __pMsg) #else #define CFG80211DBG(__Flg, __pMsg) #endif /* RT_CFG80211_DEBUG */ INT CFG80211DRV_IoctlHandle( IN VOID *pAdSrc, IN RTMP_IOCTL_INPUT_STRUCT *wrq, IN INT cmd, IN USHORT subcmd, IN VOID *pData, IN ULONG Data) { PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; switch(cmd) { case CMD_RTPRIV_IOCTL_80211_START: case CMD_RTPRIV_IOCTL_80211_END: /* nothing to do */ break; case CMD_RTPRIV_IOCTL_80211_CB_GET: *(VOID **)pData = (VOID *)(pAd->pCfg80211_CB); break; case CMD_RTPRIV_IOCTL_80211_CB_SET: pAd->pCfg80211_CB = pData; break; case CMD_RTPRIV_IOCTL_80211_CHAN_SET: if (CFG80211DRV_OpsSetChannel(pAd, pData) != TRUE) return NDIS_STATUS_FAILURE; break; case CMD_RTPRIV_IOCTL_80211_VIF_CHG: if (CFG80211DRV_OpsChgVirtualInf(pAd, pData, Data) != TRUE) return NDIS_STATUS_FAILURE; break; case CMD_RTPRIV_IOCTL_80211_SCAN: CFG80211DRV_OpsScan(pAd); break; case CMD_RTPRIV_IOCTL_80211_IBSS_JOIN: CFG80211DRV_OpsJoinIbss(pAd, pData); break; case CMD_RTPRIV_IOCTL_80211_STA_LEAVE: CFG80211DRV_OpsLeave(pAd); break; case CMD_RTPRIV_IOCTL_80211_STA_GET: if (CFG80211DRV_StaGet(pAd, pData) != TRUE) return NDIS_STATUS_FAILURE; break; case CMD_RTPRIV_IOCTL_80211_KEY_ADD: CFG80211DRV_KeyAdd(pAd, pData); break; case CMD_RTPRIV_IOCTL_80211_KEY_DEFAULT_SET: #ifdef CONFIG_STA_SUPPORT pAd->StaCfg.DefaultKeyId = Data; /* base 0 */ #endif /* CONFIG_STA_SUPPORT */ break; case CMD_RTPRIV_IOCTL_80211_CONNECT_TO: CFG80211DRV_Connect(pAd, pData); break; #ifdef RFKILL_HW_SUPPORT case CMD_RTPRIV_IOCTL_80211_RFKILL: { UINT32 data = 0; BOOLEAN active; /* Read GPIO pin2 as Hardware controlled radio state */ RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data); active = !!(data & 0x04); if (!active) { RTMPSetLED(pAd, LED_RADIO_OFF); *(UINT8 *)pData = 0; } else *(UINT8 *)pData = 1; } break; #endif /* RFKILL_HW_SUPPORT */ case CMD_RTPRIV_IOCTL_80211_REG_NOTIFY_TO: CFG80211DRV_RegNotify(pAd, pData); break; case CMD_RTPRIV_IOCTL_80211_UNREGISTER: CFG80211_UnRegister(pAd, pData); break; case CMD_RTPRIV_IOCTL_80211_BANDINFO_GET: { CFG80211_BAND *pBandInfo = (CFG80211_BAND *)pData; CFG80211_BANDINFO_FILL(pAd, pBandInfo); } break; case CMD_RTPRIV_IOCTL_80211_SURVEY_GET: CFG80211DRV_SurveyGet(pAd, pData); break; case CMD_RTPRIV_IOCTL_80211_EXTRA_IES_SET: CFG80211DRV_OpsExtraIesSet(pAd); break; case CMD_RTPRIV_IOCTL_80211_REMAIN_ON_CHAN_SET: CFG80211DRV_OpsRemainOnChannel(pAd, pData, Data); break; case CMD_RTPRIV_IOCTL_80211_CANCEL_REMAIN_ON_CHAN_SET: CFG80211DRV_OpsCancelRemainOnChannel(pAd, Data); break; case CMD_RTPRIV_IOCTL_80211_MGMT_FRAME_REG: if (Data) pAd->Cfg80211ProbeReqCount++; else { pAd->Cfg80211ProbeReqCount--; } if (pAd->Cfg80211ProbeReqCount > 0) pAd->Cfg80211RegisterProbeReqFrame = TRUE; else pAd->Cfg80211RegisterProbeReqFrame = FALSE; DBGPRINT(RT_DEBUG_ERROR, ("pAd->Cfg80211RegisterProbeReqFrame=%d[%d]\n",pAd->Cfg80211RegisterProbeReqFrame, pAd->Cfg80211ProbeReqCount)); break; case CMD_RTPRIV_IOCTL_80211_ACTION_FRAME_REG: if (Data) pAd->Cfg80211ActionCount++; else pAd->Cfg80211ActionCount--; if (pAd->Cfg80211ActionCount > 0) pAd->Cfg80211RegisterActionFrame = TRUE; else pAd->Cfg80211RegisterActionFrame = FALSE; DBGPRINT(RT_DEBUG_TRACE, ("pAd->Cfg80211RegisterActionFrame=%d [%d]\n",pAd->Cfg80211RegisterActionFrame, pAd->Cfg80211ActionCount)); break; case CMD_RTPRIV_IOCTL_80211_CHANNEL_LOCK: //pAd->CommonCfg.CentralChannel = Data; //DBGPRINT(RT_DEBUG_TRACE, ("CMD_RTPRIV_IOCTL_80211_CHANNEL_LOCK %d\n", Data)); if (pAd->CommonCfg.Channel != Data) { pAd->CommonCfg.Channel= Data; AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); AsicLockChannel(pAd, pAd->CommonCfg.Channel); } break; case CMD_RTPRIV_IOCTL_80211_MGMT_FRAME_SEND: /* send a managment frame */ pAd->TxStatusInUsed = TRUE; pAd->TxStatusSeq = pAd->Sequence; if (pData != NULL) { #ifdef WFD_SUPPORT if (pAd->StaCfg.WfdCfg.bSuppInsertWfdIe) { PP2P_PUBLIC_FRAME pFrame = (PP2P_PUBLIC_FRAME)pData; ULONG WfdIeLen = 0, WfdIeBitmap = 0; switch (pFrame->p80211Header.FC.SubType) { case SUBTYPE_BEACON: case SUBTYPE_PROBE_REQ: case SUBTYPE_ASSOC_REQ: case SUBTYPE_REASSOC_REQ: WfdIeBitmap = (0x1 << SUBID_WFD_DEVICE_INFO) | (0x1 << SUBID_WFD_ASSOCIATED_BSSID) | (0x1 << SUBID_WFD_COUPLED_SINK_INFO); break; case SUBTYPE_ASSOC_RSP: case SUBTYPE_REASSOC_RSP: WfdIeBitmap = (0x1 << SUBID_WFD_DEVICE_INFO) | (0x1 << SUBID_WFD_ASSOCIATED_BSSID) | (0x1 << SUBID_WFD_COUPLED_SINK_INFO) | (0x1 << SUBID_WFD_SESSION_INFO); break; case SUBTYPE_PROBE_RSP: WfdIeBitmap = (0x1 << SUBID_WFD_DEVICE_INFO) | (0x1 << SUBID_WFD_ASSOCIATED_BSSID) | (0x1 << SUBID_WFD_COUPLED_SINK_INFO) | (0x1 << SUBID_WFD_SESSION_INFO); break; case SUBTYPE_ACTION: if ((pFrame->Category == CATEGORY_PUBLIC) && (pFrame->Action == ACTION_WIFI_DIRECT)) { switch (pFrame->Subtype) { case GO_NEGOCIATION_REQ: case GO_NEGOCIATION_RSP: case GO_NEGOCIATION_CONFIRM: case P2P_PROVISION_REQ: WfdIeBitmap = (0x1 << SUBID_WFD_DEVICE_INFO) | (0x1 << SUBID_WFD_ASSOCIATED_BSSID) | (0x1 << SUBID_WFD_COUPLED_SINK_INFO); break; case P2P_INVITE_REQ: case P2P_INVITE_RSP: case P2P_PROVISION_RSP: WfdIeBitmap = (0x1 << SUBID_WFD_DEVICE_INFO) | (0x1 << SUBID_WFD_ASSOCIATED_BSSID) | (0x1 << SUBID_WFD_COUPLED_SINK_INFO) | (0x1 << SUBID_WFD_SESSION_INFO); break; } } break; } if (WfdIeBitmap > 0) { PUCHAR pOutBuffer; NDIS_STATUS NStatus; NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory */ if (NStatus != NDIS_STATUS_SUCCESS) DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); else { memcpy(pOutBuffer, pData, Data); WfdMakeWfdIE(pAd, WfdIeBitmap, pOutBuffer + Data, &WfdIeLen); Data += WfdIeLen; if (pAd->pTxStatusBuf != NULL) os_free_mem(NULL, pAd->pTxStatusBuf); os_alloc_mem(NULL, (UCHAR **)&pAd->pTxStatusBuf, Data); if (pAd->pTxStatusBuf != NULL) { NdisCopyMemory(pAd->pTxStatusBuf, pOutBuffer, Data); pAd->TxStatusBufLen = Data; } else { DBGPRINT(RT_DEBUG_TRACE, ("YF_TX_STATUS: MEM ALLOC ERROR\n")); MlmeFreeMemory(pAd, pOutBuffer); return NDIS_STATUS_FAILURE; } MiniportMMRequest(pAd, 0, pOutBuffer, Data); } } } else #endif /* WFD_SUPPORT */ { if (pAd->pTxStatusBuf != NULL) os_free_mem(NULL, pAd->pTxStatusBuf); os_alloc_mem(NULL, (UCHAR **)&pAd->pTxStatusBuf, Data); if (pAd->pTxStatusBuf != NULL) { NdisCopyMemory(pAd->pTxStatusBuf, pData, Data); pAd->TxStatusBufLen = Data; } else { DBGPRINT(RT_DEBUG_TRACE, ("YF_TX_STATUS: MEM ALLOC ERROR\n")); return NDIS_STATUS_FAILURE; } // pAd->pTxStatusBuf // pAd->TxStatusBufLen = Data //DBGPRINT(RT_DEBUG_TRACE, ("YF_TX_STATUS: send %d\n", pAd->TxStatusSeq)); MiniportMMRequest(pAd, 0, pData, Data); //DBGPRINT(RT_DEBUG_TRACE, ("YF_TX_STATUS: sent %d\n", pAd->TxStatusSeq)); } } break; case CMD_RTPRIV_IOCTL_80211_REMAIN_ON_CHAN_DUR_TIMER_INIT: DBGPRINT(RT_DEBUG_TRACE, ("ROC TIMER INIT\n")); RTMPInitTimer(pAd, &pAd->Cfg80211RemainOnChannelDurationTimer, GET_TIMER_FUNCTION(RemainOnChannelTimeout), pAd, FALSE); break; case CMD_RTPRIV_IOCTL_80211_CHANNEL_LIST_SET: DBGPRINT(RT_DEBUG_TRACE, ("CMD_RTPRIV_IOCTL_80211_CHANNEL_LIST_SET: %d\n", Data)); UINT32 *pChanList = (UINT32 *) pData; if (pChanList != NULL) { if (pAd->pCfg80211ChanList != NULL) os_free_mem(NULL, pAd->pCfg80211ChanList); os_alloc_mem(NULL, (UINT32 **)&pAd->pCfg80211ChanList, sizeof(UINT32 *) * Data); if (pAd->pCfg80211ChanList != NULL) { NdisCopyMemory(pAd->pCfg80211ChanList, pChanList, sizeof(UINT32 *) * Data); pAd->Cfg80211ChanListLan = Data; } else { return NDIS_STATUS_FAILURE; } } break; case CMD_RTPRIV_IOCTL_80211_BEACON_SET: CFG80211DRV_OpsBeaconSet(pAd, pData, 0); break; case CMD_RTPRIV_IOCTL_80211_BEACON_ADD: CFG80211DRV_OpsBeaconSet(pAd, pData, 1); break; case CMD_RTPRIV_IOCTL_80211_BEACON_DEL: #ifdef WFD_SUPPORT pAd->StaCfg.WfdCfg.bSuppGoOn = FALSE; #endif /* WFD_SUPPORT */ break; case CMD_RTPRIV_IOCTL_80211_CHANGE_BSS_PARM: CFG80211DRV_OpsChangeBssParm(pAd, pData); break; case CMD_RTPRIV_IOCTL_80211_AP_PROBE_RSP: if (pData != NULL) { if (pAd->pCfg80211RrobeRsp != NULL) os_free_mem(NULL, pAd->pCfg80211RrobeRsp); os_alloc_mem(NULL, (UCHAR **)&pAd->pCfg80211RrobeRsp, Data); if (pAd->pCfg80211RrobeRsp != NULL) { NdisCopyMemory(pAd->pCfg80211RrobeRsp, pData, Data); pAd->Cfg80211AssocRspLen = Data; } else { DBGPRINT(RT_DEBUG_TRACE, ("YF_AP: MEM ALLOC ERROR\n")); return NDIS_STATUS_FAILURE; } } else return NDIS_STATUS_FAILURE; break; case CMD_RTPRIV_IOCTL_80211_PORT_SECURED: CFG80211_StaPortSecured(pAd, pData, Data); break; case CMD_RTPRIV_IOCTL_80211_AP_STA_DEL: CFG80211_ApStaDel(pAd, pData); break; case CMD_RTPRIV_IOCTL_80211_BITRATE_SET: // pAd->CommonCfg.PhyMode = PHY_11AN_MIXED; // RTMPSetPhyMode(pAd, pAd->CommonCfg.PhyMode); //Set_WirelessMode_Proc(pAd, PHY_11AGN_MIXED); break; #ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT case CMD_RTPRIV_IOCTL_80211_SEND_WIRELESS_EVENT: CFG80211_SendWirelessEvent(pAd, pData); break; #endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ default: return NDIS_STATUS_FAILURE; } return NDIS_STATUS_SUCCESS; } static VOID CFG80211DRV_DisableApInterface( VOID *pAdOrg) { UINT32 Value; PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; pAd->ApCfg.MBSSID[MAIN_MBSSID].bBcnSntReq = FALSE; /* Disable pre-tbtt interrupt */ RTMP_IO_READ32(pAd, INT_TIMER_EN, &Value); Value &=0xe; RTMP_IO_WRITE32(pAd, INT_TIMER_EN, Value); if (!INFRA_ON(pAd)) { /* Disable piggyback */ RTMPSetPiggyBack(pAd, FALSE); AsicUpdateProtect(pAd, 0, (ALLN_SETPROTECT|CCKSETPROTECT|OFDMSETPROTECT), TRUE, FALSE); } if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) { /*RTMP_ASIC_INTERRUPT_DISABLE(pAd); */ AsicDisableSync(pAd); #ifdef LED_CONTROL_SUPPORT /* Set LED */ RTMPSetLED(pAd, LED_LINK_DOWN); #endif /* LED_CONTROL_SUPPORT */ } #ifdef RTMP_MAC_USB /* For RT2870, we need to clear the beacon sync buffer. */ RTUSBBssBeaconExit(pAd); #endif /* RTMP_MAC_USB */ } VOID CFG80211DRV_OpsChangeBssParm( VOID *pAdOrg, VOID *pData) { PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; CMD_RTPRIV_IOCTL_80211_BSS_PARM *pBssInfo; BOOLEAN TxPreamble; CFG80211DBG(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); pBssInfo = (CMD_RTPRIV_IOCTL_80211_BSS_PARM *)pData; /* Short Preamble */ if (pBssInfo->use_short_preamble != -1) { CFG80211DBG(RT_DEBUG_TRACE, ("%s: ShortPreamble %d\n", __FUNCTION__, pBssInfo->use_short_preamble)); pAd->CommonCfg.TxPreamble = (pBssInfo->use_short_preamble == 0 ? Rt802_11PreambleLong : Rt802_11PreambleShort); TxPreamble = (pAd->CommonCfg.TxPreamble == Rt802_11PreambleLong ? 0 : 1); MlmeSetTxPreamble(pAd, (USHORT)pAd->CommonCfg.TxPreamble); } /* CTS Protection */ if (pBssInfo->use_cts_prot != -1) { CFG80211DBG(RT_DEBUG_TRACE, ("%s: CTS Protection %d\n", __FUNCTION__, pBssInfo->use_cts_prot)); } /* Short Slot */ if (pBssInfo->use_short_slot_time != -1) { CFG80211DBG(RT_DEBUG_TRACE, ("%s: Short Slot %d\n", __FUNCTION__, pBssInfo->use_short_slot_time)); } } BOOLEAN CFG80211DRV_OpsSetChannel( VOID *pAdOrg, VOID *pData) { PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; CMD_RTPRIV_IOCTL_80211_CHAN *pChan; UINT8 ChanId; UINT8 IfType; UINT8 ChannelType; STRING ChStr[5] = { 0 }; #ifdef DOT11_N_SUPPORT UCHAR BW_Old; BOOLEAN FlgIsChanged; #endif /* DOT11_N_SUPPORT */ /* init */ pChan = (CMD_RTPRIV_IOCTL_80211_CHAN *)pData; ChanId = pChan->ChanId; IfType = pChan->IfType; ChannelType = pChan->ChanType; #ifdef DOT11_N_SUPPORT if (IfType != RT_CMD_80211_IFTYPE_MONITOR) { /* get channel BW */ FlgIsChanged = FALSE; BW_Old = pAd->CommonCfg.RegTransmitSetting.field.BW; /* set to new channel BW */ if (ChannelType == RT_CMD_80211_CHANTYPE_HT20) { pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; FlgIsChanged = TRUE; } else if ((ChannelType == RT_CMD_80211_CHANTYPE_HT40MINUS) || (ChannelType == RT_CMD_80211_CHANTYPE_HT40PLUS)) { /* not support NL80211_CHAN_HT40MINUS or NL80211_CHAN_HT40PLUS */ /* i.e. primary channel = 36, secondary channel must be 40 */ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; FlgIsChanged = TRUE; } /* End of if */ CFG80211DBG(RT_DEBUG_ERROR, ("80211> New BW = %d\n", pAd->CommonCfg.RegTransmitSetting.field.BW)); /* change HT/non-HT mode (do NOT change wireless mode here) */ if (((ChannelType == RT_CMD_80211_CHANTYPE_NOHT) && (pAd->CommonCfg.HT_Disable == 0)) || ((ChannelType != RT_CMD_80211_CHANTYPE_NOHT) && (pAd->CommonCfg.HT_Disable == 1))) { if (ChannelType == RT_CMD_80211_CHANTYPE_NOHT) pAd->CommonCfg.HT_Disable = 1; else pAd->CommonCfg.HT_Disable = 0; /* End of if */ FlgIsChanged = TRUE; CFG80211DBG(RT_DEBUG_ERROR, ("80211> HT Disable = %d\n", pAd->CommonCfg.HT_Disable)); } /* End of if */ } else { /* for monitor mode */ FlgIsChanged = TRUE; pAd->CommonCfg.HT_Disable = 0; pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; } /* End of if */ if (FlgIsChanged == TRUE) SetCommonHT(pAd); /* End of if */ #endif /* DOT11_N_SUPPORT */ /* switch to the channel */ sprintf(ChStr, "%d", ChanId); if (Set_Channel_Proc(pAd, ChStr) == FALSE) { CFG80211DBG(RT_DEBUG_ERROR, ("80211> Change channel fail!\n")); } /* End of if */ #ifdef CONFIG_STA_SUPPORT #ifdef DOT11_N_SUPPORT if ((IfType == RT_CMD_80211_IFTYPE_STATION) && (FlgIsChanged == TRUE)) { /* 1. Station mode; 2. New BW settings is 20MHz but current BW is not 20MHz; 3. New BW settings is 40MHz but current BW is 20MHz; Re-connect to the AP due to BW 20/40 or HT/non-HT change. */ Set_SSID_Proc(pAd, (PSTRING)pAd->CommonCfg.Ssid); } /* End of if */ #endif /* DOT11_N_SUPPORT */ if (IfType == RT_CMD_80211_IFTYPE_ADHOC) { /* update IBSS beacon */ MlmeUpdateTxRates(pAd, FALSE, 0); MakeIbssBeacon(pAd); AsicEnableIbssSync(pAd); Set_SSID_Proc(pAd, (PSTRING)pAd->CommonCfg.Ssid); } /* End of if */ if (IfType == RT_CMD_80211_IFTYPE_MONITOR) { /* reset monitor mode in the new channel */ Set_NetworkType_Proc(pAd, "Monitor"); RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, pChan->MonFilterFlag); } /* End of if */ #endif /* CONFIG_STA_SUPPORT */ return TRUE; } BOOLEAN CFG80211DRV_OpsChgVirtualInf( VOID *pAdOrg, VOID *pFlgFilter, UINT8 IfType) { #ifdef CONFIG_STA_SUPPORT PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; UINT32 FlgFilter = *(UINT32 *)pFlgFilter; /* change type */ if (IfType == RT_CMD_80211_IFTYPE_ADHOC) Set_NetworkType_Proc(pAd, "Adhoc"); else if (IfType == RT_CMD_80211_IFTYPE_STATION) Set_NetworkType_Proc(pAd, "Infra"); else if (IfType == RT_CMD_80211_IFTYPE_MONITOR) { /* set packet filter */ Set_NetworkType_Proc(pAd, "Monitor"); if (FlgFilter != 0) { UINT32 Filter; RTMP_IO_READ32(pAd, RX_FILTR_CFG, &Filter); if ((FlgFilter & RT_CMD_80211_FILTER_FCSFAIL) == \ RT_CMD_80211_FILTER_FCSFAIL) { Filter = Filter & (~0x01); } else Filter = Filter | 0x01; /* End of if */ if ((FlgFilter & RT_CMD_80211_FILTER_PLCPFAIL) == \ RT_CMD_80211_FILTER_PLCPFAIL) { Filter = Filter & (~0x02); } else Filter = Filter | 0x02; /* End of if */ if ((FlgFilter & RT_CMD_80211_FILTER_CONTROL) == \ RT_CMD_80211_FILTER_CONTROL) { Filter = Filter & (~0xFF00); } else Filter = Filter | 0xFF00; /* End of if */ if ((FlgFilter & RT_CMD_80211_FILTER_OTHER_BSS) == \ RT_CMD_80211_FILTER_OTHER_BSS) { Filter = Filter & (~0x08); } else Filter = Filter | 0x08; /* End of if */ RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, Filter); *(UINT32 *)pFlgFilter = Filter; } /* End of if */ return TRUE; /* not need to set SSID */ } /* End of if */ pAd->StaCfg.bAutoReconnect = TRUE; CFG80211DBG(RT_DEBUG_ERROR, ("80211> SSID = %s\n", pAd->CommonCfg.Ssid)); Set_SSID_Proc(pAd, (PSTRING)pAd->CommonCfg.Ssid); #endif /* CONFIG_STA_SUPPORT */ return TRUE; } BOOLEAN CFG80211DRV_OpsScan( VOID *pAdOrg) { PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; if (pAd->FlgCfg80211Scanning == TRUE) return FALSE; /* scanning */ /* End of if */ /* do scan */ pAd->FlgCfg80211Scanning = TRUE; return TRUE; } /* REF: ap_connect.c ApMakeBssBeacon */ BOOLEAN CFG80211DRV_OpsBeaconSet( VOID *pAdOrg, VOID *pData, BOOLEAN isAdd) { CFG80211DBG(RT_DEBUG_TRACE, ("80211> CFG80211DRV_OpsBeaconSet ==> %d\n", isAdd)); PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; CMD_RTPRIV_IOCTL_80211_BEACON *pBeacon; PTXWI_STRUC pTxWI = &pAd->BeaconTxWI; HTTRANSMIT_SETTING BeaconTransmit; /* MGMT frame PHY rate setting when operatin at Ht rate. */ BCN_TIME_CFG_STRUC csr9; UCHAR *ptr; UINT i; UINT32 longValue; UINT8 TXWISize = pAd->chipCap.TXWISize; UINT32 rx_filter_flag; BOOLEAN TxPreamble, SpectrumMgmt = FALSE; BOOLEAN bWmmCapable = FALSE; UCHAR BBPR1 = 0, BBPR3 = 0; INT idx; ULONG offset; CFG80211DBG(RT_DEBUG_TRACE, ("80211> CFG80211DRV_OpsBeaconSet ==> \n")); pBeacon = (CMD_RTPRIV_IOCTL_80211_BEACON *)pData; #ifdef WFD_SUPPORT if (pAd->StaCfg.WfdCfg.bSuppInsertWfdIe) { ULONG TmpLen, WfdIeBitmap; ptr = pBeacon->beacon + pBeacon->beacon_len; WfdIeBitmap = (0x1 << SUBID_WFD_DEVICE_INFO) | (0x1 << SUBID_WFD_ASSOCIATED_BSSID) | (0x1 << SUBID_WFD_COUPLED_SINK_INFO); WfdMakeWfdIE(pAd, WfdIeBitmap, ptr, &TmpLen); pBeacon->beacon_len += TmpLen; } #endif /* WFD_SUPPORT */ if (isAdd) { rx_filter_flag = APNORMAL; RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, rx_filter_flag); /* enable RX of DMA block */ pAd->ApCfg.BssidNum = 1; pAd->MacTab.MsduLifeTime = 20; /* default 5 seconds */ pAd->ApCfg.MBSSID[MAIN_MBSSID].bBcnSntReq = TRUE; #ifdef INF_AMAZON_SE printk("YF DEBUG: INF_AMAZON_SE\n"); for (i = 0; i < NUM_OF_TX_RING; i++) { pAd->BulkOutDataSizeLimit[i]=24576; } #endif /* INF_AMAZON_SE */ AsicDisableSync(pAd); if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) { if (pAd->CommonCfg.Channel > 14) pAd->ApCfg.MBSSID[MAIN_MBSSID].PhyMode = PHY_11AN_MIXED; else pAd->ApCfg.MBSSID[MAIN_MBSSID].PhyMode = PHY_11BGN_MIXED; } else { if (pAd->CommonCfg.Channel > 14) pAd->ApCfg.MBSSID[MAIN_MBSSID].PhyMode = PHY_11A; else pAd->ApCfg.MBSSID[MAIN_MBSSID].PhyMode = PHY_11BG_MIXED; } TxPreamble = (pAd->CommonCfg.TxPreamble == Rt802_11PreambleLong ? 0 : 1); } PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[MAIN_MBSSID]; const UCHAR *ssid_ie = NULL; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)) ssid_ie = cfg80211_find_ie(WLAN_EID_SSID, pBeacon->beacon+36, pBeacon->beacon_len-36); #endif NdisZeroMemory(pMbss->Ssid, pMbss->SsidLen); if (ssid_ie == NULL) { printk("YF Debug: SSID Not Found In Packet\n"); NdisMoveMemory(pMbss->Ssid, "P2P_Linux_AP", 12); pMbss->SsidLen = 12; } else { pMbss->SsidLen = ssid_ie[1]; NdisCopyMemory(pMbss->Ssid, ssid_ie+2, pMbss->SsidLen); printk("YF Debug: SSID: %s, %d\n", pMbss->Ssid, pMbss->SsidLen); } if (isAdd) { //if (pMbss->bWmmCapable) //{ bWmmCapable = FALSE; pMbss->bWmmCapable = FALSE; //} pMbss->MSSIDDev = pAd->net_dev; COPY_MAC_ADDR(pMbss->Bssid, pAd->CurrentAddress); printk("AP BSSID %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pAd->CurrentAddress)); /* GO always use WPA2PSK / AES */ pMbss->AuthMode = Ndis802_11AuthModeWPA2PSK; pMbss->WepStatus = Ndis802_11Encryption3Enabled; pMbss->WscSecurityMode = WPA2PSKAES; pMbss->GroupKeyWepStatus = pMbss->WepStatus; pMbss->CapabilityInfo = CAP_GENERATE(1, 0, (pMbss->WepStatus != Ndis802_11EncryptionDisabled), TxPreamble, pAd->CommonCfg.bUseShortSlotTime, SpectrumMgmt); RTMPMakeRSNIE(pAd, Ndis802_11AuthModeWPA2PSK, Ndis802_11Encryption3Enabled, MAIN_MBSSID); #ifdef DOT11_N_SUPPORT RTMPSetPhyMode(pAd, pAd->CommonCfg.PhyMode); SetCommonHT(pAd); if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->Antenna.field.TxPath == 2)) { RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1); BBPR1 &= (~0x18); BBPR1 |= 0x10; RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1); } else #endif /* DOT11_N_SUPPORT */ { RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1); BBPR1 &= (~0x18); RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1); } /* Receiver Antenna selection, write to BBP R3(bit4:3) */ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3); BBPR3 &= (~0x18); if(pAd->Antenna.field.RxPath == 3) { BBPR3 |= (0x10); } else if(pAd->Antenna.field.RxPath == 2) { BBPR3 |= (0x8); } else if(pAd->Antenna.field.RxPath == 1) { BBPR3 |= (0x0); } RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3); if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) { if ((pAd->CommonCfg.PhyMode > PHY_11G) || bWmmCapable) { /* EDCA parameters used for AP's own transmission */ pAd->CommonCfg.APEdcaParm.bValid = TRUE; pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3; pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7; pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1; pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1; pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4; pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4; pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3; pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2; pAd->CommonCfg.APEdcaParm.Cwmax[0] = 6; pAd->CommonCfg.APEdcaParm.Cwmax[1] = 10; pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4; pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3; pAd->CommonCfg.APEdcaParm.Txop[0] = 0; pAd->CommonCfg.APEdcaParm.Txop[1] = 0; pAd->CommonCfg.APEdcaParm.Txop[2] = 94; /*96; */ pAd->CommonCfg.APEdcaParm.Txop[3] = 47; /*48; */ AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm); /* EDCA parameters to be annouced in outgoing BEACON, used by WMM STA */ pAd->ApCfg.BssEdcaParm.bValid = TRUE; pAd->ApCfg.BssEdcaParm.Aifsn[0] = 3; pAd->ApCfg.BssEdcaParm.Aifsn[1] = 7; pAd->ApCfg.BssEdcaParm.Aifsn[2] = 2; pAd->ApCfg.BssEdcaParm.Aifsn[3] = 2; pAd->ApCfg.BssEdcaParm.Cwmin[0] = 4; pAd->ApCfg.BssEdcaParm.Cwmin[1] = 4; pAd->ApCfg.BssEdcaParm.Cwmin[2] = 3; pAd->ApCfg.BssEdcaParm.Cwmin[3] = 2; pAd->ApCfg.BssEdcaParm.Cwmax[0] = 10; pAd->ApCfg.BssEdcaParm.Cwmax[1] = 10; pAd->ApCfg.BssEdcaParm.Cwmax[2] = 4; pAd->ApCfg.BssEdcaParm.Cwmax[3] = 3; pAd->ApCfg.BssEdcaParm.Txop[0] = 0; pAd->ApCfg.BssEdcaParm.Txop[1] = 0; pAd->ApCfg.BssEdcaParm.Txop[2] = 94; /*96; */ pAd->ApCfg.BssEdcaParm.Txop[3] = 47; /*48; */ } else { AsicSetEdcaParm(pAd, NULL); } } #ifdef DOT11_N_SUPPORT if (pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED) { /* Patch UI */ pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = BW_20; } /* init */ if (pAd->CommonCfg.bRdg) { RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE); AsicEnableRDG(pAd); } else { RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE); AsicDisableRDG(pAd); } #endif /* DOT11_N_SUPPORT */ //AsicSetBssid(pAd, pAd->CurrentAddress); AsicSetMcastWC(pAd); /* In AP mode, First WCID Table in ASIC will never be used. To prevent it's 0xff-ff-ff-ff-ff-ff, Write 0 here. */ /* p.s ASIC use all 0xff as termination of WCID table search. */ RTMP_IO_WRITE32(pAd, MAC_WCID_BASE, 0x00); RTMP_IO_WRITE32(pAd, MAC_WCID_BASE+4, 0x0); /* reset WCID table */ for (idx=2; idx<255; idx++) { offset = MAC_WCID_BASE + (idx * HW_WCID_ENTRY_SIZE); RTMP_IO_WRITE32(pAd, offset, 0x0); RTMP_IO_WRITE32(pAd, offset+4, 0x0); } pAd->MacTab.Content[0].Addr[0] = 0x01; pAd->MacTab.Content[0].HTPhyMode.field.MODE = MODE_OFDM; pAd->MacTab.Content[0].HTPhyMode.field.MCS = 3; AsicBBPAdjust(pAd); //MlmeSetTxPreamble(pAd, (USHORT)pAd->CommonCfg.TxPreamble); { ULONG Addr4; UINT32 regValue; PUCHAR pP2PBssid = &pAd->CurrentAddress[0]; Addr4 = (ULONG)(pP2PBssid[0]) | (ULONG)(pP2PBssid[1] << 8) | (ULONG)(pP2PBssid[2] << 16) | (ULONG)(pP2PBssid[3] << 24); RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4); Addr4 = 0; Addr4 = (ULONG)(pP2PBssid[4]) | (ULONG)(pP2PBssid[5] << 8); RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4); RTMP_IO_READ32(pAd, MAC_BSSID_DW1, ®Value); regValue &= 0x0000FFFF; regValue |= (1 << 16); if (pAd->chipCap.MBSSIDMode == MBSSID_MODE1) regValue |= (1 << 21); RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, regValue); } #ifdef RTMP_MAC_USB printk("YF DEBUG: RTUSBBssBeaconInit\n"); RTUSBBssBeaconInit(pAd); #endif /* RTMP_MAC_USB */ } UCHAR apcliIdx, apidx = MAIN_MBSSID; //pAd->ApCfg.MBSSID[MAIN_MBSSID].PhyMode = PHY_11BGN_MIXED; printk("YF DEBUG: Beacon Len %d\n", pBeacon->beacon_len); printk("YF DEBUG: Beacon Interval %d\n", pBeacon->interval); BeaconTransmit.word = 0; RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, BSS0Mcast_WCID, pBeacon->beacon_len, PID_MGMT, 0, 0,IFS_HTTXOP, FALSE, &BeaconTransmit); ptr = (PUCHAR)&pAd->BeaconTxWI; #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(ptr, TYPE_TXWI); #endif for (i=0; iBeaconOffset[0] + i, longValue); ptr += 4; } /* update BEACON frame content. start right after the 16-byte TXWI field. */ ptr = pBeacon->beacon; #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE); #endif for (i= 0; i< pBeacon->beacon_len; i+=4) { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[0] + TXWISize + i, longValue); ptr += 4; } if (isAdd) { /* Enable Bss Sync*/ RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word); csr9.field.BeaconInterval = (pBeacon->interval) << 4; /* ASIC register in units of 1/16 TU*/ csr9.field.bTsfTicking = 1; csr9.field.TsfSyncMode = 3; csr9.field.bTBTTEnable = 1; csr9.field.bBeaconGen = 1; RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word); pAd->P2pCfg.bSentProbeRSP = TRUE; #ifdef RTMP_MAC_USB /* * Support multiple BulkIn IRP, * the value on pAd->CommonCfg.NumOfBulkInIRP may be large than 1. */ UCHAR num_idx; for(num_idx=0; num_idx < pAd->CommonCfg.NumOfBulkInIRP; num_idx++) { RTUSBBulkReceive(pAd); printk("RTUSBBulkReceive!\n" ); } #endif /* RTMP_MAC_USB */ } #ifdef WFD_SUPPORT pAd->StaCfg.WfdCfg.bSuppGoOn = TRUE; #endif /* WFD_SUPPORT */ return TRUE; } BOOLEAN CFG80211DRV_OpsExtraIesSet( VOID *pAdOrg) { PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; CFG80211_CB *pCfg80211_CB = pAd->pCfg80211_CB; UINT ie_len = pCfg80211_CB->pCfg80211_ScanReq->ie_len; CFG80211DBG(RT_DEBUG_ERROR, ("80211> CFG80211DRV_OpsExtraIesSet ==> %d\n", ie_len)); if (pAd->StaCfg.pWpsProbeReqIe) { os_free_mem(NULL, pAd->StaCfg.pWpsProbeReqIe); pAd->StaCfg.pWpsProbeReqIe = NULL; } pAd->StaCfg.WpsProbeReqIeLen = 0; CFG80211DBG(RT_DEBUG_ERROR, ("80211> is_wpa_supplicant_up ==> %d\n", pAd->StaCfg.WpaSupplicantUP)); os_alloc_mem(pAd, (UCHAR **)&(pAd->StaCfg.pWpsProbeReqIe), ie_len); if (pAd->StaCfg.pWpsProbeReqIe) { memcpy(pAd->StaCfg.pWpsProbeReqIe, pCfg80211_CB->pCfg80211_ScanReq->ie, ie_len); pAd->StaCfg.WpsProbeReqIeLen = ie_len; //hex_dump("WpsProbeReqIe", pAd->StaCfg.pWpsProbeReqIe, pAd->StaCfg.WpsProbeReqIeLen); DBGPRINT(RT_DEBUG_TRACE, ("Set::RT_OID_WPS_PROBE_REQ_IE, WpsProbeReqIeLen = %d!!\n", pAd->StaCfg.WpsProbeReqIeLen)); } else { CFG80211DBG(RT_DEBUG_ERROR, ("80211> CFG80211DRV_OpsExtraIesSet ==> allocate fail. \n")); return FALSE; } return TRUE; } BOOLEAN CFG80211DRV_OpsJoinIbss( VOID *pAdOrg, VOID *pData) { #ifdef CONFIG_STA_SUPPORT PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; CMD_RTPRIV_IOCTL_80211_IBSS *pIbssInfo; pIbssInfo = (CMD_RTPRIV_IOCTL_80211_IBSS *)pData; pAd->StaCfg.bAutoReconnect = TRUE; pAd->CommonCfg.BeaconPeriod = pIbssInfo->BeaconInterval; Set_SSID_Proc(pAd, (PSTRING)pIbssInfo->pSsid); #endif /* CONFIG_STA_SUPPORT */ return TRUE; } BOOLEAN CFG80211DRV_OpsLeave( VOID *pAdOrg) { #ifdef CONFIG_STA_SUPPORT PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; pAd->StaCfg.bAutoReconnect = FALSE; pAd->FlgCfg80211Connecting = FALSE; LinkDown(pAd, FALSE); #endif /* CONFIG_STA_SUPPORT */ return TRUE; } BOOLEAN CFG80211DRV_StaGet( VOID *pAdOrg, VOID *pData) { PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; CMD_RTPRIV_IOCTL_80211_STA *pIbssInfo; pIbssInfo = (CMD_RTPRIV_IOCTL_80211_STA *)pData; #ifdef CONFIG_AP_SUPPORT { MAC_TABLE_ENTRY *pEntry; ULONG DataRate = 0; UINT32 RSSI; pEntry = MacTableLookup(pAd, pIbssInfo->MAC); if (pEntry == NULL) return FALSE; /* End of if */ /* fill tx rate */ getRate(pEntry->HTPhyMode, &DataRate); if ((pEntry->HTPhyMode.field.MODE == MODE_HTMIX) || (pEntry->HTPhyMode.field.MODE == MODE_HTGREENFIELD)) { if (pEntry->HTPhyMode.field.BW) pIbssInfo->TxRateFlags |= RT_CMD_80211_TXRATE_BW_40; /* End of if */ if (pEntry->HTPhyMode.field.ShortGI) pIbssInfo->TxRateFlags |= RT_CMD_80211_TXRATE_SHORT_GI; /* End of if */ pIbssInfo->TxRateMCS = pEntry->HTPhyMode.field.MCS; } else { pIbssInfo->TxRateFlags = RT_CMD_80211_TXRATE_LEGACY; pIbssInfo->TxRateMCS = DataRate*1000; /* unit: 100kbps */ } /* End of if */ /* fill signal */ RSSI = (pEntry->RssiSample.AvgRssi0 + pEntry->RssiSample.AvgRssi1 + pEntry->RssiSample.AvgRssi2) / 3; pIbssInfo->Signal = RSSI; /* fill tx count */ pIbssInfo->TxPacketCnt = pEntry->OneSecTxNoRetryOkCount + pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount; /* fill inactive time */ pIbssInfo->InactiveTime = pEntry->NoDataIdleCount * 1000; /* unit: ms */ pIbssInfo->InactiveTime *= MLME_TASK_EXEC_MULTIPLE; pIbssInfo->InactiveTime /= 20; } #endif /* CONFIG_AP_SUPPORT */ #ifdef CONFIG_STA_SUPPORT { HTTRANSMIT_SETTING PhyInfo; ULONG DataRate = 0; UINT32 RSSI; /* fill tx rate */ if ((!WMODE_CAP_N(pAd->CommonCfg.PhyMode)) || (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE <= MODE_OFDM)) { PhyInfo.word = pAd->StaCfg.HTPhyMode.word; } else PhyInfo.word = pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word; /* End of if */ getRate(PhyInfo, &DataRate); if ((PhyInfo.field.MODE == MODE_HTMIX) || (PhyInfo.field.MODE == MODE_HTGREENFIELD)) { if (PhyInfo.field.BW) pIbssInfo->TxRateFlags |= RT_CMD_80211_TXRATE_BW_40; /* End of if */ if (PhyInfo.field.ShortGI) pIbssInfo->TxRateFlags |= RT_CMD_80211_TXRATE_SHORT_GI; /* End of if */ pIbssInfo->TxRateMCS = PhyInfo.field.MCS; } else { pIbssInfo->TxRateFlags = RT_CMD_80211_TXRATE_LEGACY; pIbssInfo->TxRateMCS = DataRate*10; /* unit: 100kbps */ } /* End of if */ /* fill signal */ RSSI = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1 + pAd->StaCfg.RssiSample.AvgRssi2) / 3; pIbssInfo->Signal = RSSI; } #endif /* CONFIG_STA_SUPPORT */ return TRUE; } BOOLEAN CFG80211DRV_KeyAdd( VOID *pAdOrg, VOID *pData) { #ifdef CONFIG_STA_SUPPORT PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; CMD_RTPRIV_IOCTL_80211_KEY *pKeyInfo; pKeyInfo = (CMD_RTPRIV_IOCTL_80211_KEY *)pData; if (pKeyInfo->KeyType == RT_CMD_80211_KEY_WEP) { switch(pKeyInfo->KeyId) { case 1: default: Set_Key1_Proc(pAd, (PSTRING)pKeyInfo->KeyBuf); break; case 2: Set_Key2_Proc(pAd, (PSTRING)pKeyInfo->KeyBuf); break; case 3: Set_Key3_Proc(pAd, (PSTRING)pKeyInfo->KeyBuf); break; case 4: Set_Key4_Proc(pAd, (PSTRING)pKeyInfo->KeyBuf); break; } /* End of switch */ } else Set_WPAPSK_Proc(pAd, (PSTRING)pKeyInfo->KeyBuf); #endif /* CONFIG_STA_SUPPORT */ return TRUE; } BOOLEAN CFG80211DRV_Connect( VOID *pAdOrg, VOID *pData) { #ifdef CONFIG_STA_SUPPORT PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; CMD_RTPRIV_IOCTL_80211_CONNECT *pConnInfo; UCHAR SSID[NDIS_802_11_LENGTH_SSID]; UINT32 SSIDLen; pConnInfo = (CMD_RTPRIV_IOCTL_80211_CONNECT *)pData; /* change to infrastructure mode if we are in ADHOC mode */ Set_NetworkType_Proc(pAd, "Infra"); /* set authentication mode */ if (pConnInfo->WpaVer == 2) { if (pConnInfo->FlgIs8021x == TRUE) Set_AuthMode_Proc(pAd, "WPA2"); else Set_AuthMode_Proc(pAd, "WPA2PSK"); /* End of if */ } else if (pConnInfo->WpaVer == 1) { if (pConnInfo->FlgIs8021x == TRUE) Set_AuthMode_Proc(pAd, "WPA"); else Set_AuthMode_Proc(pAd, "WPAPSK"); /* End of if */ } else if (pConnInfo->FlgIsAuthOpen == FALSE) Set_AuthMode_Proc(pAd, "SHARED"); else Set_AuthMode_Proc(pAd, "OPEN"); /* End of if */ CFG80211DBG(RT_DEBUG_ERROR, ("80211> AuthMode = %d\n", pAd->StaCfg.AuthMode)); /* set encryption mode */ if (pConnInfo->PairwiseEncrypType & RT_CMD_80211_CONN_ENCRYPT_CCMP) Set_EncrypType_Proc(pAd, "AES"); else if (pConnInfo->PairwiseEncrypType & RT_CMD_80211_CONN_ENCRYPT_TKIP) Set_EncrypType_Proc(pAd, "TKIP"); else if (pConnInfo->PairwiseEncrypType & RT_CMD_80211_CONN_ENCRYPT_WEP) { Set_EncrypType_Proc(pAd, "WEP"); } else if (pConnInfo->GroupwiseEncrypType & RT_CMD_80211_CONN_ENCRYPT_CCMP) Set_EncrypType_Proc(pAd, "AES"); else if (pConnInfo->GroupwiseEncrypType & RT_CMD_80211_CONN_ENCRYPT_TKIP) Set_EncrypType_Proc(pAd, "TKIP"); else Set_EncrypType_Proc(pAd, "NONE"); /* End of if */ CFG80211DBG(RT_DEBUG_ERROR, ("80211> EncrypType = %d\n", pAd->StaCfg.WepStatus)); /* set channel: STATION will auto-scan */ /* set WEP key */ if (pConnInfo->pKey && ((pConnInfo->GroupwiseEncrypType | pConnInfo->PairwiseEncrypType) & RT_CMD_80211_CONN_ENCRYPT_WEP)) { UCHAR KeyBuf[50]; /* reset AuthMode and EncrypType */ Set_AuthMode_Proc(pAd, "SHARED"); Set_EncrypType_Proc(pAd, "WEP"); /* reset key */ #ifdef RT_CFG80211_DEBUG hex_dump("KeyBuf=", (UINT8 *)pConnInfo->pKey, pConnInfo->KeyLen); #endif /* RT_CFG80211_DEBUG */ pAd->StaCfg.DefaultKeyId = pConnInfo->KeyIdx; /* base 0 */ if (pConnInfo->KeyLen >= sizeof(KeyBuf)) return FALSE; /* End of if */ memcpy(KeyBuf, pConnInfo->pKey, pConnInfo->KeyLen); KeyBuf[pConnInfo->KeyLen] = 0x00; CFG80211DBG(RT_DEBUG_ERROR, ("80211> pAd->StaCfg.DefaultKeyId = %d\n", pAd->StaCfg.DefaultKeyId)); switch(pConnInfo->KeyIdx) { case 1: default: Set_Key1_Proc(pAd, (PSTRING)KeyBuf); break; case 2: Set_Key2_Proc(pAd, (PSTRING)KeyBuf); break; case 3: Set_Key3_Proc(pAd, (PSTRING)KeyBuf); break; case 4: Set_Key4_Proc(pAd, (PSTRING)KeyBuf); break; } /* End of switch */ } /* End of if */ /* TODO: We need to provide a command to set BSSID to associate a AP */ /* re-set SSID */ pAd->StaCfg.bAutoReconnect = TRUE; pAd->FlgCfg80211Connecting = TRUE; SSIDLen = pConnInfo->SsidLen; if (SSIDLen > NDIS_802_11_LENGTH_SSID) SSIDLen = NDIS_802_11_LENGTH_SSID; /* End of if */ memset(&SSID, 0, sizeof(SSID)); memcpy(SSID, pConnInfo->pSsid, SSIDLen); Set_SSID_Proc(pAd, (PSTRING)SSID); CFG80211DBG(RT_DEBUG_ERROR, ("80211> SSID = %s\n", SSID)); #endif /* CONFIG_STA_SUPPORT */ return TRUE; } VOID CFG80211DRV_RegNotify( VOID *pAdOrg, VOID *pData) { PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; CMD_RTPRIV_IOCTL_80211_REG_NOTIFY *pRegInfo; pRegInfo = (CMD_RTPRIV_IOCTL_80211_REG_NOTIFY *)pData; /* keep Alpha2 and we can re-call the function when interface is up */ pAd->Cfg80211_Alpha2[0] = pRegInfo->Alpha2[0]; pAd->Cfg80211_Alpha2[1] = pRegInfo->Alpha2[1]; /* apply the new regulatory rule */ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) { /* interface is up */ CFG80211_RegRuleApply(pAd, pRegInfo->pWiphy, (UCHAR *)pRegInfo->Alpha2); } else { CFG80211DBG(RT_DEBUG_ERROR, ("crda> interface is down!\n")); } /* End of if */ } VOID CFG80211DRV_SurveyGet( VOID *pAdOrg, VOID *pData) { PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; CMD_RTPRIV_IOCTL_80211_SURVEY *pSurveyInfo; pSurveyInfo = (CMD_RTPRIV_IOCTL_80211_SURVEY *)pData; pSurveyInfo->pCfg80211 = pAd->pCfg80211_CB; #ifdef AP_QLOAD_SUPPORT pSurveyInfo->ChannelTimeBusy = pAd->QloadLatestChannelBusyTimePri; pSurveyInfo->ChannelTimeExtBusy = pAd->QloadLatestChannelBusyTimeSec; #endif /* AP_QLOAD_SUPPORT */ } VOID CFG80211_UnRegister( IN VOID *pAdOrg, IN VOID *pNetDev) { PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; /* sanity check */ if (pAd->pCfg80211_CB == NULL) return; /* End of if */ CFG80211OS_UnRegister(pAd->pCfg80211_CB, pNetDev); pAd->pCfg80211_CB = NULL; pAd->CommonCfg.HT_Disable = 0; } /* ======================================================================== Routine Description: Parse and handle country region in beacon from associated AP. Arguments: pAdCB - WLAN control block pointer pVIE - Beacon elements LenVIE - Total length of Beacon elements Return Value: NONE Note: ======================================================================== */ VOID CFG80211_BeaconCountryRegionParse( IN VOID *pAdCB, IN NDIS_802_11_VARIABLE_IEs *pVIE, IN UINT16 LenVIE) { PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; UCHAR *pElement = (UCHAR *)pVIE; UINT32 LenEmt; while(LenVIE > 0) { pVIE = (NDIS_802_11_VARIABLE_IEs *)pElement; if (pVIE->ElementID == IE_COUNTRY) { /* send command to do regulation hint only when associated */ RTEnqueueInternalCmd(pAd, CMDTHREAD_REG_HINT_11D, pVIE->data, pVIE->Length); break; } /* End of if */ LenEmt = pVIE->Length + 2; if (LenVIE <= LenEmt) break; /* length is not enough */ /* End of if */ pElement += LenEmt; LenVIE -= LenEmt; } /* End of while */ } /* End of CFG80211_BeaconCountryRegionParse */ /* ======================================================================== Routine Description: Hint to the wireless core a regulatory domain from driver. Arguments: pAd - WLAN control block pointer pCountryIe - pointer to the country IE CountryIeLen - length of the country IE Return Value: NONE Note: Must call the function in kernel thread. ======================================================================== */ VOID CFG80211_RegHint( IN VOID *pAdCB, IN UCHAR *pCountryIe, IN ULONG CountryIeLen) { PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; CFG80211OS_RegHint(CFG80211CB, pCountryIe, CountryIeLen); } /* End of CFG80211_RegHint */ /* ======================================================================== Routine Description: Hint to the wireless core a regulatory domain from country element. Arguments: pAdCB - WLAN control block pointer pCountryIe - pointer to the country IE CountryIeLen - length of the country IE Return Value: NONE Note: Must call the function in kernel thread. ======================================================================== */ VOID CFG80211_RegHint11D( IN VOID *pAdCB, IN UCHAR *pCountryIe, IN ULONG CountryIeLen) { /* no regulatory_hint_11d() in 2.6.32 */ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; CFG80211OS_RegHint11D(CFG80211CB, pCountryIe, CountryIeLen); } /* End of CFG80211_RegHint11D */ /* ======================================================================== Routine Description: Apply new regulatory rule. Arguments: pAdCB - WLAN control block pointer pWiphy - Wireless hardware description pAlpha2 - Regulation domain (2B) Return Value: NONE Note: Can only be called when interface is up. For general mac80211 device, it will be set to new power by Ops->config() In rt2x00/, the settings is done in rt2x00lib_config(). ======================================================================== */ VOID CFG80211_RegRuleApply( IN VOID *pAdCB, IN VOID *pWiphy, IN UCHAR *pAlpha2) { PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; VOID *pBand24G, *pBand5G; UINT32 IdBand, IdChan, IdPwr; UINT32 ChanNum, ChanId, Power, RecId, DfsType; BOOLEAN FlgIsRadar; ULONG IrqFlags; #ifdef DFS_SUPPORT RADAR_DETECT_STRUCT *pRadarDetect; #endif /* DFS_SUPPORT */ CFG80211DBG(RT_DEBUG_ERROR, ("crda> CFG80211_RegRuleApply ==>\n")); /* init */ pBand24G = NULL; pBand5G = NULL; if (pAd == NULL) return; RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); /* zero first */ NdisZeroMemory(pAd->ChannelList, MAX_NUM_OF_CHANNELS * sizeof(CHANNEL_TX_POWER)); /* 2.4GHZ & 5GHz */ RecId = 0; #ifdef DFS_SUPPORT pRadarDetect = &pAd->CommonCfg.RadarDetect; #endif /* DFS_SUPPORT */ /* find the DfsType */ DfsType = CE; pBand24G = NULL; pBand5G = NULL; if (CFG80211OS_BandInfoGet(CFG80211CB, pWiphy, &pBand24G, &pBand5G) == FALSE) return; #ifdef AUTO_CH_SELECT_ENHANCE #ifdef EXT_BUILD_CHANNEL_LIST if ((pAlpha2[0] != '0') && (pAlpha2[1] != '0')) { UINT32 IdReg; if (pBand5G != NULL) { for(IdReg=0; ; IdReg++) { if (ChRegion[IdReg].CountReg[0] == 0x00) break; /* End of if */ if ((pAlpha2[0] == ChRegion[IdReg].CountReg[0]) && (pAlpha2[1] == ChRegion[IdReg].CountReg[1])) { if (pAd->CommonCfg.DfsType != MAX_RD_REGION) DfsType = pAd->CommonCfg.DfsType; else DfsType = ChRegion[IdReg].DfsType; CFG80211DBG(RT_DEBUG_ERROR, ("crda> find region %c%c, DFS Type %d\n", pAlpha2[0], pAlpha2[1], DfsType)); break; } /* End of if */ } /* End of for */ } /* End of if */ } /* End of if */ #endif /* EXT_BUILD_CHANNEL_LIST */ #endif /* AUTO_CH_SELECT_ENHANCE */ for(IdBand=0; IdBand<2; IdBand++) { if (((IdBand == 0) && (pBand24G == NULL)) || ((IdBand == 1) && (pBand5G == NULL))) { continue; } /* End of if */ if (IdBand == 0) { CFG80211DBG(RT_DEBUG_ERROR, ("crda> reset chan/power for 2.4GHz\n")); } else { CFG80211DBG(RT_DEBUG_ERROR, ("crda> reset chan/power for 5GHz\n")); } /* End of if */ ChanNum = CFG80211OS_ChanNumGet(CFG80211CB, pWiphy, IdBand); for(IdChan=0; IdChanCommonCfg.PhyMode)) { /* 5G-only mode */ if (ChanId <= CFG80211_NUM_OF_CHAN_2GHZ) continue; } if (!WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) { /* 2.4G-only mode */ if (ChanId > CFG80211_NUM_OF_CHAN_2GHZ) continue; } for(IdPwr=0; IdPwrTxPower[IdPwr].Channel) { /* init the channel info. */ NdisMoveMemory(&pAd->ChannelList[RecId], &pAd->TxPower[IdPwr], sizeof(CHANNEL_TX_POWER)); /* keep channel number */ pAd->ChannelList[RecId].Channel = ChanId; /* keep maximum tranmission power */ pAd->ChannelList[RecId].MaxTxPwr = Power; /* keep DFS flag */ if (FlgIsRadar == TRUE) pAd->ChannelList[RecId].DfsReq = TRUE; else pAd->ChannelList[RecId].DfsReq = FALSE; /* End of if */ /* keep DFS type */ pAd->ChannelList[RecId].RegulatoryDomain = DfsType; /* re-set DFS info. */ pAd->CommonCfg.RDDurRegion = DfsType; CFG80211DBG(RT_DEBUG_ERROR, ("Chan %03d:\tpower %d dBm, " "DFS %d, DFS Type %d\n", ChanId, Power, ((FlgIsRadar == TRUE)?1:0), DfsType)); /* change to record next channel info. */ RecId ++; break; } /* End of if */ } /* End of for */ } /* End of for */ } /* End of for */ pAd->ChannelListNum = RecId; RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); CFG80211DBG(RT_DEBUG_ERROR, ("crda> Number of channels = %d\n", RecId)); } /* End of CFG80211_RegRuleApply */ /* ======================================================================== Routine Description: Inform us that a scan is got. Arguments: pAdCB - WLAN control block pointer Return Value: NONE Note: Call RT_CFG80211_SCANNING_INFORM, not CFG80211_Scaning ======================================================================== */ VOID CFG80211_Scaning( IN VOID *pAdCB, IN UINT32 BssIdx, IN UINT32 ChanId, IN UCHAR *pFrame, IN UINT32 FrameLen, IN INT32 RSSI) { #ifdef CONFIG_STA_SUPPORT PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; VOID *pCfg80211_CB = pAd->pCfg80211_CB; BOOLEAN FlgIsNMode; UINT8 BW; CFG80211DBG(RT_DEBUG_ERROR, ("80211> CFG80211_Scaning ==>\n")); if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { DBGPRINT(RT_DEBUG_TRACE, ("80211> Network is down!\n")); return; } /* End of if */ /* In connect function, we also need to report BSS information to cfg80211; Not only scan function. */ if ((pAd->FlgCfg80211Scanning == FALSE) && (pAd->FlgCfg80211Connecting == FALSE)) { return; /* no scan is running */ } /* End of if */ /* init */ /* Note: Can not use local variable to do pChan */ if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) FlgIsNMode = TRUE; else FlgIsNMode = FALSE; if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_20) BW = 0; else BW = 1; CFG80211OS_Scaning(pCfg80211_CB, ChanId, pFrame, FrameLen, RSSI, FlgIsNMode, BW); #endif /* CONFIG_STA_SUPPORT */ } /* End of CFG80211_Scaning */ /* ======================================================================== Routine Description: Inform us that scan ends. Arguments: pAdCB - WLAN control block pointer FlgIsAborted - 1: scan is aborted Return Value: NONE Note: ======================================================================== */ VOID CFG80211_ScanEnd( IN VOID *pAdCB, IN BOOLEAN FlgIsAborted) { #ifdef CONFIG_STA_SUPPORT PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) { DBGPRINT(RT_DEBUG_TRACE, ("80211> Network is down!\n")); return; } /* End of if */ if (pAd->FlgCfg80211Scanning == FALSE) { DBGPRINT(RT_DEBUG_TRACE, ("80211> No scan is running!\n")); return; /* no scan is running */ } /* End of if */ if (FlgIsAborted == TRUE) FlgIsAborted = 1; else FlgIsAborted = 0; /* End of if */ CFG80211OS_ScanEnd(CFG80211CB, FlgIsAborted); pAd->FlgCfg80211Scanning = FALSE; #endif /* CONFIG_STA_SUPPORT */ } /* End of CFG80211_ScanEnd */ /* ======================================================================== Routine Description: Inform CFG80211 about association status. Arguments: pAdCB - WLAN control block pointer pBSSID - the BSSID of the AP pReqIe - the element list in the association request frame ReqIeLen - the request element length pRspIe - the element list in the association response frame RspIeLen - the response element length FlgIsSuccess - 1: success; otherwise: fail Return Value: None Note: ======================================================================== */ VOID CFG80211_ConnectResultInform( IN VOID *pAdCB, IN UCHAR *pBSSID, IN UCHAR *pReqIe, IN UINT32 ReqIeLen, IN UCHAR *pRspIe, IN UINT32 RspIeLen, IN UCHAR FlgIsSuccess) { PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; CFG80211DBG(RT_DEBUG_ERROR, ("80211> CFG80211_ConnectResultInform ==>\n")); CFG80211OS_ConnectResultInform(CFG80211CB, pBSSID, pReqIe, ReqIeLen, pRspIe, RspIeLen, FlgIsSuccess); pAd->FlgCfg80211Connecting = FALSE; } /* End of CFG80211_ConnectResultInform */ /* ======================================================================== Routine Description: Re-Initialize wireless channel/PHY in 2.4GHZ and 5GHZ. Arguments: pAdCB - WLAN control block pointer Return Value: TRUE - re-init successfully FALSE - re-init fail Note: CFG80211_SupBandInit() is called in xx_probe(). But we do not have complete chip information in xx_probe() so we need to re-init bands in xx_open(). ======================================================================== */ BOOLEAN CFG80211_SupBandReInit( IN VOID *pAdCB) { PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; CFG80211_BAND BandInfo; CFG80211DBG(RT_DEBUG_ERROR, ("80211> re-init bands...\n")); /* re-init bands */ NdisZeroMemory(&BandInfo, sizeof(BandInfo)); CFG80211_BANDINFO_FILL(pAd, &BandInfo); return CFG80211OS_SupBandReInit(CFG80211CB, &BandInfo); } /* End of CFG80211_SupBandReInit */ INT CFG80211_StaPortSecured( IN VOID *pAdCB, IN UCHAR *pMac, IN UINT flag) { PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; MAC_TABLE_ENTRY *pEntry; pEntry = MacTableLookup(pAd, pMac); if (!pEntry) { printk("Can't find pEntry in CFG80211_StaPortSecured\n"); } else { if (flag) { printk("AID:%d, PortSecured\n", pEntry->Aid); pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; pEntry->WpaState = AS_PTKINITDONE; pEntry->PortSecured = WPA_802_1X_PORT_SECURED; } else { printk("AID:%d, PortNotSecured\n", pEntry->Aid); pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; } } return 0; } INT CFG80211_ApStaDel( IN VOID *pAdCB, IN UCHAR *pMac) { PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; MAC_TABLE_ENTRY *pEntry; if (pMac == NULL) { MacTableReset(pAd); } else { pEntry = MacTableLookup(pAd, pMac); if (pEntry) { // MlmeDeAuthAction(pAd, pEntry, 2, FALSE); } else printk("Can't find pEntry in ApStaDel\n"); } } //CMD_RTPRIV_IOCTL_80211_KEY_DEFAULT_SET: INT CFG80211_setDefaultKey( IN VOID *pAdCB, IN UINT Data ) { PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; CFG80211_CB *p80211CB = pAd->pCfg80211_CB; if (p80211CB->pCfg80211_Wdev->iftype == RT_CMD_80211_IFTYPE_AP) //if (pAd->VifNextMode == RT_CMD_80211_IFTYPE_AP) { printk("Set Ap Default Key: %d\n", Data); pAd->ApCfg.MBSSID[MAIN_MBSSID].DefaultKeyId = Data; } else #ifdef CONFIG_STA_SUPPORT { printk("Set Sta Default Key: %d\n", Data); pAd->StaCfg.DefaultKeyId = Data; /* base 0 */ } #endif /* CONFIG_STA_SUPPORT */ return 0; } #ifdef RT_P2P_SPECIFIC_WIRELESS_EVENT INT CFG80211_SendWirelessEvent( IN VOID *pAdCB, IN UCHAR *pMacAddr) { PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; P2pSendWirelessEvent(pAd, RT_P2P_CONNECTED, NULL, pMacAddr); return 0; } #endif /* RT_P2P_SPECIFIC_WIRELESS_EVENT */ #endif /* RT_CFG80211_SUPPORT */ /* End of cfg80211drv.c */