aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/net/wireless/libertas/assoc.c4
-rw-r--r--drivers/net/wireless/libertas/debugfs.c169
-rw-r--r--drivers/net/wireless/libertas/dev.h2
-rw-r--r--drivers/net/wireless/libertas/scan.c145
-rw-r--r--drivers/net/wireless/libertas/scan.h69
-rw-r--r--drivers/net/wireless/libertas/wext.c3
6 files changed, 76 insertions, 316 deletions
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index 7fe37bedf313..707b7ff592ec 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -38,7 +38,7 @@ static int assoc_helper_essid(struct lbs_private *priv,
38 escape_essid(assoc_req->ssid, assoc_req->ssid_len)); 38 escape_essid(assoc_req->ssid, assoc_req->ssid_len));
39 if (assoc_req->mode == IW_MODE_INFRA) { 39 if (assoc_req->mode == IW_MODE_INFRA) {
40 lbs_send_specific_ssid_scan(priv, assoc_req->ssid, 40 lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
41 assoc_req->ssid_len, 0); 41 assoc_req->ssid_len);
42 42
43 bss = lbs_find_ssid_in_list(priv, assoc_req->ssid, 43 bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
44 assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel); 44 assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel);
@@ -53,7 +53,7 @@ static int assoc_helper_essid(struct lbs_private *priv,
53 * scan data will cause us to join a non-existant adhoc network 53 * scan data will cause us to join a non-existant adhoc network
54 */ 54 */
55 lbs_send_specific_ssid_scan(priv, assoc_req->ssid, 55 lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
56 assoc_req->ssid_len, 1); 56 assoc_req->ssid_len);
57 57
58 /* Search for the requested SSID in the scan table */ 58 /* Search for the requested SSID in the scan table */
59 bss = lbs_find_ssid_in_list(priv, assoc_req->ssid, 59 bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index b600f2439b57..8f88786b036f 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -164,173 +164,6 @@ out_unlock:
164 return ret; 164 return ret;
165} 165}
166 166
167static ssize_t lbs_extscan(struct file *file, const char __user *userbuf,
168 size_t count, loff_t *ppos)
169{
170 struct lbs_private *priv = file->private_data;
171 ssize_t res, buf_size;
172 union iwreq_data wrqu;
173 unsigned long addr = get_zeroed_page(GFP_KERNEL);
174 char *buf = (char *)addr;
175
176 buf_size = min(count, len - 1);
177 if (copy_from_user(buf, userbuf, buf_size)) {
178 res = -EFAULT;
179 goto out_unlock;
180 }
181
182 lbs_send_specific_ssid_scan(priv, buf, strlen(buf)-1, 0);
183
184 memset(&wrqu, 0, sizeof(union iwreq_data));
185 wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
186
187out_unlock:
188 free_page(addr);
189 return count;
190}
191
192static void lbs_parse_bssid(char *buf, size_t count,
193 struct lbs_ioctl_user_scan_cfg *scan_cfg)
194{
195 char *hold;
196 unsigned int mac[ETH_ALEN];
197
198 hold = strstr(buf, "bssid=");
199 if (!hold)
200 return;
201 hold += 6;
202 sscanf(hold, "%02x:%02x:%02x:%02x:%02x:%02x",
203 mac, mac+1, mac+2, mac+3, mac+4, mac+5);
204 memcpy(scan_cfg->bssid, mac, ETH_ALEN);
205}
206
207static void lbs_parse_ssid(char *buf, size_t count,
208 struct lbs_ioctl_user_scan_cfg *scan_cfg)
209{
210 char *hold, *end;
211 ssize_t size;
212
213 hold = strstr(buf, "ssid=");
214 if (!hold)
215 return;
216 hold += 5;
217 end = strchr(hold, ' ');
218 if (!end)
219 end = buf + count - 1;
220
221 size = min((size_t)IW_ESSID_MAX_SIZE, (size_t) (end - hold));
222 strncpy(scan_cfg->ssid, hold, size);
223
224 return;
225}
226
227static int lbs_parse_clear(char *buf, size_t count, const char *tag)
228{
229 char *hold;
230 int val;
231
232 hold = strstr(buf, tag);
233 if (!hold)
234 return 0;
235 hold += strlen(tag);
236 sscanf(hold, "%d", &val);
237
238 if (val != 0)
239 val = 1;
240
241 return val;
242}
243
244static int lbs_parse_dur(char *buf, size_t count,
245 struct lbs_ioctl_user_scan_cfg *scan_cfg)
246{
247 char *hold;
248 int val;
249
250 hold = strstr(buf, "dur=");
251 if (!hold)
252 return 0;
253 hold += 4;
254 sscanf(hold, "%d", &val);
255
256 return val;
257}
258
259static void lbs_parse_type(char *buf, size_t count,
260 struct lbs_ioctl_user_scan_cfg *scan_cfg)
261{
262 char *hold;
263 int val;
264
265 hold = strstr(buf, "type=");
266 if (!hold)
267 return;
268 hold += 5;
269 sscanf(hold, "%d", &val);
270
271 /* type=1,2 or 3 */
272 if (val < 1 || val > 3)
273 return;
274
275 scan_cfg->bsstype = val;
276
277 return;
278}
279
280static ssize_t lbs_setuserscan(struct file *file,
281 const char __user *userbuf,
282 size_t count, loff_t *ppos)
283{
284 struct lbs_private *priv = file->private_data;
285 ssize_t res, buf_size;
286 struct lbs_ioctl_user_scan_cfg *scan_cfg;
287 union iwreq_data wrqu;
288 int dur;
289 char *buf = (char *)get_zeroed_page(GFP_KERNEL);
290
291 if (!buf)
292 return -ENOMEM;
293
294 buf_size = min(count, len - 1);
295 if (copy_from_user(buf, userbuf, buf_size)) {
296 res = -EFAULT;
297 goto out_buf;
298 }
299
300 scan_cfg = kzalloc(sizeof(struct lbs_ioctl_user_scan_cfg), GFP_KERNEL);
301 if (!scan_cfg) {
302 res = -ENOMEM;
303 goto out_buf;
304 }
305 res = count;
306
307 scan_cfg->bsstype = LBS_SCAN_BSS_TYPE_ANY;
308
309 dur = lbs_parse_dur(buf, count, scan_cfg);
310 lbs_parse_bssid(buf, count, scan_cfg);
311 scan_cfg->clear_bssid = lbs_parse_clear(buf, count, "clear_bssid=");
312 lbs_parse_ssid(buf, count, scan_cfg);
313 scan_cfg->clear_ssid = lbs_parse_clear(buf, count, "clear_ssid=");
314 lbs_parse_type(buf, count, scan_cfg);
315
316 lbs_scan_networks(priv, scan_cfg, 1);
317 wait_event_interruptible(priv->cmd_pending,
318 priv->surpriseremoved || !priv->scan_channel);
319
320 if (priv->surpriseremoved)
321 goto out_scan_cfg;
322
323 memset(&wrqu, 0x00, sizeof(union iwreq_data));
324 wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
325
326 out_scan_cfg:
327 kfree(scan_cfg);
328 out_buf:
329 free_page((unsigned long)buf);
330 return res;
331}
332
333
334/* 167/*
335 * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might 168 * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might
336 * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the 169 * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the
@@ -857,8 +690,6 @@ static struct lbs_debugfs_files debugfs_files[] = {
857 write_file_dummy), }, 690 write_file_dummy), },
858 { "sleepparams", 0644, FOPS(lbs_sleepparams_read, 691 { "sleepparams", 0644, FOPS(lbs_sleepparams_read,
859 lbs_sleepparams_write), }, 692 lbs_sleepparams_write), },
860 { "extscan", 0600, FOPS(NULL, lbs_extscan), },
861 { "setuserscan", 0600, FOPS(NULL, lbs_setuserscan), },
862}; 693};
863 694
864static struct lbs_debugfs_files debugfs_events_files[] = { 695static struct lbs_debugfs_files debugfs_events_files[] = {
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index fd1fcc748010..ff2c046ca73f 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -149,6 +149,8 @@ struct lbs_private {
149 struct work_struct sync_channel; 149 struct work_struct sync_channel;
150 /* remember which channel was scanned last, != 0 if currently scanning */ 150 /* remember which channel was scanned last, != 0 if currently scanning */
151 int scan_channel; 151 int scan_channel;
152 u8 scan_ssid[IW_ESSID_MAX_SIZE + 1];
153 u8 scan_ssid_len;
152 154
153 /** Hardware access */ 155 /** Hardware access */
154 int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); 156 int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
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
diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h
index 10d1196acf78..c50c8b74714b 100644
--- a/drivers/net/wireless/libertas/scan.h
+++ b/drivers/net/wireless/libertas/scan.h
@@ -12,8 +12,6 @@
12 12
13/** 13/**
14 * @brief Maximum number of channels that can be sent in a setuserscan ioctl 14 * @brief Maximum number of channels that can be sent in a setuserscan ioctl
15 *
16 * @sa lbs_ioctl_user_scan_cfg
17 */ 15 */
18#define LBS_IOCTL_USER_SCAN_CHAN_MAX 50 16#define LBS_IOCTL_USER_SCAN_CHAN_MAX 50
19 17
@@ -27,60 +25,6 @@
27#define LBS_SCAN_BSS_TYPE_ANY 3 25#define LBS_SCAN_BSS_TYPE_ANY 3
28 26
29/** 27/**
30 * @brief IOCTL channel sub-structure sent in lbs_ioctl_user_scan_cfg
31 *
32 * Multiple instances of this structure are included in the IOCTL command
33 * to configure a instance of a scan on the specific channel.
34 */
35struct lbs_ioctl_user_scan_chan {
36 u8 channumber; //!< channel Number to scan
37 u8 radiotype; //!< Radio type: 'B/G' band = 0, 'A' band = 1
38 u8 scantype; //!< Scan type: Active = 0, Passive = 1
39 u16 scantime; //!< Scan duration in milliseconds; if 0 default used
40};
41
42/**
43 * @brief IOCTL input structure to configure an immediate scan cmd to firmware
44 *
45 * Used in the setuserscan (LBS_SET_USER_SCAN) private ioctl. Specifies
46 * a number of parameters to be used in general for the scan as well
47 * as a channel list (lbs_ioctl_user_scan_chan) for each scan period
48 * desired.
49 *
50 * @sa lbs_set_user_scan_ioctl
51 */
52struct lbs_ioctl_user_scan_cfg {
53 /**
54 * @brief BSS type to be sent in the firmware command
55 *
56 * Field can be used to restrict the types of networks returned in the
57 * scan. valid settings are:
58 *
59 * - LBS_SCAN_BSS_TYPE_BSS (infrastructure)
60 * - LBS_SCAN_BSS_TYPE_IBSS (adhoc)
61 * - LBS_SCAN_BSS_TYPE_ANY (unrestricted, adhoc and infrastructure)
62 */
63 u8 bsstype;
64
65 /**
66 * @brief BSSID filter sent in the firmware command to limit the results
67 */
68 u8 bssid[ETH_ALEN];
69
70 /* Clear existing scan results matching this BSSID */
71 u8 clear_bssid;
72
73 /**
74 * @brief SSID filter sent in the firmware command to limit the results
75 */
76 char ssid[IW_ESSID_MAX_SIZE];
77 u8 ssid_len;
78
79 /* Clear existing scan results matching this SSID */
80 u8 clear_ssid;
81};
82
83/**
84 * @brief Structure used to store information for each beacon/probe response 28 * @brief Structure used to store information for each beacon/probe response
85 */ 29 */
86struct bss_descriptor { 30struct bss_descriptor {
@@ -136,21 +80,12 @@ int lbs_find_best_network_ssid(struct lbs_private *priv, u8 *out_ssid,
136 u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode); 80 u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode);
137 81
138int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid, 82int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
139 u8 ssid_len, u8 clear_ssid); 83 u8 ssid_len);
140
141int lbs_scan_networks(struct lbs_private *priv,
142 const struct lbs_ioctl_user_scan_cfg *puserscanin,
143 int full_scan);
144
145struct ifreq;
146 84
147struct iw_point;
148struct iw_param;
149struct iw_request_info;
150int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, 85int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
151 struct iw_point *dwrq, char *extra); 86 struct iw_point *dwrq, char *extra);
152int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, 87int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
153 struct iw_param *vwrq, char *extra); 88 union iwreq_data *wrqu, char *extra);
154 89
155void lbs_scan_worker(struct work_struct *work); 90void lbs_scan_worker(struct work_struct *work);
156 91
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index e8bfc26b10a4..cded4bb69164 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -579,6 +579,9 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
579 range->num_bitrates); 579 range->num_bitrates);
580 580
581 range->num_frequency = 0; 581 range->num_frequency = 0;
582
583 range->scan_capa = IW_SCAN_CAPA_ESSID;
584
582 if (priv->enable11d && 585 if (priv->enable11d &&
583 (priv->connect_status == LBS_CONNECTED || 586 (priv->connect_status == LBS_CONNECTED ||
584 priv->mesh_connect_status == LBS_CONNECTED)) { 587 priv->mesh_connect_status == LBS_CONNECTED)) {