blob: 9fb8962d34f032d6c9bd0c21bed6762de96ebb9e [file] [log] [blame]
developer05f3b2b2024-08-19 19:17:34 +08001From 75020e1c62dd8d16c872614861146d8cfc12f6df Mon Sep 17 00:00:00 2001
developer66e89bc2024-04-23 14:50:01 +08002From: Howard Hsu <howard-yh.hsu@mediatek.com>
3Date: Mon, 30 May 2022 16:31:34 +0800
developer05f3b2b2024-08-19 19:17:34 +08004Subject: [PATCH 016/126] mtk: hostapd: Support EDCCA hostapd configuration
developer66e89bc2024-04-23 14:50:01 +08005
6edcca_enable and edcca_compensation and implement edcca related handlers.
developer05f3b2b2024-08-19 19:17:34 +08007
developer66e89bc2024-04-23 14:50:01 +08008---
9 hostapd/config_file.c | 34 ++++++
10 hostapd/ctrl_iface.c | 124 +++++++++++++++++++++
11 src/ap/ap_config.c | 4 +
12 src/ap/ap_config.h | 30 ++++++
13 src/ap/ap_drv_ops.c | 24 +++++
14 src/ap/ap_drv_ops.h | 4 +
15 src/ap/hostapd.c | 7 ++
16 src/common/mtk_vendor.h | 20 ++--
17 src/drivers/driver.h | 4 +
18 src/drivers/driver_nl80211.c | 174 ++++++++++++++++++++++++++++++
19 src/drivers/driver_nl80211.h | 1 +
20 src/drivers/driver_nl80211_capa.c | 7 ++
21 12 files changed, 427 insertions(+), 6 deletions(-)
22
23diff --git a/hostapd/config_file.c b/hostapd/config_file.c
developer05f3b2b2024-08-19 19:17:34 +080024index f3968ec95..9f5ee48bf 100644
developer66e89bc2024-04-23 14:50:01 +080025--- a/hostapd/config_file.c
26+++ b/hostapd/config_file.c
developer05f3b2b2024-08-19 19:17:34 +080027@@ -5470,6 +5470,40 @@ static int hostapd_config_fill(struct hostapd_config *conf,
28 os_strlcpy(bss->apup_peer_ifname_prefix,
29 pos, sizeof(bss->apup_peer_ifname_prefix));
30 #endif // def CONFIG_APUP
developer66e89bc2024-04-23 14:50:01 +080031+ } else if (os_strcmp(buf, "edcca_threshold") == 0) {
32+ if (hostapd_parse_intlist(&conf->edcca_threshold, pos) ||
33+ conf->edcca_threshold[0] < EDCCA_MIN_CONFIG_THRES ||
34+ conf->edcca_threshold[0] > EDCCA_MAX_CONFIG_THRES ||
35+ conf->edcca_threshold[1] < EDCCA_MIN_CONFIG_THRES ||
36+ conf->edcca_threshold[1] > EDCCA_MAX_CONFIG_THRES ||
37+ conf->edcca_threshold[2] < EDCCA_MIN_CONFIG_THRES ||
38+ conf->edcca_threshold[2] > EDCCA_MAX_CONFIG_THRES ||
39+ conf->edcca_threshold[3] < EDCCA_MIN_CONFIG_THRES ||
40+ conf->edcca_threshold[3] > EDCCA_MAX_CONFIG_THRES) {
41+ wpa_printf(MSG_ERROR, "Line %d: invalid edcca threshold",
42+ line);
43+ return 1;
44+ }
45+ } else if (os_strcmp(buf, "edcca_enable") == 0) {
46+ int mode = atoi(pos);
47+ if (mode < EDCCA_MODE_FORCE_DISABLE || mode > EDCCA_MODE_AUTO) {
48+ wpa_printf(MSG_ERROR, "Line %d: Invalid edcca_enable %d;"
49+ " allowed value 0 (Force Disable) or 1(Auto) ",
50+ line, mode);
51+ return 1;
52+ }
53+ conf->edcca_enable = (u8) mode;
54+ } else if (os_strcmp(buf, "edcca_compensation") == 0) {
55+ int val = atoi(pos);
56+ if (val < EDCCA_MIN_COMPENSATION ||
57+ val > EDCCA_MAX_COMPENSATION) {
58+ wpa_printf(MSG_ERROR, "Line %d: Invalid compensation"
59+ " value %d; allowed value %d ~ %d.",
60+ line, val, EDCCA_MIN_COMPENSATION,
61+ EDCCA_MAX_COMPENSATION);
62+ return 1;
63+ }
64+ conf->edcca_compensation = (s8) val;
65 } else {
66 wpa_printf(MSG_ERROR,
67 "Line %d: unknown configuration item '%s'",
68diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
developer05f3b2b2024-08-19 19:17:34 +080069index 40244c5e7..8a9fa3ec9 100644
developer66e89bc2024-04-23 14:50:01 +080070--- a/hostapd/ctrl_iface.c
71+++ b/hostapd/ctrl_iface.c
developer05f3b2b2024-08-19 19:17:34 +080072@@ -545,6 +545,19 @@ static const char * pbc_status_str(enum pbc_status status)
developer66e89bc2024-04-23 14:50:01 +080073 }
74
75
76+static const char *edcca_mode_str(enum edcca_mode status)
77+{
78+ switch (status) {
79+ case EDCCA_MODE_FORCE_DISABLE:
80+ return "Force Disable";
81+ case EDCCA_MODE_AUTO:
82+ return "Auto";
83+ default:
84+ return "Unknown";
85+ }
86+}
87+
88+
89 static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd,
90 char *buf, size_t buflen)
91 {
developer05f3b2b2024-08-19 19:17:34 +080092@@ -3774,6 +3787,111 @@ static int hostapd_ctrl_iface_link_remove(struct hostapd_data *hapd, char *cmd,
developer66e89bc2024-04-23 14:50:01 +080093 #endif /* CONFIG_TESTING_OPTIONS */
94 #endif /* CONFIG_IEEE80211BE */
95
96+static int
97+hostapd_ctrl_iface_set_edcca(struct hostapd_data *hapd, char *cmd,
98+ char *buf, size_t buflen)
99+{
100+ char *pos, *config, *value;
101+ config = cmd;
102+ pos = os_strchr(config, ' ');
103+ if (pos == NULL)
104+ return -1;
105+ *pos++ = '\0';
106+
107+ if (pos == NULL)
108+ return -1;
109+ value = pos;
110+
111+ if (os_strcmp(config, "enable") == 0) {
112+ int mode = atoi(value);
113+ if (mode < EDCCA_MODE_FORCE_DISABLE || mode > EDCCA_MODE_AUTO) {
114+ wpa_printf(MSG_ERROR, "Invalid value for edcca enable");
115+ return -1;
116+ }
117+ hapd->iconf->edcca_enable = (u8) mode;
118+ if (hostapd_drv_configure_edcca_enable(hapd) != 0)
119+ return -1;
120+ } else if (os_strcmp(config, "compensation") == 0) {
121+ int compensation = atoi(value);
122+ if (compensation < EDCCA_MIN_COMPENSATION ||
123+ compensation > EDCCA_MAX_COMPENSATION) {
124+ wpa_printf(MSG_ERROR, "Invalid value for edcca compensation");
125+ return -1;
126+ }
127+ hapd->iconf->edcca_compensation = (s8) compensation;
128+ if (hostapd_drv_configure_edcca_enable(hapd) != 0)
129+ return -1;
130+ } else if (os_strcmp(config, "threshold") == 0) {
131+ char *thres_value;
132+ thres_value = os_strchr(value, ':');
133+ if (thres_value == NULL)
134+ return -1;
135+ *thres_value++ = '\0';
136+
137+ if (thres_value == NULL)
138+ return -1;
139+ int bw_idx = atoi(value);
140+ int threshold = atoi(thres_value);
141+
142+ if (bw_idx < EDCCA_BW_20 || bw_idx > EDCCA_BW_160) {
143+ wpa_printf(MSG_ERROR,
144+ "Unsupported Bandwidth idx %d for SET_EDCCA",
145+ bw_idx);
146+ return -1;
147+ }
148+ if (threshold < EDCCA_MIN_CONFIG_THRES ||
149+ threshold > EDCCA_MAX_CONFIG_THRES) {
150+ wpa_printf(MSG_ERROR,
151+ "Unsupported threshold %d for SET_EDCCA",
152+ threshold);
153+ return -1;
154+ }
155+
156+ int threshold_arr[EDCCA_MAX_BW_NUM];
157+ /* 0x7f means keep the origival value in firmware */
158+ os_memset(threshold_arr, 0x7f, sizeof(threshold_arr));
159+ threshold_arr[bw_idx] = threshold;
160+
161+ if (hostapd_drv_configure_edcca_threshold(hapd, threshold_arr) != 0)
162+ return -1;
163+ } else {
164+ wpa_printf(MSG_ERROR,
165+ "Unsupported parameter %s for SET_EDCCA", config);
166+ return -1;
167+ }
168+ return os_snprintf(buf, buflen, "OK\n");
169+}
170+
171+
172+static int
173+hostapd_ctrl_iface_get_edcca(struct hostapd_data *hapd, char *cmd, char *buf,
174+ size_t buflen)
175+{
176+ char *pos, *end;
177+
178+ pos = buf;
179+ end = buf + buflen;
180+ u8 value[EDCCA_MAX_BW_NUM] = {0};
181+
182+ if (os_strcmp(cmd, "enable") == 0) {
183+ return os_snprintf(pos, end - pos, "Enable: %s\n",
184+ edcca_mode_str(hapd->iconf->edcca_enable));
185+ } else if (os_strcmp(cmd, "compensation") == 0) {
186+ return os_snprintf(pos, end - pos, "Compensation: %d\n",
187+ hapd->iconf->edcca_compensation);
188+ } else if (os_strcmp(cmd, "threshold") == 0) {
189+ if (hostapd_drv_get_edcca(hapd, EDCCA_CTRL_GET_THRES, &value) != 0)
190+ return -1;
191+ return os_snprintf(pos, end - pos,
192+ "Threshold BW20: 0x%x, BW40: 0x%x, BW80: 0x%x, BW160: 0x%x\n",
193+ value[0], value[1], value[2], value[3]);
194+ } else {
195+ wpa_printf(MSG_ERROR,
196+ "Unsupported parameter %s for GET_EDCCA", cmd);
197+ return -1;
198+ }
199+}
200+
201
202 #ifdef CONFIG_NAN_USD
203
developer05f3b2b2024-08-19 19:17:34 +0800204@@ -4669,6 +4787,12 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +0800205 reply_len = -1;
206 #endif /* CONFIG_TESTING_OPTIONS */
207 #endif /* CONFIG_IEEE80211BE */
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
developer05f3b2b2024-08-19 19:17:34 +0800218index 67661dfe0..112954a89 100644
developer66e89bc2024-04-23 14:50:01 +0800219--- a/src/ap/ap_config.c
220+++ b/src/ap/ap_config.c
developer05f3b2b2024-08-19 19:17:34 +0800221@@ -305,6 +305,9 @@ struct hostapd_config * hostapd_config_defaults(void)
developer66e89bc2024-04-23 14:50:01 +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 hostapd_set_and_check_bw320_offset(conf, 0);
229
230 return conf;
developer05f3b2b2024-08-19 19:17:34 +0800231@@ -1046,6 +1049,7 @@ void hostapd_config_free(struct hostapd_config *conf)
developer66e89bc2024-04-23 14:50:01 +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 #ifdef CONFIG_AFC
239diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
developer05f3b2b2024-08-19 19:17:34 +0800240index 25ac22e31..b9afe1f47 100644
developer66e89bc2024-04-23 14:50:01 +0800241--- a/src/ap/ap_config.h
242+++ b/src/ap/ap_config.h
developer05f3b2b2024-08-19 19:17:34 +0800243@@ -1334,8 +1334,38 @@ struct hostapd_config {
developer66e89bc2024-04-23 14:50:01 +0800244 int min_power;
245 } afc;
246 #endif /* CONFIG_AFC */
247+
248+ u8 edcca_enable;
249+ s8 edcca_compensation;
250+ int *edcca_threshold;
251+};
252+
253+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,
262+ EDCCA_BW_160,
263+ 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,
272 };
273
274+#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
279
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
developer05f3b2b2024-08-19 19:17:34 +0800283index 7c9527cd3..c7cacbd81 100644
developer66e89bc2024-04-23 14:50:01 +0800284--- a/src/ap/ap_drv_ops.c
285+++ b/src/ap/ap_drv_ops.c
developer05f3b2b2024-08-19 19:17:34 +0800286@@ -1274,3 +1274,27 @@ int hostapd_drv_set_secure_ranging_ctx(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +0800287 return hapd->driver->set_secure_ranging_ctx(hapd->drv_priv, &params);
288 }
289 #endif /* CONFIG_PASN */
290+
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,
296+ hapd->iconf->edcca_enable,
297+ 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
developer05f3b2b2024-08-19 19:17:34 +0800315index 58ca046c6..23a331914 100644
developer66e89bc2024-04-23 14:50:01 +0800316--- a/src/ap/ap_drv_ops.h
317+++ b/src/ap/ap_drv_ops.h
developer05f3b2b2024-08-19 19:17:34 +0800318@@ -152,6 +152,10 @@ int hostapd_drv_set_secure_ranging_ctx(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +0800319 u8 ltf_keyseed_len,
320 const u8 *ltf_keyseed, u32 action);
321
322+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
developer05f3b2b2024-08-19 19:17:34 +0800330index 8159194e1..972bb1763 100644
developer66e89bc2024-04-23 14:50:01 +0800331--- a/src/ap/hostapd.c
332+++ b/src/ap/hostapd.c
developer05f3b2b2024-08-19 19:17:34 +0800333@@ -2756,6 +2756,13 @@ dfs_offload:
developer66e89bc2024-04-23 14:50:01 +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
348index 4a19d2fc9..6121857dd 100644
349--- a/src/common/mtk_vendor.h
350+++ b/src/common/mtk_vendor.h
351@@ -30,14 +30,22 @@ enum mtk_vendor_attr_edcca_ctrl {
352 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,
368+ MTK_VENDOR_ATTR_EDCCA_DUMP_SEC160_VAL,
369+
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
developer05f3b2b2024-08-19 19:17:34 +0800381index e1a447333..bf103516b 100644
developer66e89bc2024-04-23 14:50:01 +0800382--- a/src/drivers/driver.h
383+++ b/src/drivers/driver.h
developer05f3b2b2024-08-19 19:17:34 +0800384@@ -5246,6 +5246,10 @@ struct wpa_driver_ops {
developer66e89bc2024-04-23 14:50:01 +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
developer05f3b2b2024-08-19 19:17:34 +0800396index 2c68bf997..606632aad 100644
developer66e89bc2024-04-23 14:50:01 +0800397--- a/src/drivers/driver_nl80211.c
398+++ b/src/drivers/driver_nl80211.c
developer05f3b2b2024-08-19 19:17:34 +0800399@@ -39,6 +39,8 @@
developer66e89bc2024-04-23 14:50:01 +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
developer05f3b2b2024-08-19 19:17:34 +0800408@@ -14101,6 +14103,174 @@ static int testing_nl80211_radio_disable(void *priv, int disabled)
developer66e89bc2024-04-23 14:50:01 +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_cmd(drv, msg);
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) ||
478+ 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)) {
480+ 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_cmd(drv, msg);
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+{
496+ u8 *info = (u8 *) arg;
497+ 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+
534+ *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+
542+ *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_resp(drv, msg, edcca_info_handler, value);
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",
developer05f3b2b2024-08-19 19:17:34 +0800583@@ -14262,4 +14432,8 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
developer66e89bc2024-04-23 14:50:01 +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
593index 618746e67..62c47efbd 100644
594--- a/src/drivers/driver_nl80211.h
595+++ b/src/drivers/driver_nl80211.h
596@@ -200,6 +200,7 @@ struct wpa_driver_nl80211_data {
597 unsigned int secure_ranging_ctx_vendor_cmd_avail:1;
598 unsigned int puncturing:1;
599 unsigned int qca_ap_allowed_freqs:1;
600+ unsigned int mtk_edcca_vendor_cmd_avail:1;
601
602 u32 ignore_next_local_disconnect;
603 u32 ignore_next_local_deauth;
604diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
developer05f3b2b2024-08-19 19:17:34 +0800605index d5ba66b10..465fd318d 100644
developer66e89bc2024-04-23 14:50:01 +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)
616@@ -1138,6 +1139,12 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
617 break;
618 }
619 #endif /* CONFIG_DRIVER_NL80211_BRCM */
620+ } else if (vinfo->vendor_id == OUI_MTK) {
621+ switch (vinfo->subcmd) {
622+ case MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL:
623+ 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--
developer05f3b2b2024-08-19 19:17:34 +08006302.18.0
developer66e89bc2024-04-23 14:50:01 +0800631