|
@@ -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");
|