blob: 37f517201fb9a385c95d4d94aaa170e105169934 [file] [log] [blame]
developerd243af02023-12-21 14:49:33 +08001From 7e1b6b0dc2167af5b9d58466ce693b67e6b5dbf2 Mon Sep 17 00:00:00 2001
developer1c2c7d42023-01-18 18:20:58 +08002From: Howard Hsu <howard-yh.hsu@mediatek.com>
3Date: Mon, 30 May 2022 16:31:34 +0800
developerd243af02023-12-21 14:49:33 +08004Subject: [PATCH 05/54] mtk: hostapd: Support EDCCA hostapd configuration
developer1c2c7d42023-01-18 18:20:58 +08005
6edcca_enable and edcca_compensation and implement edcca related handlers.
7---
developer004e50c2023-06-29 20:33:22 +08008 hostapd/config_file.c | 34 ++++++
9 hostapd/ctrl_iface.c | 125 +++++++++++++++++++++
developer1c2c7d42023-01-18 18:20:58 +080010 src/ap/ap_config.c | 4 +
developer004e50c2023-06-29 20:33:22 +080011 src/ap/ap_config.h | 30 ++++++
developer1c2c7d42023-01-18 18:20:58 +080012 src/ap/ap_drv_ops.c | 24 +++++
developer505c9432023-05-12 18:58:17 +080013 src/ap/ap_drv_ops.h | 4 +
developer1c2c7d42023-01-18 18:20:58 +080014 src/ap/hostapd.c | 7 ++
developer004e50c2023-06-29 20:33:22 +080015 src/common/mtk_vendor.h | 20 ++--
developer1c2c7d42023-01-18 18:20:58 +080016 src/drivers/driver.h | 4 +
developer004e50c2023-06-29 20:33:22 +080017 src/drivers/driver_nl80211.c | 174 ++++++++++++++++++++++++++++++
developer1c2c7d42023-01-18 18:20:58 +080018 src/drivers/driver_nl80211.h | 1 +
19 src/drivers/driver_nl80211_capa.c | 7 ++
developer004e50c2023-06-29 20:33:22 +080020 12 files changed, 428 insertions(+), 6 deletions(-)
developer1c2c7d42023-01-18 18:20:58 +080021
22diff --git a/hostapd/config_file.c b/hostapd/config_file.c
developerd243af02023-12-21 14:49:33 +080023index 4b0f99fd2..d281026e8 100644
developer1c2c7d42023-01-18 18:20:58 +080024--- a/hostapd/config_file.c
25+++ b/hostapd/config_file.c
developere35b8e42023-10-16 11:04:00 +080026@@ -4809,6 +4809,40 @@ static int hostapd_config_fill(struct hostapd_config *conf,
27 return 1;
28 }
developer1c2c7d42023-01-18 18:20:58 +080029 #endif /* CONFIG_IEEE80211BE */
30+ } else if (os_strcmp(buf, "edcca_threshold") == 0) {
31+ if (hostapd_parse_intlist(&conf->edcca_threshold, pos) ||
32+ conf->edcca_threshold[0] < EDCCA_MIN_CONFIG_THRES ||
33+ conf->edcca_threshold[0] > EDCCA_MAX_CONFIG_THRES ||
34+ conf->edcca_threshold[1] < EDCCA_MIN_CONFIG_THRES ||
35+ conf->edcca_threshold[1] > EDCCA_MAX_CONFIG_THRES ||
36+ conf->edcca_threshold[2] < EDCCA_MIN_CONFIG_THRES ||
developer004e50c2023-06-29 20:33:22 +080037+ conf->edcca_threshold[2] > EDCCA_MAX_CONFIG_THRES ||
38+ conf->edcca_threshold[3] < EDCCA_MIN_CONFIG_THRES ||
39+ conf->edcca_threshold[3] > EDCCA_MAX_CONFIG_THRES) {
developer1c2c7d42023-01-18 18:20:58 +080040+ wpa_printf(MSG_ERROR, "Line %d: invalid edcca threshold",
41+ line);
42+ return 1;
43+ }
44+ } else if (os_strcmp(buf, "edcca_enable") == 0) {
45+ int mode = atoi(pos);
46+ if (mode < EDCCA_MODE_FORCE_DISABLE || mode > EDCCA_MODE_AUTO) {
47+ wpa_printf(MSG_ERROR, "Line %d: Invalid edcca_enable %d;"
48+ " allowed value 0 (Force Disable) or 1(Auto) ",
49+ line, mode);
50+ return 1;
51+ }
52+ conf->edcca_enable = (u8) mode;
53+ } else if (os_strcmp(buf, "edcca_compensation") == 0) {
54+ int val = atoi(pos);
55+ if (val < EDCCA_MIN_COMPENSATION ||
56+ val > EDCCA_MAX_COMPENSATION) {
57+ wpa_printf(MSG_ERROR, "Line %d: Invalid compensation"
58+ " value %d; allowed value %d ~ %d.",
59+ line, val, EDCCA_MIN_COMPENSATION,
60+ EDCCA_MAX_COMPENSATION);
61+ return 1;
62+ }
63+ conf->edcca_compensation = (s8) val;
64 } else {
65 wpa_printf(MSG_ERROR,
66 "Line %d: unknown configuration item '%s'",
67diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
developerd243af02023-12-21 14:49:33 +080068index ee6d492f8..cad3f863c 100644
developer1c2c7d42023-01-18 18:20:58 +080069--- a/hostapd/ctrl_iface.c
70+++ b/hostapd/ctrl_iface.c
developerdfb50982023-09-11 13:34:36 +080071@@ -542,6 +542,19 @@ static const char * pbc_status_str(enum pbc_status status)
developer1c2c7d42023-01-18 18:20:58 +080072 }
73
74
developer004e50c2023-06-29 20:33:22 +080075+static const char *edcca_mode_str(enum edcca_mode status)
developer1c2c7d42023-01-18 18:20:58 +080076+{
77+ switch (status) {
78+ case EDCCA_MODE_FORCE_DISABLE:
79+ return "Force Disable";
80+ case EDCCA_MODE_AUTO:
81+ return "Auto";
82+ default:
83+ return "Unknown";
84+ }
85+}
86+
87+
88 static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd,
89 char *buf, size_t buflen)
90 {
developerdfb50982023-09-11 13:34:36 +080091@@ -3369,6 +3382,112 @@ static int hostapd_ctrl_iface_driver_cmd(struct hostapd_data *hapd, char *cmd,
developer1c2c7d42023-01-18 18:20:58 +080092 #endif /* ANDROID */
93
94
95+static int
96+hostapd_ctrl_iface_set_edcca(struct hostapd_data *hapd, char *cmd,
97+ char *buf, size_t buflen)
98+{
99+ char *pos, *config, *value;
100+ config = cmd;
101+ pos = os_strchr(config, ' ');
102+ if (pos == NULL)
103+ return -1;
104+ *pos++ = '\0';
105+
developer004e50c2023-06-29 20:33:22 +0800106+ if (pos == NULL)
developer1c2c7d42023-01-18 18:20:58 +0800107+ return -1;
108+ value = pos;
109+
110+ if (os_strcmp(config, "enable") == 0) {
111+ int mode = atoi(value);
112+ if (mode < EDCCA_MODE_FORCE_DISABLE || mode > EDCCA_MODE_AUTO) {
113+ wpa_printf(MSG_ERROR, "Invalid value for edcca enable");
114+ return -1;
115+ }
116+ hapd->iconf->edcca_enable = (u8) mode;
117+ if (hostapd_drv_configure_edcca_enable(hapd) != 0)
118+ return -1;
119+ } else if (os_strcmp(config, "compensation") == 0) {
120+ int compensation = atoi(value);
121+ if (compensation < EDCCA_MIN_COMPENSATION ||
122+ compensation > EDCCA_MAX_COMPENSATION) {
123+ wpa_printf(MSG_ERROR, "Invalid value for edcca compensation");
124+ return -1;
125+ }
126+ hapd->iconf->edcca_compensation = (s8) compensation;
127+ if (hostapd_drv_configure_edcca_enable(hapd) != 0)
128+ return -1;
129+ } else if (os_strcmp(config, "threshold") == 0) {
130+ char *thres_value;
131+ thres_value = os_strchr(value, ':');
132+ if (thres_value == NULL)
133+ return -1;
134+ *thres_value++ = '\0';
135+
developer004e50c2023-06-29 20:33:22 +0800136+ if (thres_value == NULL)
developer1c2c7d42023-01-18 18:20:58 +0800137+ return -1;
developer004e50c2023-06-29 20:33:22 +0800138+ int bw_idx = atoi(value);
developer1c2c7d42023-01-18 18:20:58 +0800139+ int threshold = atoi(thres_value);
140+
developer004e50c2023-06-29 20:33:22 +0800141+ if (bw_idx < EDCCA_BW_20 || bw_idx > EDCCA_BW_160) {
developer1c2c7d42023-01-18 18:20:58 +0800142+ wpa_printf(MSG_ERROR,
143+ "Unsupported Bandwidth idx %d for SET_EDCCA",
144+ bw_idx);
145+ return -1;
146+ }
147+ if (threshold < EDCCA_MIN_CONFIG_THRES ||
148+ threshold > EDCCA_MAX_CONFIG_THRES) {
149+ wpa_printf(MSG_ERROR,
150+ "Unsupported threshold %d for SET_EDCCA",
151+ threshold);
152+ return -1;
153+ }
154+
155+ int threshold_arr[EDCCA_MAX_BW_NUM];
156+ /* 0x7f means keep the origival value in firmware */
157+ os_memset(threshold_arr, 0x7f, sizeof(threshold_arr));
158+ threshold_arr[bw_idx] = threshold;
159+
160+ if (hostapd_drv_configure_edcca_threshold(hapd, threshold_arr) != 0)
161+ return -1;
162+ } else {
163+ wpa_printf(MSG_ERROR,
164+ "Unsupported parameter %s for SET_EDCCA", config);
165+ return -1;
166+ }
167+ return os_snprintf(buf, buflen, "OK\n");
168+}
169+
170+
171+static int
172+hostapd_ctrl_iface_get_edcca(struct hostapd_data *hapd, char *cmd, char *buf,
173+ size_t buflen)
174+{
175+ char *pos, *end;
176+
177+ pos = buf;
178+ end = buf + buflen;
179+ u8 value[EDCCA_MAX_BW_NUM] = {0};
180+
181+ if (os_strcmp(cmd, "enable") == 0) {
182+ return os_snprintf(pos, end - pos, "Enable: %s\n",
183+ edcca_mode_str(hapd->iconf->edcca_enable));
184+ } else if (os_strcmp(cmd, "compensation") == 0) {
185+ return os_snprintf(pos, end - pos, "Compensation: %d\n",
186+ hapd->iconf->edcca_compensation);
187+ } else if (os_strcmp(cmd, "threshold") == 0) {
188+ if (hostapd_drv_get_edcca(hapd, EDCCA_CTRL_GET_THRES, &value) != 0)
189+ return -1;
190+ return os_snprintf(pos, end - pos,
developer004e50c2023-06-29 20:33:22 +0800191+ "Threshold BW20: 0x%x, BW40: 0x%x, BW80: 0x%x, BW160: 0x%x\n",
192+ value[0], value[1], value[2], value[3]);
developer1c2c7d42023-01-18 18:20:58 +0800193+ } else {
194+ wpa_printf(MSG_ERROR,
195+ "Unsupported parameter %s for GET_EDCCA", cmd);
196+ return -1;
197+ }
198+}
199+
200+
201 static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
202 char *buf, char *reply,
203 int reply_size,
developerdfb50982023-09-11 13:34:36 +0800204@@ -3922,6 +4041,12 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
developer1c2c7d42023-01-18 18:20:58 +0800205 reply_len = hostapd_ctrl_iface_driver_cmd(hapd, buf + 7, reply,
206 reply_size);
207 #endif /* ANDROID */
208+ } else if (os_strncmp(buf, "SET_EDCCA ", 10) == 0) {
209+ reply_len = hostapd_ctrl_iface_set_edcca(hapd, buf+10, reply,
210+ reply_size);
211+ } else if (os_strncmp(buf, "GET_EDCCA ", 10) == 0) {
212+ reply_len = hostapd_ctrl_iface_get_edcca(hapd, buf+10, reply,
213+ reply_size);
214 } else {
215 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
216 reply_len = 16;
217diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
developerd243af02023-12-21 14:49:33 +0800218index 73b33b42a..8e56d1082 100644
developer1c2c7d42023-01-18 18:20:58 +0800219--- a/src/ap/ap_config.c
220+++ b/src/ap/ap_config.c
developer8bff6472023-07-17 11:11:44 +0800221@@ -295,6 +295,9 @@ struct hostapd_config * hostapd_config_defaults(void)
developer1c2c7d42023-01-18 18:20:58 +0800222 conf->airtime_update_interval = AIRTIME_DEFAULT_UPDATE_INTERVAL;
223 #endif /* CONFIG_AIRTIME_POLICY */
224
225+ conf->edcca_enable = EDCCA_MODE_AUTO;
226+ conf->edcca_compensation = EDCCA_DEFAULT_COMPENSATION;
227+
228 return conf;
229 }
230
developerdfb50982023-09-11 13:34:36 +0800231@@ -1008,6 +1011,7 @@ void hostapd_config_free(struct hostapd_config *conf)
developer1c2c7d42023-01-18 18:20:58 +0800232 #ifdef CONFIG_ACS
233 os_free(conf->acs_chan_bias);
234 #endif /* CONFIG_ACS */
235+ os_free(conf->edcca_threshold);
236 wpabuf_free(conf->lci);
237 wpabuf_free(conf->civic);
238
239diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
developerd243af02023-12-21 14:49:33 +0800240index 82338e213..24d540dbf 100644
developer1c2c7d42023-01-18 18:20:58 +0800241--- a/src/ap/ap_config.h
242+++ b/src/ap/ap_config.h
developere35b8e42023-10-16 11:04:00 +0800243@@ -1193,8 +1193,38 @@ struct hostapd_config {
developer505c9432023-05-12 18:58:17 +0800244 MBSSID_ENABLED = 1,
245 ENHANCED_MBSSID_ENABLED = 2,
246 } mbssid;
247+
developer1c2c7d42023-01-18 18:20:58 +0800248+ u8 edcca_enable;
249+ s8 edcca_compensation;
250+ int *edcca_threshold;
developer505c9432023-05-12 18:58:17 +0800251+};
252+
developer1c2c7d42023-01-18 18:20:58 +0800253+enum edcca_mode {
254+ EDCCA_MODE_FORCE_DISABLE = 0,
255+ EDCCA_MODE_AUTO = 1,
256+};
257+
258+enum edcca_bw_id {
259+ EDCCA_BW_20 = 0,
260+ EDCCA_BW_40,
261+ EDCCA_BW_80,
developer004e50c2023-06-29 20:33:22 +0800262+ EDCCA_BW_160,
developer1c2c7d42023-01-18 18:20:58 +0800263+ EDCCA_MAX_BW_NUM,
264+};
265+
266+enum mtk_vendor_attr_edcca_ctrl_mode {
267+ EDCCA_CTRL_SET_EN = 0,
268+ EDCCA_CTRL_SET_THRES,
269+ EDCCA_CTRL_GET_EN,
270+ EDCCA_CTRL_GET_THRES,
271+ EDCCA_CTRL_NUM,
developer505c9432023-05-12 18:58:17 +0800272 };
273
developer1c2c7d42023-01-18 18:20:58 +0800274+#define EDCCA_DEFAULT_COMPENSATION -6
275+#define EDCCA_MIN_COMPENSATION -126
276+#define EDCCA_MAX_COMPENSATION 126
277+#define EDCCA_MIN_CONFIG_THRES -126
278+#define EDCCA_MAX_CONFIG_THRES 0
developer1c2c7d42023-01-18 18:20:58 +0800279
280 static inline enum oper_chan_width
281 hostapd_get_oper_chwidth(struct hostapd_config *conf)
282diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
developerd243af02023-12-21 14:49:33 +0800283index 75ddfa15c..99ba973aa 100644
developer1c2c7d42023-01-18 18:20:58 +0800284--- a/src/ap/ap_drv_ops.c
285+++ b/src/ap/ap_drv_ops.c
developer8bff6472023-07-17 11:11:44 +0800286@@ -1137,3 +1137,27 @@ int hostapd_drv_set_secure_ranging_ctx(struct hostapd_data *hapd,
developer505c9432023-05-12 18:58:17 +0800287 return hapd->driver->set_secure_ranging_ctx(hapd->drv_priv, &params);
developer1c2c7d42023-01-18 18:20:58 +0800288 }
developer505c9432023-05-12 18:58:17 +0800289 #endif /* CONFIG_PASN */
developer1c2c7d42023-01-18 18:20:58 +0800290+
291+int hostapd_drv_configure_edcca_enable(struct hostapd_data *hapd)
292+{
293+ if (!hapd->driver || !hapd->driver->configure_edcca_enable)
294+ return 0;
295+ return hapd->driver->configure_edcca_enable(hapd->drv_priv,
developer505c9432023-05-12 18:58:17 +0800296+ hapd->iconf->edcca_enable,
developer1c2c7d42023-01-18 18:20:58 +0800297+ hapd->iconf->edcca_compensation);
298+}
299+
300+int hostapd_drv_configure_edcca_threshold(struct hostapd_data *hapd,
301+ const int *threshold)
302+{
303+ if (!hapd->driver || !hapd->driver->configure_edcca_threshold)
304+ return 0;
305+ return hapd->driver->configure_edcca_threshold(hapd->drv_priv, threshold);
306+}
307+
308+int hostapd_drv_get_edcca(struct hostapd_data *hapd, const u8 mode, u8 *value)
309+{
310+ if (!hapd->driver || !hapd->driver->get_edcca)
311+ return 0;
312+ return hapd->driver->get_edcca(hapd->drv_priv, mode, value);
313+}
314diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
developerd243af02023-12-21 14:49:33 +0800315index 96c8c4e2c..6ca693b0b 100644
developer1c2c7d42023-01-18 18:20:58 +0800316--- a/src/ap/ap_drv_ops.h
317+++ b/src/ap/ap_drv_ops.h
developer505c9432023-05-12 18:58:17 +0800318@@ -144,6 +144,10 @@ int hostapd_drv_set_secure_ranging_ctx(struct hostapd_data *hapd,
319 u8 ltf_keyseed_len,
320 const u8 *ltf_keyseed, u32 action);
321
developer1c2c7d42023-01-18 18:20:58 +0800322+int hostapd_drv_configure_edcca_enable(struct hostapd_data *hapd);
323+int hostapd_drv_configure_edcca_threshold(struct hostapd_data *hapd,
324+ const int *threshold);
325+int hostapd_drv_get_edcca(struct hostapd_data *hapd, const u8 mode, u8 *value);
326
327 #include "drivers/driver.h"
328
329diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
developerd243af02023-12-21 14:49:33 +0800330index a203546b6..f7c80c73b 100644
developer1c2c7d42023-01-18 18:20:58 +0800331--- a/src/ap/hostapd.c
332+++ b/src/ap/hostapd.c
developerdfb50982023-09-11 13:34:36 +0800333@@ -2511,6 +2511,13 @@ dfs_offload:
developer1c2c7d42023-01-18 18:20:58 +0800334 }
335 #endif /* CONFIG_MESH */
336
337+ if (hostapd_drv_configure_edcca_enable(hapd) < 0)
338+ goto fail;
339+
340+ if (hostapd_drv_configure_edcca_threshold(hapd,
341+ hapd->iconf->edcca_threshold) < 0)
342+ goto fail;
343+
344 wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
345 iface->bss[0]->conf->iface);
346 if (iface->interfaces && iface->interfaces->terminate_on_error > 0)
347diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
developerd243af02023-12-21 14:49:33 +0800348index 4a19d2fc9..6121857dd 100644
developer1c2c7d42023-01-18 18:20:58 +0800349--- a/src/common/mtk_vendor.h
350+++ b/src/common/mtk_vendor.h
developer004e50c2023-06-29 20:33:22 +0800351@@ -30,14 +30,22 @@ enum mtk_vendor_attr_edcca_ctrl {
developer1c2c7d42023-01-18 18:20:58 +0800352 NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL - 1
353 };
354
355-enum mtk_vendor_attr_edcca_ctrl_mode {
356- EDCCA_CTRL_SET_EN = 0,
357- EDCCA_CTRL_SET_THERS,
358- EDCCA_CTRL_GET_EN,
359- EDCCA_CTRL_GET_THERS,
360- EDCCA_CTRL_NUM,
361+enum mtk_vendor_attr_edcca_dump {
362+ MTK_VENDOR_ATTR_EDCCA_DUMP_UNSPEC = 0,
363+
364+ MTK_VENDOR_ATTR_EDCCA_DUMP_MODE,
365+ MTK_VENDOR_ATTR_EDCCA_DUMP_PRI20_VAL,
366+ MTK_VENDOR_ATTR_EDCCA_DUMP_SEC40_VAL,
367+ MTK_VENDOR_ATTR_EDCCA_DUMP_SEC80_VAL,
developer004e50c2023-06-29 20:33:22 +0800368+ MTK_VENDOR_ATTR_EDCCA_DUMP_SEC160_VAL,
developer1c2c7d42023-01-18 18:20:58 +0800369+
370+ /* keep last */
371+ NUM_MTK_VENDOR_ATTRS_EDCCA_DUMP,
372+ MTK_VENDOR_ATTR_EDCCA_DUMP_MAX =
373+ NUM_MTK_VENDOR_ATTRS_EDCCA_DUMP - 1
374 };
375
376+
377 static struct nla_policy edcca_ctrl_policy[NUM_MTK_VENDOR_ATTRS_EDCCA_CTRL] = {
378 [MTK_VENDOR_ATTR_EDCCA_CTRL_MODE] = { .type = NLA_U8 },
379 [MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL] = { .type = NLA_U8 },
380diff --git a/src/drivers/driver.h b/src/drivers/driver.h
developerd243af02023-12-21 14:49:33 +0800381index c5cc26737..7d71aa783 100644
developer1c2c7d42023-01-18 18:20:58 +0800382--- a/src/drivers/driver.h
383+++ b/src/drivers/driver.h
developerd243af02023-12-21 14:49:33 +0800384@@ -5105,6 +5105,10 @@ struct wpa_driver_ops {
developer1c2c7d42023-01-18 18:20:58 +0800385 const u8 *match, size_t match_len,
386 bool multicast);
387 #endif /* CONFIG_TESTING_OPTIONS */
388+ int (*configure_edcca_enable)(void *priv, const u8 edcca_enable,
389+ const s8 edcca_compensation);
390+ int (*configure_edcca_threshold)(void *priv, const int *threshold);
391+ int (*get_edcca)(void *priv, const u8 mode, u8 *value);
392 };
393
394 /**
395diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
developerd243af02023-12-21 14:49:33 +0800396index a3e436e95..1a2f52b77 100644
developer1c2c7d42023-01-18 18:20:58 +0800397--- a/src/drivers/driver_nl80211.c
398+++ b/src/drivers/driver_nl80211.c
developer505c9432023-05-12 18:58:17 +0800399@@ -37,6 +37,8 @@
developer1c2c7d42023-01-18 18:20:58 +0800400 #include "radiotap_iter.h"
401 #include "rfkill.h"
402 #include "driver_nl80211.h"
403+#include "common/mtk_vendor.h"
404+#include "ap/ap_config.h"
405
406
407 #ifndef NETLINK_CAP_ACK
developerd243af02023-12-21 14:49:33 +0800408@@ -13768,6 +13770,174 @@ static int testing_nl80211_radio_disable(void *priv, int disabled)
developer1c2c7d42023-01-18 18:20:58 +0800409
410 #endif /* CONFIG_TESTING_OPTIONS */
411
412+static int nl80211_configure_edcca_enable(void *priv,
413+ const u8 edcca_enable,
414+ const s8 edcca_compensation)
415+{
416+ struct i802_bss *bss = priv;
417+ struct wpa_driver_nl80211_data *drv = bss->drv;
418+ struct nl_msg *msg;
419+ struct nlattr *data;
420+ int ret;
421+
422+ if (!drv->mtk_edcca_vendor_cmd_avail) {
423+ wpa_printf(MSG_INFO,
424+ "nl80211: Driver does not support setting EDCCA enable");
425+ return 0;
426+ }
427+
428+ if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
429+ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
430+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
431+ MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL) ||
432+ !(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
433+ nla_put_u8(msg, MTK_VENDOR_ATTR_EDCCA_CTRL_MODE, EDCCA_CTRL_SET_EN) ||
434+ nla_put_u8(msg, MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL, edcca_enable) ||
435+ nla_put_u8(msg, MTK_VENDOR_ATTR_EDCCA_CTRL_COMPENSATE,
436+ edcca_compensation)) {
437+ wpa_printf (MSG_ERROR, "Prepare nl80211 msg fail");
438+ nlmsg_free(msg);
439+ return -ENOBUFS;
440+ }
441+ nla_nest_end(msg, data);
442+ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
443+ if (ret) {
444+ wpa_printf(MSG_ERROR, "Failed to configure EDCCA enable. ret=%d (%s) ",
445+ ret, strerror(-ret));
446+ }
447+ return ret;
448+}
449+
450+static int nl80211_configure_edcca_threshold(void *priv, const int *threshold)
451+{
452+ struct i802_bss *bss = priv;
453+ struct wpa_driver_nl80211_data *drv = bss->drv;
454+ struct nl_msg *msg;
455+ struct nlattr *data;
456+ int ret;
457+
458+ if (!drv->mtk_edcca_vendor_cmd_avail) {
459+ wpa_printf(MSG_INFO,
460+ "nl80211: Driver does not support setting EDCCA threshold");
461+ return 0;
462+ }
463+
464+ if (!threshold) {
465+ wpa_printf(MSG_INFO,
466+ "nl80211: Input EDCCA threshold is empty!");
467+ return 0;
468+ }
469+
470+ if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
471+ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
472+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
473+ MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL) ||
474+ !(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
475+ nla_put_u8(msg, MTK_VENDOR_ATTR_EDCCA_CTRL_MODE, EDCCA_CTRL_SET_THRES) ||
476+ nla_put_u8(msg, MTK_VENDOR_ATTR_EDCCA_CTRL_PRI20_VAL, threshold[0] & 0xff) ||
477+ nla_put_u8(msg, MTK_VENDOR_ATTR_EDCCA_CTRL_SEC40_VAL, threshold[1] & 0xff) ||
developer004e50c2023-06-29 20:33:22 +0800478+ nla_put_u8(msg, MTK_VENDOR_ATTR_EDCCA_CTRL_SEC80_VAL, threshold[2] & 0xff) ||
479+ nla_put_u8(msg, MTK_VENDOR_ATTR_EDCCA_CTRL_SEC160_VAL, threshold[3] & 0xff)) {
developer1c2c7d42023-01-18 18:20:58 +0800480+ wpa_printf (MSG_ERROR, "Prepare nl80211 msg fail");
481+ nlmsg_free(msg);
482+ return -ENOBUFS;
483+ }
484+ nla_nest_end(msg, data);
485+ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
486+ if (ret) {
487+ wpa_printf(MSG_ERROR, "Failed to configure EDCCA threshold. ret=%d (%s) ",
488+ ret, strerror(-ret));
489+ }
490+ return ret;
491+}
492+
493+
494+static int edcca_info_handler(struct nl_msg *msg, void *arg)
495+{
developer004e50c2023-06-29 20:33:22 +0800496+ u8 *info = (u8 *) arg;
developer1c2c7d42023-01-18 18:20:58 +0800497+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
498+ struct nlattr *tb_vendor[MTK_VENDOR_ATTR_EDCCA_DUMP_MAX + 1];
499+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
500+ struct nlattr *nl_vend, *attr;
501+
502+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
503+ genlmsg_attrlen(gnlh, 0), NULL);
504+
505+ nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
506+ if (!nl_vend)
507+ return NL_SKIP;
508+
509+ nla_parse(tb_vendor, MTK_VENDOR_ATTR_EDCCA_DUMP_MAX,
510+ nla_data(nl_vend), nla_len(nl_vend), NULL);
511+
512+ attr = tb_vendor[MTK_VENDOR_ATTR_EDCCA_DUMP_PRI20_VAL];
513+ if (!attr) {
514+ wpa_printf(MSG_ERROR, "nl80211: MTK_VENDOR_ATTR_EDCCA_DUMP_PRI20_VAL");
515+ return NL_SKIP;
516+ }
517+
518+ *info++ = nla_get_u8(attr);
519+
520+ attr = tb_vendor[MTK_VENDOR_ATTR_EDCCA_DUMP_SEC40_VAL];
521+ if (!attr) {
522+ wpa_printf(MSG_ERROR, "nl80211: MTK_VENDOR_ATTR_EDCCA_DUMP_SEC40_VAL");
523+ return NL_SKIP;
524+ }
525+
526+ *info++ = nla_get_u8(attr);
527+
528+ attr = tb_vendor[MTK_VENDOR_ATTR_EDCCA_DUMP_SEC80_VAL];
529+ if (!attr) {
530+ wpa_printf(MSG_ERROR, "nl80211: MTK_VENDOR_ATTR_EDCCA_DUMP_SEC80_VAL");
531+ return NL_SKIP;
532+ }
533+
developer004e50c2023-06-29 20:33:22 +0800534+ *info++ = nla_get_u8(attr);
535+
536+ attr = tb_vendor[MTK_VENDOR_ATTR_EDCCA_DUMP_SEC160_VAL];
537+ if (!attr) {
538+ wpa_printf(MSG_ERROR, "nl80211: MTK_VENDOR_ATTR_EDCCA_DUMP_SEC160_VAL");
539+ return NL_SKIP;
540+ }
541+
developer1c2c7d42023-01-18 18:20:58 +0800542+ *info = nla_get_u8(attr);
543+ return NL_SKIP;
544+}
545+
546+
547+static int nl80211_get_edcca(void *priv, const u8 mode, u8 *value)
548+{
549+ struct i802_bss *bss = priv;
550+ struct wpa_driver_nl80211_data *drv = bss->drv;
551+ struct nl_msg *msg;
552+ struct nlattr *data;
553+ int ret;
554+
555+ if (!drv->mtk_edcca_vendor_cmd_avail) {
556+ wpa_printf(MSG_INFO,
557+ "nl80211: Driver does not support setting EDCCA threshold");
558+ return 0;
559+ }
560+
561+ if (!(msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_VENDOR)) ||
562+ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
563+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
564+ MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL) ||
565+ !(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA | NLA_F_NESTED)) ||
566+ nla_put_u8(msg, MTK_VENDOR_ATTR_EDCCA_CTRL_MODE, mode)) {
567+ wpa_printf (MSG_ERROR, "Prepare nl80211 msg fail");
568+ nlmsg_free(msg);
569+ return -ENOBUFS;
570+ }
571+ nla_nest_end(msg, data);
572+ ret = send_and_recv_msgs(drv, msg, edcca_info_handler, value, NULL, NULL);
573+ if (ret) {
574+ wpa_printf(MSG_ERROR, "Failed to get EDCCA configuration. ret=%d (%s)",
575+ ret, strerror(-ret));
576+ }
577+ return ret;
578+}
579+
580
581 const struct wpa_driver_ops wpa_driver_nl80211_ops = {
582 .name = "nl80211",
developerd243af02023-12-21 14:49:33 +0800583@@ -13924,4 +14094,8 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
developer1c2c7d42023-01-18 18:20:58 +0800584 .register_frame = testing_nl80211_register_frame,
585 .radio_disable = testing_nl80211_radio_disable,
586 #endif /* CONFIG_TESTING_OPTIONS */
587+/* Need ifdef CONFIG_DRIVER_NL80211_MTK */
588+ .configure_edcca_enable = nl80211_configure_edcca_enable,
589+ .configure_edcca_threshold = nl80211_configure_edcca_threshold,
590+ .get_edcca = nl80211_get_edcca,
591 };
592diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
developerd243af02023-12-21 14:49:33 +0800593index aee8c4512..51b3fbec8 100644
developer1c2c7d42023-01-18 18:20:58 +0800594--- a/src/drivers/driver_nl80211.h
595+++ b/src/drivers/driver_nl80211.h
developer8bff6472023-07-17 11:11:44 +0800596@@ -202,6 +202,7 @@ struct wpa_driver_nl80211_data {
developer505c9432023-05-12 18:58:17 +0800597 unsigned int secure_ranging_ctx_vendor_cmd_avail:1;
598 unsigned int puncturing:1;
developer8bff6472023-07-17 11:11:44 +0800599 unsigned int qca_ap_allowed_freqs:1;
developer1c2c7d42023-01-18 18:20:58 +0800600+ unsigned int mtk_edcca_vendor_cmd_avail:1;
601
602 u64 vendor_scan_cookie;
603 u64 remain_on_chan_cookie;
604diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
developerd243af02023-12-21 14:49:33 +0800605index f01a526a0..47654f65b 100644
developer1c2c7d42023-01-18 18:20:58 +0800606--- a/src/drivers/driver_nl80211_capa.c
607+++ b/src/drivers/driver_nl80211_capa.c
608@@ -18,6 +18,7 @@
609 #include "common/qca-vendor-attr.h"
610 #include "common/brcm_vendor.h"
611 #include "driver_nl80211.h"
612+#include "common/mtk_vendor.h"
613
614
615 static int protocol_feature_handler(struct nl_msg *msg, void *arg)
developerd243af02023-12-21 14:49:33 +0800616@@ -1111,6 +1112,12 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
developer1c2c7d42023-01-18 18:20:58 +0800617 break;
618 }
619 #endif /* CONFIG_DRIVER_NL80211_BRCM */
620+ } else if (vinfo->vendor_id == OUI_MTK) {
621+ switch (vinfo->subcmd) {
developer004e50c2023-06-29 20:33:22 +0800622+ case MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL:
developer1c2c7d42023-01-18 18:20:58 +0800623+ drv->mtk_edcca_vendor_cmd_avail = 1;
624+ break;
625+ }
626 }
627
628 wpa_printf(MSG_DEBUG, "nl80211: Supported vendor command: vendor_id=0x%x subcmd=%u",
629--
developerdfb50982023-09-11 13:34:36 +08006302.18.0
developer1c2c7d42023-01-18 18:20:58 +0800631