aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/scan.c
diff options
context:
space:
mode:
authorHolger Schurig <hs4233@mail.mn-solutions.de>2007-12-07 10:52:10 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:06:11 -0500
commitffd074fc78c1053b1f1697ebbe5bcfbb64949d16 (patch)
tree8021f4bad2ece20959f1d9d412ab71723df8a0ef /drivers/net/wireless/libertas/scan.c
parent83eacf233e62349c8a7282616fedc602ee95a555 (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/wireless/libertas/scan.c')
-rw-r--r--drivers/net/wireless/libertas/scan.c871
1 files changed, 360 insertions, 511 deletions
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 */
90int 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
82static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, 98static 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
168static 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 */
237int 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
266void 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 */
274static void lbs_scan_create_channel_list(struct lbs_private *priv, 296static 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/*
360void 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 */
387static 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 */
407static struct lbs_scan_cmd_config * 424static int lbs_scan_add_chanlist_tlv(u8 *tlv,
408lbs_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);
505out:
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 */
533static int lbs_scan_channel_list(struct lbs_private *priv, 449static 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
662done:
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);
678out: 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.
686static void clear_selected_scan_list_entries(struct lbs_adapter *adapter, 478 */
687 const struct lbs_ioctl_user_scan_cfg *scan_cfg) 479static 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);
731out: 517out:
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 */
752int lbs_scan_networks(struct lbs_private *priv, 539int 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
658out2:
659 adapter->last_scanned_channel = 0;
660
661out:
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);
840out:
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 */
1301int 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
1362out: 1174out:
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
1378static inline char *lbs_translate_scan(struct lbs_private *priv, 1191static 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 */
1355int 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 */
1625int lbs_cmd_80211_scan(struct lbs_private *priv, 1492int 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
1652static 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 */