Merge d04b231c96e87d4db7d7995c63f75d02c87ac710 on remote branch
Change-Id: Ida3b4259d618d1099699e10cf523f8ec4f20ef43
diff --git a/cld80211-lib/cld80211_lib.c b/cld80211-lib/cld80211_lib.c
index 1ca085a..e92d822 100644
--- a/cld80211-lib/cld80211_lib.c
+++ b/cld80211-lib/cld80211_lib.c
@@ -31,6 +31,9 @@
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
*
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#include <errno.h>
@@ -112,8 +115,10 @@
}
-void exit_cld80211_recv(struct cld80211_ctx *ctx)
+void exit_cld80211_recv(void *cldctx)
{
+ struct cld80211_ctx *ctx = (struct cld80211_ctx *) cldctx;
+
if (!ctx) {
ALOGE("%s: ctx is NULL: %s", getprogname(), __func__);
return;
@@ -257,8 +262,10 @@
}
-int cld80211_add_mcast_group(struct cld80211_ctx *ctx, const char* mcgroup)
+int cld80211_add_mcast_group(void *cldctx, const char* mcgroup)
{
+ struct cld80211_ctx *ctx = (struct cld80211_ctx *) cldctx;
+
if (!ctx || !mcgroup) {
ALOGE("%s: ctx/mcgroup is NULL: %s", getprogname(), __func__);
return 0;
@@ -280,7 +287,7 @@
}
-int cld80211_remove_mcast_group(struct cld80211_ctx *ctx, const char* mcgroup)
+int cld80211_remove_mcast_group(void *cldctx, const char* mcgroup)
{
// Drop membership is not a necessary cleanup action so comment it out.
#if 0
@@ -306,10 +313,11 @@
}
-struct nl_msg *cld80211_msg_alloc(struct cld80211_ctx *ctx, int cmd,
- struct nlattr **nla_data, int pid)
+struct nl_msg *cld80211_msg_alloc(void *cldctx, int cmd, struct nlattr **nla_data,
+ int pid)
{
struct nl_msg *nlmsg;
+ struct cld80211_ctx *ctx = (struct cld80211_ctx *) cldctx;
if (!ctx || !nla_data) {
ALOGE("%s: ctx is null: %s", getprogname(), __func__);
@@ -338,9 +346,10 @@
}
-int cld80211_send_msg(struct cld80211_ctx *ctx, struct nl_msg *nlmsg)
+int cld80211_send_msg(void *cldctx, struct nl_msg *nlmsg)
{
int err;
+ struct cld80211_ctx *ctx = (struct cld80211_ctx *) cldctx;
if (!ctx || !ctx->sock || !nlmsg) {
ALOGE("%s: Invalid data from client", getprogname());
@@ -357,11 +366,12 @@
}
-int cld80211_send_recv_msg(struct cld80211_ctx *ctx, struct nl_msg *nlmsg,
+int cld80211_send_recv_msg(void *cldctx, struct nl_msg *nlmsg,
int (*valid_handler)(struct nl_msg *, void *),
void *valid_data)
{
int err;
+ struct cld80211_ctx *ctx = (struct cld80211_ctx *) cldctx;
if (!ctx || !ctx->sock || !nlmsg) {
ALOGE("%s: Invalid data from client", getprogname());
@@ -403,13 +413,14 @@
}
-int cld80211_recv(struct cld80211_ctx *ctx, int timeout, bool recv_multi_msg,
+int cld80211_recv(void *cldctx, int timeout, bool recv_multi_msg,
int (*valid_handler)(struct nl_msg *, void *),
void *cbctx)
{
struct pollfd pfd[2];
struct nl_cb *cb;
int err;
+ struct cld80211_ctx *ctx = (struct cld80211_ctx *) cldctx;
if (!ctx || !ctx->sock || !valid_handler) {
ALOGE("%s: Invalid data from client", getprogname());
@@ -516,8 +527,10 @@
}
-void cld80211_deinit(struct cld80211_ctx *ctx)
+void cld80211_deinit(void *cldctx)
{
+ struct cld80211_ctx *ctx = (struct cld80211_ctx *) cldctx;
+
if (!ctx || !ctx->sock) {
ALOGE("%s: ctx/sock is NULL", getprogname());
return;
@@ -527,8 +540,10 @@
free (ctx);
}
-void cld80211_stop_recv(struct cld80211_ctx *ctx, bool is_terminating)
+void cld80211_stop_recv(void *cldctx, bool is_terminating)
{
+ struct cld80211_ctx *ctx = (struct cld80211_ctx *) cldctx;
+
if (!ctx || !ctx->sock) {
ALOGE("%s: ctx/sock is NULL", getprogname());
return;
@@ -536,3 +551,25 @@
ALOGE("%s: Program is terminating:%d", getprogname(), is_terminating);
ctx->is_terminating = is_terminating;
}
+
+struct nl_sock *cld80211_get_nl_socket_ctx(void *cldctx)
+{
+ struct cld80211_ctx *ctx = (struct cld80211_ctx *) cldctx;
+
+ if (!ctx || !ctx->sock) {
+ ALOGE("%s: ctx/sock is NULL", getprogname());
+ return NULL;
+ }
+ return ctx->sock;
+}
+
+int *cld80211_get_exit_socket_pair(void *cldctx)
+{
+ struct cld80211_ctx *ctx = (struct cld80211_ctx *) cldctx;
+
+ if (!ctx || !ctx->sock) {
+ ALOGE("%s: ctx/sock is NULL", getprogname());
+ return NULL;
+ }
+ return ctx->exit_sockets;
+}
diff --git a/cld80211-lib/cld80211_lib.h b/cld80211-lib/cld80211_lib.h
index c786361..ab5ba48 100644
--- a/cld80211-lib/cld80211_lib.h
+++ b/cld80211-lib/cld80211_lib.h
@@ -25,6 +25,9 @@
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#ifndef CLD80211_LIB_H
@@ -87,37 +90,37 @@
/**
* free the socket created in cld80211_init()
*/
-void cld80211_deinit(struct cld80211_ctx *ctx);
+void cld80211_deinit(void *cldctx);
/**
* Allocate nl_msg and populate family and genl header details
*/
-struct nl_msg *cld80211_msg_alloc(struct cld80211_ctx *ctx, int cmd,
- struct nlattr **nla_data, int pid);
+struct nl_msg *cld80211_msg_alloc(void *cldctx, int cmd, struct nlattr **nla_data,
+ int pid);
/**
* Send nlmsg to driver and return; It doesn't wait for response
*/
-int cld80211_send_msg(struct cld80211_ctx *ctx, struct nl_msg *nlmsg);
+int cld80211_send_msg(void *cldctx, struct nl_msg *nlmsg);
/**
* Send nlmsg to driver and get response, if any
*/
-int cld80211_send_recv_msg(struct cld80211_ctx *ctx, struct nl_msg *nlmsg,
- int (*valid_handler)(struct nl_msg *, void *),
- void *valid_data);
+int cld80211_send_recv_msg(void *cldctx, struct nl_msg *nlmsg,
+ int (*valid_handler)(struct nl_msg *, void *),
+ void *valid_data);
/**
* Add membership for multicast group "mcgroup" to receive the messages
* sent to this group from driver
*/
-int cld80211_add_mcast_group(struct cld80211_ctx *ctx, const char* mcgroup);
+int cld80211_add_mcast_group(void *cldctx, const char* mcgroup);
/**
* Remove membership of multicast group "mcgroup" to stop receiving messages
* sent to this group from driver
*/
-int cld80211_remove_mcast_group(struct cld80211_ctx *ctx, const char* mcgroup);
+int cld80211_remove_mcast_group(void *cldctx, const char* mcgroup);
/**
* Receive messages from driver on cld80211 family. Client can do
@@ -142,7 +145,7 @@
* nlmsg is received
* Returns corresponding errno when a failure happens while receiving nl msg
*/
-int cld80211_recv(struct cld80211_ctx *ctx, int timeout, bool recv_multi_msg,
+int cld80211_recv(void *cldctx, int timeout, bool recv_multi_msg,
int (*valid_handler)(struct nl_msg *, void *),
void *cbctx);
@@ -150,13 +153,23 @@
* poll() is a blocking call on sock. Client has to unblock the poll()
* first to exit gracefully.
*/
-void exit_cld80211_recv(struct cld80211_ctx *ctx);
+void exit_cld80211_recv(void *cldctx);
/**
* Client has to inform to exit gracefully during polling and reset the flag
* accordingly.
*/
-void cld80211_stop_recv(struct cld80211_ctx *ctx, bool is_terminating);
+void cld80211_stop_recv(void *cldctx, bool is_terminating);
+
+/**
+ * Get the nl socket context to listen to driver events.
+ */
+struct nl_sock *cld80211_get_nl_socket_ctx(void *cldctx);
+
+/**
+ * Get the exit socket pair for clients to stop listening to driver events.
+ */
+int *cld80211_get_exit_socket_pair(void *cldctx);
#ifdef __cplusplus
}
#endif
diff --git a/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c b/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
index f95a8fb..f93e64f 100644
--- a/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
+++ b/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211.c
@@ -268,7 +268,7 @@
};
-static char *get_next_arg(char *cmd)
+char *get_next_arg(char *cmd)
{
char *pos = cmd;
@@ -2724,7 +2724,7 @@
return (u32)val;
}
-static s32 get_s32_from_string(char *cmd_string, int *ret)
+s32 get_s32_from_string(char *cmd_string, int *ret)
{
s64 val64 = 0;
s32 val = 0;
diff --git a/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211_common.h b/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211_common.h
index 1fe2743..25b5f60 100644
--- a/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211_common.h
+++ b/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211_common.h
@@ -49,6 +49,9 @@
#include <netlink/object-api.h>
#include <linux/pkt_sched.h>
+#define OBSS_PD_THRESHOLD_MIN -82
+#define OBSS_PD_THRESHOLD_MAX -62
+
struct wpa_driver_nl80211_data *drv;
struct i802_bss *bss;
struct nl_msg *prepare_vendor_nlmsg(struct wpa_driver_nl80211_data *drv,
@@ -64,3 +67,5 @@
int wpa_driver_sr_event(struct wpa_driver_nl80211_data *drv,
u32 vendor_id, u32 subcmd, u8 *data, size_t len);
char *skip_white_space(char *cmd);
+char *get_next_arg(char *cmd);
+s32 get_s32_from_string(char *cmd_string, int *ret);
diff --git a/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211_sr.c b/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211_sr.c
index 8d8acd6..d0cb989 100644
--- a/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211_sr.c
+++ b/qcwcn/wpa_supplicant_8_lib/driver_cmd_nl80211_sr.c
@@ -80,7 +80,14 @@
*sr_cmd = QCA_WLAN_SR_OPERATION_GET_STATS;
else if (os_strncasecmp(cmd, "clearstats", 10) == 0)
*sr_cmd = QCA_WLAN_SR_OPERATION_CLEAR_STATS;
- else {
+ else if (os_strncasecmp(cmd, "getparams", 9) == 0) {
+ cmd += 9;
+ cmd = skip_white_space(cmd);
+ if (*cmd != '\0')
+ return -EINVAL;
+ else
+ *sr_cmd = QCA_WLAN_SR_OPERATION_GET_PARAMS;
+ } else {
wpa_printf(MSG_ERROR, "Unknown SR command:%s\n", cmd);
return -EINVAL;
}
@@ -159,6 +166,65 @@
return 0;
}
+static int parse_sr_get_params_response(struct resp_info *info,
+ struct nlattr *vendata, int datalen)
+{
+ int cmd_id, ret;
+ u8 srg_pd_offset_min = 0, srg_pd_offset_max = 0,
+ non_srg_pd_offset_max = 0, hesiga_val15_enable = 1,
+ non_srg_pd_disallow = 1;
+ struct nlattr *sr_attr[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_MAX + 1];
+
+ ret = nla_parse_nested(sr_attr, QCA_WLAN_VENDOR_ATTR_SR_PARAMS_MAX,
+ vendata, NULL);
+ if (ret) {
+ wpa_printf(MSG_ERROR, "SR params: nla_parse fail, error: %d", ret);
+ return ret;
+ }
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_OBSS_PD_MIN_OFFSET;
+ if (sr_attr[cmd_id])
+ srg_pd_offset_min = nla_get_u8(sr_attr[cmd_id]);
+ else
+ wpa_printf(MSG_INFO, "SR params: SRG PD min offset not found");
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_OBSS_PD_MAX_OFFSET;
+ if (sr_attr[cmd_id])
+ srg_pd_offset_max = nla_get_u8(sr_attr[cmd_id]);
+ else
+ wpa_printf(MSG_INFO, "SR params: SRG PD max offset not found");
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_OBSS_PD_MAX_OFFSET;
+ if (sr_attr[cmd_id])
+ non_srg_pd_offset_max = nla_get_u8(sr_attr[cmd_id]);
+ else
+ wpa_printf(MSG_INFO, "SR params: Non SRG PD max offset not found");
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_SR_PARAMS_HESIGA_VAL15_ENABLE;
+ if (!sr_attr[cmd_id]) {
+ wpa_printf(MSG_INFO, "SR params: Hesiga Val15 is not enabled by AP");
+ hesiga_val15_enable = 0;
+ }
+
+ cmd_id = QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_OBSS_PD_DISALLOW;
+ if (!sr_attr[cmd_id]) {
+ wpa_printf(MSG_INFO, "SR params: non SRG PD is not allowed by AP");
+ non_srg_pd_disallow = 0;
+ }
+
+ ret = os_snprintf(info->reply_buf, info->reply_buf_len,
+ "srg_obss_pd_min_offset: %u\nsrg_obss_pd_max_offset: %u\n"
+ "non_srg_obss_pd_max_offset: %u\nhesiga_val15_enable: %u\n"
+ "non_srg_pd_disallow: %u", srg_pd_offset_min,
+ srg_pd_offset_max, non_srg_pd_offset_max,
+ hesiga_val15_enable, non_srg_pd_disallow);
+ if (os_snprintf_error(info->reply_buf_len, ret)) {
+ wpa_printf(MSG_ERROR, "SR params: Failed to put in buffer, error: %d", ret);
+ return ret;
+ }
+ return 0;
+}
+
/**
* sr_response_unpack() - unpack the spatial reuse command response received from driver
*
@@ -179,16 +245,19 @@
switch (info->cmd_oper) {
case QCA_WLAN_SR_OPERATION_GET_STATS:
ret = parse_sr_get_stats_response(info, vendata, datalen);
- if (ret) {
- wpa_printf(MSG_ERROR, "Unpacking SR stats failed, error:%d\n",ret);
- return ret;
- }
+ if (ret)
+ wpa_printf(MSG_ERROR, "Unpacking SR stats failed, error:%d", ret);
+ break;
+ case QCA_WLAN_SR_OPERATION_GET_PARAMS:
+ ret = parse_sr_get_params_response(info, vendata, datalen);
+ if (ret)
+ wpa_printf(MSG_ERROR, "Unpacking SR params failed, error:%d", ret);
break;
default:
ret = -EINVAL;
- wpa_printf(MSG_ERROR, "Unsupported SR command:%d, error:%d\n",
+ wpa_printf(MSG_ERROR, "Unsupported SR command:%d, error:%d",
info->cmd_oper, ret);
- return ret;
+ break;
}
return ret;
}
@@ -216,15 +285,94 @@
drv = info->drv;
ret = sr_response_unpack(info, vendata, datalen);
- if (!ret)
- wpa_msg(drv->ctx, MSG_INFO, "CTRL-EVENT-SR STATS RESPONSE\n" "%s", info->reply_buf);
- else
- wpa_msg(drv->ctx, MSG_INFO, "CTRL-EVENT-SR STATS RESPONSE\n" " %s : Error = %d",
- info->reply_buf, ret);
-
+ switch (info->cmd_oper) {
+ case QCA_WLAN_SR_OPERATION_GET_STATS:
+ if (!ret)
+ wpa_msg(drv->ctx, MSG_INFO, "CTRL-EVENT-SR STATS RESPONSE\n"
+ "%s", info->reply_buf);
+ else
+ wpa_msg(drv->ctx, MSG_ERROR, "CTRL-EVENT-SR STATS RESPONSE\n"
+ " %s : Error = %d", info->reply_buf, ret);
+ break;
+ case QCA_WLAN_SR_OPERATION_GET_PARAMS:
+ if (!ret)
+ wpa_msg(drv->ctx, MSG_INFO, "CTRL-EVENT-SR PARAMS RESPONSE\n"
+ "%s", info->reply_buf);
+ else
+ wpa_msg(drv->ctx, MSG_ERROR, "CTRL-EVENT-SR PARAMS RESPONSE\n"
+ " %s : Error = %d", info->reply_buf, ret);
+ break;
+ }
return ret;
}
+static int pack_sr_enable_nlmsg(struct nl_msg *nlmsg, char *cmd)
+{
+
+ struct nlattr *sr_attr;
+ s8 is_srg_pd_cmd = 0, is_non_srg_pd_cmd = 0;
+ s32 pd_thres = 0, cmd_id;
+ int ret;
+
+ cmd += 6;
+ cmd = skip_white_space(cmd);
+ if (*cmd == '\0')
+ return 0;
+
+ sr_attr = nla_nest_start(nlmsg, QCA_WLAN_VENDOR_ATTR_SR_PARAMS);
+ if (!sr_attr)
+ return -ENOMEM;
+
+ for (int i = 0; i < 2; i++) {
+ if (os_strncasecmp(cmd, "srg_pd_threshold ", 17) == 0) {
+ cmd += 17;
+ cmd = skip_white_space(cmd);
+ pd_thres = get_s32_from_string(cmd, &ret);
+ if (ret < 0 || pd_thres < OBSS_PD_THRESHOLD_MIN ||
+ pd_thres > OBSS_PD_THRESHOLD_MAX) {
+ wpa_printf(MSG_ERROR, "Invalid SRG PD threshold: %d", pd_thres);
+ return -EINVAL;
+ }
+ cmd_id = QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_PD_THRESHOLD;
+ if (nla_put_s32(nlmsg, cmd_id, pd_thres)) {
+ wpa_printf(MSG_ERROR, "Failed to put SRG PD threshold");
+ return -ENOMEM;
+ }
+ is_srg_pd_cmd++;
+ } else if (os_strncasecmp(cmd, "non_srg_pd_threshold ", 21) == 0) {
+ cmd += 21;
+ cmd = skip_white_space(cmd);
+ pd_thres = get_s32_from_string(cmd, &ret);
+ /**
+ * For non-SRG OBSS, allowed range for PD threshold
+ * is -62 to -81 as -82 is fixed as min offset.
+ **/
+ if (ret < 0 || pd_thres <= OBSS_PD_THRESHOLD_MIN ||
+ pd_thres > OBSS_PD_THRESHOLD_MAX) {
+ wpa_printf(MSG_ERROR, "Invalid Non-SRG PD threshold: %d", pd_thres);
+ return -EINVAL;
+ }
+ cmd_id = QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_PD_THRESHOLD;
+ if (nla_put_s32(nlmsg, cmd_id, pd_thres)) {
+ wpa_printf(MSG_ERROR, "Failed to put Non-SRG PD threshold");
+ return -ENOMEM;
+ }
+ is_non_srg_pd_cmd++;
+ } else if (*cmd == '\0')
+ break;
+ else
+ return -EINVAL;
+
+ if (is_srg_pd_cmd > 1 || is_non_srg_pd_cmd > 1)
+ return -EINVAL;
+
+ cmd = get_next_arg(cmd);
+ cmd = skip_white_space(cmd);
+ }
+ nla_nest_end(nlmsg, sr_attr);
+ return 0;
+}
+
/**
* wpa_driver_sr_cmd() - handle the spatial reuse commands
*
@@ -288,11 +436,18 @@
}
switch (sr_cmd) {
case QCA_WLAN_SR_OPERATION_SR_ENABLE:
+ status = pack_sr_enable_nlmsg(nlmsg, cmd);
+ if (status < 0) {
+ wpa_printf(MSG_ERROR, "SR enable command failed: %d,"
+ "error:%d", sr_cmd, status);
+ goto nlmsg_fail;
+ }
case QCA_WLAN_SR_OPERATION_SR_DISABLE:
case QCA_WLAN_SR_OPERATION_PSR_AND_NON_SRG_OBSS_PD_PROHIBIT:
case QCA_WLAN_SR_OPERATION_PSR_AND_NON_SRG_OBSS_PD_ALLOW:
case QCA_WLAN_SR_OPERATION_GET_STATS:
case QCA_WLAN_SR_OPERATION_CLEAR_STATS:
+ case QCA_WLAN_SR_OPERATION_GET_PARAMS:
status = nla_put_u8(nlmsg, QCA_WLAN_VENDOR_ATTR_SR_OPERATION, sr_cmd);
if (status) {
wpa_printf(MSG_ERROR, "Fail to put SR command:%d, error:%d\n",
@@ -307,9 +462,14 @@
sr_cmd, status);
goto nlmsg_fail;
}
- status = send_nlmsg((struct nl_sock *)drv->global->nl, nlmsg,
- (sr_cmd == QCA_WLAN_SR_OPERATION_GET_STATS) ? response_handler : NULL,
- (sr_cmd == QCA_WLAN_SR_OPERATION_GET_STATS) ? &info : NULL);
+ if (sr_cmd == QCA_WLAN_SR_OPERATION_GET_STATS ||
+ sr_cmd == QCA_WLAN_SR_OPERATION_GET_PARAMS)
+ status = send_nlmsg((struct nl_sock *)drv->global->nl,
+ nlmsg, response_handler, &info);
+ else
+ status = send_nlmsg((struct nl_sock *)drv->global->nl,
+ nlmsg, NULL, NULL);
+
if (status) {
wpa_printf(MSG_ERROR, "Fail to send nlmsg SR command:%d to driver, error:%d\n",
sr_cmd, status);