diff options
author | Holger Schurig <hs4233@mail.mn-solutions.de> | 2007-12-07 10:52:10 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:06:11 -0500 |
commit | ffd074fc78c1053b1f1697ebbe5bcfbb64949d16 (patch) | |
tree | 8021f4bad2ece20959f1d9d412ab71723df8a0ef /drivers/net | |
parent | 83eacf233e62349c8a7282616fedc602ee95a555 (diff) |
libertas: implement new scanning logic
This changes the code that is used for scanning and makes it hopefully
easier to understand:
* move function into logical blocks
* create a bunch of lbs_scan_add_XXXX_tlv() functions, that
help to create the TLV parameter of CMD_802_11_SCAN
* all of them are now called from the much simpler lbs_do_scan()
* no **puserscancfg double-pointers :-)
Signed-off-by: Holger Schurig <hs4233@mail.mn-solutions.de>
Acked-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/libertas/dev.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/scan.c | 871 |
2 files changed, 361 insertions, 513 deletions
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 1efea63c6691..96a34c5bce80 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -366,9 +366,8 @@ struct lbs_adapter { | |||
366 | struct cmd_ds_802_11_get_log logmsg; | 366 | struct cmd_ds_802_11_get_log logmsg; |
367 | 367 | ||
368 | u32 monitormode; | 368 | u32 monitormode; |
369 | int last_scanned_channel; | ||
369 | u8 fw_ready; | 370 | u8 fw_ready; |
370 | |||
371 | u8 last_scanned_channel; | ||
372 | }; | 371 | }; |
373 | 372 | ||
374 | #endif | 373 | #endif |
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 236bc7daf4de..90c18889b717 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c | |||
@@ -79,6 +79,22 @@ static inline void clear_bss_descriptor (struct bss_descriptor * bss) | |||
79 | memset(bss, 0, offsetof(struct bss_descriptor, list)); | 79 | memset(bss, 0, offsetof(struct bss_descriptor, list)); |
80 | } | 80 | } |
81 | 81 | ||
82 | /** | ||
83 | * @brief Compare two SSIDs | ||
84 | * | ||
85 | * @param ssid1 A pointer to ssid to compare | ||
86 | * @param ssid2 A pointer to ssid to compare | ||
87 | * | ||
88 | * @return 0: ssid is same, otherwise is different | ||
89 | */ | ||
90 | int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len) | ||
91 | { | ||
92 | if (ssid1_len != ssid2_len) | ||
93 | return -1; | ||
94 | |||
95 | return memcmp(ssid1, ssid2, ssid1_len); | ||
96 | } | ||
97 | |||
82 | static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, | 98 | static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, |
83 | struct bss_descriptor * match_bss) | 99 | struct bss_descriptor * match_bss) |
84 | { | 100 | { |
@@ -149,6 +165,18 @@ static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo, | |||
149 | return 0; | 165 | return 0; |
150 | } | 166 | } |
151 | 167 | ||
168 | static inline int is_same_network(struct bss_descriptor *src, | ||
169 | struct bss_descriptor *dst) | ||
170 | { | ||
171 | /* A network is only a duplicate if the channel, BSSID, and ESSID | ||
172 | * all match. We treat all <hidden> with the same BSSID and channel | ||
173 | * as one network */ | ||
174 | return ((src->ssid_len == dst->ssid_len) && | ||
175 | (src->channel == dst->channel) && | ||
176 | !compare_ether_addr(src->bssid, dst->bssid) && | ||
177 | !memcmp(src->ssid, dst->ssid, src->ssid_len)); | ||
178 | } | ||
179 | |||
152 | /** | 180 | /** |
153 | * @brief Check if a scanned network compatible with the driver settings | 181 | * @brief Check if a scanned network compatible with the driver settings |
154 | * | 182 | * |
@@ -184,9 +212,9 @@ static int is_network_compatible(struct lbs_adapter *adapter, | |||
184 | goto done; | 212 | goto done; |
185 | } else if ((matched = match_bss_wpa(&adapter->secinfo, bss))) { | 213 | } else if ((matched = match_bss_wpa(&adapter->secinfo, bss))) { |
186 | lbs_deb_scan( | 214 | lbs_deb_scan( |
187 | "is_network_compatible() WPA: wpa_ie=%#x " | 215 | "is_network_compatible() WPA: wpa_ie 0x%x " |
188 | "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s " | 216 | "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " |
189 | "privacy=%#x\n", bss->wpa_ie[0], bss->rsn_ie[0], | 217 | "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], |
190 | adapter->secinfo.wep_enabled ? "e" : "d", | 218 | adapter->secinfo.wep_enabled ? "e" : "d", |
191 | adapter->secinfo.WPAenabled ? "e" : "d", | 219 | adapter->secinfo.WPAenabled ? "e" : "d", |
192 | adapter->secinfo.WPA2enabled ? "e" : "d", | 220 | adapter->secinfo.WPA2enabled ? "e" : "d", |
@@ -194,9 +222,9 @@ static int is_network_compatible(struct lbs_adapter *adapter, | |||
194 | goto done; | 222 | goto done; |
195 | } else if ((matched = match_bss_wpa2(&adapter->secinfo, bss))) { | 223 | } else if ((matched = match_bss_wpa2(&adapter->secinfo, bss))) { |
196 | lbs_deb_scan( | 224 | lbs_deb_scan( |
197 | "is_network_compatible() WPA2: wpa_ie=%#x " | 225 | "is_network_compatible() WPA2: wpa_ie 0x%x " |
198 | "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s " | 226 | "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " |
199 | "privacy=%#x\n", bss->wpa_ie[0], bss->rsn_ie[0], | 227 | "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], |
200 | adapter->secinfo.wep_enabled ? "e" : "d", | 228 | adapter->secinfo.wep_enabled ? "e" : "d", |
201 | adapter->secinfo.WPAenabled ? "e" : "d", | 229 | adapter->secinfo.WPAenabled ? "e" : "d", |
202 | adapter->secinfo.WPA2enabled ? "e" : "d", | 230 | adapter->secinfo.WPA2enabled ? "e" : "d", |
@@ -205,7 +233,7 @@ static int is_network_compatible(struct lbs_adapter *adapter, | |||
205 | } else if ((matched = match_bss_dynamic_wep(&adapter->secinfo, bss))) { | 233 | } else if ((matched = match_bss_dynamic_wep(&adapter->secinfo, bss))) { |
206 | lbs_deb_scan( | 234 | lbs_deb_scan( |
207 | "is_network_compatible() dynamic WEP: " | 235 | "is_network_compatible() dynamic WEP: " |
208 | "wpa_ie=%#x wpa2_ie=%#x privacy=%#x\n", | 236 | "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n", |
209 | bss->wpa_ie[0], bss->rsn_ie[0], | 237 | bss->wpa_ie[0], bss->rsn_ie[0], |
210 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); | 238 | (bss->capability & WLAN_CAPABILITY_PRIVACY)); |
211 | goto done; | 239 | goto done; |
@@ -213,8 +241,8 @@ static int is_network_compatible(struct lbs_adapter *adapter, | |||
213 | 241 | ||
214 | /* bss security settings don't match those configured on card */ | 242 | /* bss security settings don't match those configured on card */ |
215 | lbs_deb_scan( | 243 | lbs_deb_scan( |
216 | "is_network_compatible() FAILED: wpa_ie=%#x " | 244 | "is_network_compatible() FAILED: wpa_ie 0x%x " |
217 | "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s privacy=%#x\n", | 245 | "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n", |
218 | bss->wpa_ie[0], bss->rsn_ie[0], | 246 | bss->wpa_ie[0], bss->rsn_ie[0], |
219 | adapter->secinfo.wep_enabled ? "e" : "d", | 247 | adapter->secinfo.wep_enabled ? "e" : "d", |
220 | adapter->secinfo.WPAenabled ? "e" : "d", | 248 | adapter->secinfo.WPAenabled ? "e" : "d", |
@@ -226,22 +254,6 @@ done: | |||
226 | return matched; | 254 | return matched; |
227 | } | 255 | } |
228 | 256 | ||
229 | /** | ||
230 | * @brief Compare two SSIDs | ||
231 | * | ||
232 | * @param ssid1 A pointer to ssid to compare | ||
233 | * @param ssid2 A pointer to ssid to compare | ||
234 | * | ||
235 | * @return 0--ssid is same, otherwise is different | ||
236 | */ | ||
237 | int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len) | ||
238 | { | ||
239 | if (ssid1_len != ssid2_len) | ||
240 | return -1; | ||
241 | |||
242 | return memcmp(ssid1, ssid2, ssid1_len); | ||
243 | } | ||
244 | |||
245 | 257 | ||
246 | 258 | ||
247 | 259 | ||
@@ -251,6 +263,16 @@ int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len) | |||
251 | /* */ | 263 | /* */ |
252 | /*********************************************************************/ | 264 | /*********************************************************************/ |
253 | 265 | ||
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 | |||
254 | 276 | ||
255 | /** | 277 | /** |
256 | * @brief Create a channel list for the driver to scan based on region info | 278 | * @brief Create a channel list for the driver to scan based on region info |
@@ -271,7 +293,7 @@ int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len) | |||
271 | * | 293 | * |
272 | * @return void | 294 | * @return void |
273 | */ | 295 | */ |
274 | static void lbs_scan_create_channel_list(struct lbs_private *priv, | 296 | static int lbs_scan_create_channel_list(struct lbs_private *priv, |
275 | struct chanscanparamset * scanchanlist, | 297 | struct chanscanparamset * scanchanlist, |
276 | u8 filteredscan) | 298 | u8 filteredscan) |
277 | { | 299 | { |
@@ -284,8 +306,6 @@ static void lbs_scan_create_channel_list(struct lbs_private *priv, | |||
284 | int nextchan; | 306 | int nextchan; |
285 | u8 scantype; | 307 | u8 scantype; |
286 | 308 | ||
287 | lbs_deb_enter_args(LBS_DEB_SCAN, "filteredscan %d", filteredscan); | ||
288 | |||
289 | chanidx = 0; | 309 | chanidx = 0; |
290 | 310 | ||
291 | /* Set the default scan type to the user specified type, will later | 311 | /* Set the default scan type to the user specified type, will later |
@@ -353,383 +373,151 @@ static void lbs_scan_create_channel_list(struct lbs_private *priv, | |||
353 | } | 373 | } |
354 | } | 374 | } |
355 | } | 375 | } |
376 | return chanidx; | ||
356 | } | 377 | } |
357 | 378 | ||
358 | 379 | ||
359 | /* Delayed partial scan worker */ | 380 | /* |
360 | void lbs_scan_worker(struct work_struct *work) | 381 | * Add SSID TLV of the form: |
382 | * | ||
383 | * TLV-ID SSID 00 00 | ||
384 | * length 06 00 | ||
385 | * ssid 4d 4e 54 45 53 54 | ||
386 | */ | ||
387 | static int lbs_scan_add_ssid_tlv(u8 *tlv, | ||
388 | const struct lbs_ioctl_user_scan_cfg *user_cfg) | ||
361 | { | 389 | { |
362 | struct lbs_private *priv = container_of(work, | 390 | struct mrvlietypes_ssidparamset *ssid_tlv = |
363 | struct lbs_private, | 391 | (struct mrvlietypes_ssidparamset *)tlv; |
364 | scan_work.work); | 392 | ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID); |
365 | 393 | ssid_tlv->header.len = cpu_to_le16(user_cfg->ssid_len); | |
366 | lbs_scan_networks(priv, NULL, 0); | 394 | memcpy(ssid_tlv->ssid, user_cfg->ssid, user_cfg->ssid_len); |
395 | return sizeof(ssid_tlv->header) + user_cfg->ssid_len; | ||
367 | } | 396 | } |
368 | 397 | ||
369 | 398 | ||
370 | /** | 399 | /* |
371 | * @brief Construct a lbs_scan_cmd_config structure to use in issue scan cmds | 400 | * Add CHANLIST TLV of the form |
372 | * | ||
373 | * Application layer or other functions can invoke lbs_scan_networks | ||
374 | * with a scan configuration supplied in a lbs_ioctl_user_scan_cfg struct. | ||
375 | * This structure is used as the basis of one or many lbs_scan_cmd_config | ||
376 | * commands that are sent to the command processing module and sent to | ||
377 | * firmware. | ||
378 | * | ||
379 | * Create a lbs_scan_cmd_config based on the following user supplied | ||
380 | * parameters (if present): | ||
381 | * - SSID filter | ||
382 | * - BSSID filter | ||
383 | * - Number of Probes to be sent | ||
384 | * - channel list | ||
385 | * | ||
386 | * If the SSID or BSSID filter is not present, disable/clear the filter. | ||
387 | * Qualify the channel | ||
388 | * | 401 | * |
389 | * @param priv A pointer to struct lbs_private structure | 402 | * TLV-ID CHANLIST 01 01 |
390 | * @param puserscanin NULL or pointer to scan configuration parameters | 403 | * length 5b 00 |
391 | * @param ppchantlvout Output parameter: Pointer to the start of the | 404 | * channel 1 00 01 00 00 00 64 00 |
392 | * channel TLV portion of the output scan config | 405 | * radio type 00 |
393 | * @param pscanchanlist Output parameter: Pointer to the resulting channel | 406 | * channel 01 |
394 | * list to scan | 407 | * scan type 00 |
395 | * @param pmaxchanperscan Output parameter: Number of channels to scan for | 408 | * min scan time 00 00 |
396 | * each issuance of the firmware scan command | 409 | * max scan time 64 00 |
397 | * @param pfilteredscan Output parameter: Flag indicating whether or not | 410 | * channel 2 00 02 00 00 00 64 00 |
398 | * a BSSID or SSID filter is being sent in the | 411 | * channel 3 00 03 00 00 00 64 00 |
399 | * command to firmware. Used to increase the number | 412 | * channel 4 00 04 00 00 00 64 00 |
400 | * of channels sent in a scan command and to | 413 | * channel 5 00 05 00 00 00 64 00 |
401 | * disable the firmware channel scan filter. | 414 | * channel 6 00 06 00 00 00 64 00 |
402 | * @param pscancurrentonly Output parameter: Flag indicating whether or not | 415 | * channel 7 00 07 00 00 00 64 00 |
403 | * we are only scanning our current active channel | 416 | * channel 8 00 08 00 00 00 64 00 |
417 | * channel 9 00 09 00 00 00 64 00 | ||
418 | * channel 10 00 0a 00 00 00 64 00 | ||
419 | * channel 11 00 0b 00 00 00 64 00 | ||
420 | * channel 12 00 0c 00 00 00 64 00 | ||
421 | * channel 13 00 0d 00 00 00 64 00 | ||
404 | * | 422 | * |
405 | * @return resulting scan configuration | ||
406 | */ | 423 | */ |
407 | static struct lbs_scan_cmd_config * | 424 | static int lbs_scan_add_chanlist_tlv(u8 *tlv, |
408 | lbs_scan_setup_scan_config(struct lbs_private *priv, | 425 | struct chanscanparamset *chan_list, |
409 | const struct lbs_ioctl_user_scan_cfg *puserscanin, | 426 | int chan_count) |
410 | struct mrvlietypes_chanlistparamset ** ppchantlvout, | ||
411 | struct chanscanparamset * pscanchanlist, | ||
412 | int *pmaxchanperscan, | ||
413 | u8 * pfilteredscan, | ||
414 | u8 * pscancurrentonly) | ||
415 | { | 427 | { |
416 | struct mrvlietypes_ssidparamset *pssidtlv; | 428 | size_t size = sizeof(struct chanscanparamset) * chan_count; |
417 | struct lbs_scan_cmd_config *pscancfgout = NULL; | 429 | struct mrvlietypes_chanlistparamset *chan_tlv = |
418 | u8 *ptlvpos; | 430 | (struct mrvlietypes_chanlistparamset *) tlv; |
419 | 431 | ||
420 | lbs_deb_enter(LBS_DEB_SCAN); | 432 | chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); |
421 | 433 | memcpy(chan_tlv->chanscanparam, chan_list, size); | |
422 | pscancfgout = kzalloc(MAX_SCAN_CFG_ALLOC, GFP_KERNEL); | 434 | chan_tlv->header.len = cpu_to_le16(size); |
423 | if (pscancfgout == NULL) | 435 | return sizeof(chan_tlv->header) + size; |
424 | goto out; | ||
425 | |||
426 | /* The tlvbufferlen is calculated for each scan command. The TLVs added | ||
427 | * in this routine will be preserved since the routine that sends | ||
428 | * the command will append channelTLVs at *ppchantlvout. The difference | ||
429 | * between the *ppchantlvout and the tlvbuffer start will be used | ||
430 | * to calculate the size of anything we add in this routine. | ||
431 | */ | ||
432 | pscancfgout->tlvbufferlen = 0; | ||
433 | |||
434 | /* Running tlv pointer. Assigned to ppchantlvout at end of function | ||
435 | * so later routines know where channels can be added to the command buf | ||
436 | */ | ||
437 | ptlvpos = pscancfgout->tlvbuffer; | ||
438 | |||
439 | /* | ||
440 | * Set the initial scan paramters for progressive scanning. If a specific | ||
441 | * BSSID or SSID is used, the number of channels in the scan command | ||
442 | * will be increased to the absolute maximum | ||
443 | */ | ||
444 | *pmaxchanperscan = MRVDRV_CHANNELS_PER_SCAN_CMD; | ||
445 | |||
446 | /* Initialize the scan as un-filtered by firmware, set to TRUE below if | ||
447 | * a SSID or BSSID filter is sent in the command | ||
448 | */ | ||
449 | *pfilteredscan = 0; | ||
450 | |||
451 | /* Initialize the scan as not being only on the current channel. If | ||
452 | * the channel list is customized, only contains one channel, and | ||
453 | * is the active channel, this is set true and data flow is not halted. | ||
454 | */ | ||
455 | *pscancurrentonly = 0; | ||
456 | |||
457 | if (puserscanin) { | ||
458 | /* Set the bss type scan filter, use adapter setting if unset */ | ||
459 | pscancfgout->bsstype = | ||
460 | puserscanin->bsstype ? puserscanin->bsstype : CMD_BSS_TYPE_ANY; | ||
461 | |||
462 | /* | ||
463 | * Set the BSSID filter to the incoming configuration, | ||
464 | * if non-zero. If not set, it will remain disabled (all zeros). | ||
465 | */ | ||
466 | memcpy(pscancfgout->bssid, puserscanin->bssid, | ||
467 | sizeof(pscancfgout->bssid)); | ||
468 | |||
469 | if (puserscanin->ssid_len) { | ||
470 | pssidtlv = | ||
471 | (struct mrvlietypes_ssidparamset *) pscancfgout-> | ||
472 | tlvbuffer; | ||
473 | pssidtlv->header.type = cpu_to_le16(TLV_TYPE_SSID); | ||
474 | pssidtlv->header.len = cpu_to_le16(puserscanin->ssid_len); | ||
475 | memcpy(pssidtlv->ssid, puserscanin->ssid, | ||
476 | puserscanin->ssid_len); | ||
477 | ptlvpos += sizeof(pssidtlv->header) + puserscanin->ssid_len; | ||
478 | } | ||
479 | |||
480 | /* | ||
481 | * The default number of channels sent in the command is low to | ||
482 | * ensure the response buffer from the firmware does not truncate | ||
483 | * scan results. That is not an issue with an SSID or BSSID | ||
484 | * filter applied to the scan results in the firmware. | ||
485 | */ | ||
486 | if ( puserscanin->ssid_len | ||
487 | || (compare_ether_addr(pscancfgout->bssid, &zeromac[0]) != 0)) { | ||
488 | *pmaxchanperscan = MRVDRV_MAX_CHANNELS_PER_SCAN; | ||
489 | *pfilteredscan = 1; | ||
490 | } | ||
491 | } else { | ||
492 | pscancfgout->bsstype = CMD_BSS_TYPE_ANY; | ||
493 | } | ||
494 | |||
495 | /* | ||
496 | * Set the output for the channel TLV to the address in the tlv buffer | ||
497 | * past any TLVs that were added in this fuction (SSID). | ||
498 | * channel TLVs will be added past this for each scan command, preserving | ||
499 | * the TLVs that were previously added. | ||
500 | */ | ||
501 | *ppchantlvout = (struct mrvlietypes_chanlistparamset *) ptlvpos; | ||
502 | |||
503 | lbs_scan_create_channel_list(priv, pscanchanlist, | ||
504 | *pfilteredscan); | ||
505 | out: | ||
506 | return pscancfgout; | ||
507 | } | 436 | } |
508 | 437 | ||
509 | /** | 438 | |
510 | * @brief Construct and send multiple scan config commands to the firmware | 439 | /* |
511 | * | 440 | * Add RATES TLV of the form |
512 | * Only used from lbs_scan_networks() | ||
513 | * | ||
514 | * Previous routines have created a lbs_scan_cmd_config with any requested | ||
515 | * TLVs. This function splits the channel TLV into maxchanperscan lists | ||
516 | * and sends the portion of the channel TLV along with the other TLVs | ||
517 | * to the lbs_cmd routines for execution in the firmware. | ||
518 | * | 441 | * |
519 | * @param priv A pointer to struct lbs_private structure | 442 | * TLV-ID RATES 01 00 |
520 | * @param maxchanperscan Maximum number channels to be included in each | 443 | * length 0e 00 |
521 | * scan command sent to firmware | 444 | * rates 82 84 8b 96 0c 12 18 24 30 48 60 6c |
522 | * @param filteredscan Flag indicating whether or not a BSSID or SSID | ||
523 | * filter is being used for the firmware command | ||
524 | * scan command sent to firmware | ||
525 | * @param pscancfgout Scan configuration used for this scan. | ||
526 | * @param pchantlvout Pointer in the pscancfgout where the channel TLV | ||
527 | * should start. This is past any other TLVs that | ||
528 | * must be sent down in each firmware command. | ||
529 | * @param pscanchanlist List of channels to scan in maxchanperscan segments | ||
530 | * | 445 | * |
531 | * @return 0 or error return otherwise | 446 | * The rates are in lbs_bg_rates[], but for the 802.11b |
447 | * rates the high bit isn't set. | ||
532 | */ | 448 | */ |
533 | static int lbs_scan_channel_list(struct lbs_private *priv, | 449 | static int lbs_scan_add_rates_tlv(u8 *tlv) |
534 | int maxchanperscan, | ||
535 | u8 filteredscan, | ||
536 | struct lbs_scan_cmd_config *pscancfgout, | ||
537 | struct mrvlietypes_chanlistparamset * pchantlvout, | ||
538 | struct chanscanparamset * pscanchanlist, | ||
539 | const struct lbs_ioctl_user_scan_cfg *puserscanin, | ||
540 | int full_scan) | ||
541 | { | 450 | { |
542 | struct chanscanparamset *ptmpchan; | 451 | int i; |
543 | struct chanscanparamset *pstartchan; | 452 | struct mrvlietypes_ratesparamset *rate_tlv = |
544 | u8 scanband; | 453 | (struct mrvlietypes_ratesparamset *) tlv; |
545 | int doneearly; | 454 | |
546 | int tlvidx; | 455 | rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES); |
547 | int ret = 0; | 456 | tlv += sizeof(rate_tlv->header); |
548 | int scanned = 0; | 457 | for (i = 0; i < MAX_RATES; i++) { |
549 | union iwreq_data wrqu; | 458 | *tlv = lbs_bg_rates[i]; |
550 | 459 | if (*tlv == 0) | |
551 | lbs_deb_enter_args(LBS_DEB_SCAN, "maxchanperscan %d, filteredscan %d, " | 460 | break; |
552 | "full_scan %d", maxchanperscan, filteredscan, full_scan); | 461 | /* This code makes sure that the 802.11b rates (1 MBit/s, 2 |
553 | 462 | MBit/s, 5.5 MBit/s and 11 MBit/s get's the high bit set. | |
554 | if (!pscancfgout || !pchantlvout || !pscanchanlist) { | 463 | Note that the values are MBit/s * 2, to mark them as |
555 | lbs_deb_scan("pscancfgout, pchantlvout or " | 464 | basic rates so that the firmware likes it better */ |
556 | "pscanchanlist is NULL\n"); | 465 | if (*tlv == 0x02 || *tlv == 0x04 || |
557 | ret = -1; | 466 | *tlv == 0x0b || *tlv == 0x16) |
558 | goto out; | 467 | *tlv |= 0x80; |
559 | } | 468 | tlv++; |
560 | |||
561 | pchantlvout->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); | ||
562 | |||
563 | /* Set the temp channel struct pointer to the start of the desired list */ | ||
564 | ptmpchan = pscanchanlist; | ||
565 | |||
566 | if (priv->adapter->last_scanned_channel && !puserscanin) | ||
567 | ptmpchan += priv->adapter->last_scanned_channel; | ||
568 | |||
569 | /* Loop through the desired channel list, sending a new firmware scan | ||
570 | * commands for each maxchanperscan channels (or for 1,6,11 individually | ||
571 | * if configured accordingly) | ||
572 | */ | ||
573 | while (ptmpchan->channumber) { | ||
574 | |||
575 | tlvidx = 0; | ||
576 | pchantlvout->header.len = 0; | ||
577 | scanband = ptmpchan->radiotype; | ||
578 | pstartchan = ptmpchan; | ||
579 | doneearly = 0; | ||
580 | |||
581 | /* Construct the channel TLV for the scan command. Continue to | ||
582 | * insert channel TLVs until: | ||
583 | * - the tlvidx hits the maximum configured per scan command | ||
584 | * - the next channel to insert is 0 (end of desired channel list) | ||
585 | * - doneearly is set (controlling individual scanning of 1,6,11) | ||
586 | */ | ||
587 | while (tlvidx < maxchanperscan && ptmpchan->channumber | ||
588 | && !doneearly && scanned < 2) { | ||
589 | |||
590 | lbs_deb_scan("channel %d, radio %d, passive %d, " | ||
591 | "dischanflt %d, maxscantime %d\n", | ||
592 | ptmpchan->channumber, | ||
593 | ptmpchan->radiotype, | ||
594 | ptmpchan->chanscanmode.passivescan, | ||
595 | ptmpchan->chanscanmode.disablechanfilt, | ||
596 | ptmpchan->maxscantime); | ||
597 | |||
598 | /* Copy the current channel TLV to the command being prepared */ | ||
599 | memcpy(pchantlvout->chanscanparam + tlvidx, | ||
600 | ptmpchan, sizeof(pchantlvout->chanscanparam)); | ||
601 | |||
602 | /* Increment the TLV header length by the size appended */ | ||
603 | /* Ew, it would be _so_ nice if we could just declare the | ||
604 | variable little-endian and let GCC handle it for us */ | ||
605 | pchantlvout->header.len = | ||
606 | cpu_to_le16(le16_to_cpu(pchantlvout->header.len) + | ||
607 | sizeof(pchantlvout->chanscanparam)); | ||
608 | |||
609 | /* | ||
610 | * The tlv buffer length is set to the number of bytes of the | ||
611 | * between the channel tlv pointer and the start of the | ||
612 | * tlv buffer. This compensates for any TLVs that were appended | ||
613 | * before the channel list. | ||
614 | */ | ||
615 | pscancfgout->tlvbufferlen = ((u8 *) pchantlvout | ||
616 | - pscancfgout->tlvbuffer); | ||
617 | |||
618 | /* Add the size of the channel tlv header and the data length */ | ||
619 | pscancfgout->tlvbufferlen += | ||
620 | (sizeof(pchantlvout->header) | ||
621 | + le16_to_cpu(pchantlvout->header.len)); | ||
622 | |||
623 | /* Increment the index to the channel tlv we are constructing */ | ||
624 | tlvidx++; | ||
625 | |||
626 | doneearly = 0; | ||
627 | |||
628 | /* Stop the loop if the *current* channel is in the 1,6,11 set | ||
629 | * and we are not filtering on a BSSID or SSID. | ||
630 | */ | ||
631 | if (!filteredscan && (ptmpchan->channumber == 1 | ||
632 | || ptmpchan->channumber == 6 | ||
633 | || ptmpchan->channumber == 11)) { | ||
634 | doneearly = 1; | ||
635 | } | ||
636 | |||
637 | /* Increment the tmp pointer to the next channel to be scanned */ | ||
638 | ptmpchan++; | ||
639 | scanned++; | ||
640 | |||
641 | /* Stop the loop if the *next* channel is in the 1,6,11 set. | ||
642 | * This will cause it to be the only channel scanned on the next | ||
643 | * interation | ||
644 | */ | ||
645 | if (!filteredscan && (ptmpchan->channumber == 1 | ||
646 | || ptmpchan->channumber == 6 | ||
647 | || ptmpchan->channumber == 11)) { | ||
648 | doneearly = 1; | ||
649 | } | ||
650 | } | ||
651 | |||
652 | /* Send the scan command to the firmware with the specified cfg */ | ||
653 | ret = lbs_prepare_and_send_command(priv, CMD_802_11_SCAN, 0, | ||
654 | 0, 0, pscancfgout); | ||
655 | if (scanned >= 2 && !full_scan) { | ||
656 | ret = 0; | ||
657 | goto done; | ||
658 | } | ||
659 | scanned = 0; | ||
660 | } | ||
661 | |||
662 | done: | ||
663 | priv->adapter->last_scanned_channel = ptmpchan->channumber; | ||
664 | |||
665 | if (priv->adapter->last_scanned_channel) { | ||
666 | /* Schedule the next part of the partial scan */ | ||
667 | if (!full_scan && !priv->adapter->surpriseremoved) { | ||
668 | cancel_delayed_work(&priv->scan_work); | ||
669 | queue_delayed_work(priv->work_thread, &priv->scan_work, | ||
670 | msecs_to_jiffies(300)); | ||
671 | } | ||
672 | } else { | ||
673 | /* All done, tell userspace the scan table has been updated */ | ||
674 | memset(&wrqu, 0, sizeof(union iwreq_data)); | ||
675 | wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL); | ||
676 | } | 469 | } |
677 | 470 | rate_tlv->header.len = cpu_to_le16(i); | |
678 | out: | 471 | return sizeof(rate_tlv->header) + i; |
679 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); | ||
680 | return ret; | ||
681 | } | 472 | } |
682 | 473 | ||
474 | |||
683 | /* | 475 | /* |
684 | * Only used from lbs_scan_networks() | 476 | * Generate the CMD_802_11_SCAN command with the proper tlv |
685 | */ | 477 | * for a bunch of channels. |
686 | static void clear_selected_scan_list_entries(struct lbs_adapter *adapter, | 478 | */ |
687 | const struct lbs_ioctl_user_scan_cfg *scan_cfg) | 479 | static int lbs_do_scan(struct lbs_private *priv, |
480 | u8 bsstype, | ||
481 | struct chanscanparamset *chan_list, | ||
482 | int chan_count, | ||
483 | const struct lbs_ioctl_user_scan_cfg *user_cfg) | ||
688 | { | 484 | { |
689 | struct bss_descriptor *bss; | 485 | int ret = -ENOMEM; |
690 | struct bss_descriptor *safe; | 486 | struct lbs_scan_cmd_config *scan_cmd; |
691 | u32 clear_ssid_flag = 0, clear_bssid_flag = 0; | 487 | u8 *tlv; /* pointer into our current, growing TLV storage area */ |
692 | 488 | ||
693 | lbs_deb_enter(LBS_DEB_SCAN); | 489 | lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, " |
490 | "chan_count %d", | ||
491 | bsstype, chan_list[0].channumber, chan_count); | ||
694 | 492 | ||
695 | if (!scan_cfg) | 493 | /* create the fixed part for scan command */ |
494 | scan_cmd = kzalloc(MAX_SCAN_CFG_ALLOC, GFP_KERNEL); | ||
495 | if (scan_cmd == NULL) | ||
696 | goto out; | 496 | goto out; |
697 | 497 | tlv = scan_cmd->tlvbuffer; | |
698 | if (scan_cfg->clear_ssid && scan_cfg->ssid_len) | 498 | if (user_cfg) |
699 | clear_ssid_flag = 1; | 499 | memcpy(scan_cmd->bssid, user_cfg->bssid, ETH_ALEN); |
700 | 500 | scan_cmd->bsstype = bsstype; | |
701 | if (scan_cfg->clear_bssid | 501 | |
702 | && (compare_ether_addr(scan_cfg->bssid, &zeromac[0]) != 0) | 502 | /* add TLVs */ |
703 | && (compare_ether_addr(scan_cfg->bssid, &bcastmac[0]) != 0)) { | 503 | if (user_cfg && user_cfg->ssid_len) |
704 | clear_bssid_flag = 1; | 504 | tlv += lbs_scan_add_ssid_tlv(tlv, user_cfg); |
705 | } | 505 | if (chan_list && chan_count) |
706 | 506 | tlv += lbs_scan_add_chanlist_tlv(tlv, chan_list, chan_count); | |
707 | if (!clear_ssid_flag && !clear_bssid_flag) | 507 | tlv += lbs_scan_add_rates_tlv(tlv); |
708 | goto out; | 508 | |
709 | 509 | /* This is the final data we are about to send */ | |
710 | mutex_lock(&adapter->lock); | 510 | scan_cmd->tlvbufferlen = tlv - scan_cmd->tlvbuffer; |
711 | list_for_each_entry_safe (bss, safe, &adapter->network_list, list) { | 511 | lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd, 1+6); |
712 | u32 clear = 0; | 512 | lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TLV", scan_cmd->tlvbuffer, |
713 | 513 | scan_cmd->tlvbufferlen); | |
714 | /* Check for an SSID match */ | 514 | |
715 | if ( clear_ssid_flag | 515 | ret = lbs_prepare_and_send_command(priv, CMD_802_11_SCAN, 0, |
716 | && (bss->ssid_len == scan_cfg->ssid_len) | 516 | CMD_OPTION_WAITFORRSP, 0, scan_cmd); |
717 | && !memcmp(bss->ssid, scan_cfg->ssid, bss->ssid_len)) | ||
718 | clear = 1; | ||
719 | |||
720 | /* Check for a BSSID match */ | ||
721 | if ( clear_bssid_flag | ||
722 | && !compare_ether_addr(bss->bssid, scan_cfg->bssid)) | ||
723 | clear = 1; | ||
724 | |||
725 | if (clear) { | ||
726 | list_move_tail (&bss->list, &adapter->network_free_list); | ||
727 | clear_bss_descriptor(bss); | ||
728 | } | ||
729 | } | ||
730 | mutex_unlock(&adapter->lock); | ||
731 | out: | 517 | out: |
732 | lbs_deb_leave(LBS_DEB_SCAN); | 518 | kfree(scan_cmd); |
519 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); | ||
520 | return ret; | ||
733 | } | 521 | } |
734 | 522 | ||
735 | 523 | ||
@@ -745,29 +533,30 @@ out: | |||
745 | * @param priv A pointer to struct lbs_private structure | 533 | * @param priv A pointer to struct lbs_private structure |
746 | * @param puserscanin Pointer to the input configuration for the requested | 534 | * @param puserscanin Pointer to the input configuration for the requested |
747 | * scan. | 535 | * scan. |
748 | * @param full_scan ??? | ||
749 | * | 536 | * |
750 | * @return 0 or < 0 if error | 537 | * @return 0 or < 0 if error |
751 | */ | 538 | */ |
752 | int lbs_scan_networks(struct lbs_private *priv, | 539 | int lbs_scan_networks(struct lbs_private *priv, |
753 | const struct lbs_ioctl_user_scan_cfg *puserscanin, | 540 | const struct lbs_ioctl_user_scan_cfg *user_cfg, |
754 | int full_scan) | 541 | int full_scan) |
755 | { | 542 | { |
756 | struct lbs_adapter *adapter = priv->adapter; | 543 | struct lbs_adapter *adapter = priv->adapter; |
757 | struct mrvlietypes_chanlistparamset *pchantlvout; | 544 | int ret = -ENOMEM; |
758 | struct chanscanparamset * scan_chan_list = NULL; | 545 | struct chanscanparamset *chan_list; |
759 | struct lbs_scan_cmd_config *scan_cfg = NULL; | 546 | struct chanscanparamset *curr_chans; |
760 | u8 filteredscan; | 547 | int chan_count; |
761 | u8 scancurrentchanonly; | 548 | u8 bsstype = CMD_BSS_TYPE_ANY; |
762 | int maxchanperscan; | 549 | int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD; |
763 | int ret; | 550 | int filteredscan = 0; |
551 | union iwreq_data wrqu; | ||
764 | #ifdef CONFIG_LIBERTAS_DEBUG | 552 | #ifdef CONFIG_LIBERTAS_DEBUG |
765 | struct bss_descriptor * iter_bss; | 553 | struct bss_descriptor *iter; |
766 | int i = 0; | 554 | int i = 0; |
767 | DECLARE_MAC_BUF(mac); | 555 | DECLARE_MAC_BUF(mac); |
768 | #endif | 556 | #endif |
769 | 557 | ||
770 | lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", full_scan); | 558 | lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", |
559 | full_scan); | ||
771 | 560 | ||
772 | /* Cancel any partial outstanding partial scans if this scan | 561 | /* Cancel any partial outstanding partial scans if this scan |
773 | * is a full scan. | 562 | * is a full scan. |
@@ -775,85 +564,130 @@ int lbs_scan_networks(struct lbs_private *priv, | |||
775 | if (full_scan && delayed_work_pending(&priv->scan_work)) | 564 | if (full_scan && delayed_work_pending(&priv->scan_work)) |
776 | cancel_delayed_work(&priv->scan_work); | 565 | cancel_delayed_work(&priv->scan_work); |
777 | 566 | ||
778 | scan_chan_list = kzalloc(sizeof(struct chanscanparamset) * | 567 | /* Determine same scan parameters */ |
779 | LBS_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL); | 568 | if (user_cfg) { |
780 | if (scan_chan_list == NULL) { | 569 | if (user_cfg->bsstype) |
781 | ret = -ENOMEM; | 570 | bsstype = user_cfg->bsstype; |
782 | goto out; | 571 | if (compare_ether_addr(user_cfg->bssid, &zeromac[0]) != 0) { |
572 | numchannels = MRVDRV_MAX_CHANNELS_PER_SCAN; | ||
573 | filteredscan = 1; | ||
574 | } | ||
783 | } | 575 | } |
576 | lbs_deb_scan("numchannels %d, bsstype %d, " | ||
577 | "filteredscan %d\n", | ||
578 | numchannels, bsstype, filteredscan); | ||
784 | 579 | ||
785 | scan_cfg = lbs_scan_setup_scan_config(priv, | 580 | /* Create list of channels to scan */ |
786 | puserscanin, | 581 | chan_list = kzalloc(sizeof(struct chanscanparamset) * |
787 | &pchantlvout, | 582 | LBS_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL); |
788 | scan_chan_list, | 583 | if (!chan_list) { |
789 | &maxchanperscan, | 584 | lbs_pr_alert("SCAN: chan_list empty\n"); |
790 | &filteredscan, | ||
791 | &scancurrentchanonly); | ||
792 | if (scan_cfg == NULL) { | ||
793 | ret = -ENOMEM; | ||
794 | goto out; | 585 | goto out; |
795 | } | 586 | } |
796 | 587 | ||
797 | clear_selected_scan_list_entries(adapter, puserscanin); | 588 | /* We want to scan all channels */ |
589 | chan_count = lbs_scan_create_channel_list(priv, chan_list, | ||
590 | filteredscan); | ||
798 | 591 | ||
799 | /* Keep the data path active if we are only scanning our current channel */ | 592 | netif_stop_queue(priv->dev); |
800 | if (!scancurrentchanonly) { | 593 | netif_carrier_off(priv->dev); |
801 | netif_stop_queue(priv->dev); | 594 | if (priv->mesh_dev) { |
802 | netif_carrier_off(priv->dev); | ||
803 | if (priv->mesh_dev) { | ||
804 | netif_stop_queue(priv->mesh_dev); | 595 | netif_stop_queue(priv->mesh_dev); |
805 | netif_carrier_off(priv->mesh_dev); | 596 | netif_carrier_off(priv->mesh_dev); |
806 | } | ||
807 | } | 597 | } |
808 | 598 | ||
809 | ret = lbs_scan_channel_list(priv, | 599 | /* Prepare to continue an interrupted scan */ |
810 | maxchanperscan, | 600 | lbs_deb_scan("chan_count %d, last_scanned_channel %d\n", |
811 | filteredscan, | 601 | chan_count, adapter->last_scanned_channel); |
812 | scan_cfg, | 602 | curr_chans = chan_list; |
813 | pchantlvout, | 603 | /* advance channel list by already-scanned-channels */ |
814 | scan_chan_list, | 604 | if (adapter->last_scanned_channel > 0) { |
815 | puserscanin, | 605 | curr_chans += adapter->last_scanned_channel; |
816 | full_scan); | 606 | chan_count -= adapter->last_scanned_channel; |
607 | } | ||
608 | |||
609 | /* Send scan command(s) | ||
610 | * numchannels contains the number of channels we should maximally scan | ||
611 | * chan_count is the total number of channels to scan | ||
612 | */ | ||
613 | |||
614 | while (chan_count) { | ||
615 | int to_scan = min(numchannels, chan_count); | ||
616 | lbs_deb_scan("scanning %d of %d channels\n", | ||
617 | to_scan, chan_count); | ||
618 | ret = lbs_do_scan(priv, bsstype, curr_chans, | ||
619 | to_scan, user_cfg); | ||
620 | if (ret) { | ||
621 | lbs_pr_err("SCAN_CMD failed\n"); | ||
622 | goto out2; | ||
623 | } | ||
624 | curr_chans += to_scan; | ||
625 | chan_count -= to_scan; | ||
626 | |||
627 | /* somehow schedule the next part of the scan */ | ||
628 | if (chan_count && | ||
629 | !full_scan && | ||
630 | !priv->adapter->surpriseremoved) { | ||
631 | /* -1 marks just that we're currently scanning */ | ||
632 | if (adapter->last_scanned_channel < 0) | ||
633 | adapter->last_scanned_channel = to_scan; | ||
634 | else | ||
635 | adapter->last_scanned_channel += to_scan; | ||
636 | cancel_delayed_work(&priv->scan_work); | ||
637 | queue_delayed_work(priv->work_thread, &priv->scan_work, | ||
638 | msecs_to_jiffies(300)); | ||
639 | /* skip over GIWSCAN event */ | ||
640 | goto out; | ||
641 | } | ||
642 | |||
643 | } | ||
644 | memset(&wrqu, 0, sizeof(union iwreq_data)); | ||
645 | wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL); | ||
817 | 646 | ||
818 | #ifdef CONFIG_LIBERTAS_DEBUG | 647 | #ifdef CONFIG_LIBERTAS_DEBUG |
819 | /* Dump the scan table */ | 648 | /* Dump the scan table */ |
820 | mutex_lock(&adapter->lock); | 649 | mutex_lock(&adapter->lock); |
821 | lbs_deb_scan("The scan table contains:\n"); | 650 | lbs_deb_scan("scan table:\n"); |
822 | list_for_each_entry (iter_bss, &adapter->network_list, list) { | 651 | list_for_each_entry(iter, &adapter->network_list, list) |
823 | lbs_deb_scan("scan %02d, %s, RSSI, %d, SSID '%s'\n", | 652 | lbs_deb_scan("%02d: BSSID %s, RSSI %d, SSID '%s'\n", |
824 | i++, print_mac(mac, iter_bss->bssid), (s32) iter_bss->rssi, | 653 | i++, print_mac(mac, iter->bssid), (s32) iter->rssi, |
825 | escape_essid(iter_bss->ssid, iter_bss->ssid_len)); | 654 | escape_essid(iter->ssid, iter->ssid_len)); |
826 | } | ||
827 | mutex_unlock(&adapter->lock); | 655 | mutex_unlock(&adapter->lock); |
828 | #endif | 656 | #endif |
829 | 657 | ||
658 | out2: | ||
659 | adapter->last_scanned_channel = 0; | ||
660 | |||
661 | out: | ||
830 | if (adapter->connect_status == LBS_CONNECTED) { | 662 | if (adapter->connect_status == LBS_CONNECTED) { |
831 | netif_carrier_on(priv->dev); | 663 | netif_carrier_on(priv->dev); |
832 | netif_wake_queue(priv->dev); | 664 | netif_wake_queue(priv->dev); |
833 | } | 665 | } |
834 | |||
835 | if (priv->mesh_dev && (adapter->mesh_connect_status == LBS_CONNECTED)) { | 666 | if (priv->mesh_dev && (adapter->mesh_connect_status == LBS_CONNECTED)) { |
836 | netif_carrier_on(priv->mesh_dev); | 667 | netif_carrier_on(priv->mesh_dev); |
837 | netif_wake_queue(priv->mesh_dev); | 668 | netif_wake_queue(priv->mesh_dev); |
838 | } | 669 | } |
839 | 670 | kfree(chan_list); | |
840 | out: | ||
841 | if (scan_cfg) | ||
842 | kfree(scan_cfg); | ||
843 | |||
844 | if (scan_chan_list) | ||
845 | kfree(scan_chan_list); | ||
846 | 671 | ||
847 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); | 672 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); |
848 | return ret; | 673 | return ret; |
849 | } | 674 | } |
850 | 675 | ||
676 | |||
677 | |||
678 | |||
679 | /*********************************************************************/ | ||
680 | /* */ | ||
681 | /* Result interpretation */ | ||
682 | /* */ | ||
683 | /*********************************************************************/ | ||
684 | |||
851 | /** | 685 | /** |
852 | * @brief Interpret a BSS scan response returned from the firmware | 686 | * @brief Interpret a BSS scan response returned from the firmware |
853 | * | 687 | * |
854 | * Parse the various fixed fields and IEs passed back for a a BSS probe | 688 | * Parse the various fixed fields and IEs passed back for a a BSS probe |
855 | * response or beacon from the scan command. Record information as needed | 689 | * response or beacon from the scan command. Record information as needed |
856 | * in the scan table struct bss_descriptor for that entry. | 690 | * in the scan table struct bss_descriptor for that entry. |
857 | * | 691 | * |
858 | * @param bss Output parameter: Pointer to the BSS Entry | 692 | * @param bss Output parameter: Pointer to the BSS Entry |
859 | * | 693 | * |
@@ -898,7 +732,7 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
898 | *bytesleft -= beaconsize; | 732 | *bytesleft -= beaconsize; |
899 | 733 | ||
900 | memcpy(bss->bssid, pos, ETH_ALEN); | 734 | memcpy(bss->bssid, pos, ETH_ALEN); |
901 | lbs_deb_scan("process_bss: AP BSSID %s\n", print_mac(mac, bss->bssid)); | 735 | lbs_deb_scan("process_bss: BSSID %s\n", print_mac(mac, bss->bssid)); |
902 | pos += ETH_ALEN; | 736 | pos += ETH_ALEN; |
903 | 737 | ||
904 | if ((end - pos) < 12) { | 738 | if ((end - pos) < 12) { |
@@ -914,7 +748,7 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
914 | 748 | ||
915 | /* RSSI is 1 byte long */ | 749 | /* RSSI is 1 byte long */ |
916 | bss->rssi = *pos; | 750 | bss->rssi = *pos; |
917 | lbs_deb_scan("process_bss: RSSI=%02X\n", *pos); | 751 | lbs_deb_scan("process_bss: RSSI %d\n", *pos); |
918 | pos++; | 752 | pos++; |
919 | 753 | ||
920 | /* time stamp is 8 bytes long */ | 754 | /* time stamp is 8 bytes long */ |
@@ -926,18 +760,18 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
926 | 760 | ||
927 | /* capability information is 2 bytes long */ | 761 | /* capability information is 2 bytes long */ |
928 | bss->capability = le16_to_cpup((void *) pos); | 762 | bss->capability = le16_to_cpup((void *) pos); |
929 | lbs_deb_scan("process_bss: capabilities = 0x%4X\n", bss->capability); | 763 | lbs_deb_scan("process_bss: capabilities 0x%04x\n", bss->capability); |
930 | pos += 2; | 764 | pos += 2; |
931 | 765 | ||
932 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) | 766 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) |
933 | lbs_deb_scan("process_bss: AP WEP enabled\n"); | 767 | lbs_deb_scan("process_bss: WEP enabled\n"); |
934 | if (bss->capability & WLAN_CAPABILITY_IBSS) | 768 | if (bss->capability & WLAN_CAPABILITY_IBSS) |
935 | bss->mode = IW_MODE_ADHOC; | 769 | bss->mode = IW_MODE_ADHOC; |
936 | else | 770 | else |
937 | bss->mode = IW_MODE_INFRA; | 771 | bss->mode = IW_MODE_INFRA; |
938 | 772 | ||
939 | /* rest of the current buffer are IE's */ | 773 | /* rest of the current buffer are IE's */ |
940 | lbs_deb_scan("process_bss: IE length for this AP = %zd\n", end - pos); | 774 | lbs_deb_scan("process_bss: IE len %zd\n", end - pos); |
941 | lbs_deb_hex(LBS_DEB_SCAN, "process_bss: IE info", pos, end - pos); | 775 | lbs_deb_hex(LBS_DEB_SCAN, "process_bss: IE info", pos, end - pos); |
942 | 776 | ||
943 | /* process variable IE */ | 777 | /* process variable IE */ |
@@ -955,7 +789,7 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
955 | case MFIE_TYPE_SSID: | 789 | case MFIE_TYPE_SSID: |
956 | bss->ssid_len = elem->len; | 790 | bss->ssid_len = elem->len; |
957 | memcpy(bss->ssid, elem->data, elem->len); | 791 | memcpy(bss->ssid, elem->data, elem->len); |
958 | lbs_deb_scan("ssid '%s', ssid length %u\n", | 792 | lbs_deb_scan("got SSID IE: '%s', len %u\n", |
959 | escape_essid(bss->ssid, bss->ssid_len), | 793 | escape_essid(bss->ssid, bss->ssid_len), |
960 | bss->ssid_len); | 794 | bss->ssid_len); |
961 | break; | 795 | break; |
@@ -964,16 +798,14 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
964 | n_basic_rates = min_t(u8, MAX_RATES, elem->len); | 798 | n_basic_rates = min_t(u8, MAX_RATES, elem->len); |
965 | memcpy(bss->rates, elem->data, n_basic_rates); | 799 | memcpy(bss->rates, elem->data, n_basic_rates); |
966 | got_basic_rates = 1; | 800 | got_basic_rates = 1; |
801 | lbs_deb_scan("got RATES IE\n"); | ||
967 | break; | 802 | break; |
968 | 803 | ||
969 | case MFIE_TYPE_FH_SET: | 804 | case MFIE_TYPE_FH_SET: |
970 | pFH = (struct ieeetypes_fhparamset *) pos; | 805 | pFH = (struct ieeetypes_fhparamset *) pos; |
971 | memmove(&bss->phyparamset.fhparamset, pFH, | 806 | memmove(&bss->phyparamset.fhparamset, pFH, |
972 | sizeof(struct ieeetypes_fhparamset)); | 807 | sizeof(struct ieeetypes_fhparamset)); |
973 | #if 0 /* I think we can store these LE */ | 808 | lbs_deb_scan("got FH IE\n"); |
974 | bss->phyparamset.fhparamset.dwelltime | ||
975 | = le16_to_cpu(bss->phyparamset.fhparamset.dwelltime); | ||
976 | #endif | ||
977 | break; | 809 | break; |
978 | 810 | ||
979 | case MFIE_TYPE_DS_SET: | 811 | case MFIE_TYPE_DS_SET: |
@@ -981,12 +813,14 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
981 | bss->channel = pDS->currentchan; | 813 | bss->channel = pDS->currentchan; |
982 | memcpy(&bss->phyparamset.dsparamset, pDS, | 814 | memcpy(&bss->phyparamset.dsparamset, pDS, |
983 | sizeof(struct ieeetypes_dsparamset)); | 815 | sizeof(struct ieeetypes_dsparamset)); |
816 | lbs_deb_scan("got DS IE, channel %d\n", bss->channel); | ||
984 | break; | 817 | break; |
985 | 818 | ||
986 | case MFIE_TYPE_CF_SET: | 819 | case MFIE_TYPE_CF_SET: |
987 | pCF = (struct ieeetypes_cfparamset *) pos; | 820 | pCF = (struct ieeetypes_cfparamset *) pos; |
988 | memcpy(&bss->ssparamset.cfparamset, pCF, | 821 | memcpy(&bss->ssparamset.cfparamset, pCF, |
989 | sizeof(struct ieeetypes_cfparamset)); | 822 | sizeof(struct ieeetypes_cfparamset)); |
823 | lbs_deb_scan("got CF IE\n"); | ||
990 | break; | 824 | break; |
991 | 825 | ||
992 | case MFIE_TYPE_IBSS_SET: | 826 | case MFIE_TYPE_IBSS_SET: |
@@ -994,18 +828,16 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
994 | bss->atimwindow = le32_to_cpu(pibss->atimwindow); | 828 | bss->atimwindow = le32_to_cpu(pibss->atimwindow); |
995 | memmove(&bss->ssparamset.ibssparamset, pibss, | 829 | memmove(&bss->ssparamset.ibssparamset, pibss, |
996 | sizeof(struct ieeetypes_ibssparamset)); | 830 | sizeof(struct ieeetypes_ibssparamset)); |
997 | #if 0 | 831 | lbs_deb_scan("got IBSS IE\n"); |
998 | bss->ssparamset.ibssparamset.atimwindow | ||
999 | = le16_to_cpu(bss->ssparamset.ibssparamset.atimwindow); | ||
1000 | #endif | ||
1001 | break; | 832 | break; |
1002 | 833 | ||
1003 | case MFIE_TYPE_COUNTRY: | 834 | case MFIE_TYPE_COUNTRY: |
1004 | pcountryinfo = (struct ieeetypes_countryinfoset *) pos; | 835 | pcountryinfo = (struct ieeetypes_countryinfoset *) pos; |
836 | lbs_deb_scan("got COUNTRY IE\n"); | ||
1005 | if (pcountryinfo->len < sizeof(pcountryinfo->countrycode) | 837 | if (pcountryinfo->len < sizeof(pcountryinfo->countrycode) |
1006 | || pcountryinfo->len > 254) { | 838 | || pcountryinfo->len > 254) { |
1007 | lbs_deb_scan("process_bss: 11D- Err " | 839 | lbs_deb_scan("process_bss: 11D- Err " |
1008 | "CountryInfo len =%d min=%zd max=254\n", | 840 | "CountryInfo len %d, min %zd, max 254\n", |
1009 | pcountryinfo->len, | 841 | pcountryinfo->len, |
1010 | sizeof(pcountryinfo->countrycode)); | 842 | sizeof(pcountryinfo->countrycode)); |
1011 | ret = -1; | 843 | ret = -1; |
@@ -1024,8 +856,11 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
1024 | * already found. Data rate IE should come before | 856 | * already found. Data rate IE should come before |
1025 | * extended supported rate IE | 857 | * extended supported rate IE |
1026 | */ | 858 | */ |
1027 | if (!got_basic_rates) | 859 | lbs_deb_scan("got RATESEX IE\n"); |
860 | if (!got_basic_rates) { | ||
861 | lbs_deb_scan("... but ignoring it\n"); | ||
1028 | break; | 862 | break; |
863 | } | ||
1029 | 864 | ||
1030 | n_ex_rates = elem->len; | 865 | n_ex_rates = elem->len; |
1031 | if (n_basic_rates + n_ex_rates > MAX_RATES) | 866 | if (n_basic_rates + n_ex_rates > MAX_RATES) |
@@ -1044,24 +879,36 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
1044 | bss->wpa_ie_len = min(elem->len + 2, | 879 | bss->wpa_ie_len = min(elem->len + 2, |
1045 | MAX_WPA_IE_LEN); | 880 | MAX_WPA_IE_LEN); |
1046 | memcpy(bss->wpa_ie, elem, bss->wpa_ie_len); | 881 | memcpy(bss->wpa_ie, elem, bss->wpa_ie_len); |
1047 | lbs_deb_hex(LBS_DEB_SCAN, "process_bss: WPA IE", bss->wpa_ie, | 882 | lbs_deb_scan("got WPA IE\n"); |
883 | lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie, | ||
1048 | elem->len); | 884 | elem->len); |
1049 | } else if (elem->len >= MARVELL_MESH_IE_LENGTH && | 885 | } else if (elem->len >= MARVELL_MESH_IE_LENGTH && |
1050 | elem->data[0] == 0x00 && | 886 | elem->data[0] == 0x00 && |
1051 | elem->data[1] == 0x50 && | 887 | elem->data[1] == 0x50 && |
1052 | elem->data[2] == 0x43 && | 888 | elem->data[2] == 0x43 && |
1053 | elem->data[3] == 0x04) { | 889 | elem->data[3] == 0x04) { |
890 | lbs_deb_scan("got mesh IE\n"); | ||
1054 | bss->mesh = 1; | 891 | bss->mesh = 1; |
892 | } else { | ||
893 | lbs_deb_scan("got generiec IE: " | ||
894 | "%02x:%02x:%02x:%02x, len %d\n", | ||
895 | elem->data[0], elem->data[1], | ||
896 | elem->data[2], elem->data[3], | ||
897 | elem->len); | ||
1055 | } | 898 | } |
1056 | break; | 899 | break; |
1057 | 900 | ||
1058 | case MFIE_TYPE_RSN: | 901 | case MFIE_TYPE_RSN: |
902 | lbs_deb_scan("got RSN IE\n"); | ||
1059 | bss->rsn_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN); | 903 | bss->rsn_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN); |
1060 | memcpy(bss->rsn_ie, elem, bss->rsn_ie_len); | 904 | memcpy(bss->rsn_ie, elem, bss->rsn_ie_len); |
1061 | lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE", bss->rsn_ie, elem->len); | 905 | lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE", |
906 | bss->rsn_ie, elem->len); | ||
1062 | break; | 907 | break; |
1063 | 908 | ||
1064 | default: | 909 | default: |
910 | lbs_deb_scan("got IE 0x%04x, len %d\n", | ||
911 | elem->id, elem->len); | ||
1065 | break; | 912 | break; |
1066 | } | 913 | } |
1067 | 914 | ||
@@ -1273,8 +1120,6 @@ int lbs_find_best_network_ssid(struct lbs_private *priv, | |||
1273 | if (adapter->surpriseremoved) | 1120 | if (adapter->surpriseremoved) |
1274 | goto out; | 1121 | goto out; |
1275 | 1122 | ||
1276 | wait_event_interruptible(adapter->cmd_pending, !adapter->nr_cmd_pending); | ||
1277 | |||
1278 | found = lbs_find_best_ssid_in_list(adapter, preferred_mode); | 1123 | found = lbs_find_best_ssid_in_list(adapter, preferred_mode); |
1279 | if (found && (found->ssid_len > 0)) { | 1124 | if (found && (found->ssid_len > 0)) { |
1280 | memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE); | 1125 | memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE); |
@@ -1288,36 +1133,6 @@ out: | |||
1288 | return ret; | 1133 | return ret; |
1289 | } | 1134 | } |
1290 | 1135 | ||
1291 | /** | ||
1292 | * @brief Scan Network | ||
1293 | * | ||
1294 | * @param dev A pointer to net_device structure | ||
1295 | * @param info A pointer to iw_request_info structure | ||
1296 | * @param vwrq A pointer to iw_param structure | ||
1297 | * @param extra A pointer to extra data buf | ||
1298 | * | ||
1299 | * @return 0 --success, otherwise fail | ||
1300 | */ | ||
1301 | int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, | ||
1302 | struct iw_param *vwrq, char *extra) | ||
1303 | { | ||
1304 | struct lbs_private *priv = dev->priv; | ||
1305 | struct lbs_adapter *adapter = priv->adapter; | ||
1306 | |||
1307 | lbs_deb_enter(LBS_DEB_SCAN); | ||
1308 | |||
1309 | if (!delayed_work_pending(&priv->scan_work)) { | ||
1310 | queue_delayed_work(priv->work_thread, &priv->scan_work, | ||
1311 | msecs_to_jiffies(50)); | ||
1312 | } | ||
1313 | |||
1314 | if (adapter->surpriseremoved) | ||
1315 | return -1; | ||
1316 | |||
1317 | lbs_deb_leave(LBS_DEB_SCAN); | ||
1318 | return 0; | ||
1319 | } | ||
1320 | |||
1321 | 1136 | ||
1322 | /** | 1137 | /** |
1323 | * @brief Send a scan command for all available channels filtered on a spec | 1138 | * @brief Send a scan command for all available channels filtered on a spec |
@@ -1329,8 +1144,6 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, | |||
1329 | * @param ssid_len Length of the SSID | 1144 | * @param ssid_len Length of the SSID |
1330 | * @param clear_ssid Should existing scan results with this SSID | 1145 | * @param clear_ssid Should existing scan results with this SSID |
1331 | * be cleared? | 1146 | * be cleared? |
1332 | * @param prequestedssid A pointer to AP's ssid | ||
1333 | * @param keeppreviousscan Flag used to save/clear scan table before scan | ||
1334 | * | 1147 | * |
1335 | * @return 0-success, otherwise fail | 1148 | * @return 0-success, otherwise fail |
1336 | */ | 1149 | */ |
@@ -1357,7 +1170,6 @@ int lbs_send_specific_ssid_scan(struct lbs_private *priv, | |||
1357 | ret = -1; | 1170 | ret = -1; |
1358 | goto out; | 1171 | goto out; |
1359 | } | 1172 | } |
1360 | wait_event_interruptible(adapter->cmd_pending, !adapter->nr_cmd_pending); | ||
1361 | 1173 | ||
1362 | out: | 1174 | out: |
1363 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); | 1175 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); |
@@ -1373,6 +1185,7 @@ out: | |||
1373 | /* */ | 1185 | /* */ |
1374 | /*********************************************************************/ | 1186 | /*********************************************************************/ |
1375 | 1187 | ||
1188 | |||
1376 | #define MAX_CUSTOM_LEN 64 | 1189 | #define MAX_CUSTOM_LEN 64 |
1377 | 1190 | ||
1378 | static inline char *lbs_translate_scan(struct lbs_private *priv, | 1191 | static inline char *lbs_translate_scan(struct lbs_private *priv, |
@@ -1398,7 +1211,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, | |||
1398 | goto out; | 1211 | goto out; |
1399 | } | 1212 | } |
1400 | 1213 | ||
1401 | /* First entry *MUST* be the AP BSSID */ | 1214 | /* First entry *MUST* be the BSSID */ |
1402 | iwe.cmd = SIOCGIWAP; | 1215 | iwe.cmd = SIOCGIWAP; |
1403 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | 1216 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; |
1404 | memcpy(iwe.u.ap_addr.sa_data, &bss->bssid, ETH_ALEN); | 1217 | memcpy(iwe.u.ap_addr.sa_data, &bss->bssid, ETH_ALEN); |
@@ -1528,6 +1341,55 @@ out: | |||
1528 | return start; | 1341 | return start; |
1529 | } | 1342 | } |
1530 | 1343 | ||
1344 | |||
1345 | /** | ||
1346 | * @brief Handle Scan Network ioctl | ||
1347 | * | ||
1348 | * @param dev A pointer to net_device structure | ||
1349 | * @param info A pointer to iw_request_info structure | ||
1350 | * @param vwrq A pointer to iw_param structure | ||
1351 | * @param extra A pointer to extra data buf | ||
1352 | * | ||
1353 | * @return 0 --success, otherwise fail | ||
1354 | */ | ||
1355 | int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, | ||
1356 | struct iw_param *wrqu, char *extra) | ||
1357 | { | ||
1358 | struct lbs_private *priv = dev->priv; | ||
1359 | struct lbs_adapter *adapter = priv->adapter; | ||
1360 | |||
1361 | lbs_deb_enter(LBS_DEB_SCAN); | ||
1362 | |||
1363 | if (!netif_running(dev)) | ||
1364 | return -ENETDOWN; | ||
1365 | |||
1366 | /* mac80211 does this: | ||
1367 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1368 | if (sdata->type != IEEE80211_IF_TYPE_xxx) | ||
1369 | return -EOPNOTSUPP; | ||
1370 | |||
1371 | if (wrqu->data.length == sizeof(struct iw_scan_req) && | ||
1372 | wrqu->data.flags & IW_SCAN_THIS_ESSID) { | ||
1373 | req = (struct iw_scan_req *)extra; | ||
1374 | ssid = req->essid; | ||
1375 | ssid_len = req->essid_len; | ||
1376 | } | ||
1377 | */ | ||
1378 | |||
1379 | if (!delayed_work_pending(&priv->scan_work)) | ||
1380 | queue_delayed_work(priv->work_thread, &priv->scan_work, | ||
1381 | msecs_to_jiffies(50)); | ||
1382 | /* set marker that currently a scan is taking place */ | ||
1383 | adapter->last_scanned_channel = -1; | ||
1384 | |||
1385 | if (adapter->surpriseremoved) | ||
1386 | return -EIO; | ||
1387 | |||
1388 | lbs_deb_leave(LBS_DEB_SCAN); | ||
1389 | return 0; | ||
1390 | } | ||
1391 | |||
1392 | |||
1531 | /** | 1393 | /** |
1532 | * @brief Handle Retrieve scan table ioctl | 1394 | * @brief Handle Retrieve scan table ioctl |
1533 | * | 1395 | * |
@@ -1552,6 +1414,10 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
1552 | 1414 | ||
1553 | lbs_deb_enter(LBS_DEB_SCAN); | 1415 | lbs_deb_enter(LBS_DEB_SCAN); |
1554 | 1416 | ||
1417 | /* iwlist should wait until the current scan is finished */ | ||
1418 | if (adapter->last_scanned_channel) | ||
1419 | return -EAGAIN; | ||
1420 | |||
1555 | /* Update RSSI if current BSS is a locally created ad-hoc BSS */ | 1421 | /* Update RSSI if current BSS is a locally created ad-hoc BSS */ |
1556 | if ((adapter->mode == IW_MODE_ADHOC) && adapter->adhoccreate) { | 1422 | if ((adapter->mode == IW_MODE_ADHOC) && adapter->adhoccreate) { |
1557 | lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, | 1423 | lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, |
@@ -1609,7 +1475,8 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
1609 | /** | 1475 | /** |
1610 | * @brief Prepare a scan command to be sent to the firmware | 1476 | * @brief Prepare a scan command to be sent to the firmware |
1611 | * | 1477 | * |
1612 | * Called from lbs_prepare_and_send_command() in cmd.c | 1478 | * Called via lbs_prepare_and_send_command(priv, CMD_802_11_SCAN, ...) |
1479 | * from cmd.c | ||
1613 | * | 1480 | * |
1614 | * Sends a fixed lenght data part (specifying the BSS type and BSSID filters) | 1481 | * Sends a fixed lenght data part (specifying the BSS type and BSSID filters) |
1615 | * as well as a variable number/length of TLVs to the firmware. | 1482 | * as well as a variable number/length of TLVs to the firmware. |
@@ -1623,7 +1490,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
1623 | * @return 0 or -1 | 1490 | * @return 0 or -1 |
1624 | */ | 1491 | */ |
1625 | int lbs_cmd_80211_scan(struct lbs_private *priv, | 1492 | int lbs_cmd_80211_scan(struct lbs_private *priv, |
1626 | struct cmd_ds_command *cmd, void *pdata_buf) | 1493 | struct cmd_ds_command *cmd, void *pdata_buf) |
1627 | { | 1494 | { |
1628 | struct cmd_ds_802_11_scan *pscan = &cmd->params.scan; | 1495 | struct cmd_ds_802_11_scan *pscan = &cmd->params.scan; |
1629 | struct lbs_scan_cmd_config *pscancfg = pdata_buf; | 1496 | struct lbs_scan_cmd_config *pscancfg = pdata_buf; |
@@ -1635,32 +1502,14 @@ int lbs_cmd_80211_scan(struct lbs_private *priv, | |||
1635 | memcpy(pscan->bssid, pscancfg->bssid, ETH_ALEN); | 1502 | memcpy(pscan->bssid, pscancfg->bssid, ETH_ALEN); |
1636 | memcpy(pscan->tlvbuffer, pscancfg->tlvbuffer, pscancfg->tlvbufferlen); | 1503 | memcpy(pscan->tlvbuffer, pscancfg->tlvbuffer, pscancfg->tlvbufferlen); |
1637 | 1504 | ||
1638 | cmd->command = cpu_to_le16(CMD_802_11_SCAN); | ||
1639 | |||
1640 | /* size is equal to the sizeof(fixed portions) + the TLV len + header */ | 1505 | /* size is equal to the sizeof(fixed portions) + the TLV len + header */ |
1641 | cmd->size = cpu_to_le16(sizeof(pscan->bsstype) + ETH_ALEN | 1506 | cmd->size = cpu_to_le16(sizeof(pscan->bsstype) + ETH_ALEN |
1642 | + pscancfg->tlvbufferlen + S_DS_GEN); | 1507 | + pscancfg->tlvbufferlen + S_DS_GEN); |
1643 | 1508 | ||
1644 | lbs_deb_scan("SCAN_CMD: command 0x%04x, size %d, seqnum %d\n", | ||
1645 | le16_to_cpu(cmd->command), le16_to_cpu(cmd->size), | ||
1646 | le16_to_cpu(cmd->seqnum)); | ||
1647 | |||
1648 | lbs_deb_leave(LBS_DEB_SCAN); | 1509 | lbs_deb_leave(LBS_DEB_SCAN); |
1649 | return 0; | 1510 | return 0; |
1650 | } | 1511 | } |
1651 | 1512 | ||
1652 | static inline int is_same_network(struct bss_descriptor *src, | ||
1653 | struct bss_descriptor *dst) | ||
1654 | { | ||
1655 | /* A network is only a duplicate if the channel, BSSID, and ESSID | ||
1656 | * all match. We treat all <hidden> with the same BSSID and channel | ||
1657 | * as one network */ | ||
1658 | return ((src->ssid_len == dst->ssid_len) && | ||
1659 | (src->channel == dst->channel) && | ||
1660 | !compare_ether_addr(src->bssid, dst->bssid) && | ||
1661 | !memcmp(src->ssid, dst->ssid, src->ssid_len)); | ||
1662 | } | ||
1663 | |||
1664 | /** | 1513 | /** |
1665 | * @brief This function handles the command response of scan | 1514 | * @brief This function handles the command response of scan |
1666 | * | 1515 | * |
@@ -1725,7 +1574,7 @@ int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp) | |||
1725 | lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft); | 1574 | lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft); |
1726 | 1575 | ||
1727 | scanrespsize = le16_to_cpu(get_unaligned((u16*)&resp->size)); | 1576 | scanrespsize = le16_to_cpu(get_unaligned((u16*)&resp->size)); |
1728 | lbs_deb_scan("SCAN_RESP: returned %d AP before parsing\n", | 1577 | lbs_deb_scan("SCAN_RESP: scan results %d\n", |
1729 | pscan->nr_sets); | 1578 | pscan->nr_sets); |
1730 | 1579 | ||
1731 | pbssinfo = pscan->bssdesc_and_tlvbuffer; | 1580 | pbssinfo = pscan->bssdesc_and_tlvbuffer; |
@@ -1788,7 +1637,7 @@ int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp) | |||
1788 | continue; | 1637 | continue; |
1789 | } | 1638 | } |
1790 | 1639 | ||
1791 | lbs_deb_scan("SCAN_RESP: BSSID = %s\n", | 1640 | lbs_deb_scan("SCAN_RESP: BSSID %s\n", |
1792 | print_mac(mac, new.bssid)); | 1641 | print_mac(mac, new.bssid)); |
1793 | 1642 | ||
1794 | /* Copy the locally created newbssentry to the scan table */ | 1643 | /* Copy the locally created newbssentry to the scan table */ |