diff options
Diffstat (limited to 'drivers/net/wireless/libertas/scan.c')
-rw-r--r-- | drivers/net/wireless/libertas/scan.c | 685 |
1 files changed, 299 insertions, 386 deletions
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 69f94c92b32d..0598541451d8 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "dev.h" | 20 | #include "dev.h" |
21 | #include "scan.h" | 21 | #include "scan.h" |
22 | #include "join.h" | 22 | #include "join.h" |
23 | #include "cmd.h" | ||
23 | 24 | ||
24 | //! Approximate amount of data needed to pass a scan result back to iwlist | 25 | //! Approximate amount of data needed to pass a scan result back to iwlist |
25 | #define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \ | 26 | #define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \ |
@@ -39,10 +40,9 @@ | |||
39 | //! Memory needed to store a max number/size SSID TLV for a firmware scan | 40 | //! Memory needed to store a max number/size SSID TLV for a firmware scan |
40 | #define SSID_TLV_MAX_SIZE (1 * sizeof(struct mrvlietypes_ssidparamset)) | 41 | #define SSID_TLV_MAX_SIZE (1 * sizeof(struct mrvlietypes_ssidparamset)) |
41 | 42 | ||
42 | //! Maximum memory needed for a lbs_scan_cmd_config with all TLVs at max | 43 | //! Maximum memory needed for a cmd_ds_802_11_scan with all TLVs at max |
43 | #define MAX_SCAN_CFG_ALLOC (sizeof(struct lbs_scan_cmd_config) \ | 44 | #define MAX_SCAN_CFG_ALLOC (sizeof(struct cmd_ds_802_11_scan) \ |
44 | + CHAN_TLV_MAX_SIZE \ | 45 | + CHAN_TLV_MAX_SIZE + SSID_TLV_MAX_SIZE) |
45 | + SSID_TLV_MAX_SIZE) | ||
46 | 46 | ||
47 | //! The maximum number of channels the firmware can scan per command | 47 | //! The maximum number of channels the firmware can scan per command |
48 | #define MRVDRV_MAX_CHANNELS_PER_SCAN 14 | 48 | #define MRVDRV_MAX_CHANNELS_PER_SCAN 14 |
@@ -61,11 +61,8 @@ | |||
61 | //! Scan time specified in the channel TLV for each channel for active scans | 61 | //! Scan time specified in the channel TLV for each channel for active scans |
62 | #define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100 | 62 | #define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100 |
63 | 63 | ||
64 | static const u8 zeromac[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; | 64 | static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy, |
65 | static const u8 bcastmac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | 65 | struct cmd_header *resp); |
66 | |||
67 | |||
68 | |||
69 | 66 | ||
70 | /*********************************************************************/ | 67 | /*********************************************************************/ |
71 | /* */ | 68 | /* */ |
@@ -73,7 +70,24 @@ static const u8 bcastmac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | |||
73 | /* */ | 70 | /* */ |
74 | /*********************************************************************/ | 71 | /*********************************************************************/ |
75 | 72 | ||
76 | static inline void clear_bss_descriptor (struct bss_descriptor * bss) | 73 | /** |
74 | * @brief Unsets the MSB on basic rates | ||
75 | * | ||
76 | * Scan through an array and unset the MSB for basic data rates. | ||
77 | * | ||
78 | * @param rates buffer of data rates | ||
79 | * @param len size of buffer | ||
80 | */ | ||
81 | static void lbs_unset_basic_rate_flags(u8 *rates, size_t len) | ||
82 | { | ||
83 | int i; | ||
84 | |||
85 | for (i = 0; i < len; i++) | ||
86 | rates[i] &= 0x7f; | ||
87 | } | ||
88 | |||
89 | |||
90 | static inline void clear_bss_descriptor(struct bss_descriptor *bss) | ||
77 | { | 91 | { |
78 | /* Don't blow away ->list, just BSS data */ | 92 | /* Don't blow away ->list, just BSS data */ |
79 | memset(bss, 0, offsetof(struct bss_descriptor, list)); | 93 | memset(bss, 0, offsetof(struct bss_descriptor, list)); |
@@ -87,7 +101,8 @@ static inline void clear_bss_descriptor (struct bss_descriptor * bss) | |||
87 | * | 101 | * |
88 | * @return 0: ssid is same, otherwise is different | 102 | * @return 0: ssid is same, otherwise is different |
89 | */ | 103 | */ |
90 | int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len) | 104 | int lbs_ssid_cmp(uint8_t *ssid1, uint8_t ssid1_len, uint8_t *ssid2, |
105 | uint8_t ssid2_len) | ||
91 | { | 106 | { |
92 | if (ssid1_len != ssid2_len) | 107 | if (ssid1_len != ssid2_len) |
93 | return -1; | 108 | return -1; |
@@ -96,73 +111,66 @@ int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len) | |||
96 | } | 111 | } |
97 | 112 | ||
98 | static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, | 113 | static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, |
99 | struct bss_descriptor * match_bss) | 114 | struct bss_descriptor *match_bss) |
100 | { | 115 | { |
101 | if ( !secinfo->wep_enabled | 116 | if (!secinfo->wep_enabled && !secinfo->WPAenabled |
102 | && !secinfo->WPAenabled | ||
103 | && !secinfo->WPA2enabled | 117 | && !secinfo->WPA2enabled |
104 | && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC | 118 | && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC |
105 | && match_bss->rsn_ie[0] != MFIE_TYPE_RSN | 119 | && match_bss->rsn_ie[0] != MFIE_TYPE_RSN |
106 | && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { | 120 | && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) |
107 | return 1; | 121 | return 1; |
108 | } | 122 | else |
109 | return 0; | 123 | return 0; |
110 | } | 124 | } |
111 | 125 | ||
112 | static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo, | 126 | static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo, |
113 | struct bss_descriptor * match_bss) | 127 | struct bss_descriptor *match_bss) |
114 | { | 128 | { |
115 | if ( secinfo->wep_enabled | 129 | if (secinfo->wep_enabled && !secinfo->WPAenabled |
116 | && !secinfo->WPAenabled | 130 | && !secinfo->WPA2enabled |
117 | && !secinfo->WPA2enabled | 131 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) |
118 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { | ||
119 | return 1; | 132 | return 1; |
120 | } | 133 | else |
121 | return 0; | 134 | return 0; |
122 | } | 135 | } |
123 | 136 | ||
124 | static inline int match_bss_wpa(struct lbs_802_11_security *secinfo, | 137 | static inline int match_bss_wpa(struct lbs_802_11_security *secinfo, |
125 | struct bss_descriptor * match_bss) | 138 | struct bss_descriptor *match_bss) |
126 | { | 139 | { |
127 | if ( !secinfo->wep_enabled | 140 | if (!secinfo->wep_enabled && secinfo->WPAenabled |
128 | && secinfo->WPAenabled | 141 | && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC) |
129 | && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC) | 142 | /* privacy bit may NOT be set in some APs like LinkSys WRT54G |
130 | /* privacy bit may NOT be set in some APs like LinkSys WRT54G | 143 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */ |
131 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { | 144 | ) |
132 | */ | ||
133 | ) { | ||
134 | return 1; | 145 | return 1; |
135 | } | 146 | else |
136 | return 0; | 147 | return 0; |
137 | } | 148 | } |
138 | 149 | ||
139 | static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo, | 150 | static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo, |
140 | struct bss_descriptor * match_bss) | 151 | struct bss_descriptor *match_bss) |
141 | { | 152 | { |
142 | if ( !secinfo->wep_enabled | 153 | if (!secinfo->wep_enabled && secinfo->WPA2enabled |
143 | && secinfo->WPA2enabled | 154 | && (match_bss->rsn_ie[0] == MFIE_TYPE_RSN) |
144 | && (match_bss->rsn_ie[0] == MFIE_TYPE_RSN) | 155 | /* privacy bit may NOT be set in some APs like LinkSys WRT54G |
145 | /* privacy bit may NOT be set in some APs like LinkSys WRT54G | 156 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */ |
146 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { | 157 | ) |
147 | */ | ||
148 | ) { | ||
149 | return 1; | 158 | return 1; |
150 | } | 159 | else |
151 | return 0; | 160 | return 0; |
152 | } | 161 | } |
153 | 162 | ||
154 | static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo, | 163 | static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo, |
155 | struct bss_descriptor * match_bss) | 164 | struct bss_descriptor *match_bss) |
156 | { | 165 | { |
157 | if ( !secinfo->wep_enabled | 166 | if (!secinfo->wep_enabled && !secinfo->WPAenabled |
158 | && !secinfo->WPAenabled | 167 | && !secinfo->WPA2enabled |
159 | && !secinfo->WPA2enabled | 168 | && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC) |
160 | && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC) | 169 | && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN) |
161 | && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN) | 170 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) |
162 | && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { | ||
163 | return 1; | 171 | return 1; |
164 | } | 172 | else |
165 | return 0; | 173 | return 0; |
166 | } | 174 | } |
167 | 175 | ||
168 | static inline int is_same_network(struct bss_descriptor *src, | 176 | static inline int is_same_network(struct bss_descriptor *src, |
@@ -197,7 +205,7 @@ static inline int is_same_network(struct bss_descriptor *src, | |||
197 | * @return Index in scantable, or error code if negative | 205 | * @return Index in scantable, or error code if negative |
198 | */ | 206 | */ |
199 | static int is_network_compatible(struct lbs_private *priv, | 207 | static int is_network_compatible(struct lbs_private *priv, |
200 | struct bss_descriptor * bss, u8 mode) | 208 | struct bss_descriptor *bss, uint8_t mode) |
201 | { | 209 | { |
202 | int matched = 0; | 210 | int matched = 0; |
203 | 211 | ||
@@ -211,43 +219,39 @@ static int is_network_compatible(struct lbs_private *priv, | |||
211 | } else if ((matched = match_bss_static_wep(&priv->secinfo, bss))) { | 219 | } else if ((matched = match_bss_static_wep(&priv->secinfo, bss))) { |
212 | goto done; | 220 | goto done; |
213 | } else if ((matched = match_bss_wpa(&priv->secinfo, bss))) { | 221 | } else if ((matched = match_bss_wpa(&priv->secinfo, bss))) { |
214 | lbs_deb_scan( | 222 | lbs_deb_scan("is_network_compatible() WPA: wpa_ie 0x%x " |
215 | "is_network_compatible() WPA: wpa_ie 0x%x " | 223 | "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " |
216 | "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " | 224 | "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], |
217 | "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], | 225 | priv->secinfo.wep_enabled ? "e" : "d", |
218 | priv->secinfo.wep_enabled ? "e" : "d", | 226 | priv->secinfo.WPAenabled ? "e" : "d", |
219 | priv->secinfo.WPAenabled ? "e" : "d", | 227 | priv->secinfo.WPA2enabled ? "e" : "d", |
220 | priv->secinfo.WPA2enabled ? "e" : "d", | 228 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); |
221 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); | ||
222 | goto done; | 229 | goto done; |
223 | } else if ((matched = match_bss_wpa2(&priv->secinfo, bss))) { | 230 | } else if ((matched = match_bss_wpa2(&priv->secinfo, bss))) { |
224 | lbs_deb_scan( | 231 | lbs_deb_scan("is_network_compatible() WPA2: wpa_ie 0x%x " |
225 | "is_network_compatible() WPA2: wpa_ie 0x%x " | 232 | "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " |
226 | "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " | 233 | "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], |
227 | "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], | 234 | priv->secinfo.wep_enabled ? "e" : "d", |
228 | priv->secinfo.wep_enabled ? "e" : "d", | 235 | priv->secinfo.WPAenabled ? "e" : "d", |
229 | priv->secinfo.WPAenabled ? "e" : "d", | 236 | priv->secinfo.WPA2enabled ? "e" : "d", |
230 | priv->secinfo.WPA2enabled ? "e" : "d", | 237 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); |
231 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); | ||
232 | goto done; | 238 | goto done; |
233 | } else if ((matched = match_bss_dynamic_wep(&priv->secinfo, bss))) { | 239 | } else if ((matched = match_bss_dynamic_wep(&priv->secinfo, bss))) { |
234 | lbs_deb_scan( | 240 | lbs_deb_scan("is_network_compatible() dynamic WEP: " |
235 | "is_network_compatible() dynamic WEP: " | 241 | "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n", |
236 | "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n", | 242 | bss->wpa_ie[0], bss->rsn_ie[0], |
237 | bss->wpa_ie[0], bss->rsn_ie[0], | 243 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); |
238 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); | ||
239 | goto done; | 244 | goto done; |
240 | } | 245 | } |
241 | 246 | ||
242 | /* bss security settings don't match those configured on card */ | 247 | /* bss security settings don't match those configured on card */ |
243 | lbs_deb_scan( | 248 | lbs_deb_scan("is_network_compatible() FAILED: wpa_ie 0x%x " |
244 | "is_network_compatible() FAILED: wpa_ie 0x%x " | 249 | "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n", |
245 | "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n", | 250 | bss->wpa_ie[0], bss->rsn_ie[0], |
246 | bss->wpa_ie[0], bss->rsn_ie[0], | 251 | priv->secinfo.wep_enabled ? "e" : "d", |
247 | priv->secinfo.wep_enabled ? "e" : "d", | 252 | priv->secinfo.WPAenabled ? "e" : "d", |
248 | priv->secinfo.WPAenabled ? "e" : "d", | 253 | priv->secinfo.WPA2enabled ? "e" : "d", |
249 | priv->secinfo.WPA2enabled ? "e" : "d", | 254 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); |
250 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); | ||
251 | 255 | ||
252 | done: | 256 | done: |
253 | lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched); | 257 | lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched); |
@@ -256,24 +260,12 @@ done: | |||
256 | 260 | ||
257 | 261 | ||
258 | 262 | ||
259 | |||
260 | /*********************************************************************/ | 263 | /*********************************************************************/ |
261 | /* */ | 264 | /* */ |
262 | /* Main scanning support */ | 265 | /* Main scanning support */ |
263 | /* */ | 266 | /* */ |
264 | /*********************************************************************/ | 267 | /*********************************************************************/ |
265 | 268 | ||
266 | void lbs_scan_worker(struct work_struct *work) | ||
267 | { | ||
268 | struct lbs_private *priv = | ||
269 | container_of(work, struct lbs_private, scan_work.work); | ||
270 | |||
271 | lbs_deb_enter(LBS_DEB_SCAN); | ||
272 | lbs_scan_networks(priv, NULL, 0); | ||
273 | lbs_deb_leave(LBS_DEB_SCAN); | ||
274 | } | ||
275 | |||
276 | |||
277 | /** | 269 | /** |
278 | * @brief Create a channel list for the driver to scan based on region info | 270 | * @brief Create a channel list for the driver to scan based on region info |
279 | * | 271 | * |
@@ -285,25 +277,18 @@ void lbs_scan_worker(struct work_struct *work) | |||
285 | * | 277 | * |
286 | * @param priv A pointer to struct lbs_private structure | 278 | * @param priv A pointer to struct lbs_private structure |
287 | * @param scanchanlist Output parameter: resulting channel list to scan | 279 | * @param scanchanlist Output parameter: resulting channel list to scan |
288 | * @param filteredscan Flag indicating whether or not a BSSID or SSID filter | ||
289 | * is being sent in the command to firmware. Used to | ||
290 | * increase the number of channels sent in a scan | ||
291 | * command and to disable the firmware channel scan | ||
292 | * filter. | ||
293 | * | 280 | * |
294 | * @return void | 281 | * @return void |
295 | */ | 282 | */ |
296 | static int lbs_scan_create_channel_list(struct lbs_private *priv, | 283 | static int lbs_scan_create_channel_list(struct lbs_private *priv, |
297 | struct chanscanparamset * scanchanlist, | 284 | struct chanscanparamset *scanchanlist) |
298 | u8 filteredscan) | ||
299 | { | 285 | { |
300 | |||
301 | struct region_channel *scanregion; | 286 | struct region_channel *scanregion; |
302 | struct chan_freq_power *cfp; | 287 | struct chan_freq_power *cfp; |
303 | int rgnidx; | 288 | int rgnidx; |
304 | int chanidx; | 289 | int chanidx; |
305 | int nextchan; | 290 | int nextchan; |
306 | u8 scantype; | 291 | uint8_t scantype; |
307 | 292 | ||
308 | chanidx = 0; | 293 | chanidx = 0; |
309 | 294 | ||
@@ -314,9 +299,8 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv, | |||
314 | scantype = CMD_SCAN_TYPE_ACTIVE; | 299 | scantype = CMD_SCAN_TYPE_ACTIVE; |
315 | 300 | ||
316 | for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) { | 301 | for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) { |
317 | if (priv->enable11d && | 302 | if (priv->enable11d && (priv->connect_status != LBS_CONNECTED) |
318 | (priv->connect_status != LBS_CONNECTED) && | 303 | && (priv->mesh_connect_status != LBS_CONNECTED)) { |
319 | (priv->mesh_connect_status != LBS_CONNECTED)) { | ||
320 | /* Scan all the supported chan for the first scan */ | 304 | /* Scan all the supported chan for the first scan */ |
321 | if (!priv->universal_channel[rgnidx].valid) | 305 | if (!priv->universal_channel[rgnidx].valid) |
322 | continue; | 306 | continue; |
@@ -331,45 +315,27 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv, | |||
331 | scanregion = &priv->region_channel[rgnidx]; | 315 | scanregion = &priv->region_channel[rgnidx]; |
332 | } | 316 | } |
333 | 317 | ||
334 | for (nextchan = 0; | 318 | for (nextchan = 0; nextchan < scanregion->nrcfp; nextchan++, chanidx++) { |
335 | nextchan < scanregion->nrcfp; nextchan++, chanidx++) { | 319 | struct chanscanparamset *chan = &scanchanlist[chanidx]; |
336 | 320 | ||
337 | cfp = scanregion->CFP + nextchan; | 321 | cfp = scanregion->CFP + nextchan; |
338 | 322 | ||
339 | if (priv->enable11d) { | 323 | if (priv->enable11d) |
340 | scantype = | 324 | scantype = lbs_get_scan_type_11d(cfp->channel, |
341 | lbs_get_scan_type_11d(cfp->channel, | 325 | &priv->parsed_region_chan); |
342 | &priv-> | ||
343 | parsed_region_chan); | ||
344 | } | ||
345 | 326 | ||
346 | switch (scanregion->band) { | 327 | if (scanregion->band == BAND_B || scanregion->band == BAND_G) |
347 | case BAND_B: | 328 | chan->radiotype = CMD_SCAN_RADIO_TYPE_BG; |
348 | case BAND_G: | ||
349 | default: | ||
350 | scanchanlist[chanidx].radiotype = | ||
351 | CMD_SCAN_RADIO_TYPE_BG; | ||
352 | break; | ||
353 | } | ||
354 | 329 | ||
355 | if (scantype == CMD_SCAN_TYPE_PASSIVE) { | 330 | if (scantype == CMD_SCAN_TYPE_PASSIVE) { |
356 | scanchanlist[chanidx].maxscantime = | 331 | chan->maxscantime = cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME); |
357 | cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME); | 332 | chan->chanscanmode.passivescan = 1; |
358 | scanchanlist[chanidx].chanscanmode.passivescan = | ||
359 | 1; | ||
360 | } else { | 333 | } else { |
361 | scanchanlist[chanidx].maxscantime = | 334 | chan->maxscantime = cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME); |
362 | cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME); | 335 | chan->chanscanmode.passivescan = 0; |
363 | scanchanlist[chanidx].chanscanmode.passivescan = | ||
364 | 0; | ||
365 | } | 336 | } |
366 | 337 | ||
367 | scanchanlist[chanidx].channumber = cfp->channel; | 338 | chan->channumber = cfp->channel; |
368 | |||
369 | if (filteredscan) { | ||
370 | scanchanlist[chanidx].chanscanmode. | ||
371 | disablechanfilt = 1; | ||
372 | } | ||
373 | } | 339 | } |
374 | } | 340 | } |
375 | return chanidx; | 341 | return chanidx; |
@@ -383,15 +349,14 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv, | |||
383 | * length 06 00 | 349 | * length 06 00 |
384 | * ssid 4d 4e 54 45 53 54 | 350 | * ssid 4d 4e 54 45 53 54 |
385 | */ | 351 | */ |
386 | static int lbs_scan_add_ssid_tlv(u8 *tlv, | 352 | static int lbs_scan_add_ssid_tlv(struct lbs_private *priv, u8 *tlv) |
387 | const struct lbs_ioctl_user_scan_cfg *user_cfg) | ||
388 | { | 353 | { |
389 | struct mrvlietypes_ssidparamset *ssid_tlv = | 354 | struct mrvlietypes_ssidparamset *ssid_tlv = (void *)tlv; |
390 | (struct mrvlietypes_ssidparamset *)tlv; | 355 | |
391 | ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID); | 356 | ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID); |
392 | ssid_tlv->header.len = cpu_to_le16(user_cfg->ssid_len); | 357 | ssid_tlv->header.len = cpu_to_le16(priv->scan_ssid_len); |
393 | memcpy(ssid_tlv->ssid, user_cfg->ssid, user_cfg->ssid_len); | 358 | memcpy(ssid_tlv->ssid, priv->scan_ssid, priv->scan_ssid_len); |
394 | return sizeof(ssid_tlv->header) + user_cfg->ssid_len; | 359 | return sizeof(ssid_tlv->header) + priv->scan_ssid_len; |
395 | } | 360 | } |
396 | 361 | ||
397 | 362 | ||
@@ -420,13 +385,12 @@ static int lbs_scan_add_ssid_tlv(u8 *tlv, | |||
420 | * channel 13 00 0d 00 00 00 64 00 | 385 | * channel 13 00 0d 00 00 00 64 00 |
421 | * | 386 | * |
422 | */ | 387 | */ |
423 | static int lbs_scan_add_chanlist_tlv(u8 *tlv, | 388 | static int lbs_scan_add_chanlist_tlv(uint8_t *tlv, |
424 | struct chanscanparamset *chan_list, | 389 | struct chanscanparamset *chan_list, |
425 | int chan_count) | 390 | int chan_count) |
426 | { | 391 | { |
427 | size_t size = sizeof(struct chanscanparamset) * chan_count; | 392 | size_t size = sizeof(struct chanscanparamset) *chan_count; |
428 | struct mrvlietypes_chanlistparamset *chan_tlv = | 393 | struct mrvlietypes_chanlistparamset *chan_tlv = (void *)tlv; |
429 | (struct mrvlietypes_chanlistparamset *) tlv; | ||
430 | 394 | ||
431 | chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); | 395 | chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); |
432 | memcpy(chan_tlv->chanscanparam, chan_list, size); | 396 | memcpy(chan_tlv->chanscanparam, chan_list, size); |
@@ -445,11 +409,10 @@ static int lbs_scan_add_chanlist_tlv(u8 *tlv, | |||
445 | * The rates are in lbs_bg_rates[], but for the 802.11b | 409 | * The rates are in lbs_bg_rates[], but for the 802.11b |
446 | * rates the high bit isn't set. | 410 | * rates the high bit isn't set. |
447 | */ | 411 | */ |
448 | static int lbs_scan_add_rates_tlv(u8 *tlv) | 412 | static int lbs_scan_add_rates_tlv(uint8_t *tlv) |
449 | { | 413 | { |
450 | int i; | 414 | int i; |
451 | struct mrvlietypes_ratesparamset *rate_tlv = | 415 | struct mrvlietypes_ratesparamset *rate_tlv = (void *)tlv; |
452 | (struct mrvlietypes_ratesparamset *) tlv; | ||
453 | 416 | ||
454 | rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES); | 417 | rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES); |
455 | tlv += sizeof(rate_tlv->header); | 418 | tlv += sizeof(rate_tlv->header); |
@@ -475,44 +438,44 @@ static int lbs_scan_add_rates_tlv(u8 *tlv) | |||
475 | * Generate the CMD_802_11_SCAN command with the proper tlv | 438 | * Generate the CMD_802_11_SCAN command with the proper tlv |
476 | * for a bunch of channels. | 439 | * for a bunch of channels. |
477 | */ | 440 | */ |
478 | static int lbs_do_scan(struct lbs_private *priv, | 441 | static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype, |
479 | u8 bsstype, | 442 | struct chanscanparamset *chan_list, int chan_count) |
480 | struct chanscanparamset *chan_list, | ||
481 | int chan_count, | ||
482 | const struct lbs_ioctl_user_scan_cfg *user_cfg) | ||
483 | { | 443 | { |
484 | int ret = -ENOMEM; | 444 | int ret = -ENOMEM; |
485 | struct lbs_scan_cmd_config *scan_cmd; | 445 | struct cmd_ds_802_11_scan *scan_cmd; |
486 | u8 *tlv; /* pointer into our current, growing TLV storage area */ | 446 | uint8_t *tlv; /* pointer into our current, growing TLV storage area */ |
487 | 447 | ||
488 | lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, " | 448 | lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, chan_count %d", |
489 | "chan_count %d", | 449 | bsstype, chan_list[0].channumber, chan_count); |
490 | bsstype, chan_list[0].channumber, chan_count); | ||
491 | 450 | ||
492 | /* create the fixed part for scan command */ | 451 | /* create the fixed part for scan command */ |
493 | scan_cmd = kzalloc(MAX_SCAN_CFG_ALLOC, GFP_KERNEL); | 452 | scan_cmd = kzalloc(MAX_SCAN_CFG_ALLOC, GFP_KERNEL); |
494 | if (scan_cmd == NULL) | 453 | if (scan_cmd == NULL) |
495 | goto out; | 454 | goto out; |
455 | |||
496 | tlv = scan_cmd->tlvbuffer; | 456 | tlv = scan_cmd->tlvbuffer; |
497 | if (user_cfg) | 457 | /* TODO: do we need to scan for a specific BSSID? |
498 | memcpy(scan_cmd->bssid, user_cfg->bssid, ETH_ALEN); | 458 | memcpy(scan_cmd->bssid, priv->scan_bssid, ETH_ALEN); */ |
499 | scan_cmd->bsstype = bsstype; | 459 | scan_cmd->bsstype = bsstype; |
500 | 460 | ||
501 | /* add TLVs */ | 461 | /* add TLVs */ |
502 | if (user_cfg && user_cfg->ssid_len) | 462 | if (priv->scan_ssid_len) |
503 | tlv += lbs_scan_add_ssid_tlv(tlv, user_cfg); | 463 | tlv += lbs_scan_add_ssid_tlv(priv, tlv); |
504 | if (chan_list && chan_count) | 464 | if (chan_list && chan_count) |
505 | tlv += lbs_scan_add_chanlist_tlv(tlv, chan_list, chan_count); | 465 | tlv += lbs_scan_add_chanlist_tlv(tlv, chan_list, chan_count); |
506 | tlv += lbs_scan_add_rates_tlv(tlv); | 466 | tlv += lbs_scan_add_rates_tlv(tlv); |
507 | 467 | ||
508 | /* This is the final data we are about to send */ | 468 | /* This is the final data we are about to send */ |
509 | scan_cmd->tlvbufferlen = tlv - scan_cmd->tlvbuffer; | 469 | scan_cmd->hdr.size = cpu_to_le16(tlv - (uint8_t *)scan_cmd); |
510 | lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd, 1+6); | 470 | lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd, |
471 | sizeof(*scan_cmd)); | ||
511 | lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TLV", scan_cmd->tlvbuffer, | 472 | lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TLV", scan_cmd->tlvbuffer, |
512 | scan_cmd->tlvbufferlen); | 473 | tlv - scan_cmd->tlvbuffer); |
474 | |||
475 | ret = __lbs_cmd(priv, CMD_802_11_SCAN, &scan_cmd->hdr, | ||
476 | le16_to_cpu(scan_cmd->hdr.size), | ||
477 | lbs_ret_80211_scan, 0); | ||
513 | 478 | ||
514 | ret = lbs_prepare_and_send_command(priv, CMD_802_11_SCAN, 0, | ||
515 | CMD_OPTION_WAITFORRSP, 0, scan_cmd); | ||
516 | out: | 479 | out: |
517 | kfree(scan_cmd); | 480 | kfree(scan_cmd); |
518 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); | 481 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); |
@@ -530,22 +493,18 @@ out: | |||
530 | * update the internal driver scan table | 493 | * update the internal driver scan table |
531 | * | 494 | * |
532 | * @param priv A pointer to struct lbs_private structure | 495 | * @param priv A pointer to struct lbs_private structure |
533 | * @param puserscanin Pointer to the input configuration for the requested | 496 | * @param full_scan Do a full-scan (blocking) |
534 | * scan. | ||
535 | * | 497 | * |
536 | * @return 0 or < 0 if error | 498 | * @return 0 or < 0 if error |
537 | */ | 499 | */ |
538 | int lbs_scan_networks(struct lbs_private *priv, | 500 | static int lbs_scan_networks(struct lbs_private *priv, int full_scan) |
539 | const struct lbs_ioctl_user_scan_cfg *user_cfg, | ||
540 | int full_scan) | ||
541 | { | 501 | { |
542 | int ret = -ENOMEM; | 502 | int ret = -ENOMEM; |
543 | struct chanscanparamset *chan_list; | 503 | struct chanscanparamset *chan_list; |
544 | struct chanscanparamset *curr_chans; | 504 | struct chanscanparamset *curr_chans; |
545 | int chan_count; | 505 | int chan_count; |
546 | u8 bsstype = CMD_BSS_TYPE_ANY; | 506 | uint8_t bsstype = CMD_BSS_TYPE_ANY; |
547 | int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD; | 507 | int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD; |
548 | int filteredscan = 0; | ||
549 | union iwreq_data wrqu; | 508 | union iwreq_data wrqu; |
550 | #ifdef CONFIG_LIBERTAS_DEBUG | 509 | #ifdef CONFIG_LIBERTAS_DEBUG |
551 | struct bss_descriptor *iter; | 510 | struct bss_descriptor *iter; |
@@ -553,8 +512,7 @@ int lbs_scan_networks(struct lbs_private *priv, | |||
553 | DECLARE_MAC_BUF(mac); | 512 | DECLARE_MAC_BUF(mac); |
554 | #endif | 513 | #endif |
555 | 514 | ||
556 | lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", | 515 | lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", full_scan); |
557 | full_scan); | ||
558 | 516 | ||
559 | /* Cancel any partial outstanding partial scans if this scan | 517 | /* Cancel any partial outstanding partial scans if this scan |
560 | * is a full scan. | 518 | * is a full scan. |
@@ -562,30 +520,27 @@ int lbs_scan_networks(struct lbs_private *priv, | |||
562 | if (full_scan && delayed_work_pending(&priv->scan_work)) | 520 | if (full_scan && delayed_work_pending(&priv->scan_work)) |
563 | cancel_delayed_work(&priv->scan_work); | 521 | cancel_delayed_work(&priv->scan_work); |
564 | 522 | ||
565 | /* Determine same scan parameters */ | 523 | /* User-specified bsstype or channel list |
524 | TODO: this can be implemented if some user-space application | ||
525 | need the feature. Formerly, it was accessible from debugfs, | ||
526 | but then nowhere used. | ||
566 | if (user_cfg) { | 527 | if (user_cfg) { |
567 | if (user_cfg->bsstype) | 528 | if (user_cfg->bsstype) |
568 | bsstype = user_cfg->bsstype; | 529 | bsstype = user_cfg->bsstype; |
569 | if (compare_ether_addr(user_cfg->bssid, &zeromac[0]) != 0) { | 530 | } */ |
570 | numchannels = MRVDRV_MAX_CHANNELS_PER_SCAN; | 531 | |
571 | filteredscan = 1; | 532 | lbs_deb_scan("numchannels %d, bsstype %d\n", numchannels, bsstype); |
572 | } | ||
573 | } | ||
574 | lbs_deb_scan("numchannels %d, bsstype %d, " | ||
575 | "filteredscan %d\n", | ||
576 | numchannels, bsstype, filteredscan); | ||
577 | 533 | ||
578 | /* Create list of channels to scan */ | 534 | /* Create list of channels to scan */ |
579 | chan_list = kzalloc(sizeof(struct chanscanparamset) * | 535 | chan_list = kzalloc(sizeof(struct chanscanparamset) * |
580 | LBS_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL); | 536 | LBS_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL); |
581 | if (!chan_list) { | 537 | if (!chan_list) { |
582 | lbs_pr_alert("SCAN: chan_list empty\n"); | 538 | lbs_pr_alert("SCAN: chan_list empty\n"); |
583 | goto out; | 539 | goto out; |
584 | } | 540 | } |
585 | 541 | ||
586 | /* We want to scan all channels */ | 542 | /* We want to scan all channels */ |
587 | chan_count = lbs_scan_create_channel_list(priv, chan_list, | 543 | chan_count = lbs_scan_create_channel_list(priv, chan_list); |
588 | filteredscan); | ||
589 | 544 | ||
590 | netif_stop_queue(priv->dev); | 545 | netif_stop_queue(priv->dev); |
591 | netif_carrier_off(priv->dev); | 546 | netif_carrier_off(priv->dev); |
@@ -595,13 +550,13 @@ int lbs_scan_networks(struct lbs_private *priv, | |||
595 | } | 550 | } |
596 | 551 | ||
597 | /* Prepare to continue an interrupted scan */ | 552 | /* Prepare to continue an interrupted scan */ |
598 | lbs_deb_scan("chan_count %d, last_scanned_channel %d\n", | 553 | lbs_deb_scan("chan_count %d, scan_channel %d\n", |
599 | chan_count, priv->last_scanned_channel); | 554 | chan_count, priv->scan_channel); |
600 | curr_chans = chan_list; | 555 | curr_chans = chan_list; |
601 | /* advance channel list by already-scanned-channels */ | 556 | /* advance channel list by already-scanned-channels */ |
602 | if (priv->last_scanned_channel > 0) { | 557 | if (priv->scan_channel > 0) { |
603 | curr_chans += priv->last_scanned_channel; | 558 | curr_chans += priv->scan_channel; |
604 | chan_count -= priv->last_scanned_channel; | 559 | chan_count -= priv->scan_channel; |
605 | } | 560 | } |
606 | 561 | ||
607 | /* Send scan command(s) | 562 | /* Send scan command(s) |
@@ -612,9 +567,9 @@ int lbs_scan_networks(struct lbs_private *priv, | |||
612 | while (chan_count) { | 567 | while (chan_count) { |
613 | int to_scan = min(numchannels, chan_count); | 568 | int to_scan = min(numchannels, chan_count); |
614 | lbs_deb_scan("scanning %d of %d channels\n", | 569 | lbs_deb_scan("scanning %d of %d channels\n", |
615 | to_scan, chan_count); | 570 | to_scan, chan_count); |
616 | ret = lbs_do_scan(priv, bsstype, curr_chans, | 571 | ret = lbs_do_scan(priv, bsstype, curr_chans, |
617 | to_scan, user_cfg); | 572 | to_scan); |
618 | if (ret) { | 573 | if (ret) { |
619 | lbs_pr_err("SCAN_CMD failed\n"); | 574 | lbs_pr_err("SCAN_CMD failed\n"); |
620 | goto out2; | 575 | goto out2; |
@@ -623,17 +578,16 @@ int lbs_scan_networks(struct lbs_private *priv, | |||
623 | chan_count -= to_scan; | 578 | chan_count -= to_scan; |
624 | 579 | ||
625 | /* somehow schedule the next part of the scan */ | 580 | /* somehow schedule the next part of the scan */ |
626 | if (chan_count && | 581 | if (chan_count && !full_scan && |
627 | !full_scan && | ||
628 | !priv->surpriseremoved) { | 582 | !priv->surpriseremoved) { |
629 | /* -1 marks just that we're currently scanning */ | 583 | /* -1 marks just that we're currently scanning */ |
630 | if (priv->last_scanned_channel < 0) | 584 | if (priv->scan_channel < 0) |
631 | priv->last_scanned_channel = to_scan; | 585 | priv->scan_channel = to_scan; |
632 | else | 586 | else |
633 | priv->last_scanned_channel += to_scan; | 587 | priv->scan_channel += to_scan; |
634 | cancel_delayed_work(&priv->scan_work); | 588 | cancel_delayed_work(&priv->scan_work); |
635 | queue_delayed_work(priv->work_thread, &priv->scan_work, | 589 | queue_delayed_work(priv->work_thread, &priv->scan_work, |
636 | msecs_to_jiffies(300)); | 590 | msecs_to_jiffies(300)); |
637 | /* skip over GIWSCAN event */ | 591 | /* skip over GIWSCAN event */ |
638 | goto out; | 592 | goto out; |
639 | } | 593 | } |
@@ -648,13 +602,13 @@ int lbs_scan_networks(struct lbs_private *priv, | |||
648 | lbs_deb_scan("scan table:\n"); | 602 | lbs_deb_scan("scan table:\n"); |
649 | list_for_each_entry(iter, &priv->network_list, list) | 603 | list_for_each_entry(iter, &priv->network_list, list) |
650 | lbs_deb_scan("%02d: BSSID %s, RSSI %d, SSID '%s'\n", | 604 | lbs_deb_scan("%02d: BSSID %s, RSSI %d, SSID '%s'\n", |
651 | i++, print_mac(mac, iter->bssid), (s32) iter->rssi, | 605 | i++, print_mac(mac, iter->bssid), (int)iter->rssi, |
652 | escape_essid(iter->ssid, iter->ssid_len)); | 606 | escape_essid(iter->ssid, iter->ssid_len)); |
653 | mutex_unlock(&priv->lock); | 607 | mutex_unlock(&priv->lock); |
654 | #endif | 608 | #endif |
655 | 609 | ||
656 | out2: | 610 | out2: |
657 | priv->last_scanned_channel = 0; | 611 | priv->scan_channel = 0; |
658 | 612 | ||
659 | out: | 613 | out: |
660 | if (priv->connect_status == LBS_CONNECTED) { | 614 | if (priv->connect_status == LBS_CONNECTED) { |
@@ -676,6 +630,17 @@ out: | |||
676 | 630 | ||
677 | 631 | ||
678 | 632 | ||
633 | void lbs_scan_worker(struct work_struct *work) | ||
634 | { | ||
635 | struct lbs_private *priv = | ||
636 | container_of(work, struct lbs_private, scan_work.work); | ||
637 | |||
638 | lbs_deb_enter(LBS_DEB_SCAN); | ||
639 | lbs_scan_networks(priv, 0); | ||
640 | lbs_deb_leave(LBS_DEB_SCAN); | ||
641 | } | ||
642 | |||
643 | |||
679 | /*********************************************************************/ | 644 | /*********************************************************************/ |
680 | /* */ | 645 | /* */ |
681 | /* Result interpretation */ | 646 | /* Result interpretation */ |
@@ -694,7 +659,7 @@ out: | |||
694 | * @return 0 or -1 | 659 | * @return 0 or -1 |
695 | */ | 660 | */ |
696 | static int lbs_process_bss(struct bss_descriptor *bss, | 661 | static int lbs_process_bss(struct bss_descriptor *bss, |
697 | u8 ** pbeaconinfo, int *bytesleft) | 662 | uint8_t **pbeaconinfo, int *bytesleft) |
698 | { | 663 | { |
699 | struct ieeetypes_fhparamset *pFH; | 664 | struct ieeetypes_fhparamset *pFH; |
700 | struct ieeetypes_dsparamset *pDS; | 665 | struct ieeetypes_dsparamset *pDS; |
@@ -702,9 +667,9 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
702 | struct ieeetypes_ibssparamset *pibss; | 667 | struct ieeetypes_ibssparamset *pibss; |
703 | DECLARE_MAC_BUF(mac); | 668 | DECLARE_MAC_BUF(mac); |
704 | struct ieeetypes_countryinfoset *pcountryinfo; | 669 | struct ieeetypes_countryinfoset *pcountryinfo; |
705 | u8 *pos, *end, *p; | 670 | uint8_t *pos, *end, *p; |
706 | u8 n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0; | 671 | uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0; |
707 | u16 beaconsize = 0; | 672 | uint16_t beaconsize = 0; |
708 | int ret; | 673 | int ret; |
709 | 674 | ||
710 | lbs_deb_enter(LBS_DEB_SCAN); | 675 | lbs_deb_enter(LBS_DEB_SCAN); |
@@ -776,12 +741,11 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
776 | 741 | ||
777 | /* process variable IE */ | 742 | /* process variable IE */ |
778 | while (pos <= end - 2) { | 743 | while (pos <= end - 2) { |
779 | struct ieee80211_info_element * elem = | 744 | struct ieee80211_info_element * elem = (void *)pos; |
780 | (struct ieee80211_info_element *) pos; | ||
781 | 745 | ||
782 | if (pos + elem->len > end) { | 746 | if (pos + elem->len > end) { |
783 | lbs_deb_scan("process_bss: error in processing IE, " | 747 | lbs_deb_scan("process_bss: error in processing IE, " |
784 | "bytes left < IE length\n"); | 748 | "bytes left < IE length\n"); |
785 | break; | 749 | break; |
786 | } | 750 | } |
787 | 751 | ||
@@ -795,7 +759,7 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
795 | break; | 759 | break; |
796 | 760 | ||
797 | case MFIE_TYPE_RATES: | 761 | case MFIE_TYPE_RATES: |
798 | n_basic_rates = min_t(u8, MAX_RATES, elem->len); | 762 | n_basic_rates = min_t(uint8_t, MAX_RATES, elem->len); |
799 | memcpy(bss->rates, elem->data, n_basic_rates); | 763 | memcpy(bss->rates, elem->data, n_basic_rates); |
800 | got_basic_rates = 1; | 764 | got_basic_rates = 1; |
801 | lbs_deb_scan("got RATES IE\n"); | 765 | lbs_deb_scan("got RATES IE\n"); |
@@ -836,19 +800,16 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
836 | lbs_deb_scan("got COUNTRY IE\n"); | 800 | lbs_deb_scan("got COUNTRY IE\n"); |
837 | if (pcountryinfo->len < sizeof(pcountryinfo->countrycode) | 801 | if (pcountryinfo->len < sizeof(pcountryinfo->countrycode) |
838 | || pcountryinfo->len > 254) { | 802 | || pcountryinfo->len > 254) { |
839 | lbs_deb_scan("process_bss: 11D- Err " | 803 | lbs_deb_scan("process_bss: 11D- Err CountryInfo len %d, min %zd, max 254\n", |
840 | "CountryInfo len %d, min %zd, max 254\n", | 804 | pcountryinfo->len, sizeof(pcountryinfo->countrycode)); |
841 | pcountryinfo->len, | ||
842 | sizeof(pcountryinfo->countrycode)); | ||
843 | ret = -1; | 805 | ret = -1; |
844 | goto done; | 806 | goto done; |
845 | } | 807 | } |
846 | 808 | ||
847 | memcpy(&bss->countryinfo, | 809 | memcpy(&bss->countryinfo, pcountryinfo, pcountryinfo->len + 2); |
848 | pcountryinfo, pcountryinfo->len + 2); | ||
849 | lbs_deb_hex(LBS_DEB_SCAN, "process_bss: 11d countryinfo", | 810 | lbs_deb_hex(LBS_DEB_SCAN, "process_bss: 11d countryinfo", |
850 | (u8 *) pcountryinfo, | 811 | (uint8_t *) pcountryinfo, |
851 | (u32) (pcountryinfo->len + 2)); | 812 | (int) (pcountryinfo->len + 2)); |
852 | break; | 813 | break; |
853 | 814 | ||
854 | case MFIE_TYPE_RATES_EX: | 815 | case MFIE_TYPE_RATES_EX: |
@@ -872,26 +833,19 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
872 | 833 | ||
873 | case MFIE_TYPE_GENERIC: | 834 | case MFIE_TYPE_GENERIC: |
874 | if (elem->len >= 4 && | 835 | if (elem->len >= 4 && |
875 | elem->data[0] == 0x00 && | 836 | elem->data[0] == 0x00 && elem->data[1] == 0x50 && |
876 | elem->data[1] == 0x50 && | 837 | elem->data[2] == 0xf2 && elem->data[3] == 0x01) { |
877 | elem->data[2] == 0xf2 && | 838 | bss->wpa_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN); |
878 | elem->data[3] == 0x01) { | ||
879 | bss->wpa_ie_len = min(elem->len + 2, | ||
880 | MAX_WPA_IE_LEN); | ||
881 | memcpy(bss->wpa_ie, elem, bss->wpa_ie_len); | 839 | memcpy(bss->wpa_ie, elem, bss->wpa_ie_len); |
882 | lbs_deb_scan("got WPA IE\n"); | 840 | lbs_deb_scan("got WPA IE\n"); |
883 | lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie, | 841 | lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie, elem->len); |
884 | elem->len); | ||
885 | } else if (elem->len >= MARVELL_MESH_IE_LENGTH && | 842 | } else if (elem->len >= MARVELL_MESH_IE_LENGTH && |
886 | elem->data[0] == 0x00 && | 843 | elem->data[0] == 0x00 && elem->data[1] == 0x50 && |
887 | elem->data[1] == 0x50 && | 844 | elem->data[2] == 0x43 && elem->data[3] == 0x04) { |
888 | elem->data[2] == 0x43 && | ||
889 | elem->data[3] == 0x04) { | ||
890 | lbs_deb_scan("got mesh IE\n"); | 845 | lbs_deb_scan("got mesh IE\n"); |
891 | bss->mesh = 1; | 846 | bss->mesh = 1; |
892 | } else { | 847 | } else { |
893 | lbs_deb_scan("got generiec IE: " | 848 | lbs_deb_scan("got generic IE: %02x:%02x:%02x:%02x, len %d\n", |
894 | "%02x:%02x:%02x:%02x, len %d\n", | ||
895 | elem->data[0], elem->data[1], | 849 | elem->data[0], elem->data[1], |
896 | elem->data[2], elem->data[3], | 850 | elem->data[2], elem->data[3], |
897 | elem->len); | 851 | elem->len); |
@@ -903,12 +857,12 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
903 | bss->rsn_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN); | 857 | bss->rsn_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN); |
904 | memcpy(bss->rsn_ie, elem, bss->rsn_ie_len); | 858 | memcpy(bss->rsn_ie, elem, bss->rsn_ie_len); |
905 | lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE", | 859 | lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE", |
906 | bss->rsn_ie, elem->len); | 860 | bss->rsn_ie, elem->len); |
907 | break; | 861 | break; |
908 | 862 | ||
909 | default: | 863 | default: |
910 | lbs_deb_scan("got IE 0x%04x, len %d\n", | 864 | lbs_deb_scan("got IE 0x%04x, len %d\n", |
911 | elem->id, elem->len); | 865 | elem->id, elem->len); |
912 | break; | 866 | break; |
913 | } | 867 | } |
914 | 868 | ||
@@ -938,18 +892,17 @@ done: | |||
938 | * @return index in BSSID list, or error return code (< 0) | 892 | * @return index in BSSID list, or error return code (< 0) |
939 | */ | 893 | */ |
940 | struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv, | 894 | struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv, |
941 | u8 * bssid, u8 mode) | 895 | uint8_t *bssid, uint8_t mode) |
942 | { | 896 | { |
943 | struct bss_descriptor * iter_bss; | 897 | struct bss_descriptor *iter_bss; |
944 | struct bss_descriptor * found_bss = NULL; | 898 | struct bss_descriptor *found_bss = NULL; |
945 | 899 | ||
946 | lbs_deb_enter(LBS_DEB_SCAN); | 900 | lbs_deb_enter(LBS_DEB_SCAN); |
947 | 901 | ||
948 | if (!bssid) | 902 | if (!bssid) |
949 | goto out; | 903 | goto out; |
950 | 904 | ||
951 | lbs_deb_hex(LBS_DEB_SCAN, "looking for", | 905 | lbs_deb_hex(LBS_DEB_SCAN, "looking for", bssid, ETH_ALEN); |
952 | bssid, ETH_ALEN); | ||
953 | 906 | ||
954 | /* Look through the scan table for a compatible match. The loop will | 907 | /* Look through the scan table for a compatible match. The loop will |
955 | * continue past a matched bssid that is not compatible in case there | 908 | * continue past a matched bssid that is not compatible in case there |
@@ -991,10 +944,11 @@ out: | |||
991 | * @return index in BSSID list | 944 | * @return index in BSSID list |
992 | */ | 945 | */ |
993 | struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv, | 946 | struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv, |
994 | u8 *ssid, u8 ssid_len, u8 * bssid, u8 mode, | 947 | uint8_t *ssid, uint8_t ssid_len, |
995 | int channel) | 948 | uint8_t *bssid, uint8_t mode, |
949 | int channel) | ||
996 | { | 950 | { |
997 | u8 bestrssi = 0; | 951 | uint8_t bestrssi = 0; |
998 | struct bss_descriptor * iter_bss = NULL; | 952 | struct bss_descriptor * iter_bss = NULL; |
999 | struct bss_descriptor * found_bss = NULL; | 953 | struct bss_descriptor * found_bss = NULL; |
1000 | struct bss_descriptor * tmp_oldest = NULL; | 954 | struct bss_descriptor * tmp_oldest = NULL; |
@@ -1009,7 +963,7 @@ struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv, | |||
1009 | tmp_oldest = iter_bss; | 963 | tmp_oldest = iter_bss; |
1010 | 964 | ||
1011 | if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len, | 965 | if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len, |
1012 | ssid, ssid_len) != 0) | 966 | ssid, ssid_len) != 0) |
1013 | continue; /* ssid doesn't match */ | 967 | continue; /* ssid doesn't match */ |
1014 | if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0) | 968 | if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0) |
1015 | continue; /* bssid doesn't match */ | 969 | continue; /* bssid doesn't match */ |
@@ -1059,13 +1013,12 @@ out: | |||
1059 | * | 1013 | * |
1060 | * @return index in BSSID list | 1014 | * @return index in BSSID list |
1061 | */ | 1015 | */ |
1062 | static struct bss_descriptor *lbs_find_best_ssid_in_list( | 1016 | static struct bss_descriptor *lbs_find_best_ssid_in_list(struct lbs_private *priv, |
1063 | struct lbs_private *priv, | 1017 | uint8_t mode) |
1064 | u8 mode) | ||
1065 | { | 1018 | { |
1066 | u8 bestrssi = 0; | 1019 | uint8_t bestrssi = 0; |
1067 | struct bss_descriptor * iter_bss; | 1020 | struct bss_descriptor *iter_bss; |
1068 | struct bss_descriptor * best_bss = NULL; | 1021 | struct bss_descriptor *best_bss = NULL; |
1069 | 1022 | ||
1070 | lbs_deb_enter(LBS_DEB_SCAN); | 1023 | lbs_deb_enter(LBS_DEB_SCAN); |
1071 | 1024 | ||
@@ -1098,7 +1051,7 @@ static struct bss_descriptor *lbs_find_best_ssid_in_list( | |||
1098 | } | 1051 | } |
1099 | 1052 | ||
1100 | /** | 1053 | /** |
1101 | * @brief Find the AP with specific ssid in the scan list | 1054 | * @brief Find the best AP |
1102 | * | 1055 | * |
1103 | * Used from association worker. | 1056 | * Used from association worker. |
1104 | * | 1057 | * |
@@ -1107,15 +1060,17 @@ static struct bss_descriptor *lbs_find_best_ssid_in_list( | |||
1107 | * | 1060 | * |
1108 | * @return 0--success, otherwise--fail | 1061 | * @return 0--success, otherwise--fail |
1109 | */ | 1062 | */ |
1110 | int lbs_find_best_network_ssid(struct lbs_private *priv, | 1063 | int lbs_find_best_network_ssid(struct lbs_private *priv, uint8_t *out_ssid, |
1111 | u8 *out_ssid, u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode) | 1064 | uint8_t *out_ssid_len, uint8_t preferred_mode, |
1065 | uint8_t *out_mode) | ||
1112 | { | 1066 | { |
1113 | int ret = -1; | 1067 | int ret = -1; |
1114 | struct bss_descriptor * found; | 1068 | struct bss_descriptor *found; |
1115 | 1069 | ||
1116 | lbs_deb_enter(LBS_DEB_SCAN); | 1070 | lbs_deb_enter(LBS_DEB_SCAN); |
1117 | 1071 | ||
1118 | lbs_scan_networks(priv, NULL, 1); | 1072 | priv->scan_ssid_len = 0; |
1073 | lbs_scan_networks(priv, 1); | ||
1119 | if (priv->surpriseremoved) | 1074 | if (priv->surpriseremoved) |
1120 | goto out; | 1075 | goto out; |
1121 | 1076 | ||
@@ -1141,29 +1096,24 @@ out: | |||
1141 | * @param priv A pointer to struct lbs_private structure | 1096 | * @param priv A pointer to struct lbs_private structure |
1142 | * @param ssid A pointer to the SSID to scan for | 1097 | * @param ssid A pointer to the SSID to scan for |
1143 | * @param ssid_len Length of the SSID | 1098 | * @param ssid_len Length of the SSID |
1144 | * @param clear_ssid Should existing scan results with this SSID | ||
1145 | * be cleared? | ||
1146 | * | 1099 | * |
1147 | * @return 0-success, otherwise fail | 1100 | * @return 0-success, otherwise fail |
1148 | */ | 1101 | */ |
1149 | int lbs_send_specific_ssid_scan(struct lbs_private *priv, | 1102 | int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid, |
1150 | u8 *ssid, u8 ssid_len, u8 clear_ssid) | 1103 | uint8_t ssid_len) |
1151 | { | 1104 | { |
1152 | struct lbs_ioctl_user_scan_cfg scancfg; | ||
1153 | int ret = 0; | 1105 | int ret = 0; |
1154 | 1106 | ||
1155 | lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s', clear %d", | 1107 | lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s'\n", |
1156 | escape_essid(ssid, ssid_len), clear_ssid); | 1108 | escape_essid(ssid, ssid_len)); |
1157 | 1109 | ||
1158 | if (!ssid_len) | 1110 | if (!ssid_len) |
1159 | goto out; | 1111 | goto out; |
1160 | 1112 | ||
1161 | memset(&scancfg, 0x00, sizeof(scancfg)); | 1113 | memcpy(priv->scan_ssid, ssid, ssid_len); |
1162 | memcpy(scancfg.ssid, ssid, ssid_len); | 1114 | priv->scan_ssid_len = ssid_len; |
1163 | scancfg.ssid_len = ssid_len; | ||
1164 | scancfg.clear_ssid = clear_ssid; | ||
1165 | 1115 | ||
1166 | lbs_scan_networks(priv, &scancfg, 1); | 1116 | lbs_scan_networks(priv, 1); |
1167 | if (priv->surpriseremoved) { | 1117 | if (priv->surpriseremoved) { |
1168 | ret = -1; | 1118 | ret = -1; |
1169 | goto out; | 1119 | goto out; |
@@ -1187,17 +1137,17 @@ out: | |||
1187 | #define MAX_CUSTOM_LEN 64 | 1137 | #define MAX_CUSTOM_LEN 64 |
1188 | 1138 | ||
1189 | static inline char *lbs_translate_scan(struct lbs_private *priv, | 1139 | static inline char *lbs_translate_scan(struct lbs_private *priv, |
1190 | char *start, char *stop, | 1140 | char *start, char *stop, |
1191 | struct bss_descriptor *bss) | 1141 | struct bss_descriptor *bss) |
1192 | { | 1142 | { |
1193 | struct chan_freq_power *cfp; | 1143 | struct chan_freq_power *cfp; |
1194 | char *current_val; /* For rates */ | 1144 | char *current_val; /* For rates */ |
1195 | struct iw_event iwe; /* Temporary buffer */ | 1145 | struct iw_event iwe; /* Temporary buffer */ |
1196 | int j; | 1146 | int j; |
1197 | #define PERFECT_RSSI ((u8)50) | 1147 | #define PERFECT_RSSI ((uint8_t)50) |
1198 | #define WORST_RSSI ((u8)0) | 1148 | #define WORST_RSSI ((uint8_t)0) |
1199 | #define RSSI_DIFF ((u8)(PERFECT_RSSI - WORST_RSSI)) | 1149 | #define RSSI_DIFF ((uint8_t)(PERFECT_RSSI - WORST_RSSI)) |
1200 | u8 rssi; | 1150 | uint8_t rssi; |
1201 | 1151 | ||
1202 | lbs_deb_enter(LBS_DEB_SCAN); | 1152 | lbs_deb_enter(LBS_DEB_SCAN); |
1203 | 1153 | ||
@@ -1217,7 +1167,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, | |||
1217 | /* SSID */ | 1167 | /* SSID */ |
1218 | iwe.cmd = SIOCGIWESSID; | 1168 | iwe.cmd = SIOCGIWESSID; |
1219 | iwe.u.data.flags = 1; | 1169 | iwe.u.data.flags = 1; |
1220 | iwe.u.data.length = min((u32) bss->ssid_len, (u32) IW_ESSID_MAX_SIZE); | 1170 | iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IW_ESSID_MAX_SIZE); |
1221 | start = iwe_stream_add_point(start, stop, &iwe, bss->ssid); | 1171 | start = iwe_stream_add_point(start, stop, &iwe, bss->ssid); |
1222 | 1172 | ||
1223 | /* Mode */ | 1173 | /* Mode */ |
@@ -1238,28 +1188,26 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, | |||
1238 | 1188 | ||
1239 | rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE; | 1189 | rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE; |
1240 | iwe.u.qual.qual = | 1190 | iwe.u.qual.qual = |
1241 | (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) * | 1191 | (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) * |
1242 | (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) / | 1192 | (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) / |
1243 | (RSSI_DIFF * RSSI_DIFF); | 1193 | (RSSI_DIFF * RSSI_DIFF); |
1244 | if (iwe.u.qual.qual > 100) | 1194 | if (iwe.u.qual.qual > 100) |
1245 | iwe.u.qual.qual = 100; | 1195 | iwe.u.qual.qual = 100; |
1246 | 1196 | ||
1247 | if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) { | 1197 | if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) { |
1248 | iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE; | 1198 | iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE; |
1249 | } else { | 1199 | } else { |
1250 | iwe.u.qual.noise = | 1200 | iwe.u.qual.noise = CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]); |
1251 | CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]); | ||
1252 | } | 1201 | } |
1253 | 1202 | ||
1254 | /* Locally created ad-hoc BSSs won't have beacons if this is the | 1203 | /* Locally created ad-hoc BSSs won't have beacons if this is the |
1255 | * only station in the adhoc network; so get signal strength | 1204 | * only station in the adhoc network; so get signal strength |
1256 | * from receive statistics. | 1205 | * from receive statistics. |
1257 | */ | 1206 | */ |
1258 | if ((priv->mode == IW_MODE_ADHOC) | 1207 | if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate |
1259 | && priv->adhoccreate | ||
1260 | && !lbs_ssid_cmp(priv->curbssparams.ssid, | 1208 | && !lbs_ssid_cmp(priv->curbssparams.ssid, |
1261 | priv->curbssparams.ssid_len, | 1209 | priv->curbssparams.ssid_len, |
1262 | bss->ssid, bss->ssid_len)) { | 1210 | bss->ssid, bss->ssid_len)) { |
1263 | int snr, nf; | 1211 | int snr, nf; |
1264 | snr = priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; | 1212 | snr = priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; |
1265 | nf = priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; | 1213 | nf = priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; |
@@ -1290,14 +1238,13 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, | |||
1290 | current_val = iwe_stream_add_value(start, current_val, | 1238 | current_val = iwe_stream_add_value(start, current_val, |
1291 | stop, &iwe, IW_EV_PARAM_LEN); | 1239 | stop, &iwe, IW_EV_PARAM_LEN); |
1292 | } | 1240 | } |
1293 | if ((bss->mode == IW_MODE_ADHOC) | 1241 | if ((bss->mode == IW_MODE_ADHOC) && priv->adhoccreate |
1294 | && !lbs_ssid_cmp(priv->curbssparams.ssid, | 1242 | && !lbs_ssid_cmp(priv->curbssparams.ssid, |
1295 | priv->curbssparams.ssid_len, | 1243 | priv->curbssparams.ssid_len, |
1296 | bss->ssid, bss->ssid_len) | 1244 | bss->ssid, bss->ssid_len)) { |
1297 | && priv->adhoccreate) { | ||
1298 | iwe.u.bitrate.value = 22 * 500000; | 1245 | iwe.u.bitrate.value = 22 * 500000; |
1299 | current_val = iwe_stream_add_value(start, current_val, | 1246 | current_val = iwe_stream_add_value(start, current_val, |
1300 | stop, &iwe, IW_EV_PARAM_LEN); | 1247 | stop, &iwe, IW_EV_PARAM_LEN); |
1301 | } | 1248 | } |
1302 | /* Check if we added any event */ | 1249 | /* Check if we added any event */ |
1303 | if((current_val - start) > IW_EV_LCP_LEN) | 1250 | if((current_val - start) > IW_EV_LCP_LEN) |
@@ -1326,8 +1273,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, | |||
1326 | char *p = custom; | 1273 | char *p = custom; |
1327 | 1274 | ||
1328 | iwe.cmd = IWEVCUSTOM; | 1275 | iwe.cmd = IWEVCUSTOM; |
1329 | p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), | 1276 | p += snprintf(p, MAX_CUSTOM_LEN, "mesh-type: olpc"); |
1330 | "mesh-type: olpc"); | ||
1331 | iwe.u.data.length = p - custom; | 1277 | iwe.u.data.length = p - custom; |
1332 | if (iwe.u.data.length) | 1278 | if (iwe.u.data.length) |
1333 | start = iwe_stream_add_point(start, stop, &iwe, custom); | 1279 | start = iwe_stream_add_point(start, stop, &iwe, custom); |
@@ -1350,39 +1296,49 @@ out: | |||
1350 | * @return 0 --success, otherwise fail | 1296 | * @return 0 --success, otherwise fail |
1351 | */ | 1297 | */ |
1352 | int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, | 1298 | int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, |
1353 | struct iw_param *wrqu, char *extra) | 1299 | union iwreq_data *wrqu, char *extra) |
1354 | { | 1300 | { |
1355 | struct lbs_private *priv = dev->priv; | 1301 | struct lbs_private *priv = dev->priv; |
1302 | int ret = 0; | ||
1356 | 1303 | ||
1357 | lbs_deb_enter(LBS_DEB_SCAN); | 1304 | lbs_deb_enter(LBS_DEB_WEXT); |
1358 | 1305 | ||
1359 | if (!netif_running(dev)) | 1306 | if (!netif_running(dev)) { |
1360 | return -ENETDOWN; | 1307 | ret = -ENETDOWN; |
1308 | goto out; | ||
1309 | } | ||
1361 | 1310 | ||
1362 | /* mac80211 does this: | 1311 | /* mac80211 does this: |
1363 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1312 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1364 | if (sdata->type != IEEE80211_IF_TYPE_xxx) | 1313 | if (sdata->type != IEEE80211_IF_TYPE_xxx) { |
1365 | return -EOPNOTSUPP; | 1314 | ret = -EOPNOTSUPP; |
1315 | goto out; | ||
1316 | } | ||
1317 | */ | ||
1366 | 1318 | ||
1367 | if (wrqu->data.length == sizeof(struct iw_scan_req) && | 1319 | if (wrqu->data.length == sizeof(struct iw_scan_req) && |
1368 | wrqu->data.flags & IW_SCAN_THIS_ESSID) { | 1320 | wrqu->data.flags & IW_SCAN_THIS_ESSID) { |
1369 | req = (struct iw_scan_req *)extra; | 1321 | struct iw_scan_req *req = (struct iw_scan_req *)extra; |
1370 | ssid = req->essid; | 1322 | priv->scan_ssid_len = req->essid_len; |
1371 | ssid_len = req->essid_len; | 1323 | memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len); |
1324 | lbs_deb_wext("set_scan, essid '%s'\n", | ||
1325 | escape_essid(priv->scan_ssid, priv->scan_ssid_len)); | ||
1326 | } else { | ||
1327 | priv->scan_ssid_len = 0; | ||
1372 | } | 1328 | } |
1373 | */ | ||
1374 | 1329 | ||
1375 | if (!delayed_work_pending(&priv->scan_work)) | 1330 | if (!delayed_work_pending(&priv->scan_work)) |
1376 | queue_delayed_work(priv->work_thread, &priv->scan_work, | 1331 | queue_delayed_work(priv->work_thread, &priv->scan_work, |
1377 | msecs_to_jiffies(50)); | 1332 | msecs_to_jiffies(50)); |
1378 | /* set marker that currently a scan is taking place */ | 1333 | /* set marker that currently a scan is taking place */ |
1379 | priv->last_scanned_channel = -1; | 1334 | priv->scan_channel = -1; |
1380 | 1335 | ||
1381 | if (priv->surpriseremoved) | 1336 | if (priv->surpriseremoved) |
1382 | return -EIO; | 1337 | ret = -EIO; |
1383 | 1338 | ||
1384 | lbs_deb_leave(LBS_DEB_SCAN); | 1339 | out: |
1385 | return 0; | 1340 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); |
1341 | return ret; | ||
1386 | } | 1342 | } |
1387 | 1343 | ||
1388 | 1344 | ||
@@ -1397,31 +1353,30 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, | |||
1397 | * @return 0 --success, otherwise fail | 1353 | * @return 0 --success, otherwise fail |
1398 | */ | 1354 | */ |
1399 | int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | 1355 | int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, |
1400 | struct iw_point *dwrq, char *extra) | 1356 | struct iw_point *dwrq, char *extra) |
1401 | { | 1357 | { |
1402 | #define SCAN_ITEM_SIZE 128 | 1358 | #define SCAN_ITEM_SIZE 128 |
1403 | struct lbs_private *priv = dev->priv; | 1359 | struct lbs_private *priv = dev->priv; |
1404 | int err = 0; | 1360 | int err = 0; |
1405 | char *ev = extra; | 1361 | char *ev = extra; |
1406 | char *stop = ev + dwrq->length; | 1362 | char *stop = ev + dwrq->length; |
1407 | struct bss_descriptor * iter_bss; | 1363 | struct bss_descriptor *iter_bss; |
1408 | struct bss_descriptor * safe; | 1364 | struct bss_descriptor *safe; |
1409 | 1365 | ||
1410 | lbs_deb_enter(LBS_DEB_SCAN); | 1366 | lbs_deb_enter(LBS_DEB_WEXT); |
1411 | 1367 | ||
1412 | /* iwlist should wait until the current scan is finished */ | 1368 | /* iwlist should wait until the current scan is finished */ |
1413 | if (priv->last_scanned_channel) | 1369 | if (priv->scan_channel) |
1414 | return -EAGAIN; | 1370 | return -EAGAIN; |
1415 | 1371 | ||
1416 | /* Update RSSI if current BSS is a locally created ad-hoc BSS */ | 1372 | /* Update RSSI if current BSS is a locally created ad-hoc BSS */ |
1417 | if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) { | 1373 | if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) |
1418 | lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, | 1374 | lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, |
1419 | CMD_OPTION_WAITFORRSP, 0, NULL); | 1375 | CMD_OPTION_WAITFORRSP, 0, NULL); |
1420 | } | ||
1421 | 1376 | ||
1422 | mutex_lock(&priv->lock); | 1377 | mutex_lock(&priv->lock); |
1423 | list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) { | 1378 | list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) { |
1424 | char * next_ev; | 1379 | char *next_ev; |
1425 | unsigned long stale_time; | 1380 | unsigned long stale_time; |
1426 | 1381 | ||
1427 | if (stop - ev < SCAN_ITEM_SIZE) { | 1382 | if (stop - ev < SCAN_ITEM_SIZE) { |
@@ -1436,8 +1391,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
1436 | /* Prune old an old scan result */ | 1391 | /* Prune old an old scan result */ |
1437 | stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE; | 1392 | stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE; |
1438 | if (time_after(jiffies, stale_time)) { | 1393 | if (time_after(jiffies, stale_time)) { |
1439 | list_move_tail (&iter_bss->list, | 1394 | list_move_tail(&iter_bss->list, &priv->network_free_list); |
1440 | &priv->network_free_list); | ||
1441 | clear_bss_descriptor(iter_bss); | 1395 | clear_bss_descriptor(iter_bss); |
1442 | continue; | 1396 | continue; |
1443 | } | 1397 | } |
@@ -1453,7 +1407,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
1453 | dwrq->length = (ev - extra); | 1407 | dwrq->length = (ev - extra); |
1454 | dwrq->flags = 0; | 1408 | dwrq->flags = 0; |
1455 | 1409 | ||
1456 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", err); | 1410 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err); |
1457 | return err; | 1411 | return err; |
1458 | } | 1412 | } |
1459 | 1413 | ||
@@ -1468,44 +1422,6 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
1468 | 1422 | ||
1469 | 1423 | ||
1470 | /** | 1424 | /** |
1471 | * @brief Prepare a scan command to be sent to the firmware | ||
1472 | * | ||
1473 | * Called via lbs_prepare_and_send_command(priv, CMD_802_11_SCAN, ...) | ||
1474 | * from cmd.c | ||
1475 | * | ||
1476 | * Sends a fixed length data part (specifying the BSS type and BSSID filters) | ||
1477 | * as well as a variable number/length of TLVs to the firmware. | ||
1478 | * | ||
1479 | * @param priv A pointer to struct lbs_private structure | ||
1480 | * @param cmd A pointer to cmd_ds_command structure to be sent to | ||
1481 | * firmware with the cmd_DS_801_11_SCAN structure | ||
1482 | * @param pdata_buf Void pointer cast of a lbs_scan_cmd_config struct used | ||
1483 | * to set the fields/TLVs for the command sent to firmware | ||
1484 | * | ||
1485 | * @return 0 or -1 | ||
1486 | */ | ||
1487 | int lbs_cmd_80211_scan(struct lbs_private *priv, | ||
1488 | struct cmd_ds_command *cmd, void *pdata_buf) | ||
1489 | { | ||
1490 | struct cmd_ds_802_11_scan *pscan = &cmd->params.scan; | ||
1491 | struct lbs_scan_cmd_config *pscancfg = pdata_buf; | ||
1492 | |||
1493 | lbs_deb_enter(LBS_DEB_SCAN); | ||
1494 | |||
1495 | /* Set fixed field variables in scan command */ | ||
1496 | pscan->bsstype = pscancfg->bsstype; | ||
1497 | memcpy(pscan->bssid, pscancfg->bssid, ETH_ALEN); | ||
1498 | memcpy(pscan->tlvbuffer, pscancfg->tlvbuffer, pscancfg->tlvbufferlen); | ||
1499 | |||
1500 | /* size is equal to the sizeof(fixed portions) + the TLV len + header */ | ||
1501 | cmd->size = cpu_to_le16(sizeof(pscan->bsstype) + ETH_ALEN | ||
1502 | + pscancfg->tlvbufferlen + S_DS_GEN); | ||
1503 | |||
1504 | lbs_deb_leave(LBS_DEB_SCAN); | ||
1505 | return 0; | ||
1506 | } | ||
1507 | |||
1508 | /** | ||
1509 | * @brief This function handles the command response of scan | 1425 | * @brief This function handles the command response of scan |
1510 | * | 1426 | * |
1511 | * Called from handle_cmd_response() in cmdrespc. | 1427 | * Called from handle_cmd_response() in cmdrespc. |
@@ -1531,13 +1447,14 @@ int lbs_cmd_80211_scan(struct lbs_private *priv, | |||
1531 | * | 1447 | * |
1532 | * @return 0 or -1 | 1448 | * @return 0 or -1 |
1533 | */ | 1449 | */ |
1534 | int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp) | 1450 | static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy, |
1451 | struct cmd_header *resp) | ||
1535 | { | 1452 | { |
1536 | struct cmd_ds_802_11_scan_rsp *pscan; | 1453 | struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp; |
1537 | struct bss_descriptor * iter_bss; | 1454 | struct bss_descriptor *iter_bss; |
1538 | struct bss_descriptor * safe; | 1455 | struct bss_descriptor *safe; |
1539 | u8 *pbssinfo; | 1456 | uint8_t *bssinfo; |
1540 | u16 scanrespsize; | 1457 | uint16_t scanrespsize; |
1541 | int bytesleft; | 1458 | int bytesleft; |
1542 | int idx; | 1459 | int idx; |
1543 | int tlvbufsize; | 1460 | int tlvbufsize; |
@@ -1554,48 +1471,45 @@ int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp) | |||
1554 | clear_bss_descriptor(iter_bss); | 1471 | clear_bss_descriptor(iter_bss); |
1555 | } | 1472 | } |
1556 | 1473 | ||
1557 | pscan = &resp->params.scanresp; | 1474 | if (scanresp->nr_sets > MAX_NETWORK_COUNT) { |
1558 | 1475 | lbs_deb_scan("SCAN_RESP: too many scan results (%d, max %d)\n", | |
1559 | if (pscan->nr_sets > MAX_NETWORK_COUNT) { | 1476 | scanresp->nr_sets, MAX_NETWORK_COUNT); |
1560 | lbs_deb_scan( | ||
1561 | "SCAN_RESP: too many scan results (%d, max %d)!!\n", | ||
1562 | pscan->nr_sets, MAX_NETWORK_COUNT); | ||
1563 | ret = -1; | 1477 | ret = -1; |
1564 | goto done; | 1478 | goto done; |
1565 | } | 1479 | } |
1566 | 1480 | ||
1567 | bytesleft = le16_to_cpu(pscan->bssdescriptsize); | 1481 | bytesleft = le16_to_cpu(scanresp->bssdescriptsize); |
1568 | lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft); | 1482 | lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft); |
1569 | 1483 | ||
1570 | scanrespsize = le16_to_cpu(resp->size); | 1484 | scanrespsize = le16_to_cpu(resp->size); |
1571 | lbs_deb_scan("SCAN_RESP: scan results %d\n", pscan->nr_sets); | 1485 | lbs_deb_scan("SCAN_RESP: scan results %d\n", scanresp->nr_sets); |
1572 | 1486 | ||
1573 | pbssinfo = pscan->bssdesc_and_tlvbuffer; | 1487 | bssinfo = scanresp->bssdesc_and_tlvbuffer; |
1574 | 1488 | ||
1575 | /* The size of the TLV buffer is equal to the entire command response | 1489 | /* The size of the TLV buffer is equal to the entire command response |
1576 | * size (scanrespsize) minus the fixed fields (sizeof()'s), the | 1490 | * size (scanrespsize) minus the fixed fields (sizeof()'s), the |
1577 | * BSS Descriptions (bssdescriptsize as bytesLef) and the command | 1491 | * BSS Descriptions (bssdescriptsize as bytesLef) and the command |
1578 | * response header (S_DS_GEN) | 1492 | * response header (S_DS_GEN) |
1579 | */ | 1493 | */ |
1580 | tlvbufsize = scanrespsize - (bytesleft + sizeof(pscan->bssdescriptsize) | 1494 | tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize) |
1581 | + sizeof(pscan->nr_sets) | 1495 | + sizeof(scanresp->nr_sets) |
1582 | + S_DS_GEN); | 1496 | + S_DS_GEN); |
1583 | 1497 | ||
1584 | /* | 1498 | /* |
1585 | * Process each scan response returned (pscan->nr_sets). Save | 1499 | * Process each scan response returned (scanresp->nr_sets). Save |
1586 | * the information in the newbssentry and then insert into the | 1500 | * the information in the newbssentry and then insert into the |
1587 | * driver scan table either as an update to an existing entry | 1501 | * driver scan table either as an update to an existing entry |
1588 | * or as an addition at the end of the table | 1502 | * or as an addition at the end of the table |
1589 | */ | 1503 | */ |
1590 | for (idx = 0; idx < pscan->nr_sets && bytesleft; idx++) { | 1504 | for (idx = 0; idx < scanresp->nr_sets && bytesleft; idx++) { |
1591 | struct bss_descriptor new; | 1505 | struct bss_descriptor new; |
1592 | struct bss_descriptor * found = NULL; | 1506 | struct bss_descriptor *found = NULL; |
1593 | struct bss_descriptor * oldest = NULL; | 1507 | struct bss_descriptor *oldest = NULL; |
1594 | DECLARE_MAC_BUF(mac); | 1508 | DECLARE_MAC_BUF(mac); |
1595 | 1509 | ||
1596 | /* Process the data fields and IEs returned for this BSS */ | 1510 | /* Process the data fields and IEs returned for this BSS */ |
1597 | memset(&new, 0, sizeof (struct bss_descriptor)); | 1511 | memset(&new, 0, sizeof (struct bss_descriptor)); |
1598 | if (lbs_process_bss(&new, &pbssinfo, &bytesleft) != 0) { | 1512 | if (lbs_process_bss(&new, &bssinfo, &bytesleft) != 0) { |
1599 | /* error parsing the scan response, skipped */ | 1513 | /* error parsing the scan response, skipped */ |
1600 | lbs_deb_scan("SCAN_RESP: process_bss returned ERROR\n"); | 1514 | lbs_deb_scan("SCAN_RESP: process_bss returned ERROR\n"); |
1601 | continue; | 1515 | continue; |
@@ -1630,8 +1544,7 @@ int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp) | |||
1630 | continue; | 1544 | continue; |
1631 | } | 1545 | } |
1632 | 1546 | ||
1633 | lbs_deb_scan("SCAN_RESP: BSSID %s\n", | 1547 | lbs_deb_scan("SCAN_RESP: BSSID %s\n", print_mac(mac, new.bssid)); |
1634 | print_mac(mac, new.bssid)); | ||
1635 | 1548 | ||
1636 | /* Copy the locally created newbssentry to the scan table */ | 1549 | /* Copy the locally created newbssentry to the scan table */ |
1637 | memcpy(found, &new, offsetof(struct bss_descriptor, list)); | 1550 | memcpy(found, &new, offsetof(struct bss_descriptor, list)); |