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