Skip to content

Commit

Permalink
wl12xx: add support for sched_scan filters
Browse files Browse the repository at this point in the history
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: Luciano Coelho <coelho@ti.com>
  • Loading branch information
Luciano Coelho committed Sep 14, 2011
1 parent 1ec23f7 commit fb55377
Showing 1 changed file with 72 additions and 35 deletions.
107 changes: 72 additions & 35 deletions drivers/net/wireless/wl12xx/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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,
Expand Down Expand Up @@ -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");
Expand Down

0 comments on commit fb55377

Please sign in to comment.