linux/drivers/staging/rtl8192u/ieee80211/dot11d.c
<<
>>
Prefs
   1//-----------------------------------------------------------------------------
   2//      File:
   3//              Dot11d.c
   4//
   5//      Description:
   6//              Implement 802.11d.
   7//
   8//-----------------------------------------------------------------------------
   9
  10#include "dot11d.h"
  11
  12void
  13Dot11d_Init(struct ieee80211_device *ieee)
  14{
  15        PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
  16
  17        pDot11dInfo->bEnabled = 0;
  18
  19        pDot11dInfo->State = DOT11D_STATE_NONE;
  20        pDot11dInfo->CountryIeLen = 0;
  21        memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
  22        memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
  23        RESET_CIE_WATCHDOG(ieee);
  24
  25        printk("Dot11d_Init()\n");
  26}
  27
  28//
  29//      Description:
  30//              Reset to the state as we are just entering a regulatory domain.
  31//
  32void
  33Dot11d_Reset(struct ieee80211_device *ieee)
  34{
  35        u32 i;
  36        PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
  37        // Clear old channel map
  38        memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
  39        memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
  40        // Set new channel map
  41        for (i=1; i<=11; i++) {
  42                (pDot11dInfo->channel_map)[i] = 1;
  43        }
  44        for (i=12; i<=14; i++) {
  45                (pDot11dInfo->channel_map)[i] = 2;
  46        }
  47
  48        pDot11dInfo->State = DOT11D_STATE_NONE;
  49        pDot11dInfo->CountryIeLen = 0;
  50        RESET_CIE_WATCHDOG(ieee);
  51
  52        //printk("Dot11d_Reset()\n");
  53}
  54
  55//
  56//      Description:
  57//              Update country IE from Beacon or Probe Resopnse
  58//              and configure PHY for operation in the regulatory domain.
  59//
  60//      TODO:
  61//              Configure Tx power.
  62//
  63//      Assumption:
  64//              1. IS_DOT11D_ENABLE() is TRUE.
  65//              2. Input IE is an valid one.
  66//
  67void
  68Dot11d_UpdateCountryIe(
  69        struct ieee80211_device *dev,
  70        u8 *pTaddr,
  71        u16     CoutryIeLen,
  72        u8 *pCoutryIe
  73        )
  74{
  75        PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
  76        u8 i, j, NumTriples, MaxChnlNum;
  77        PCHNL_TXPOWER_TRIPLE pTriple;
  78
  79        memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
  80        memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
  81        MaxChnlNum = 0;
  82        NumTriples = (CoutryIeLen - 3) / 3; // skip 3-byte country string.
  83        pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3);
  84        for(i = 0; i < NumTriples; i++)
  85        {
  86                if(MaxChnlNum >= pTriple->FirstChnl)
  87                { // It is not in a monotonically increasing order, so stop processing.
  88                        printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
  89                        return;
  90                }
  91                if(MAX_CHANNEL_NUMBER < (pTriple->FirstChnl + pTriple->NumChnls))
  92                { // It is not a valid set of channel id, so stop processing.
  93                        printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n");
  94                        return;
  95                }
  96
  97                for(j = 0 ; j < pTriple->NumChnls; j++)
  98                {
  99                        pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1;
 100                        pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] = pTriple->MaxTxPowerInDbm;
 101                        MaxChnlNum = pTriple->FirstChnl + j;
 102                }
 103
 104                pTriple = (PCHNL_TXPOWER_TRIPLE)((u8 *)pTriple + 3);
 105        }
 106        //printk("Dot11d_UpdateCountryIe(): Channel List:\n");
 107        printk("Channel List:");
 108        for(i=1; i<= MAX_CHANNEL_NUMBER; i++)
 109                if(pDot11dInfo->channel_map[i] > 0)
 110                        printk(" %d", i);
 111        printk("\n");
 112
 113        UPDATE_CIE_SRC(dev, pTaddr);
 114
 115        pDot11dInfo->CountryIeLen = CoutryIeLen;
 116        memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe,CoutryIeLen);
 117        pDot11dInfo->State = DOT11D_STATE_LEARNED;
 118}
 119
 120
 121u8
 122DOT11D_GetMaxTxPwrInDbm(
 123        struct ieee80211_device *dev,
 124        u8 Channel
 125        )
 126{
 127        PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
 128        u8 MaxTxPwrInDbm = 255;
 129
 130        if(MAX_CHANNEL_NUMBER < Channel)
 131        {
 132                printk("DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n");
 133                return MaxTxPwrInDbm;
 134        }
 135        if(pDot11dInfo->channel_map[Channel])
 136        {
 137                MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel];
 138        }
 139
 140        return MaxTxPwrInDbm;
 141}
 142
 143
 144void
 145DOT11D_ScanComplete(
 146        struct ieee80211_device *dev
 147        )
 148{
 149        PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
 150
 151        switch (pDot11dInfo->State)
 152        {
 153        case DOT11D_STATE_LEARNED:
 154                pDot11dInfo->State = DOT11D_STATE_DONE;
 155                break;
 156
 157        case DOT11D_STATE_DONE:
 158                if( GET_CIE_WATCHDOG(dev) == 0 )
 159                { // Reset country IE if previous one is gone.
 160                        Dot11d_Reset(dev);
 161                }
 162                break;
 163        case DOT11D_STATE_NONE:
 164                break;
 165        }
 166}
 167
 168int IsLegalChannel(
 169        struct ieee80211_device *dev,
 170        u8 channel
 171)
 172{
 173        PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
 174
 175        if(MAX_CHANNEL_NUMBER < channel)
 176        {
 177                printk("IsLegalChannel(): Invalid Channel\n");
 178                return 0;
 179        }
 180        if(pDot11dInfo->channel_map[channel] > 0)
 181                return 1;
 182        return 0;
 183}
 184
 185int ToLegalChannel(
 186        struct ieee80211_device *dev,
 187        u8 channel
 188)
 189{
 190        PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
 191        u8 default_chn = 0;
 192        u32 i = 0;
 193
 194        for (i=1; i<= MAX_CHANNEL_NUMBER; i++)
 195        {
 196                if(pDot11dInfo->channel_map[i] > 0)
 197                {
 198                        default_chn = i;
 199                        break;
 200                }
 201        }
 202
 203        if(MAX_CHANNEL_NUMBER < channel)
 204        {
 205                printk("IsLegalChannel(): Invalid Channel\n");
 206                return default_chn;
 207        }
 208
 209        if(pDot11dInfo->channel_map[channel] > 0)
 210                return channel;
 211
 212        return default_chn;
 213}
 214EXPORT_SYMBOL(Dot11d_Init);
 215EXPORT_SYMBOL(Dot11d_Reset);
 216EXPORT_SYMBOL(Dot11d_UpdateCountryIe);
 217EXPORT_SYMBOL(DOT11D_GetMaxTxPwrInDbm);
 218EXPORT_SYMBOL(DOT11D_ScanComplete);
 219EXPORT_SYMBOL(IsLegalChannel);
 220EXPORT_SYMBOL(ToLegalChannel);
 221