blob: ffdab20384c99d9c003b13c26b9286a91161bff6 [file] [log] [blame]
developer683be522023-05-11 14:24:50 +08001From e3a3b2a33385a97229956f83574b1ae60f39d2cc Mon Sep 17 00:00:00 2001
2From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
3Date: Thu, 26 Jan 2023 09:16:00 +0800
4Subject: [PATCH 20/28] hostapd: mtk: Add available color bitmap
5
6Signed-off-by: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
7---
8 hostapd/ctrl_iface.c | 74 +++++++++++
9 hostapd/hostapd_cli.c | 18 +++
10 src/ap/ap_drv_ops.c | 10 +-
11 src/ap/ap_drv_ops.h | 2 +
12 src/common/mtk_vendor.h | 11 ++
13 src/drivers/driver.h | 8 ++
14 src/drivers/driver_nl80211.c | 199 +++++++++++++++++++++++++++++-
15 src/drivers/driver_nl80211.h | 1 +
16 src/drivers/driver_nl80211_capa.c | 3 +
17 9 files changed, 324 insertions(+), 2 deletions(-)
18
19diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
20index d09c22f..bc7a97b 100644
21--- a/hostapd/ctrl_iface.c
22+++ b/hostapd/ctrl_iface.c
23@@ -3720,6 +3720,76 @@ hostapd_ctrl_iface_get_amsdu(struct hostapd_data *hapd, char *buf,
24 return ret;
25 }
26
27+static int
28+hostapd_ctrl_iface_get_bss_color(struct hostapd_data *hapd, char *buf,
29+ size_t buflen)
30+{
31+ int ret;
32+ char *pos, *end;
33+ int i;
34+
35+ pos = buf;
36+ end = buf + buflen;
37+
38+ if (hapd->iface->conf->he_op.he_bss_color_disabled)
39+ ret = os_snprintf(buf, buflen, "BSS Color disabled\n");
40+ else
41+ ret = os_snprintf(buf, buflen, "BSS Color=%u\n",
42+ hapd->iface->conf->he_op.he_bss_color);
43+
44+ pos += ret;
45+
46+ return pos - buf;
47+}
48+
49+
50+static int
51+hostapd_ctrl_iface_get_aval_color_bmp(struct hostapd_data *hapd, char *buf,
52+ size_t buflen)
53+{
54+ int ret;
55+ char *pos, *end;
56+ int i;
57+ u64 aval_color_bmp = 0;
58+
59+ hostapd_drv_get_aval_bss_color_bmp(hapd, &aval_color_bmp);
60+ hapd->color_collision_bitmap = ~aval_color_bmp;
61+
62+ pos = buf;
63+ end = buf + buflen;
64+
65+ ret = os_snprintf(buf, buflen,
66+ "available color bitmap=0x%llx\n",
67+ aval_color_bmp);
68+ if (os_snprintf_error(end - pos, ret))
69+ return pos - buf;
70+ pos += ret;
71+
72+ for (i = 0; i < HE_OPERATION_BSS_COLOR_MAX; i++) {
73+ int bit = !!((aval_color_bmp >> i) & 1LLU);
74+
75+ if (i % 8 == 0) {
76+ ret = os_snprintf(pos, end - pos, "%2d: ", i);
77+ if (os_snprintf_error(end - pos, ret))
78+ return pos - buf;
79+ pos += ret;
80+ }
81+
82+ ret = os_snprintf(pos, end - pos, "%d ", bit);
83+ if (os_snprintf_error(end - pos, ret))
84+ return pos - buf;
85+ pos += ret;
86+
87+ if (i % 8 == 7) {
88+ ret = os_snprintf(pos, end - pos, "\n");
89+ if (os_snprintf_error(end - pos, ret))
90+ return pos - buf;
91+ pos += ret;
92+ }
93+ }
94+ return pos - buf;
95+}
96+
97
98 static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
99 char *buf, char *reply,
100@@ -4296,6 +4366,10 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
101 reply_len = hostapd_ctrl_iface_set_offchan_ctrl(hapd, buf + 16, reply, reply_size);
102 } else if (os_strncmp(buf, "GET_AMSDU", 9) == 0) {
103 reply_len = hostapd_ctrl_iface_get_amsdu(hapd, reply, reply_size);
104+ } else if (os_strncmp(buf, "GET_BSS_COLOR", 13) == 0) {
105+ reply_len = hostapd_ctrl_iface_get_bss_color(hapd, reply, reply_size);
106+ } else if (os_strncmp(buf, "AVAL_COLOR_BMP", 14) == 0) {
107+ reply_len = hostapd_ctrl_iface_get_aval_color_bmp(hapd, reply, reply_size);
108 } else {
109 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
110 reply_len = 16;
111diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
112index 36d19d8..dc01ad9 100644
113--- a/hostapd/hostapd_cli.c
114+++ b/hostapd/hostapd_cli.c
115@@ -1598,6 +1598,20 @@ static int hostapd_cli_cmd_reload_wpa_psk(struct wpa_ctrl *ctrl, int argc,
116 }
117
118
119+static int hostapd_cli_cmd_get_bss_color(struct wpa_ctrl *ctrl, int argc,
120+ char *argv[])
121+{
122+ return wpa_ctrl_command(ctrl, "GET_BSS_COLOR");
123+}
124+
125+
126+static int hostapd_cli_cmd_get_aval_color_bmp(struct wpa_ctrl *ctrl, int argc,
127+ char *argv[])
128+{
129+ return wpa_ctrl_command(ctrl, "AVAL_COLOR_BMP");
130+}
131+
132+
133 #ifdef ANDROID
134 static int hostapd_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
135 {
136@@ -1819,6 +1833,10 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
137 "<addr> [req_mode=] <measurement request hexdump> = send a Beacon report request to a station" },
138 { "reload_wpa_psk", hostapd_cli_cmd_reload_wpa_psk, NULL,
139 "= reload wpa_psk_file only" },
140+ { "get_bss_color", hostapd_cli_cmd_get_bss_color, NULL,
141+ "= get current BSS color" },
142+ { "get_color_bmp", hostapd_cli_cmd_get_aval_color_bmp, NULL,
143+ "= get available BSS color bitmap" },
144 #ifdef ANDROID
145 { "driver", hostapd_cli_cmd_driver, NULL,
146 "<driver sub command> [<hex formatted data>] = send driver command data" },
147diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
148index 00492b8..7b686e5 100644
149--- a/src/ap/ap_drv_ops.c
150+++ b/src/ap/ap_drv_ops.c
151@@ -1130,4 +1130,12 @@ int hostapd_drv_amsdu_dump(struct hostapd_data *hapd, u8 *amsdu)
152 if (!hapd->driver || !hapd->driver->amsdu_dump)
153 return 0;
154 return hapd->driver->amsdu_dump(hapd->drv_priv, amsdu);
155-}
156\ No newline at end of file
157+}
158+
159+int hostapd_drv_get_aval_bss_color_bmp(struct hostapd_data *hapd, u64 *aval_color_bmp)
160+{
161+ if (!hapd->driver || !hapd->driver->get_aval_color_bmp ||
162+ hapd->iface->conf->he_op.he_bss_color_disabled)
163+ return 0;
164+ return hapd->driver->get_aval_color_bmp(hapd->drv_priv, aval_color_bmp);
165+}
166diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
167index 2b8b587..47356ab 100644
168--- a/src/ap/ap_drv_ops.h
169+++ b/src/ap/ap_drv_ops.h
170@@ -155,6 +155,8 @@ int hostapd_drv_ibf_ctrl(struct hostapd_data *hapd);
171 int hostapd_drv_ibf_dump(struct hostapd_data *hapd, u8 *ibf_enable);
172 int hostapd_drv_amsdu_ctrl(struct hostapd_data *hapd);
173 int hostapd_drv_amsdu_dump(struct hostapd_data *hapd, u8 *amsdu);
174+int hostapd_drv_get_aval_bss_color_bmp(struct hostapd_data *hapd,
175+ u64 *aval_color_bmp);
176
177 #include "drivers/driver.h"
178
179diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
180index 62d79cb..a99e6f2 100644
181--- a/src/common/mtk_vendor.h
182+++ b/src/common/mtk_vendor.h
183@@ -15,6 +15,7 @@ enum mtk_nl80211_vendor_subcmds {
184 MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL = 0xc7,
185 MTK_NL80211_VENDOR_SUBCMD_3WIRE_CTRL = 0xc8,
186 MTK_NL80211_VENDOR_SUBCMD_IBF_CTRL = 0xc9,
187+ MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL = 0xca,
188 };
189
190 enum mtk_vendor_attr_edcca_ctrl {
191@@ -253,6 +254,16 @@ ibf_dump_policy[NUM_MTK_VENDOR_ATTRS_IBF_DUMP] = {
192 [MTK_VENDOR_ATTR_IBF_DUMP_ENABLE] = { .type = NLA_U8 },
193 };
194
195+enum mtk_vendor_attr_bss_color_ctrl {
196+ MTK_VENDOR_ATTR_BSS_COLOR_CTRL_UNSPEC,
197+
198+ MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP,
199+
200+ /* keep last */
201+ NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL,
202+ MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX =
203+ NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL - 1
204+};
205
206 #define CSI_MAX_COUNT 256
207 #define ETH_ALEN 6
208diff --git a/src/drivers/driver.h b/src/drivers/driver.h
209index faa4b7b..f9f9fb5 100644
210--- a/src/drivers/driver.h
211+++ b/src/drivers/driver.h
212@@ -5054,6 +5054,14 @@ struct wpa_driver_ops {
213 */
214 int (*amsdu_ctrl)(void *priv, u8 amsdu);
215 int (*amsdu_dump)(void *priv, u8 *amsdu);
216+
217+ /**
218+ * get_aval_color_bmp - get available BSS color bitmap
219+ * @priv: Private driver interface data
220+ * @aval_color_bmp: available bss color bitmap
221+ *
222+ */
223+ int (*get_aval_color_bmp)(void *priv, u64 *aval_color_bmp);
224 };
225
226 /**
227diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
228index 7c20b14..18a5647 100644
229--- a/src/drivers/driver_nl80211.c
230+++ b/src/drivers/driver_nl80211.c
231@@ -12498,7 +12498,6 @@ static void nl80211_parse_btm_candidate_info(struct candidate_list *candidate,
232 num, MAC2STR(candidate->bssid), buf);
233 }
234
235-
236 static int
237 nl80211_get_bss_transition_status_handler(struct nl_msg *msg, void *arg)
238 {
239@@ -13886,6 +13885,203 @@ fail:
240 return -ENOBUFS;
241 }
242
243+static int nl80211_get_aval_color_bmp_handler(struct nl_msg *msg, void *arg)
244+{
245+ u64 *aval_color_bmp = arg;
246+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
247+ struct nlattr *tb_vendor[MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX + 1];
248+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
249+ struct nlattr *nl_vend, *attr;
250+
251+ static const struct nla_policy
252+ bss_color_ctrl_policy[NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL + 1] = {
253+ [MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP] = { .type = NLA_U64 },
254+ };
255+
256+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
257+ genlmsg_attrlen(gnlh, 0), NULL);
258+
259+ nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
260+ if (!nl_vend)
261+ return NL_SKIP;
262+
263+ nla_parse(tb_vendor, MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX,
264+ nla_data(nl_vend), nla_len(nl_vend), NULL);
265+
266+ *aval_color_bmp = nla_get_u64(tb_vendor[MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP]);
267+
268+ return 0;
269+}
270+
271+static int nl80211_get_aval_color_bmp(void *priv, u64 *aval_color_bmp)
272+{
273+ struct i802_bss *bss = priv;
274+ struct wpa_driver_nl80211_data *drv = bss->drv;
275+ struct nl_msg *msg;
276+ struct nlattr *attr;
277+ int ret;
278+
279+ if (!drv->mtk_bss_color_vendor_cmd_avail) {
280+ wpa_printf(MSG_INFO,
281+ "nl80211: Driver does not support BSS COLOR vendor cmd");
282+ return 0;
283+ }
284+
285+ if (!(msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_VENDOR)) ||
286+ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
287+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
288+ MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL))
289+ return -ENOBUFS;
290+
291+ attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
292+ if (!attr) {
293+ nlmsg_free(msg);
294+ return -1;
295+ }
296+
297+ nla_nest_end(msg, attr);
298+
299+ ret = send_and_recv_msgs(drv, msg,
300+ nl80211_get_aval_color_bmp_handler, aval_color_bmp, NULL, NULL);
301+
302+ if (ret) {
303+ wpa_printf(MSG_ERROR, "Failed to send BSS COLOR vendor cmd. ret=%d (%s) ",
304+ ret, strerror(-ret));
305+ }
306+ return ret;
307+}
308+
309+static int nl80211_ap_wireless(void *priv, u8 sub_vendor_id, int value)
310+{
311+ struct i802_bss *bss = priv;
312+ struct wpa_driver_nl80211_data *drv = bss->drv;
313+ struct nl_msg *msg;
314+ struct nlattr *data;
315+ int ret;
316+
317+ if (!drv->mtk_wireless_vendor_cmd_avail) {
318+ wpa_printf(MSG_INFO,
319+ "nl80211: Driver does not support setting ap wireless control");
320+ return 0;
321+ }
322+
323+ msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
324+ if (!msg)
325+ goto fail;
326+
327+ if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
328+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL))
329+ goto fail;
330+
331+ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
332+ if (!data)
333+ goto fail;
334+
335+ if (sub_vendor_id == MTK_VENDOR_ATTR_WIRELESS_CTRL_BA_BUFFER_SIZE)
336+ nla_put_u16(msg, sub_vendor_id, (u16) value);
337+ else
338+ nla_put_u8(msg, sub_vendor_id, (u8) value);
339+
340+ nla_nest_end(msg, data);
341+ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
342+ if (ret)
343+ wpa_printf(MSG_ERROR, "Failed to set ap_wireless. ret=%d (%s)", ret, strerror(-ret));
344+
345+ return ret;
346+
347+fail:
348+ nlmsg_free(msg);
349+ return -ENOBUFS;
350+}
351+
352+static int nl80211_ap_rfeatures(void *priv, u8 sub_vendor_id, int value)
353+{
354+ struct i802_bss *bss = priv;
355+ struct wpa_driver_nl80211_data *drv = bss->drv;
356+ struct nl_msg *msg;
357+ struct nlattr *data;
358+ int ret;
359+
360+ if (!drv->mtk_rfeatures_vendor_cmd_avail) {
361+ wpa_printf(MSG_INFO,
362+ "nl80211: Driver does not support setting ap rfeatures control");
363+ return 0;
364+ }
365+
366+ msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
367+ if (!msg)
368+ goto fail;
369+
370+ if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
371+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_RFEATURE_CTRL))
372+ goto fail;
373+
374+ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
375+ if (!data)
376+ goto fail;
377+
378+ nla_put_u8(msg, sub_vendor_id, (u8) value);
379+
380+ nla_nest_end(msg, data);
381+
382+ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
383+ if (ret)
384+ wpa_printf(MSG_ERROR, "Failed to set rf_features. ret=%d (%s)", ret, strerror(-ret));
385+
386+ return ret;
387+
388+fail:
389+ nlmsg_free(msg);
390+ return -ENOBUFS;
391+}
392+
393+static int nl80211_ap_trigtype(void *priv, u8 enable, u8 type)
394+{
395+ struct i802_bss *bss = priv;
396+ struct wpa_driver_nl80211_data *drv = bss->drv;
397+ struct nl_msg *msg;
398+ struct nlattr *data, *data2;
399+ int ret;
400+
401+ if (!drv->mtk_rfeatures_vendor_cmd_avail) {
402+ wpa_printf(MSG_INFO,
403+ "nl80211: Driver does not support setting ap rfeatures control");
404+ return 0;
405+ }
406+
407+ msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
408+ if (!msg)
409+ goto fail;
410+
411+ if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
412+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_RFEATURE_CTRL))
413+ goto fail;
414+
415+ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
416+ if (!data)
417+ goto fail;
418+
419+ data2 = nla_nest_start(msg, MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_CFG);
420+ if (!data2)
421+ goto fail;
422+
423+ nla_put_u8(msg, MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE_EN, enable);
424+ nla_put_u8(msg, MTK_VENDOR_ATTR_RFEATURE_CTRL_TRIG_TYPE, type);
425+
426+ nla_nest_end(msg, data2);
427+ nla_nest_end(msg, data);
428+
429+ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
430+ if (ret)
431+ wpa_printf(MSG_ERROR, "Failed to set trig_type. ret=%d (%s)", ret, strerror(-ret));
432+
433+ return ret;
434+
435+fail:
436+ nlmsg_free(msg);
437+ return -ENOBUFS;
438+}
439+
440 const struct wpa_driver_ops wpa_driver_nl80211_ops = {
441 .name = "nl80211",
442 .desc = "Linux nl80211/cfg80211",
443@@ -14049,4 +14245,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
444 .ibf_dump = nl80211_ibf_dump,
445 .amsdu_ctrl = nl80211_enable_amsdu,
446 .amsdu_dump = nl80211_dump_amsdu,
447+ .get_aval_color_bmp = nl80211_get_aval_color_bmp,
448 };
449diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
450index 3bcc770..190e7a5 100644
451--- a/src/drivers/driver_nl80211.h
452+++ b/src/drivers/driver_nl80211.h
453@@ -204,6 +204,7 @@ struct wpa_driver_nl80211_data {
454 unsigned int mtk_3wire_vendor_cmd_avail:1;
455 unsigned int mtk_ibf_vendor_cmd_avail:1;
456 unsigned int mtk_wireless_vendor_cmd_avail:1;
457+ unsigned int mtk_bss_color_vendor_cmd_avail:1;
458
459 u64 vendor_scan_cookie;
460 u64 remain_on_chan_cookie;
461diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
462index dee99f0..a266926 100644
463--- a/src/drivers/driver_nl80211_capa.c
464+++ b/src/drivers/driver_nl80211_capa.c
465@@ -1117,6 +1117,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
466 case MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL:
467 drv->mtk_wireless_vendor_cmd_avail = 1;
468 break;
469+ case MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL :
470+ drv->mtk_bss_color_vendor_cmd_avail = 1;
471+ break;
472 }
473 }
474
475--
4762.18.0
477