aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/libertas/scan.c')
-rw-r--r--drivers/net/wireless/libertas/scan.c250
1 files changed, 200 insertions, 50 deletions
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index 6c95af3023cc..c6a6c042b82f 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -12,18 +12,19 @@
12#include <net/lib80211.h> 12#include <net/lib80211.h>
13 13
14#include "host.h" 14#include "host.h"
15#include "decl.h"
16#include "dev.h" 15#include "dev.h"
17#include "scan.h" 16#include "scan.h"
17#include "assoc.h"
18#include "wext.h"
18#include "cmd.h" 19#include "cmd.h"
19 20
20//! Approximate amount of data needed to pass a scan result back to iwlist 21//! Approximate amount of data needed to pass a scan result back to iwlist
21#define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \ 22#define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \
22 + IW_ESSID_MAX_SIZE \ 23 + IEEE80211_MAX_SSID_LEN \
23 + IW_EV_UINT_LEN \ 24 + IW_EV_UINT_LEN \
24 + IW_EV_FREQ_LEN \ 25 + IW_EV_FREQ_LEN \
25 + IW_EV_QUAL_LEN \ 26 + IW_EV_QUAL_LEN \
26 + IW_ESSID_MAX_SIZE \ 27 + IEEE80211_MAX_SSID_LEN \
27 + IW_EV_PARAM_LEN \ 28 + IW_EV_PARAM_LEN \
28 + 40) /* 40 for WPAIE */ 29 + 40) /* 40 for WPAIE */
29 30
@@ -121,6 +122,189 @@ static inline int is_same_network(struct bss_descriptor *src,
121 122
122 123
123 124
125/*********************************************************************/
126/* */
127/* Region channel support */
128/* */
129/*********************************************************************/
130
131#define LBS_TX_PWR_DEFAULT 20 /*100mW */
132#define LBS_TX_PWR_US_DEFAULT 20 /*100mW */
133#define LBS_TX_PWR_JP_DEFAULT 16 /*50mW */
134#define LBS_TX_PWR_FR_DEFAULT 20 /*100mW */
135#define LBS_TX_PWR_EMEA_DEFAULT 20 /*100mW */
136
137/* Format { channel, frequency (MHz), maxtxpower } */
138/* band: 'B/G', region: USA FCC/Canada IC */
139static struct chan_freq_power channel_freq_power_US_BG[] = {
140 {1, 2412, LBS_TX_PWR_US_DEFAULT},
141 {2, 2417, LBS_TX_PWR_US_DEFAULT},
142 {3, 2422, LBS_TX_PWR_US_DEFAULT},
143 {4, 2427, LBS_TX_PWR_US_DEFAULT},
144 {5, 2432, LBS_TX_PWR_US_DEFAULT},
145 {6, 2437, LBS_TX_PWR_US_DEFAULT},
146 {7, 2442, LBS_TX_PWR_US_DEFAULT},
147 {8, 2447, LBS_TX_PWR_US_DEFAULT},
148 {9, 2452, LBS_TX_PWR_US_DEFAULT},
149 {10, 2457, LBS_TX_PWR_US_DEFAULT},
150 {11, 2462, LBS_TX_PWR_US_DEFAULT}
151};
152
153/* band: 'B/G', region: Europe ETSI */
154static struct chan_freq_power channel_freq_power_EU_BG[] = {
155 {1, 2412, LBS_TX_PWR_EMEA_DEFAULT},
156 {2, 2417, LBS_TX_PWR_EMEA_DEFAULT},
157 {3, 2422, LBS_TX_PWR_EMEA_DEFAULT},
158 {4, 2427, LBS_TX_PWR_EMEA_DEFAULT},
159 {5, 2432, LBS_TX_PWR_EMEA_DEFAULT},
160 {6, 2437, LBS_TX_PWR_EMEA_DEFAULT},
161 {7, 2442, LBS_TX_PWR_EMEA_DEFAULT},
162 {8, 2447, LBS_TX_PWR_EMEA_DEFAULT},
163 {9, 2452, LBS_TX_PWR_EMEA_DEFAULT},
164 {10, 2457, LBS_TX_PWR_EMEA_DEFAULT},
165 {11, 2462, LBS_TX_PWR_EMEA_DEFAULT},
166 {12, 2467, LBS_TX_PWR_EMEA_DEFAULT},
167 {13, 2472, LBS_TX_PWR_EMEA_DEFAULT}
168};
169
170/* band: 'B/G', region: Spain */
171static struct chan_freq_power channel_freq_power_SPN_BG[] = {
172 {10, 2457, LBS_TX_PWR_DEFAULT},
173 {11, 2462, LBS_TX_PWR_DEFAULT}
174};
175
176/* band: 'B/G', region: France */
177static struct chan_freq_power channel_freq_power_FR_BG[] = {
178 {10, 2457, LBS_TX_PWR_FR_DEFAULT},
179 {11, 2462, LBS_TX_PWR_FR_DEFAULT},
180 {12, 2467, LBS_TX_PWR_FR_DEFAULT},
181 {13, 2472, LBS_TX_PWR_FR_DEFAULT}
182};
183
184/* band: 'B/G', region: Japan */
185static struct chan_freq_power channel_freq_power_JPN_BG[] = {
186 {1, 2412, LBS_TX_PWR_JP_DEFAULT},
187 {2, 2417, LBS_TX_PWR_JP_DEFAULT},
188 {3, 2422, LBS_TX_PWR_JP_DEFAULT},
189 {4, 2427, LBS_TX_PWR_JP_DEFAULT},
190 {5, 2432, LBS_TX_PWR_JP_DEFAULT},
191 {6, 2437, LBS_TX_PWR_JP_DEFAULT},
192 {7, 2442, LBS_TX_PWR_JP_DEFAULT},
193 {8, 2447, LBS_TX_PWR_JP_DEFAULT},
194 {9, 2452, LBS_TX_PWR_JP_DEFAULT},
195 {10, 2457, LBS_TX_PWR_JP_DEFAULT},
196 {11, 2462, LBS_TX_PWR_JP_DEFAULT},
197 {12, 2467, LBS_TX_PWR_JP_DEFAULT},
198 {13, 2472, LBS_TX_PWR_JP_DEFAULT},
199 {14, 2484, LBS_TX_PWR_JP_DEFAULT}
200};
201
202/**
203 * the structure for channel, frequency and power
204 */
205struct region_cfp_table {
206 u8 region;
207 struct chan_freq_power *cfp_BG;
208 int cfp_no_BG;
209};
210
211/**
212 * the structure for the mapping between region and CFP
213 */
214static struct region_cfp_table region_cfp_table[] = {
215 {0x10, /*US FCC */
216 channel_freq_power_US_BG,
217 ARRAY_SIZE(channel_freq_power_US_BG),
218 }
219 ,
220 {0x20, /*CANADA IC */
221 channel_freq_power_US_BG,
222 ARRAY_SIZE(channel_freq_power_US_BG),
223 }
224 ,
225 {0x30, /*EU*/ channel_freq_power_EU_BG,
226 ARRAY_SIZE(channel_freq_power_EU_BG),
227 }
228 ,
229 {0x31, /*SPAIN*/ channel_freq_power_SPN_BG,
230 ARRAY_SIZE(channel_freq_power_SPN_BG),
231 }
232 ,
233 {0x32, /*FRANCE*/ channel_freq_power_FR_BG,
234 ARRAY_SIZE(channel_freq_power_FR_BG),
235 }
236 ,
237 {0x40, /*JAPAN*/ channel_freq_power_JPN_BG,
238 ARRAY_SIZE(channel_freq_power_JPN_BG),
239 }
240 ,
241/*Add new region here */
242};
243
244/**
245 * @brief This function finds the CFP in
246 * region_cfp_table based on region and band parameter.
247 *
248 * @param region The region code
249 * @param band The band
250 * @param cfp_no A pointer to CFP number
251 * @return A pointer to CFP
252 */
253static struct chan_freq_power *lbs_get_region_cfp_table(u8 region, int *cfp_no)
254{
255 int i, end;
256
257 lbs_deb_enter(LBS_DEB_MAIN);
258
259 end = ARRAY_SIZE(region_cfp_table);
260
261 for (i = 0; i < end ; i++) {
262 lbs_deb_main("region_cfp_table[i].region=%d\n",
263 region_cfp_table[i].region);
264 if (region_cfp_table[i].region == region) {
265 *cfp_no = region_cfp_table[i].cfp_no_BG;
266 lbs_deb_leave(LBS_DEB_MAIN);
267 return region_cfp_table[i].cfp_BG;
268 }
269 }
270
271 lbs_deb_leave_args(LBS_DEB_MAIN, "ret NULL");
272 return NULL;
273}
274
275int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band)
276{
277 int ret = 0;
278 int i = 0;
279
280 struct chan_freq_power *cfp;
281 int cfp_no;
282
283 lbs_deb_enter(LBS_DEB_MAIN);
284
285 memset(priv->region_channel, 0, sizeof(priv->region_channel));
286
287 cfp = lbs_get_region_cfp_table(region, &cfp_no);
288 if (cfp != NULL) {
289 priv->region_channel[i].nrcfp = cfp_no;
290 priv->region_channel[i].CFP = cfp;
291 } else {
292 lbs_deb_main("wrong region code %#x in band B/G\n",
293 region);
294 ret = -1;
295 goto out;
296 }
297 priv->region_channel[i].valid = 1;
298 priv->region_channel[i].region = region;
299 priv->region_channel[i].band = band;
300 i++;
301out:
302 lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
303 return ret;
304}
305
306
307
124 308
125/*********************************************************************/ 309/*********************************************************************/
126/* */ 310/* */
@@ -161,31 +345,15 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv,
161 scantype = CMD_SCAN_TYPE_ACTIVE; 345 scantype = CMD_SCAN_TYPE_ACTIVE;
162 346
163 for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) { 347 for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) {
164 if (priv->enable11d && (priv->connect_status != LBS_CONNECTED) 348 if (!priv->region_channel[rgnidx].valid)
165 && (priv->mesh_connect_status != LBS_CONNECTED)) { 349 continue;
166 /* Scan all the supported chan for the first scan */ 350 scanregion = &priv->region_channel[rgnidx];
167 if (!priv->universal_channel[rgnidx].valid)
168 continue;
169 scanregion = &priv->universal_channel[rgnidx];
170
171 /* clear the parsed_region_chan for the first scan */
172 memset(&priv->parsed_region_chan, 0x00,
173 sizeof(priv->parsed_region_chan));
174 } else {
175 if (!priv->region_channel[rgnidx].valid)
176 continue;
177 scanregion = &priv->region_channel[rgnidx];
178 }
179 351
180 for (nextchan = 0; nextchan < scanregion->nrcfp; nextchan++, chanidx++) { 352 for (nextchan = 0; nextchan < scanregion->nrcfp; nextchan++, chanidx++) {
181 struct chanscanparamset *chan = &scanchanlist[chanidx]; 353 struct chanscanparamset *chan = &scanchanlist[chanidx];
182 354
183 cfp = scanregion->CFP + nextchan; 355 cfp = scanregion->CFP + nextchan;
184 356
185 if (priv->enable11d)
186 scantype = lbs_get_scan_type_11d(cfp->channel,
187 &priv->parsed_region_chan);
188
189 if (scanregion->band == BAND_B || scanregion->band == BAND_G) 357 if (scanregion->band == BAND_B || scanregion->band == BAND_G)
190 chan->radiotype = CMD_SCAN_RADIO_TYPE_BG; 358 chan->radiotype = CMD_SCAN_RADIO_TYPE_BG;
191 359
@@ -519,7 +687,6 @@ static int lbs_process_bss(struct bss_descriptor *bss,
519 struct ieee_ie_cf_param_set *cf; 687 struct ieee_ie_cf_param_set *cf;
520 struct ieee_ie_ibss_param_set *ibss; 688 struct ieee_ie_ibss_param_set *ibss;
521 DECLARE_SSID_BUF(ssid); 689 DECLARE_SSID_BUF(ssid);
522 struct ieee_ie_country_info_set *pcountryinfo;
523 uint8_t *pos, *end, *p; 690 uint8_t *pos, *end, *p;
524 uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0; 691 uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0;
525 uint16_t beaconsize = 0; 692 uint16_t beaconsize = 0;
@@ -642,26 +809,6 @@ static int lbs_process_bss(struct bss_descriptor *bss,
642 lbs_deb_scan("got IBSS IE\n"); 809 lbs_deb_scan("got IBSS IE\n");
643 break; 810 break;
644 811
645 case WLAN_EID_COUNTRY:
646 pcountryinfo = (struct ieee_ie_country_info_set *) pos;
647 lbs_deb_scan("got COUNTRY IE\n");
648 if (pcountryinfo->header.len < sizeof(pcountryinfo->countrycode)
649 || pcountryinfo->header.len > 254) {
650 lbs_deb_scan("%s: 11D- Err CountryInfo len %d, min %zd, max 254\n",
651 __func__,
652 pcountryinfo->header.len,
653 sizeof(pcountryinfo->countrycode));
654 ret = -1;
655 goto done;
656 }
657
658 memcpy(&bss->countryinfo, pcountryinfo,
659 pcountryinfo->header.len + 2);
660 lbs_deb_hex(LBS_DEB_SCAN, "process_bss: 11d countryinfo",
661 (uint8_t *) pcountryinfo,
662 (int) (pcountryinfo->header.len + 2));
663 break;
664
665 case WLAN_EID_EXT_SUPP_RATES: 812 case WLAN_EID_EXT_SUPP_RATES:
666 /* only process extended supported rate if data rate is 813 /* only process extended supported rate if data rate is
667 * already found. Data rate IE should come before 814 * already found. Data rate IE should come before
@@ -812,7 +959,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv,
812 /* SSID */ 959 /* SSID */
813 iwe.cmd = SIOCGIWESSID; 960 iwe.cmd = SIOCGIWESSID;
814 iwe.u.data.flags = 1; 961 iwe.u.data.flags = 1;
815 iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IW_ESSID_MAX_SIZE); 962 iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IEEE80211_MAX_SSID_LEN);
816 start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid); 963 start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid);
817 964
818 /* Mode */ 965 /* Mode */
@@ -1022,9 +1169,12 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
1022 return -EAGAIN; 1169 return -EAGAIN;
1023 1170
1024 /* Update RSSI if current BSS is a locally created ad-hoc BSS */ 1171 /* Update RSSI if current BSS is a locally created ad-hoc BSS */
1025 if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) 1172 if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) {
1026 lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, 1173 err = lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
1027 CMD_OPTION_WAITFORRSP, 0, NULL); 1174 CMD_OPTION_WAITFORRSP, 0, NULL);
1175 if (err)
1176 goto out;
1177 }
1028 1178
1029 mutex_lock(&priv->lock); 1179 mutex_lock(&priv->lock);
1030 list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) { 1180 list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) {
@@ -1058,7 +1208,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
1058 1208
1059 dwrq->length = (ev - extra); 1209 dwrq->length = (ev - extra);
1060 dwrq->flags = 0; 1210 dwrq->flags = 0;
1061 1211out:
1062 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err); 1212 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err);
1063 return err; 1213 return err;
1064} 1214}
@@ -1141,11 +1291,11 @@ static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
1141 /* The size of the TLV buffer is equal to the entire command response 1291 /* The size of the TLV buffer is equal to the entire command response
1142 * size (scanrespsize) minus the fixed fields (sizeof()'s), the 1292 * size (scanrespsize) minus the fixed fields (sizeof()'s), the
1143 * BSS Descriptions (bssdescriptsize as bytesLef) and the command 1293 * BSS Descriptions (bssdescriptsize as bytesLef) and the command
1144 * response header (S_DS_GEN) 1294 * response header (sizeof(struct cmd_header))
1145 */ 1295 */
1146 tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize) 1296 tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize)
1147 + sizeof(scanresp->nr_sets) 1297 + sizeof(scanresp->nr_sets)
1148 + S_DS_GEN); 1298 + sizeof(struct cmd_header));
1149 1299
1150 /* 1300 /*
1151 * Process each scan response returned (scanresp->nr_sets). Save 1301 * Process each scan response returned (scanresp->nr_sets). Save