0001
0002
0003
0004
0005
0006
0007
0008 #include "dot11d.h"
0009
0010 struct channel_list {
0011 u8 channel[32];
0012 u8 len;
0013 };
0014
0015 static struct channel_list channel_array[] = {
0016 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 52, 56, 60, 64,
0017 149, 153, 157, 161, 165}, 24},
0018 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},
0019 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56,
0020 60, 64}, 21},
0021 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
0022 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
0023 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52,
0024 56, 60, 64}, 22},
0025 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52,
0026 56, 60, 64}, 22},
0027 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
0028 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52,
0029 56, 60, 64}, 22},
0030 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52,
0031 56, 60, 64}, 22},
0032 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},
0033 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
0034 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52,
0035 56, 60, 64}, 21}
0036 };
0037
0038 void dot11d_init(struct rtllib_device *ieee)
0039 {
0040 struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(ieee);
0041
0042 dot11d_info->enabled = false;
0043
0044 dot11d_info->state = DOT11D_STATE_NONE;
0045 dot11d_info->country_len = 0;
0046 memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1);
0047 memset(dot11d_info->max_tx_power_list, 0xFF, MAX_CHANNEL_NUMBER + 1);
0048 RESET_CIE_WATCHDOG(ieee);
0049 }
0050 EXPORT_SYMBOL(dot11d_init);
0051
0052 void dot11d_channel_map(u8 channel_plan, struct rtllib_device *ieee)
0053 {
0054 int i, max_chan = 14, min_chan = 1;
0055
0056 ieee->global_domain = false;
0057
0058 if (channel_array[channel_plan].len != 0) {
0059 memset(GET_DOT11D_INFO(ieee)->channel_map, 0,
0060 sizeof(GET_DOT11D_INFO(ieee)->channel_map));
0061 for (i = 0; i < channel_array[channel_plan].len; i++) {
0062 if (channel_array[channel_plan].channel[i] < min_chan ||
0063 channel_array[channel_plan].channel[i] > max_chan)
0064 break;
0065 GET_DOT11D_INFO(ieee)->channel_map[channel_array
0066 [channel_plan].channel[i]] = 1;
0067 }
0068 }
0069
0070 switch (channel_plan) {
0071 case COUNTRY_CODE_GLOBAL_DOMAIN:
0072 ieee->global_domain = true;
0073 for (i = 12; i <= 14; i++)
0074 GET_DOT11D_INFO(ieee)->channel_map[i] = 2;
0075 ieee->bss_start_channel = 10;
0076 ieee->ibss_maxjoin_chal = 11;
0077 break;
0078
0079 case COUNTRY_CODE_WORLD_WIDE_13:
0080 for (i = 12; i <= 13; i++)
0081 GET_DOT11D_INFO(ieee)->channel_map[i] = 2;
0082 ieee->bss_start_channel = 10;
0083 ieee->ibss_maxjoin_chal = 11;
0084 break;
0085
0086 default:
0087 ieee->bss_start_channel = 1;
0088 ieee->ibss_maxjoin_chal = 14;
0089 break;
0090 }
0091 }
0092 EXPORT_SYMBOL(dot11d_channel_map);
0093
0094 void dot11d_reset(struct rtllib_device *ieee)
0095 {
0096 struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(ieee);
0097 u32 i;
0098
0099 memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1);
0100 memset(dot11d_info->max_tx_power_list, 0xFF, MAX_CHANNEL_NUMBER + 1);
0101 for (i = 1; i <= 11; i++)
0102 (dot11d_info->channel_map)[i] = 1;
0103 for (i = 12; i <= 14; i++)
0104 (dot11d_info->channel_map)[i] = 2;
0105 dot11d_info->state = DOT11D_STATE_NONE;
0106 dot11d_info->country_len = 0;
0107 RESET_CIE_WATCHDOG(ieee);
0108 }
0109
0110 void dot11d_update_country(struct rtllib_device *dev, u8 *address,
0111 u16 country_len, u8 *country)
0112 {
0113 struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(dev);
0114 u8 i, j, number_of_triples, max_channel_number;
0115 struct chnl_txpow_triple *triple;
0116
0117 memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1);
0118 memset(dot11d_info->max_tx_power_list, 0xFF, MAX_CHANNEL_NUMBER + 1);
0119 max_channel_number = 0;
0120 number_of_triples = (country_len - 3) / 3;
0121 triple = (struct chnl_txpow_triple *)(country + 3);
0122 for (i = 0; i < number_of_triples; i++) {
0123 if (max_channel_number >= triple->first_channel) {
0124 netdev_info(dev->dev,
0125 "%s: Invalid country IE, skip it......1\n",
0126 __func__);
0127 return;
0128 }
0129 if (MAX_CHANNEL_NUMBER < (triple->first_channel +
0130 triple->num_channels)) {
0131 netdev_info(dev->dev,
0132 "%s: Invalid country IE, skip it......2\n",
0133 __func__);
0134 return;
0135 }
0136
0137 for (j = 0; j < triple->num_channels; j++) {
0138 dot11d_info->channel_map[triple->first_channel + j] = 1;
0139 dot11d_info->max_tx_power_list[triple->first_channel + j] =
0140 triple->max_tx_power;
0141 max_channel_number = triple->first_channel + j;
0142 }
0143
0144 triple = (struct chnl_txpow_triple *)((u8 *)triple + 3);
0145 }
0146
0147 UPDATE_CIE_SRC(dev, address);
0148
0149 dot11d_info->country_len = country_len;
0150 memcpy(dot11d_info->country_buffer, country, country_len);
0151 dot11d_info->state = DOT11D_STATE_LEARNED;
0152 }
0153
0154 void dot11d_scan_complete(struct rtllib_device *dev)
0155 {
0156 struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(dev);
0157
0158 switch (dot11d_info->state) {
0159 case DOT11D_STATE_LEARNED:
0160 dot11d_info->state = DOT11D_STATE_DONE;
0161 break;
0162 case DOT11D_STATE_DONE:
0163 dot11d_reset(dev);
0164 break;
0165 case DOT11D_STATE_NONE:
0166 break;
0167 }
0168 }