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