root/drivers/staging/rtl8192u/ieee80211/dot11d.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rtl8192u_dot11d_init
  2. dot11d_reset
  3. dot11d_update_country_ie
  4. dot11d_get_max_tx_pwr_in_dbm
  5. dot11d_scan_complete
  6. is_legal_channel
  7. to_legal_channel

   1 // SPDX-License-Identifier: GPL-2.0
   2 /* Implement 802.11d. */
   3 
   4 #include "dot11d.h"
   5 
   6 void rtl8192u_dot11d_init(struct ieee80211_device *ieee)
   7 {
   8         struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(ieee);
   9 
  10         dot11d_info->dot11d_enabled = false;
  11 
  12         dot11d_info->state = DOT11D_STATE_NONE;
  13         dot11d_info->country_ie_len = 0;
  14         memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1);
  15         memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER + 1);
  16         RESET_CIE_WATCHDOG(ieee);
  17 
  18         netdev_info(ieee->dev, "rtl8192u_dot11d_init()\n");
  19 }
  20 EXPORT_SYMBOL(rtl8192u_dot11d_init);
  21 
  22 /* Reset to the state as we are just entering a regulatory domain. */
  23 void dot11d_reset(struct ieee80211_device *ieee)
  24 {
  25         u32 i;
  26         struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(ieee);
  27         /* Clear old channel map */
  28         memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1);
  29         memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER + 1);
  30         /* Set new channel map */
  31         for (i = 1; i <= 11; i++)
  32                 (dot11d_info->channel_map)[i] = 1;
  33 
  34         for (i = 12; i <= 14; i++)
  35                 (dot11d_info->channel_map)[i] = 2;
  36 
  37         dot11d_info->state = DOT11D_STATE_NONE;
  38         dot11d_info->country_ie_len = 0;
  39         RESET_CIE_WATCHDOG(ieee);
  40 }
  41 EXPORT_SYMBOL(dot11d_reset);
  42 
  43 /*
  44  * Update country IE from Beacon or Probe Resopnse and configure PHY for
  45  * operation in the regulatory domain.
  46  *
  47  * TODO: Configure Tx power.
  48  * Assumption:
  49  * 1. IS_DOT11D_ENABLE() is TRUE.
  50  * 2. Input IE is an valid one.
  51  */
  52 void dot11d_update_country_ie(struct ieee80211_device *dev, u8 *pTaddr,
  53                             u16 CoutryIeLen, u8 *pCoutryIe)
  54 {
  55         struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(dev);
  56         u8 i, j, NumTriples, MaxChnlNum;
  57         struct chnl_txpower_triple *pTriple;
  58 
  59         memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1);
  60         memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER + 1);
  61         MaxChnlNum = 0;
  62         NumTriples = (CoutryIeLen - 3) / 3; /* skip 3-byte country string. */
  63         pTriple = (struct chnl_txpower_triple *)(pCoutryIe + 3);
  64         for (i = 0; i < NumTriples; i++) {
  65                 if (MaxChnlNum >= pTriple->first_channel) {
  66                         /* It is not in a monotonically increasing order, so
  67                          * stop processing.
  68                          */
  69                         netdev_err(dev->dev, "dot11d_update_country_ie(): Invalid country IE, skip it........1\n");
  70                         return;
  71                 }
  72                 if (MAX_CHANNEL_NUMBER < (pTriple->first_channel + pTriple->num_channels)) {
  73                         /* It is not a valid set of channel id, so stop
  74                          * processing.
  75                          */
  76                         netdev_err(dev->dev, "dot11d_update_country_ie(): Invalid country IE, skip it........2\n");
  77                         return;
  78                 }
  79 
  80                 for (j = 0; j < pTriple->num_channels; j++) {
  81                         dot11d_info->channel_map[pTriple->first_channel + j] = 1;
  82                         dot11d_info->max_tx_pwr_dbm_list[pTriple->first_channel + j] = pTriple->max_tx_pwr_dbm;
  83                         MaxChnlNum = pTriple->first_channel + j;
  84                 }
  85 
  86                 pTriple = (struct chnl_txpower_triple *)((u8 *)pTriple + 3);
  87         }
  88         netdev_info(dev->dev, "Channel List:");
  89         for (i = 1; i <= MAX_CHANNEL_NUMBER; i++)
  90                 if (dot11d_info->channel_map[i] > 0)
  91                         netdev_info(dev->dev, " %d", i);
  92         netdev_info(dev->dev, "\n");
  93 
  94         UPDATE_CIE_SRC(dev, pTaddr);
  95 
  96         dot11d_info->country_ie_len = CoutryIeLen;
  97         memcpy(dot11d_info->country_ie_buf, pCoutryIe, CoutryIeLen);
  98         dot11d_info->state = DOT11D_STATE_LEARNED;
  99 }
 100 EXPORT_SYMBOL(dot11d_update_country_ie);
 101 
 102 u8 dot11d_get_max_tx_pwr_in_dbm(struct ieee80211_device *dev, u8 Channel)
 103 {
 104         struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(dev);
 105         u8 MaxTxPwrInDbm = 255;
 106 
 107         if (Channel > MAX_CHANNEL_NUMBER) {
 108                 netdev_err(dev->dev, "dot11d_get_max_tx_pwr_in_dbm(): Invalid Channel\n");
 109                 return MaxTxPwrInDbm;
 110         }
 111         if (dot11d_info->channel_map[Channel])
 112                 MaxTxPwrInDbm = dot11d_info->max_tx_pwr_dbm_list[Channel];
 113 
 114         return MaxTxPwrInDbm;
 115 }
 116 EXPORT_SYMBOL(dot11d_get_max_tx_pwr_in_dbm);
 117 
 118 void dot11d_scan_complete(struct ieee80211_device *dev)
 119 {
 120         struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(dev);
 121 
 122         switch (dot11d_info->state) {
 123         case DOT11D_STATE_LEARNED:
 124                 dot11d_info->state = DOT11D_STATE_DONE;
 125                 break;
 126 
 127         case DOT11D_STATE_DONE:
 128                 if (GET_CIE_WATCHDOG(dev) == 0) {
 129                         /* Reset country IE if previous one is gone. */
 130                         dot11d_reset(dev);
 131                 }
 132                 break;
 133         case DOT11D_STATE_NONE:
 134                 break;
 135         }
 136 }
 137 EXPORT_SYMBOL(dot11d_scan_complete);
 138 
 139 int is_legal_channel(struct ieee80211_device *dev, u8 channel)
 140 {
 141         struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(dev);
 142 
 143         if (channel > MAX_CHANNEL_NUMBER) {
 144                 netdev_err(dev->dev, "is_legal_channel(): Invalid Channel\n");
 145                 return 0;
 146         }
 147         if (dot11d_info->channel_map[channel] > 0)
 148                 return 1;
 149         return 0;
 150 }
 151 EXPORT_SYMBOL(is_legal_channel);
 152 
 153 int to_legal_channel(struct ieee80211_device *dev, u8 channel)
 154 {
 155         struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(dev);
 156         u8 default_chn = 0;
 157         u32 i = 0;
 158 
 159         for (i = 1; i <= MAX_CHANNEL_NUMBER; i++) {
 160                 if (dot11d_info->channel_map[i] > 0) {
 161                         default_chn = i;
 162                         break;
 163                 }
 164         }
 165 
 166         if (channel > MAX_CHANNEL_NUMBER) {
 167                 netdev_err(dev->dev, "is_legal_channel(): Invalid Channel\n");
 168                 return default_chn;
 169         }
 170 
 171         if (dot11d_info->channel_map[channel] > 0)
 172                 return channel;
 173 
 174         return default_chn;
 175 }
 176 EXPORT_SYMBOL(to_legal_channel);

/* [<][>][^][v][top][bottom][index][help] */