Commit fb55377b authored by Luciano Coelho's avatar Luciano Coelho

wl12xx: add support for sched_scan filters

Implement support for filtering in scheduled scans.

With this commit we now use the match sets passed by cfg80211 to
filter on SSIDs.  Due to the nature of the wl12xx firmware API, we
don't allow SSIDs to be sent in the probe requests if they are not
going to match any of the filters.
Signed-off-by: default avatarLuciano Coelho <coelho@ti.com>
parent 1ec23f7f
...@@ -471,34 +471,77 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl, ...@@ -471,34 +471,77 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl,
cfg->passive[2] || cfg->active[2]; cfg->passive[2] || cfg->active[2];
} }
/* Returns 0 if no wildcard is used, 1 if wildcard is used or a /* Returns the scan type to be used or a negative value on error */
* negative value on error */
static int static int
wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
struct cfg80211_sched_scan_request *req) struct cfg80211_sched_scan_request *req)
{ {
struct wl1271_cmd_sched_scan_ssid_list *cmd = NULL; struct wl1271_cmd_sched_scan_ssid_list *cmd = NULL;
struct cfg80211_ssid *ssid = req->ssids; struct cfg80211_match_set *sets = req->match_sets;
int ret, wildcard = 0; struct cfg80211_ssid *ssids = req->ssids;
int ret = 0, type, i, j;
wl1271_debug(DEBUG_CMD, "cmd sched scan ssid list"); 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); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) if (!cmd) {
return -ENOMEM; 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) { /* Add all SSIDs from the filters */
if (ssid->ssid_len == 0) { for (i = 0; i < req->n_match_sets; i++) {
wildcard = 1;
cmd->ssids[cmd->n_ssids].type = SCAN_SSID_TYPE_PUBLIC; cmd->ssids[cmd->n_ssids].type = SCAN_SSID_TYPE_PUBLIC;
} else { cmd->ssids[cmd->n_ssids].len = sets[i].ssid.ssid_len;
cmd->ssids[cmd->n_ssids].type = SCAN_SSID_TYPE_HIDDEN; 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)); wl1271_dump(DEBUG_SCAN, "SSID_LIST: ", cmd, sizeof(*cmd));
...@@ -507,13 +550,15 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, ...@@ -507,13 +550,15 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
sizeof(*cmd), 0); sizeof(*cmd), 0);
if (ret < 0) { if (ret < 0) {
wl1271_error("cmd sched scan ssid list failed"); wl1271_error("cmd sched scan ssid list failed");
goto out; goto out_free;
} }
ret = wildcard; out_free:
out:
kfree(cmd); kfree(cmd);
return ret; out:
if (ret < 0)
return ret;
return type;
} }
int wl1271_scan_sched_scan_config(struct wl1271 *wl, int wl1271_scan_sched_scan_config(struct wl1271 *wl,
...@@ -548,21 +593,13 @@ 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->intervals[i] = cpu_to_le32(req->interval);
cfg->ssid_len = 0; cfg->ssid_len = 0;
if (req->n_ssids == 0) { ret = wl12xx_scan_sched_scan_ssid_list(wl, req);
wl1271_debug(DEBUG_SCAN, "using SCAN_SSID_FILTER_ANY"); if (ret < 0)
cfg->filter_type = SCAN_SSID_FILTER_ANY; goto out;
} else {
ret = wl12xx_scan_sched_scan_ssid_list(wl, req); cfg->filter_type = ret;
if (ret < 0)
goto out; wl1271_debug(DEBUG_SCAN, "filter_type = %d", cfg->filter_type);
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;
}
}
if (!wl1271_scan_sched_scan_channels(wl, req, cfg)) { if (!wl1271_scan_sched_scan_channels(wl, req, cfg)) {
wl1271_error("scan channel list is empty"); wl1271_error("scan channel list is empty");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment