Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f952079a authored by Luciano Coelho's avatar Luciano Coelho
Browse files

wl12xx: add support for multiple SSIDs in sched_scan



The wl12xx firmwares support multiple SSIDs in a single sched_scan
run.  This patch implements support for it.

We use three different types os sched_scan: FILTER_ANY (ie. not
filtering, only wildcard SSID in the probe_reqs); FILTER_LIST (ie. send out
probe_reqs with the specified SSIDs and only report if they are
found); and FILTER_DISABLED (ie. send out probe_reqs with the
specified SSIDs, but report anything found).

Since we still don't have proper filter support in nl80211/cfg80211
yet, we cannot use filters when the wildcard SSID is used.  Thus, we
will not filter anything if the wildcard SSID is specified.

Signed-off-by: default avatarLuciano Coelho <coelho@ti.com>
parent 05dba355
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -4491,6 +4491,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
	wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
		BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP);
	wl->hw->wiphy->max_scan_ssids = 1;
	wl->hw->wiphy->max_sched_scan_ssids = 8;
	/*
	 * Maximum length of elements in scanning probe request templates
	 * should be the maximum length possible for a template, without
+56 −7
Original line number Diff line number Diff line
@@ -473,6 +473,48 @@ 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 */
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;

	wl1271_debug(DEBUG_CMD, "cmd sched scan ssid list");

	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
	if (!cmd)
		return -ENOMEM;

	while ((cmd->n_ssids < req->n_ssids) && ssid) {
		if (ssid->ssid_len == 0)
			wildcard = 1;
		cmd->ssids[cmd->n_ssids].type = SCAN_SSID_TYPE_HIDDEN;
		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));

	ret = wl1271_cmd_send(wl, CMD_CONNECTION_SCAN_SSID_CFG, cmd,
			      sizeof(*cmd), 0);
	if (ret < 0) {
		wl1271_error("cmd sched scan ssid list failed");
		goto out;
	}

	ret = wildcard;
out:
	kfree(cmd);
	return ret;
}

int wl1271_scan_sched_scan_config(struct wl1271 *wl,
				  struct cfg80211_sched_scan_request *req,
				  struct ieee80211_sched_scan_ies *ies)
@@ -504,14 +546,21 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
	for (i = 0; i < SCAN_MAX_CYCLE_INTERVALS; i++)
		cfg->intervals[i] = cpu_to_le32(req->interval);

	if (!force_passive && req->ssids[0].ssid_len && req->ssids[0].ssid) {
		cfg->filter_type = SCAN_SSID_FILTER_SPECIFIC;
		cfg->ssid_len = req->ssids[0].ssid_len;
		memcpy(cfg->ssid, req->ssids[0].ssid,
		       req->ssids[0].ssid_len);
	} else {
		cfg->filter_type = SCAN_SSID_FILTER_ANY;
	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;
		}
	}

	if (!wl1271_scan_sched_scan_channels(wl, req, cfg)) {