NESTED_ATTR_UNSPECIFIED = 2,
};
+/* Preferred channel list information */
+
+/* GO role */
+#define WEIGHTED_PCL_GO BIT(0)
+/* P2P Client role */
+#define WEIGHTED_PCL_CLI BIT(1)
+/* Must be considered for operating channel */
+#define WEIGHTED_PCL_MUST_CONSIDER BIT(2)
+/* Should be excluded in GO negotiation */
+#define WEIGHTED_PCL_EXCLUDE BIT(3)
+
+/* Preferred channel list with weight */
+struct weighted_pcl {
+ u32 freq; /* MHz */
+ u8 weight;
+ u32 flag; /* bitmap for WEIGHTED_PCL_* */
+};
+
/**
* struct wpa_driver_ops - Driver interface API definition
*
* @priv: Private driver interface data
* @if_type: Interface type
* @num: Number of channels
- * @freq_list: Preferred channel frequency list encoded in MHz values
+ * @freq_list: Weighted preferred channel list
* Returns 0 on success, -1 on failure
*
* This command can be used to query the preferred frequency list from
- * the driver specific to a particular interface type.
+ * the driver specific to a particular interface type. The freq_list
+ * array needs to have room for *num entries. *num will be updated to
+ * indicate the number of entries fetched from the driver.
*/
int (*get_pref_freq_list)(void *priv, enum wpa_driver_if_type if_type,
- unsigned int *num, unsigned int *freq_list);
+ unsigned int *num,
+ struct weighted_pcl *freq_list);
/**
* set_prob_oper_freq - Indicate probable P2P operating channel
struct nl80211_pcl {
unsigned int num;
- unsigned int *freq_list;
+ struct weighted_pcl *freq_list;
};
+static void get_pcl_attr_values(struct weighted_pcl *wpcl, struct nlattr *nl[])
+{
+ if (nl[QCA_WLAN_VENDOR_ATTR_PCL_FREQ])
+ wpcl->freq = nla_get_u32(nl[QCA_WLAN_VENDOR_ATTR_PCL_FREQ]);
+ if (nl[QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT])
+ wpcl->weight = nla_get_u8(nl[QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT]);
+ if (nl[QCA_WLAN_VENDOR_ATTR_PCL_FLAG]) {
+ u32 flags = nla_get_u32(nl[QCA_WLAN_VENDOR_ATTR_PCL_FLAG]);
+
+ wpcl->flag = 0;
+ if (flags & BIT(0))
+ wpcl->flag |= WEIGHTED_PCL_GO;
+ if (flags & BIT(1))
+ wpcl->flag |= WEIGHTED_PCL_CLI;
+ if (flags & BIT(2))
+ wpcl->flag |= WEIGHTED_PCL_MUST_CONSIDER;
+ if (flags & BIT(3))
+ wpcl->flag |= WEIGHTED_PCL_EXCLUDE;
+ } else {
+ wpcl->flag = WEIGHTED_PCL_GO | WEIGHTED_PCL_CLI;
+ }
+}
+
+
static int preferred_freq_info_handler(struct nl_msg *msg, void *arg)
{
struct nlattr *tb[NL80211_ATTR_MAX + 1];
struct nlattr *nl_vend, *attr;
enum qca_iface_type iface_type;
struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_MAX + 1];
+ struct nlattr *nl_pcl[QCA_WLAN_VENDOR_ATTR_PCL_MAX + 1];
unsigned int num, max_num;
u32 *freqs;
wpa_printf(MSG_DEBUG, "nl80211: Driver returned iface_type=%d",
iface_type);
- attr = tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST];
- if (!attr) {
+ attr = tb_vendor[
+ QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_WEIGHED_PCL];
+ if (attr) {
+ int rem;
+ struct nlattr *wpcl = attr;
+ unsigned int i;
+
+ num = 0;
+ nla_for_each_nested(attr, wpcl, rem) {
+ if (num == param->num)
+ break; /* not enough room for all entries */
+ if (nla_parse(nl_pcl, QCA_WLAN_VENDOR_ATTR_PCL_MAX,
+ nla_data(attr), nla_len(attr), NULL)) {
+ wpa_printf(MSG_ERROR,
+ "nl80211: Failed to parse PCL info");
+ param->num = 0;
+ return NL_SKIP;
+ }
+ get_pcl_attr_values(¶m->freq_list[num], nl_pcl);
+ num++;
+ }
+ param->num = num;
+
+ /* Sort frequencies based on their weight */
+ for (i = 0; i < num; i++) {
+ unsigned int j;
+
+ for (j = i + 1; j < num; j++) {
+ if (param->freq_list[i].weight <
+ param->freq_list[j].weight) {
+ struct weighted_pcl tmp;
+
+ tmp = param->freq_list[i];
+ param->freq_list[i] =
+ param->freq_list[j];
+ param->freq_list[j] = tmp;
+ }
+ }
+ }
+ } else if (tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST]) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Driver does not provide weighted PCL; use the non-weighted variant");
+ attr = tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST];
+ /*
+ * param->num has the maximum number of entries for which there
+ * is room in the freq_list provided by the caller.
+ */
+ freqs = nla_data(attr);
+ max_num = nla_len(attr) / sizeof(u32);
+ if (max_num > param->num)
+ max_num = param->num;
+ for (num = 0; num < max_num; num++) {
+ param->freq_list[num].freq = freqs[num];
+ param->freq_list[num].flag =
+ WEIGHTED_PCL_GO | WEIGHTED_PCL_CLI;
+ }
+ param->num = num;
+ } else {
wpa_printf(MSG_ERROR,
"nl80211: preferred_freq_list couldn't be found");
param->num = 0;
return NL_SKIP;
}
-
- /*
- * param->num has the maximum number of entries for which there
- * is room in the freq_list provided by the caller.
- */
- freqs = nla_data(attr);
- max_num = nla_len(attr) / sizeof(u32);
- if (max_num > param->num)
- max_num = param->num;
- for (num = 0; num < max_num; num++)
- param->freq_list[num] = freqs[num];
- param->num = num;
-
return NL_SKIP;
}
static int nl80211_get_pref_freq_list(void *priv,
enum wpa_driver_if_type if_type,
unsigned int *num,
- unsigned int *freq_list)
+ struct weighted_pcl *freq_list)
{
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
}
nla_nest_end(msg, params);
- os_memset(freq_list, 0, *num * sizeof(freq_list[0]));
+ if (freq_list)
+ os_memset(freq_list, 0, *num * sizeof(struct weighted_pcl));
ret = send_and_recv_msgs(drv, msg, preferred_freq_info_handler, ¶m,
NULL, NULL);
if (ret) {
*num = param.num;
for (i = 0; i < *num; i++) {
- wpa_printf(MSG_DEBUG, "nl80211: preferred_channel_list[%d]=%d",
- i, freq_list[i]);
+ wpa_printf(MSG_DEBUG,
+ "nl80211: preferred_channel_list[%d]=%d[%d]:0x%x",
+ i, freq_list[i].freq, freq_list[i].weight,
+ freq_list[i].flag);
}
return 0;
void p2p_set_own_pref_freq_list(struct p2p_data *p2p,
- const unsigned int *pref_freq_list,
+ const struct weighted_pcl *pref_freq_list,
unsigned int size)
{
unsigned int i;
if (size > P2P_MAX_PREF_CHANNELS)
size = P2P_MAX_PREF_CHANNELS;
p2p->num_pref_freq = size;
+ os_memcpy(p2p->pref_freq_list, pref_freq_list,
+ size * sizeof(struct weighted_pcl));
for (i = 0; i < size; i++) {
- p2p->pref_freq_list[i] = pref_freq_list[i];
p2p_dbg(p2p, "Own preferred frequency list[%u]=%u MHz",
- i, p2p->pref_freq_list[i]);
+ i, p2p->pref_freq_list[i].freq);
}
}
#include "common/ieee802_11_defs.h"
#include "wps/wps.h"
+struct weighted_pcl;
+
/* P2P ASP Setup Capability */
#define P2PS_SETUP_NONE 0
#define P2PS_SETUP_NEW BIT(0)
* the driver specific to a particular interface type.
*/
int (*get_pref_freq_list)(void *ctx, int go,
- unsigned int *len, unsigned int *freq_list);
+ unsigned int *len,
+ struct weighted_pcl *freq_list);
};
const u8 *go_dev_addr,
const u8 *ssid, size_t ssid_len);
+bool p2p_pref_freq_allowed(const struct weighted_pcl *freq_list, bool go);
+
struct p2p_nfc_params {
int sel;
const u8 *wsc_attr;
void p2p_expire_peers(struct p2p_data *p2p);
void p2p_set_own_pref_freq_list(struct p2p_data *p2p,
- const unsigned int *pref_freq_list,
+ const struct weighted_pcl *pref_freq_list,
unsigned int size);
void p2p_set_override_pref_op_chan(struct p2p_data *p2p, u8 op_class,
u8 chan);
bool p2p_wfd_enabled(struct p2p_data *p2p);
bool is_p2p_allow_6ghz(struct p2p_data *p2p);
void set_p2p_allow_6ghz(struct p2p_data *p2p, bool value);
-int p2p_remove_6ghz_channels(unsigned int *pref_freq_list, int size);
+int p2p_remove_6ghz_channels(struct weighted_pcl *pref_freq_list, int size);
#endif /* P2P_H */
void p2p_buf_add_pref_channel_list(struct wpabuf *buf,
- const unsigned int *preferred_freq_list,
+ const struct weighted_pcl *pref_freq_list,
unsigned int size)
{
unsigned int i, count = 0;
* of the vendor IE size.
*/
for (i = 0; i < size; i++) {
- if (p2p_freq_to_channel(preferred_freq_list[i], &op_class,
- &op_channel) == 0)
+ if (p2p_freq_to_channel(pref_freq_list[i].freq, &op_class,
+ &op_channel) == 0 &&
+ !(pref_freq_list[i].flag & WEIGHTED_PCL_EXCLUDE))
count++;
}
wpabuf_put_be24(buf, OUI_QCA);
wpabuf_put_u8(buf, QCA_VENDOR_ELEM_P2P_PREF_CHAN_LIST);
for (i = 0; i < size; i++) {
- if (p2p_freq_to_channel(preferred_freq_list[i], &op_class,
- &op_channel) < 0) {
+ if (p2p_freq_to_channel(pref_freq_list[i].freq, &op_class,
+ &op_channel) < 0 ||
+ (pref_freq_list[i].flag & WEIGHTED_PCL_EXCLUDE)) {
wpa_printf(MSG_DEBUG, "Unsupported frequency %u MHz",
- preferred_freq_list[i]);
+ pref_freq_list[i].freq);
continue;
}
wpabuf_put_u8(buf, op_class);
p2p_buf_add_intended_addr(buf, p2p->intended_addr);
is_6ghz_capab = is_p2p_6ghz_capable(p2p) &&
p2p_is_peer_6ghz_capab(p2p, peer->info.p2p_device_addr);
- p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->channels,
- is_6ghz_capab);
+ if (p2p->num_pref_freq) {
+ bool go = p2p->go_intent == 15;
+ struct p2p_channels pref_chanlist;
+
+ p2p_pref_channel_filter(&p2p->channels, p2p->pref_freq_list,
+ p2p->num_pref_freq, &pref_chanlist, go);
+ p2p_channels_dump(p2p, "channel list after filtering",
+ &pref_chanlist);
+ p2p_buf_add_channel_list(buf, p2p->cfg->country,
+ &pref_chanlist, is_6ghz_capab);
+ } else {
+ p2p_buf_add_channel_list(buf, p2p->cfg->country,
+ &p2p->channels, is_6ghz_capab);
+ }
p2p_buf_add_device_info(buf, p2p, peer);
p2p_buf_add_operating_channel(buf, p2p->cfg->country,
p2p->op_reg_class, p2p->op_channel);
size_t extra = 0;
u16 pw_id;
bool is_6ghz_capab;
+ struct p2p_channels pref_chanlist;
p2p_dbg(p2p, "Building GO Negotiation Response");
p2p->op_channel);
}
p2p_buf_add_intended_addr(buf, p2p->intended_addr);
+ if (p2p->num_pref_freq) {
+ bool go = (peer && peer->go_state == LOCAL_GO) ||
+ p2p->go_intent == 15;
+
+ p2p_pref_channel_filter(&p2p->channels, p2p->pref_freq_list,
+ p2p->num_pref_freq, &pref_chanlist, go);
+ p2p_channels_dump(p2p, "channel list after filtering",
+ &pref_chanlist);
+ } else {
+ p2p_copy_channels(&pref_chanlist, &p2p->channels,
+ p2p->allow_6ghz);
+ }
if (status || peer == NULL) {
p2p_buf_add_channel_list(buf, p2p->cfg->country,
- &p2p->channels, false);
+ &pref_chanlist, false);
} else if (peer->go_state == REMOTE_GO) {
is_6ghz_capab = is_p2p_6ghz_capable(p2p) &&
p2p_is_peer_6ghz_capab(p2p, peer->info.p2p_device_addr);
p2p_buf_add_channel_list(buf, p2p->cfg->country,
- &p2p->channels, is_6ghz_capab);
+ &pref_chanlist, is_6ghz_capab);
} else {
struct p2p_channels res;
is_6ghz_capab = is_p2p_6ghz_capable(p2p) &&
p2p_is_peer_6ghz_capab(p2p, peer->info.p2p_device_addr);
- p2p_channels_intersect(&p2p->channels, &peer->channels,
+ p2p_channels_intersect(&pref_chanlist, &peer->channels,
&res);
p2p_buf_add_channel_list(buf, p2p->cfg->country, &res,
is_6ghz_capab);
static void p2p_check_pref_chan_no_recv(struct p2p_data *p2p, int go,
struct p2p_device *dev,
struct p2p_message *msg,
- unsigned freq_list[], unsigned int size)
+ const struct weighted_pcl freq_list[],
+ unsigned int size)
{
u8 op_class, op_channel;
unsigned int oper_freq = 0, i, j;
*/
for (i = 0; i < size && !found; i++) {
/* Make sure that the common frequency is supported by peer. */
- oper_freq = freq_list[i];
+ oper_freq = freq_list[i].freq;
if (p2p_freq_to_channel(oper_freq, &op_class,
- &op_channel) < 0)
- continue; /* cannot happen due to earlier check */
+ &op_channel) < 0 ||
+ !p2p_pref_freq_allowed(&freq_list[i], go))
+ continue;
for (j = 0; j < msg->channel_list_len; j++) {
if (!msg->channel_list ||
op_channel != msg->channel_list[j])
static void p2p_check_pref_chan_recv(struct p2p_data *p2p, int go,
struct p2p_device *dev,
struct p2p_message *msg,
- unsigned freq_list[], unsigned int size)
+ const struct weighted_pcl freq_list[],
+ unsigned int size)
{
u8 op_class, op_channel;
unsigned int oper_freq = 0, i, j;
oper_freq = p2p_channel_to_freq(
msg->pref_freq_list[2 * j],
msg->pref_freq_list[2 * j + 1]);
- if (freq_list[i] != oper_freq)
+ if (freq_list[i].freq != oper_freq)
continue;
if (p2p_freq_to_channel(oper_freq, &op_class,
&op_channel) < 0)
continue; /* cannot happen */
+ if (!p2p_pref_freq_allowed(&freq_list[i], go))
+ break;
p2p->op_reg_class = op_class;
p2p->op_channel = op_channel;
os_memcpy(&p2p->channels, &p2p->cfg->channels,
void p2p_check_pref_chan(struct p2p_data *p2p, int go,
struct p2p_device *dev, struct p2p_message *msg)
{
- unsigned int freq_list[P2P_MAX_PREF_CHANNELS], size;
+ unsigned int size;
unsigned int i;
u8 op_class, op_channel;
char txt[100], *pos, *end;
/* Obtain our preferred frequency list from driver based on P2P role. */
size = P2P_MAX_PREF_CHANNELS;
- if (p2p->cfg->get_pref_freq_list(p2p->cfg->cb_ctx, go, &size,
- freq_list))
+ if (p2p->cfg->get_pref_freq_list(p2p->cfg->cb_ctx, go,
+ &p2p->num_pref_freq,
+ p2p->pref_freq_list))
+ return;
+ size = p2p->num_pref_freq;
+ if (!size)
return;
/* Filter out frequencies that are not acceptable for P2P use */
i = 0;
while (i < size) {
- if (p2p_freq_to_channel(freq_list[i], &op_class,
- &op_channel) < 0 ||
+ if (p2p_freq_to_channel(p2p->pref_freq_list[i].freq,
+ &op_class, &op_channel) < 0 ||
(!p2p_channels_includes(&p2p->cfg->channels,
op_class, op_channel) &&
(go || !p2p_channels_includes(&p2p->cfg->cli_channels,
op_class, op_channel)))) {
p2p_dbg(p2p,
"Ignore local driver frequency preference %u MHz since it is not acceptable for P2P use (go=%d)",
- freq_list[i], go);
+ p2p->pref_freq_list[i].freq, go);
if (size - i - 1 > 0)
- os_memmove(&freq_list[i], &freq_list[i + 1],
+ os_memmove(&p2p->pref_freq_list[i],
+ &p2p->pref_freq_list[i + 1],
(size - i - 1) *
- sizeof(unsigned int));
+ sizeof(struct weighted_pcl));
size--;
continue;
}
pos = txt;
end = pos + sizeof(txt);
for (i = 0; i < size; i++) {
- res = os_snprintf(pos, end - pos, " %u", freq_list[i]);
+ res = os_snprintf(pos, end - pos, " %u",
+ p2p->pref_freq_list[i].freq);
if (os_snprintf_error(end - pos, res))
break;
pos += res;
* our preferred channel list.
*/
for (i = 0; i < size; i++) {
- if (freq_list[i] == (unsigned int) dev->oper_freq)
+ if (p2p->pref_freq_list[i].freq ==
+ (unsigned int) dev->oper_freq &&
+ p2p_pref_freq_allowed(&p2p->pref_freq_list[i], go))
break;
}
if (i != size &&
- p2p_freq_to_channel(freq_list[i], &op_class, &op_channel) == 0) {
+ p2p_freq_to_channel(p2p->pref_freq_list[i].freq, &op_class,
+ &op_channel) == 0) {
/* Peer operating channel preference matches our preference */
p2p->op_reg_class = op_class;
p2p->op_channel = op_channel;
* _not_ included in the GO Negotiation Request or Invitation Request.
*/
if (msg->pref_freq_list_len == 0)
- p2p_check_pref_chan_no_recv(p2p, go, dev, msg, freq_list, size);
+ p2p_check_pref_chan_no_recv(p2p, go, dev, msg,
+ p2p->pref_freq_list, size);
else
- p2p_check_pref_chan_recv(p2p, go, dev, msg, freq_list, size);
+ p2p_check_pref_chan_recv(p2p, go, dev, msg,
+ p2p->pref_freq_list, size);
}
#define P2P_I_H
#include "utils/list.h"
+#include "drivers/driver.h"
#include "p2p.h"
#define P2P_GO_NEG_CNF_MAX_RETRY_COUNT 1
struct wpabuf **vendor_elem;
- unsigned int pref_freq_list[P2P_MAX_PREF_CHANNELS];
+ struct weighted_pcl pref_freq_list[P2P_MAX_PREF_CHANNELS];
unsigned int num_pref_freq;
/* Override option for preferred operating channel in GO Negotiation */
int p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id,
int all_attr);
void p2p_buf_add_pref_channel_list(struct wpabuf *buf,
- const unsigned int *preferred_freq_list,
+ const struct weighted_pcl *pref_freq_list,
unsigned int size);
/* p2p_sd.c */
void p2p_go_neg_wait_timeout(void *eloop_ctx, void *timeout_ctx);
int p2p_go_select_channel(struct p2p_data *p2p, struct p2p_device *dev,
u8 *status);
+void p2p_pref_channel_filter(const struct p2p_channels *a,
+ const struct weighted_pcl *freq_list,
+ unsigned int num_channels,
+ struct p2p_channels *res, bool go);
void p2p_dbg(struct p2p_data *p2p, const char *fmt, ...)
PRINTF_FORMAT(2, 3);
void p2p_info(struct p2p_data *p2p, const char *fmt, ...)
}
-int p2p_remove_6ghz_channels(unsigned int *pref_freq_list, int size)
+int p2p_remove_6ghz_channels(struct weighted_pcl *pref_freq_list, int size)
{
int i;
for (i = 0; i < size; i++) {
- if (is_6ghz_freq(pref_freq_list[i])) {
+ if (is_6ghz_freq(pref_freq_list[i].freq)) {
wpa_printf(MSG_DEBUG, "P2P: Remove 6 GHz channel %d",
- pref_freq_list[i]);
+ pref_freq_list[i].freq);
size--;
os_memmove(&pref_freq_list[i], &pref_freq_list[i + 1],
(size - i) * sizeof(pref_freq_list[0]));
}
return i;
}
+
+
+/**
+ * p2p_pref_freq_allowed - Based on the flags set, check if the preferred
+ * frequency is allowed
+ * @freq_list: Weighted preferred channel list
+ * @go: Whether the local device is the group owner
+ * Returns: Whether the preferred frequency is allowed
+ */
+bool p2p_pref_freq_allowed(const struct weighted_pcl *freq_list, bool go)
+{
+ if (freq_list->flag & WEIGHTED_PCL_EXCLUDE)
+ return false;
+ if (!(freq_list->flag & WEIGHTED_PCL_CLI) && !go)
+ return false;
+ if (!(freq_list->flag & WEIGHTED_PCL_GO) && go)
+ return false;
+ return true;
+}
+
+
+static int p2p_check_pref_channel(int channel, u8 op_class,
+ const struct weighted_pcl *freq_list,
+ unsigned int num_channels, bool go)
+{
+ unsigned int i;
+
+ /* If the channel is present in the preferred channel list, check if it
+ * has appropriate flags for the role.
+ */
+ for (i = 0; i < num_channels; i++) {
+ if (p2p_channel_to_freq(op_class, channel) !=
+ (int) freq_list[i].freq)
+ continue;
+ if (!p2p_pref_freq_allowed(&freq_list[i], go))
+ return -1;
+ break;
+ }
+
+ return 0;
+}
+
+
+void p2p_pref_channel_filter(const struct p2p_channels *p2p_chan,
+ const struct weighted_pcl *freq_list,
+ unsigned int num_channels,
+ struct p2p_channels *res, bool go)
+{
+ size_t i, j;
+
+ os_memset(res, 0, sizeof(*res));
+
+ for (i = 0; i < p2p_chan->reg_classes; i++) {
+ const struct p2p_reg_class *reg = &p2p_chan->reg_class[i];
+ struct p2p_reg_class *res_reg = &res->reg_class[i];
+
+ if (num_channels > 0) {
+ for (j = 0; j < reg->channels; j++) {
+ if (p2p_check_pref_channel(reg->channel[j],
+ reg->reg_class,
+ freq_list,
+ num_channels,
+ go) < 0)
+ continue;
+
+ res_reg->channel[res_reg->channels++] =
+ reg->channel[j];
+ }
+ }
+
+ if (res_reg->channels == 0)
+ continue;
+ res->reg_classes++;
+ res_reg->reg_class = reg->reg_class;
+ }
+}
int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s,
enum wpa_driver_if_type if_type,
unsigned int *num,
- unsigned int *freq_list)
+ struct weighted_pcl *freq_list)
{
char *pos = wpa_s->get_pref_freq_list_override;
char *end;
pos++;
end = os_strchr(pos, ' ');
while (pos && (!end || pos < end) && count < *num) {
- freq_list[count++] = atoi(pos);
+ freq_list[count].freq = atoi(pos);
+ freq_list[count++].flag = WEIGHTED_PCL_GO | WEIGHTED_PCL_CLI;
pos = os_strchr(pos, ',');
if (pos)
pos++;
static int wpas_ctrl_iface_get_pref_freq_list(
struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
{
- unsigned int freq_list[100], num = 100, i;
+ unsigned int num = 100, i;
int ret;
enum wpa_driver_if_type iface_type;
char *pos, *end;
+ struct weighted_pcl freq_list[100];
pos = buf;
end = buf + buflen;
for (i = 0; i < num; i++) {
ret = os_snprintf(pos, end - pos, "%s%u",
- i > 0 ? "," : "", freq_list[i]);
+ i > 0 ? "," : "", freq_list[i].freq);
if (os_snprintf_error(end - pos, ret))
return -1;
pos += ret;
static inline int wpa_drv_get_pref_freq_list(struct wpa_supplicant *wpa_s,
enum wpa_driver_if_type if_type,
unsigned int *num,
- unsigned int *freq_list)
+ struct weighted_pcl *freq_list)
{
#ifdef CONFIG_TESTING_OPTIONS
if (wpa_s->get_pref_freq_list_override)
const u8 *ssid, size_t ssid_len);
static int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq,
int *force_freq, int *pref_freq, int go,
- unsigned int *pref_freq_list,
+ struct weighted_pcl *pref_freq_list,
unsigned int *num_pref_freq);
static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq,
const u8 *ssid, size_t ssid_len);
struct wpa_supplicant *go_wpa_s, *cli_wpa_s;
struct wpa_ssid *persistent_go;
int p2p_no_group_iface;
- unsigned int pref_freq_list[P2P_MAX_PREF_CHANNELS], size;
+ struct weighted_pcl pref_freq_list[P2P_MAX_PREF_CHANNELS];
+ unsigned int size;
wpa_printf(MSG_DEBUG, "P2P: Conncap - in:%d role:%d", incoming, role);
static int wpas_p2p_get_pref_freq_list(void *ctx, int go,
unsigned int *len,
- unsigned int *freq_list)
+ struct weighted_pcl *freq_list)
{
struct wpa_supplicant *wpa_s = ctx;
static int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq,
int *force_freq, int *pref_freq, int go,
- unsigned int *pref_freq_list,
+ struct weighted_pcl *pref_freq_list,
unsigned int *num_pref_freq)
{
struct wpa_used_freq_data *freqs;
i = 0;
while (i < *num_pref_freq &&
(!p2p_supported_freq(wpa_s->global->p2p,
- pref_freq_list[i]) ||
- wpas_p2p_disallowed_freq(wpa_s->global,
- pref_freq_list[i]))) {
+ pref_freq_list[i].freq) ||
+ wpas_p2p_disallowed_freq(
+ wpa_s->global,
+ pref_freq_list[i].freq) ||
+ !p2p_pref_freq_allowed(&pref_freq_list[i],
+ go))) {
wpa_printf(MSG_DEBUG,
"P2P: preferred_freq_list[%d]=%d is disallowed",
- i, pref_freq_list[i]);
+ i, pref_freq_list[i].freq);
i++;
}
if (i != *num_pref_freq) {
- best_freq = pref_freq_list[i];
+ best_freq = pref_freq_list[i].freq;
wpa_printf(MSG_DEBUG,
"P2P: Using preferred_freq_list[%d]=%d",
i, best_freq);
enum wpa_driver_if_type iftype;
const u8 *if_addr;
struct wpa_ssid *ssid = NULL;
- unsigned int pref_freq_list[P2P_MAX_PREF_CHANNELS], size;
+ struct weighted_pcl pref_freq_list[P2P_MAX_PREF_CHANNELS];
+ unsigned int size;
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return -1;
if (!wpa_s->conf->num_p2p_pref_chan && !freq) {
unsigned int i, size = P2P_MAX_PREF_CHANNELS;
- unsigned int pref_freq_list[P2P_MAX_PREF_CHANNELS];
+ struct weighted_pcl pref_freq_list[P2P_MAX_PREF_CHANNELS];
int res;
res = wpa_drv_get_pref_freq_list(wpa_s, WPA_IF_P2P_GO,
i = 0;
while (i < size &&
(!p2p_supported_freq(wpa_s->global->p2p,
- pref_freq_list[i]) ||
- wpas_p2p_disallowed_freq(wpa_s->global,
- pref_freq_list[i]))) {
+ pref_freq_list[i].freq) ||
+ wpas_p2p_disallowed_freq(
+ wpa_s->global,
+ pref_freq_list[i].freq) ||
+ !p2p_pref_freq_allowed(&pref_freq_list[i],
+ true))) {
wpa_printf(MSG_DEBUG,
"P2P: preferred_freq_list[%d]=%d is disallowed",
- i, pref_freq_list[i]);
+ i, pref_freq_list[i].freq);
i++;
}
if (i != size) {
- freq = pref_freq_list[i];
+ freq = pref_freq_list[i].freq;
wpa_printf(MSG_DEBUG,
"P2P: Using preferred_freq_list[%d]=%d",
i, freq);
int force_freq = 0;
int res;
int no_pref_freq_given = pref_freq == 0;
- unsigned int pref_freq_list[P2P_MAX_PREF_CHANNELS], size;
+ struct weighted_pcl pref_freq_list[P2P_MAX_PREF_CHANNELS];
+ unsigned int size;
if (wpas_p2p_check_6ghz(wpa_s, NULL, allow_6ghz, freq))
return -1;
int persistent;
int freq = 0, force_freq = 0, pref_freq = 0;
int res;
- unsigned int pref_freq_list[P2P_MAX_PREF_CHANNELS], size;
+ struct weighted_pcl pref_freq_list[P2P_MAX_PREF_CHANNELS];
+ unsigned int size;
wpa_s->p2p_persistent_go_freq = 0;
wpa_s->p2p_go_ht40 = 0;
int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s,
enum wpa_driver_if_type if_type,
unsigned int *num,
- unsigned int *freq_list);
+ struct weighted_pcl *freq_list);
int wpa_is_fils_supported(struct wpa_supplicant *wpa_s);
int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s);