aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/scan.c
diff options
context:
space:
mode:
authorHolger Schurig <hs4233@mail.mn-solutions.de>2008-03-05 01:05:32 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-03-13 16:02:32 -0400
commit52933d815bff78605a490582a2212a8131482e00 (patch)
treed30f7107a771b3ef2b5d1b187fc9baa3c733b0b2 /drivers/net/wireless/libertas/scan.c
parentd9357136ac4729f589543afb6b1d17d443ae4f71 (diff)
libertas: implement SSID scanning for SIOCSIWSCAN
After my bit scan re-writing the SIOCSIWSCAN wext ioctl no longer supported scanning for a specific SSID. However, wpa_supplicant is a possible user of this ioctl, so here is code that add's this. While passing, removed even more of the debugfs-based scanning. You can (and should) the SIOCSIWSCAN to ask for scans, so there is no need for proprietary interfaces for scanning. And, besides, the scan result couldn't be used further, e.g. not for associating. Signed-off-by: Holger Schurig <hs4233@mail.mn-solutions.de> Acked-by: Dan Williams <dcbw@redhat.com> 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.c145
1 files changed, 67 insertions, 78 deletions
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index 99f11a56d84e..0598541451d8 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -260,24 +260,12 @@ done:
260 260
261 261
262 262
263
264/*********************************************************************/ 263/*********************************************************************/
265/* */ 264/* */
266/* Main scanning support */ 265/* Main scanning support */
267/* */ 266/* */
268/*********************************************************************/ 267/*********************************************************************/
269 268
270void lbs_scan_worker(struct work_struct *work)
271{
272 struct lbs_private *priv =
273 container_of(work, struct lbs_private, scan_work.work);
274
275 lbs_deb_enter(LBS_DEB_SCAN);
276 lbs_scan_networks(priv, NULL, 0);
277 lbs_deb_leave(LBS_DEB_SCAN);
278}
279
280
281/** 269/**
282 * @brief Create a channel list for the driver to scan based on region info 270 * @brief Create a channel list for the driver to scan based on region info
283 * 271 *
@@ -289,17 +277,11 @@ void lbs_scan_worker(struct work_struct *work)
289 * 277 *
290 * @param priv A pointer to struct lbs_private structure 278 * @param priv A pointer to struct lbs_private structure
291 * @param scanchanlist Output parameter: resulting channel list to scan 279 * @param scanchanlist Output parameter: resulting channel list to scan
292 * @param filteredscan Flag indicating whether or not a BSSID or SSID filter
293 * is being sent in the command to firmware. Used to
294 * increase the number of channels sent in a scan
295 * command and to disable the firmware channel scan
296 * filter.
297 * 280 *
298 * @return void 281 * @return void
299 */ 282 */
300static int lbs_scan_create_channel_list(struct lbs_private *priv, 283static int lbs_scan_create_channel_list(struct lbs_private *priv,
301 struct chanscanparamset *scanchanlist, 284 struct chanscanparamset *scanchanlist)
302 uint8_t filteredscan)
303{ 285{
304 struct region_channel *scanregion; 286 struct region_channel *scanregion;
305 struct chan_freq_power *cfp; 287 struct chan_freq_power *cfp;
@@ -354,9 +336,6 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv,
354 } 336 }
355 337
356 chan->channumber = cfp->channel; 338 chan->channumber = cfp->channel;
357
358 if (filteredscan)
359 chan->chanscanmode.disablechanfilt = 1;
360 } 339 }
361 } 340 }
362 return chanidx; 341 return chanidx;
@@ -370,15 +349,14 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv,
370 * length 06 00 349 * length 06 00
371 * ssid 4d 4e 54 45 53 54 350 * ssid 4d 4e 54 45 53 54
372 */ 351 */
373static int lbs_scan_add_ssid_tlv(uint8_t *tlv, 352static int lbs_scan_add_ssid_tlv(struct lbs_private *priv, u8 *tlv)
374 const struct lbs_ioctl_user_scan_cfg *user_cfg)
375{ 353{
376 struct mrvlietypes_ssidparamset *ssid_tlv = (void *)tlv; 354 struct mrvlietypes_ssidparamset *ssid_tlv = (void *)tlv;
377 355
378 ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID); 356 ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID);
379 ssid_tlv->header.len = cpu_to_le16(user_cfg->ssid_len); 357 ssid_tlv->header.len = cpu_to_le16(priv->scan_ssid_len);
380 memcpy(ssid_tlv->ssid, user_cfg->ssid, user_cfg->ssid_len); 358 memcpy(ssid_tlv->ssid, priv->scan_ssid, priv->scan_ssid_len);
381 return sizeof(ssid_tlv->header) + user_cfg->ssid_len; 359 return sizeof(ssid_tlv->header) + priv->scan_ssid_len;
382} 360}
383 361
384 362
@@ -461,8 +439,7 @@ static int lbs_scan_add_rates_tlv(uint8_t *tlv)
461 * for a bunch of channels. 439 * for a bunch of channels.
462 */ 440 */
463static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype, 441static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype,
464 struct chanscanparamset *chan_list, int chan_count, 442 struct chanscanparamset *chan_list, int chan_count)
465 const struct lbs_ioctl_user_scan_cfg *user_cfg)
466{ 443{
467 int ret = -ENOMEM; 444 int ret = -ENOMEM;
468 struct cmd_ds_802_11_scan *scan_cmd; 445 struct cmd_ds_802_11_scan *scan_cmd;
@@ -477,13 +454,13 @@ static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype,
477 goto out; 454 goto out;
478 455
479 tlv = scan_cmd->tlvbuffer; 456 tlv = scan_cmd->tlvbuffer;
480 if (user_cfg) 457 /* TODO: do we need to scan for a specific BSSID?
481 memcpy(scan_cmd->bssid, user_cfg->bssid, ETH_ALEN); 458 memcpy(scan_cmd->bssid, priv->scan_bssid, ETH_ALEN); */
482 scan_cmd->bsstype = bsstype; 459 scan_cmd->bsstype = bsstype;
483 460
484 /* add TLVs */ 461 /* add TLVs */
485 if (user_cfg && user_cfg->ssid_len) 462 if (priv->scan_ssid_len)
486 tlv += lbs_scan_add_ssid_tlv(tlv, user_cfg); 463 tlv += lbs_scan_add_ssid_tlv(priv, tlv);
487 if (chan_list && chan_count) 464 if (chan_list && chan_count)
488 tlv += lbs_scan_add_chanlist_tlv(tlv, chan_list, chan_count); 465 tlv += lbs_scan_add_chanlist_tlv(tlv, chan_list, chan_count);
489 tlv += lbs_scan_add_rates_tlv(tlv); 466 tlv += lbs_scan_add_rates_tlv(tlv);
@@ -516,14 +493,11 @@ out:
516 * update the internal driver scan table 493 * update the internal driver scan table
517 * 494 *
518 * @param priv A pointer to struct lbs_private structure 495 * @param priv A pointer to struct lbs_private structure
519 * @param puserscanin Pointer to the input configuration for the requested 496 * @param full_scan Do a full-scan (blocking)
520 * scan.
521 * 497 *
522 * @return 0 or < 0 if error 498 * @return 0 or < 0 if error
523 */ 499 */
524int lbs_scan_networks(struct lbs_private *priv, 500static int lbs_scan_networks(struct lbs_private *priv, int full_scan)
525 const struct lbs_ioctl_user_scan_cfg *user_cfg,
526 int full_scan)
527{ 501{
528 int ret = -ENOMEM; 502 int ret = -ENOMEM;
529 struct chanscanparamset *chan_list; 503 struct chanscanparamset *chan_list;
@@ -531,7 +505,6 @@ int lbs_scan_networks(struct lbs_private *priv,
531 int chan_count; 505 int chan_count;
532 uint8_t bsstype = CMD_BSS_TYPE_ANY; 506 uint8_t bsstype = CMD_BSS_TYPE_ANY;
533 int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD; 507 int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD;
534 int filteredscan = 0;
535 union iwreq_data wrqu; 508 union iwreq_data wrqu;
536#ifdef CONFIG_LIBERTAS_DEBUG 509#ifdef CONFIG_LIBERTAS_DEBUG
537 struct bss_descriptor *iter; 510 struct bss_descriptor *iter;
@@ -547,17 +520,16 @@ int lbs_scan_networks(struct lbs_private *priv,
547 if (full_scan && delayed_work_pending(&priv->scan_work)) 520 if (full_scan && delayed_work_pending(&priv->scan_work))
548 cancel_delayed_work(&priv->scan_work); 521 cancel_delayed_work(&priv->scan_work);
549 522
550 /* Determine same scan parameters */ 523 /* User-specified bsstype or channel list
524 TODO: this can be implemented if some user-space application
525 need the feature. Formerly, it was accessible from debugfs,
526 but then nowhere used.
551 if (user_cfg) { 527 if (user_cfg) {
552 if (user_cfg->bsstype) 528 if (user_cfg->bsstype)
553 bsstype = user_cfg->bsstype; 529 bsstype = user_cfg->bsstype;
554 if (!is_zero_ether_addr(user_cfg->bssid)) { 530 } */
555 numchannels = MRVDRV_MAX_CHANNELS_PER_SCAN; 531
556 filteredscan = 1; 532 lbs_deb_scan("numchannels %d, bsstype %d\n", numchannels, bsstype);
557 }
558 }
559 lbs_deb_scan("numchannels %d, bsstype %d, filteredscan %d\n",
560 numchannels, bsstype, filteredscan);
561 533
562 /* Create list of channels to scan */ 534 /* Create list of channels to scan */
563 chan_list = kzalloc(sizeof(struct chanscanparamset) * 535 chan_list = kzalloc(sizeof(struct chanscanparamset) *
@@ -568,7 +540,7 @@ int lbs_scan_networks(struct lbs_private *priv,
568 } 540 }
569 541
570 /* We want to scan all channels */ 542 /* We want to scan all channels */
571 chan_count = lbs_scan_create_channel_list(priv, chan_list, filteredscan); 543 chan_count = lbs_scan_create_channel_list(priv, chan_list);
572 544
573 netif_stop_queue(priv->dev); 545 netif_stop_queue(priv->dev);
574 netif_carrier_off(priv->dev); 546 netif_carrier_off(priv->dev);
@@ -597,7 +569,7 @@ int lbs_scan_networks(struct lbs_private *priv,
597 lbs_deb_scan("scanning %d of %d channels\n", 569 lbs_deb_scan("scanning %d of %d channels\n",
598 to_scan, chan_count); 570 to_scan, chan_count);
599 ret = lbs_do_scan(priv, bsstype, curr_chans, 571 ret = lbs_do_scan(priv, bsstype, curr_chans,
600 to_scan, user_cfg); 572 to_scan);
601 if (ret) { 573 if (ret) {
602 lbs_pr_err("SCAN_CMD failed\n"); 574 lbs_pr_err("SCAN_CMD failed\n");
603 goto out2; 575 goto out2;
@@ -658,6 +630,17 @@ out:
658 630
659 631
660 632
633void lbs_scan_worker(struct work_struct *work)
634{
635 struct lbs_private *priv =
636 container_of(work, struct lbs_private, scan_work.work);
637
638 lbs_deb_enter(LBS_DEB_SCAN);
639 lbs_scan_networks(priv, 0);
640 lbs_deb_leave(LBS_DEB_SCAN);
641}
642
643
661/*********************************************************************/ 644/*********************************************************************/
662/* */ 645/* */
663/* Result interpretation */ 646/* Result interpretation */
@@ -1068,7 +1051,7 @@ static struct bss_descriptor *lbs_find_best_ssid_in_list(struct lbs_private *pri
1068} 1051}
1069 1052
1070/** 1053/**
1071 * @brief Find the AP with specific ssid in the scan list 1054 * @brief Find the best AP
1072 * 1055 *
1073 * Used from association worker. 1056 * Used from association worker.
1074 * 1057 *
@@ -1086,7 +1069,8 @@ int lbs_find_best_network_ssid(struct lbs_private *priv, uint8_t *out_ssid,
1086 1069
1087 lbs_deb_enter(LBS_DEB_SCAN); 1070 lbs_deb_enter(LBS_DEB_SCAN);
1088 1071
1089 lbs_scan_networks(priv, NULL, 1); 1072 priv->scan_ssid_len = 0;
1073 lbs_scan_networks(priv, 1);
1090 if (priv->surpriseremoved) 1074 if (priv->surpriseremoved)
1091 goto out; 1075 goto out;
1092 1076
@@ -1112,29 +1096,24 @@ out:
1112 * @param priv A pointer to struct lbs_private structure 1096 * @param priv A pointer to struct lbs_private structure
1113 * @param ssid A pointer to the SSID to scan for 1097 * @param ssid A pointer to the SSID to scan for
1114 * @param ssid_len Length of the SSID 1098 * @param ssid_len Length of the SSID
1115 * @param clear_ssid Should existing scan results with this SSID
1116 * be cleared?
1117 * 1099 *
1118 * @return 0-success, otherwise fail 1100 * @return 0-success, otherwise fail
1119 */ 1101 */
1120int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid, 1102int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid,
1121 uint8_t ssid_len, uint8_t clear_ssid) 1103 uint8_t ssid_len)
1122{ 1104{
1123 struct lbs_ioctl_user_scan_cfg scancfg;
1124 int ret = 0; 1105 int ret = 0;
1125 1106
1126 lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s', clear %d", 1107 lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s'\n",
1127 escape_essid(ssid, ssid_len), clear_ssid); 1108 escape_essid(ssid, ssid_len));
1128 1109
1129 if (!ssid_len) 1110 if (!ssid_len)
1130 goto out; 1111 goto out;
1131 1112
1132 memset(&scancfg, 0x00, sizeof(scancfg)); 1113 memcpy(priv->scan_ssid, ssid, ssid_len);
1133 memcpy(scancfg.ssid, ssid, ssid_len); 1114 priv->scan_ssid_len = ssid_len;
1134 scancfg.ssid_len = ssid_len;
1135 scancfg.clear_ssid = clear_ssid;
1136 1115
1137 lbs_scan_networks(priv, &scancfg, 1); 1116 lbs_scan_networks(priv, 1);
1138 if (priv->surpriseremoved) { 1117 if (priv->surpriseremoved) {
1139 ret = -1; 1118 ret = -1;
1140 goto out; 1119 goto out;
@@ -1317,27 +1296,36 @@ out:
1317 * @return 0 --success, otherwise fail 1296 * @return 0 --success, otherwise fail
1318 */ 1297 */
1319int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, 1298int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
1320 struct iw_param *wrqu, char *extra) 1299 union iwreq_data *wrqu, char *extra)
1321{ 1300{
1322 struct lbs_private *priv = dev->priv; 1301 struct lbs_private *priv = dev->priv;
1302 int ret = 0;
1323 1303
1324 lbs_deb_enter(LBS_DEB_SCAN); 1304 lbs_deb_enter(LBS_DEB_WEXT);
1325 1305
1326 if (!netif_running(dev)) 1306 if (!netif_running(dev)) {
1327 return -ENETDOWN; 1307 ret = -ENETDOWN;
1308 goto out;
1309 }
1328 1310
1329 /* mac80211 does this: 1311 /* mac80211 does this:
1330 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1312 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1331 if (sdata->type != IEEE80211_IF_TYPE_xxx) 1313 if (sdata->type != IEEE80211_IF_TYPE_xxx) {
1332 return -EOPNOTSUPP; 1314 ret = -EOPNOTSUPP;
1315 goto out;
1316 }
1317 */
1333 1318
1334 if (wrqu->data.length == sizeof(struct iw_scan_req) && 1319 if (wrqu->data.length == sizeof(struct iw_scan_req) &&
1335 wrqu->data.flags & IW_SCAN_THIS_ESSID) { 1320 wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1336 req = (struct iw_scan_req *)extra; 1321 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1337 ssid = req->essid; 1322 priv->scan_ssid_len = req->essid_len;
1338 ssid_len = req->essid_len; 1323 memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len);
1324 lbs_deb_wext("set_scan, essid '%s'\n",
1325 escape_essid(priv->scan_ssid, priv->scan_ssid_len));
1326 } else {
1327 priv->scan_ssid_len = 0;
1339 } 1328 }
1340 */
1341 1329
1342 if (!delayed_work_pending(&priv->scan_work)) 1330 if (!delayed_work_pending(&priv->scan_work))
1343 queue_delayed_work(priv->work_thread, &priv->scan_work, 1331 queue_delayed_work(priv->work_thread, &priv->scan_work,
@@ -1346,10 +1334,11 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
1346 priv->scan_channel = -1; 1334 priv->scan_channel = -1;
1347 1335
1348 if (priv->surpriseremoved) 1336 if (priv->surpriseremoved)
1349 return -EIO; 1337 ret = -EIO;
1350 1338
1351 lbs_deb_leave(LBS_DEB_SCAN); 1339out:
1352 return 0; 1340 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1341 return ret;
1353} 1342}
1354 1343
1355 1344
@@ -1374,7 +1363,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
1374 struct bss_descriptor *iter_bss; 1363 struct bss_descriptor *iter_bss;
1375 struct bss_descriptor *safe; 1364 struct bss_descriptor *safe;
1376 1365
1377 lbs_deb_enter(LBS_DEB_SCAN); 1366 lbs_deb_enter(LBS_DEB_WEXT);
1378 1367
1379 /* iwlist should wait until the current scan is finished */ 1368 /* iwlist should wait until the current scan is finished */
1380 if (priv->scan_channel) 1369 if (priv->scan_channel)
@@ -1418,7 +1407,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
1418 dwrq->length = (ev - extra); 1407 dwrq->length = (ev - extra);
1419 dwrq->flags = 0; 1408 dwrq->flags = 0;
1420 1409
1421 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", err); 1410 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err);
1422 return err; 1411 return err;
1423} 1412}
1424 1413