aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/wl12xx/scan.c107
1 files changed, 72 insertions, 35 deletions
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index 4a4d0d03fa1f..488033b2a39b 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -471,34 +471,77 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl,
cfg->passive[2] || cfg->active[2];
}
-/* Returns 0 if no wildcard is used, 1 if wildcard is used or a
- * negative value on error */
+/* Returns the scan type to be used or a negative value on error */
static int
wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
struct cfg80211_sched_scan_request *req)
{
struct wl1271_cmd_sched_scan_ssid_list *cmd = NULL;
- struct cfg80211_ssid *ssid = req->ssids;
- int ret, wildcard = 0;
+ struct cfg80211_match_set *sets = req->match_sets;
+ struct cfg80211_ssid *ssids = req->ssids;
+ int ret = 0, type, i, j;
wl1271_debug(DEBUG_CMD, "cmd sched scan ssid list");
+ /* No filter, no ssids or only bcast ssid */
+ if (!req->n_match_sets &&
+ (!req->n_ssids ||
+ (req->n_ssids == 1 && req->ssids[0].ssid_len == 0))) {
+ type = SCAN_SSID_FILTER_ANY;
+ goto out;
+ }
+
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
- if (!cmd)
- return -ENOMEM;
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (!req->n_match_sets) {
+ /* No filter, with ssids */
+ type = SCAN_SSID_FILTER_DISABLED;
+
+ for (i = 0; i < req->n_ssids; i++) {
+ cmd->ssids[cmd->n_ssids].type = (ssids[i].ssid_len) ?
+ SCAN_SSID_TYPE_HIDDEN : SCAN_SSID_TYPE_PUBLIC;
+ cmd->ssids[cmd->n_ssids].len = ssids[i].ssid_len;
+ memcpy(cmd->ssids[cmd->n_ssids].ssid, ssids[i].ssid,
+ ssids[i].ssid_len);
+ cmd->n_ssids++;
+ }
+ } else {
+ type = SCAN_SSID_FILTER_LIST;
- while ((cmd->n_ssids < req->n_ssids) && ssid) {
- if (ssid->ssid_len == 0) {
- wildcard = 1;
+ /* Add all SSIDs from the filters */
+ for (i = 0; i < req->n_match_sets; i++) {
cmd->ssids[cmd->n_ssids].type = SCAN_SSID_TYPE_PUBLIC;
- } else {
- cmd->ssids[cmd->n_ssids].type = SCAN_SSID_TYPE_HIDDEN;
+ cmd->ssids[cmd->n_ssids].len = sets[i].ssid.ssid_len;
+ memcpy(cmd->ssids[cmd->n_ssids].ssid,
+ sets[i].ssid.ssid, sets[i].ssid.ssid_len);
+ cmd->n_ssids++;
+ }
+ if ((req->n_ssids > 1) ||
+ (req->n_ssids == 1 && req->ssids[0].ssid_len > 0)) {
+ /*
+ * Mark all the SSIDs passed in the SSID list as HIDDEN,
+ * so they're used in probe requests.
+ */
+ for (i = 0; i < req->n_ssids; i++) {
+ for (j = 0; j < cmd->n_ssids; j++)
+ if (!memcmp(req->ssids[i].ssid,
+ cmd->ssids[j].ssid,
+ req->ssids[i].ssid_len)) {
+ cmd->ssids[j].type =
+ SCAN_SSID_TYPE_HIDDEN;
+ break;
+ }
+ /* Fail if SSID isn't present in the filters */
+ if (j == req->n_ssids) {
+ ret = -EINVAL;
+ goto out_free;
+ }
+ }
}
- cmd->ssids[cmd->n_ssids].len = ssid->ssid_len;
- memcpy(cmd->ssids[cmd->n_ssids].ssid, ssid->ssid,
- ssid->ssid_len);
- ssid++;
- cmd->n_ssids++;
}
wl1271_dump(DEBUG_SCAN, "SSID_LIST: ", cmd, sizeof(*cmd));
@@ -507,13 +550,15 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("cmd sched scan ssid list failed");
- goto out;
+ goto out_free;
}
- ret = wildcard;
-out:
+out_free:
kfree(cmd);
- return ret;
+out:
+ if (ret < 0)
+ return ret;
+ return type;
}
int wl1271_scan_sched_scan_config(struct wl1271 *wl,
@@ -548,21 +593,13 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
cfg->intervals[i] = cpu_to_le32(req->interval);
cfg->ssid_len = 0;
- if (req->n_ssids == 0) {
- wl1271_debug(DEBUG_SCAN, "using SCAN_SSID_FILTER_ANY");
- cfg->filter_type = SCAN_SSID_FILTER_ANY;
- } else {
- ret = wl12xx_scan_sched_scan_ssid_list(wl, req);
- if (ret < 0)
- goto out;
- if (ret) {
- wl1271_debug(DEBUG_SCAN, "using SCAN_SSID_FILTER_DISABLED");
- cfg->filter_type = SCAN_SSID_FILTER_DISABLED;
- } else {
- wl1271_debug(DEBUG_SCAN, "using SCAN_SSID_FILTER_LIST");
- cfg->filter_type = SCAN_SSID_FILTER_LIST;
- }
- }
+ ret = wl12xx_scan_sched_scan_ssid_list(wl, req);
+ if (ret < 0)
+ goto out;
+
+ cfg->filter_type = ret;
+
+ wl1271_debug(DEBUG_SCAN, "filter_type = %d", cfg->filter_type);
if (!wl1271_scan_sched_scan_channels(wl, req, cfg)) {
wl1271_error("scan channel list is empty");