summaryrefslogtreecommitdiff
path: root/drivers/staging/rtl8187se/ieee80211/dot11d.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/rtl8187se/ieee80211/dot11d.c')
-rw-r--r--drivers/staging/rtl8187se/ieee80211/dot11d.c213
1 files changed, 213 insertions, 0 deletions
diff --git a/drivers/staging/rtl8187se/ieee80211/dot11d.c b/drivers/staging/rtl8187se/ieee80211/dot11d.c
new file mode 100644
index 00000000..9d2d5c58
--- /dev/null
+++ b/drivers/staging/rtl8187se/ieee80211/dot11d.c
@@ -0,0 +1,213 @@
+//-----------------------------------------------------------------------------
+// File:
+// Dot11d.c
+//
+// Description:
+// Implement 802.11d.
+//
+//-----------------------------------------------------------------------------
+
+#include "dot11d.h"
+
+void
+Dot11d_Init(struct ieee80211_device *ieee)
+{
+ PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
+
+ pDot11dInfo->bEnabled = 0;
+
+ pDot11dInfo->State = DOT11D_STATE_NONE;
+ pDot11dInfo->CountryIeLen = 0;
+ memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
+ memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
+ RESET_CIE_WATCHDOG(ieee);
+
+ printk("Dot11d_Init()\n");
+}
+
+//
+// Description:
+// Reset to the state as we are just entering a regulatory domain.
+//
+void
+Dot11d_Reset(struct ieee80211_device *ieee)
+{
+ u32 i;
+ PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
+
+ // Clear old channel map
+ memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
+ memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
+ // Set new channel map
+ for (i = 1; i <= 11; i++)
+ (pDot11dInfo->channel_map)[i] = 1;
+
+ for (i = 12; i <= 14; i++)
+ (pDot11dInfo->channel_map)[i] = 2;
+
+ pDot11dInfo->State = DOT11D_STATE_NONE;
+ pDot11dInfo->CountryIeLen = 0;
+ RESET_CIE_WATCHDOG(ieee);
+
+ //printk("Dot11d_Reset()\n");
+}
+
+//
+// Description:
+// Update country IE from Beacon or Probe Response
+// and configure PHY for operation in the regulatory domain.
+//
+// TODO:
+// Configure Tx power.
+//
+// Assumption:
+// 1. IS_DOT11D_ENABLE() is TRUE.
+// 2. Input IE is an valid one.
+//
+void
+Dot11d_UpdateCountryIe(
+ struct ieee80211_device *dev,
+ u8 *pTaddr,
+ u16 CoutryIeLen,
+ u8 *pCoutryIe
+ )
+{
+ PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
+ u8 i, j, NumTriples, MaxChnlNum;
+ PCHNL_TXPOWER_TRIPLE pTriple;
+
+ if ((CoutryIeLen - 3)%3 != 0) {
+ printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
+ Dot11d_Reset(dev);
+ return;
+ }
+
+ memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
+ memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
+ MaxChnlNum = 0;
+ NumTriples = (CoutryIeLen - 3) / 3; // skip 3-byte country string.
+ pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3);
+ for (i = 0; i < NumTriples; i++) {
+ if (MaxChnlNum >= pTriple->FirstChnl) {
+ // It is not in a monotonically increasing order, so stop processing.
+ printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
+ Dot11d_Reset(dev);
+ return;
+ }
+ if (MAX_CHANNEL_NUMBER < (pTriple->FirstChnl + pTriple->NumChnls)) {
+ // It is not a valid set of channel id, so stop processing.
+ printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n");
+ Dot11d_Reset(dev);
+ return;
+ }
+
+ for (j = 0 ; j < pTriple->NumChnls; j++) {
+ pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1;
+ pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] = pTriple->MaxTxPowerInDbm;
+ MaxChnlNum = pTriple->FirstChnl + j;
+ }
+
+ pTriple = (PCHNL_TXPOWER_TRIPLE)((u8 *)pTriple + 3);
+ }
+#if 1
+ //printk("Dot11d_UpdateCountryIe(): Channel List:\n");
+ printk("Channel List:");
+ for (i = 1; i <= MAX_CHANNEL_NUMBER; i++)
+ if (pDot11dInfo->channel_map[i] > 0)
+ printk(" %d", i);
+ printk("\n");
+#endif
+
+ UPDATE_CIE_SRC(dev, pTaddr);
+
+ pDot11dInfo->CountryIeLen = CoutryIeLen;
+ memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe, CoutryIeLen);
+ pDot11dInfo->State = DOT11D_STATE_LEARNED;
+}
+
+u8
+DOT11D_GetMaxTxPwrInDbm(
+ struct ieee80211_device *dev,
+ u8 Channel
+ )
+{
+ PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
+ u8 MaxTxPwrInDbm = 255;
+
+ if (MAX_CHANNEL_NUMBER < Channel) {
+ printk("DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n");
+ return MaxTxPwrInDbm;
+ }
+ if (pDot11dInfo->channel_map[Channel]) {
+ MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel];
+ }
+
+ return MaxTxPwrInDbm;
+}
+
+
+void
+DOT11D_ScanComplete(
+ struct ieee80211_device *dev
+ )
+{
+ PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
+
+ switch (pDot11dInfo->State) {
+ case DOT11D_STATE_LEARNED:
+ pDot11dInfo->State = DOT11D_STATE_DONE;
+ break;
+
+ case DOT11D_STATE_DONE:
+ if (GET_CIE_WATCHDOG(dev) == 0) {
+ // Reset country IE if previous one is gone.
+ Dot11d_Reset(dev);
+ }
+ break;
+ case DOT11D_STATE_NONE:
+ break;
+ }
+}
+
+int IsLegalChannel(
+ struct ieee80211_device *dev,
+ u8 channel
+)
+{
+ PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
+
+ if (MAX_CHANNEL_NUMBER < channel) {
+ printk("IsLegalChannel(): Invalid Channel\n");
+ return 0;
+ }
+ if (pDot11dInfo->channel_map[channel] > 0)
+ return 1;
+ return 0;
+}
+
+int ToLegalChannel(
+ struct ieee80211_device *dev,
+ u8 channel
+)
+{
+ PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
+ u8 default_chn = 0;
+ u32 i = 0;
+
+ for (i = 1; i <= MAX_CHANNEL_NUMBER; i++) {
+ if (pDot11dInfo->channel_map[i] > 0) {
+ default_chn = i;
+ break;
+ }
+ }
+
+ if (MAX_CHANNEL_NUMBER < channel) {
+ printk("IsLegalChannel(): Invalid Channel\n");
+ return default_chn;
+ }
+
+ if (pDot11dInfo->channel_map[channel] > 0)
+ return channel;
+
+ return default_chn;
+}