blob: f27676754b0c2f6a9bdfbce933150e264caab31c [file] [log] [blame]
developer05f3b2b2024-08-19 19:17:34 +08001From b0f18aac90c7144db84f880aedb5aeaba3f37305 Mon Sep 17 00:00:00 2001
developer66e89bc2024-04-23 14:50:01 +08002From: mtk20656 <chank.chen@mediatek.com>
3Date: Tue, 6 Feb 2024 15:46:05 +0800
developer05f3b2b2024-08-19 19:17:34 +08004Subject: [PATCH 076/126] mtk: hostapd: add connac3 csi control interface
developer66e89bc2024-04-23 14:50:01 +08005
61. add hostapd_cli interface
72. add csi set/dump flow
83. add csi raw data to json
9
developer66e89bc2024-04-23 14:50:01 +080010Signed-off-by: mtk20656 <chank.chen@mediatek.com>
11---
12 hostapd/ctrl_iface.c | 193 ++++++++++++++++++++++++
13 hostapd/hostapd_cli.c | 16 ++
14 src/ap/ap_drv_ops.c | 13 ++
15 src/ap/ap_drv_ops.h | 2 +
developer05f3b2b2024-08-19 19:17:34 +080016 src/common/mtk_vendor.h | 33 ++++-
17 src/drivers/driver.h | 18 +++
18 src/drivers/driver_nl80211.c | 239 ++++++++++++++++++++++++++++++
developer66e89bc2024-04-23 14:50:01 +080019 src/drivers/driver_nl80211.h | 1 +
20 src/drivers/driver_nl80211_capa.c | 3 +
developer05f3b2b2024-08-19 19:17:34 +080021 9 files changed, 511 insertions(+), 7 deletions(-)
developer66e89bc2024-04-23 14:50:01 +080022
23diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
developer05f3b2b2024-08-19 19:17:34 +080024index 76fd25d8b..9bd8a46b3 100644
developer66e89bc2024-04-23 14:50:01 +080025--- a/hostapd/ctrl_iface.c
26+++ b/hostapd/ctrl_iface.c
developer05f3b2b2024-08-19 19:17:34 +080027@@ -5063,6 +5063,193 @@ hostapd_ctrl_iface_disable_beacon(struct hostapd_data *hapd, char *value,
developer66e89bc2024-04-23 14:50:01 +080028
29 }
30
31+static int
32+hostapd_ctrl_iface_set_csi(struct hostapd_data *hapd, char *cmd,
33+ char *buf, size_t buflen)
34+{
35+ char *tmp;
36+ u8 sta_mac[ETH_ALEN] = {0};
37+ u32 csi_para[4] = {0};
38+ char mac_str[18] = {0};
39+ u8 csi_para_cnt = 0;
40+
41+ tmp = strtok_r(cmd, ",", &cmd);
42+
43+ while (tmp) {
44+ csi_para_cnt++;
45+
46+ if (csi_para_cnt <= 4)
47+ csi_para[csi_para_cnt - 1] = strtol(tmp, &tmp, 10);
48+ else if (csi_para_cnt == 5) {
49+ memcpy(mac_str, tmp, sizeof(mac_str) - 1);
50+ break;
51+ }
52+
53+ tmp = strtok_r(NULL, ",", &cmd);
54+ }
55+
56+ if (strlen(mac_str)) { /* user input mac string */
57+ if (hwaddr_aton(mac_str, sta_mac) < 0) {
58+ wpa_printf(MSG_ERROR, "station mac is not right.\n");
59+ return -1;
60+ }
61+
62+ if (hostapd_drv_csi_set(hapd, csi_para[0], csi_para[1], csi_para[2], csi_para[3], sta_mac)) {
63+ wpa_printf(MSG_ERROR, "Not able to set csi, %d,%d,%d,%d,%s\n",
64+ csi_para[0], csi_para[1], csi_para[2], csi_para[3], mac_str);
65+ return -1;
66+ }
67+ } else {
68+ if (hostapd_drv_csi_set(hapd, csi_para[0], csi_para[1], csi_para[2], csi_para[3], NULL)) {
69+ wpa_printf(MSG_ERROR, "Not able to set csi, %d,%d,%d,%d\n",
70+ csi_para[0], csi_para[1], csi_para[2], csi_para[3]);
71+ return -1;
72+ }
73+ }
74+
75+ return os_snprintf(buf, buflen, "OK\n");
76+}
77+
78+static int mt76_csi_to_json(char *fname, struct csi_resp_data *resp_buf)
79+{
80+#define MAX_BUF_SIZE 10000
81+ FILE *f;
82+ int i;
83+
84+ if (!fname) {
85+ wpa_printf(MSG_ERROR, "csi dump file name is null!\n");
86+ return -1;
87+ }
88+
89+ f = fopen(fname, "a+");
90+ if (!f) {
91+ wpa_printf(MSG_ERROR, "open csi dump file %s failed\n", fname);
92+ return -1;
93+ }
94+
95+ if (fwrite("[", 1, 1, f) != 1) {
96+ fclose(f);
97+ return -1;
98+ }
99+
100+ for (i = 0; i < resp_buf->buf_cnt; i++) {
101+ struct csi_data *c = &resp_buf->csi_buf[i];
102+ char *pos, *buf;
103+ int j;
104+
105+ buf = malloc(MAX_BUF_SIZE);
106+ if (!buf) {
107+ fclose(f);
108+ return -1;
109+ }
110+
111+ pos = buf;
112+ pos += snprintf(pos, MAX_BUF_SIZE, "%c", '[');
113+
114+ pos += snprintf(pos, MAX_BUF_SIZE, "%d,", c->ts);
115+ pos += snprintf(pos, MAX_BUF_SIZE, "\"%02x%02x%02x%02x%02x%02x\",", c->ta[0], c->ta[1], c->ta[2], c->ta[3], c->ta[4], c->ta[5]);
116+
117+ pos += snprintf(pos, MAX_BUF_SIZE, "%d,", c->rssi);
118+ pos += snprintf(pos, MAX_BUF_SIZE, "%u,", c->snr);
119+ pos += snprintf(pos, MAX_BUF_SIZE, "%u,", c->data_bw);
120+ pos += snprintf(pos, MAX_BUF_SIZE, "%u,", c->pri_ch_idx);
121+ pos += snprintf(pos, MAX_BUF_SIZE, "%u,", c->rx_mode);
122+ pos += snprintf(pos, MAX_BUF_SIZE, "%d,", c->tx_idx);
123+ pos += snprintf(pos, MAX_BUF_SIZE, "%d,", c->rx_idx);
124+ pos += snprintf(pos, MAX_BUF_SIZE, "%d,", c->chain_info);
125+ pos += snprintf(pos, MAX_BUF_SIZE, "%d,", c->ext_info);
126+
127+ pos += snprintf(pos, MAX_BUF_SIZE, "%c", '[');
128+ for (j = 0; j < c->data_num; j++) {
129+ pos += snprintf(pos, MAX_BUF_SIZE, "%d", c->data_i[j]);
130+ if (j != (c->data_num - 1))
131+ pos += snprintf(pos, MAX_BUF_SIZE, ",");
132+ }
133+ pos += snprintf(pos, MAX_BUF_SIZE, "%c,", ']');
134+
135+ pos += snprintf(pos, MAX_BUF_SIZE, "%c", '[');
136+ for (j = 0; j < c->data_num; j++) {
137+ pos += snprintf(pos, MAX_BUF_SIZE, "%d", c->data_q[j]);
138+ if (j != (c->data_num - 1))
139+ pos += snprintf(pos, MAX_BUF_SIZE, ",");
140+ }
141+ pos += snprintf(pos, MAX_BUF_SIZE, "%c", ']');
142+
143+ pos += snprintf(pos, MAX_BUF_SIZE, "%c", ']');
144+ if (i != resp_buf->buf_cnt - 1)
145+ pos += snprintf(pos, MAX_BUF_SIZE, ",");
146+
147+ if (fwrite(buf, 1, pos - buf, f) != (pos - buf)) {
148+ perror("fwrite");
149+ free(buf);
150+ fclose(f);
151+ return -1;
152+ }
153+
154+ free(buf);
155+ }
156+
157+ if (fwrite("]", 1, 1, f) != 1) {
158+ fclose(f);
159+ return -1;
160+ }
161+
162+ fclose(f);
163+
164+ return 0;
165+}
166+
167+static int
168+hostapd_ctrl_iface_dump_csi(struct hostapd_data *hapd, char *cmd,
169+ char *buf, size_t buflen)
170+{
171+ char *tmp, *fname;
172+ int data_cnt = 0, ret = 0;
173+ struct csi_resp_data resp_buf;
174+
175+ tmp = strtok_r(cmd, ",", &cmd);
176+
177+ if (!tmp) {
178+ wpa_printf(MSG_ERROR, "Error in command format\n");
179+ return -1;
180+ }
181+
182+ data_cnt = strtoul(tmp, &tmp, 0);
183+
184+ if (data_cnt > 3000) {
185+ wpa_printf(MSG_ERROR, "Wrong input csi data cnt\n");
186+ return -1;
187+ }
188+
189+ fname = strtok_r(NULL, ",", &cmd);
190+
191+ if (!fname) {
192+ wpa_printf(MSG_ERROR, "Error in command format, csi_filename.\n");
193+ return -1;
194+ }
195+
196+ resp_buf.csi_buf = (struct csi_data *)os_zalloc(sizeof(struct csi_data) * data_cnt);
197+
198+ if (resp_buf.csi_buf == NULL) {
199+ wpa_printf(MSG_ERROR, "Error in memory allocation\n");
200+ return -1;
201+ }
202+
203+ resp_buf.usr_need_cnt = data_cnt;
204+ resp_buf.buf_cnt = 0;
205+
206+ if (hostapd_drv_csi_dump(hapd, (void *)&resp_buf)) {
207+ wpa_printf(MSG_ERROR, "Not able to set csi dump\n");
208+ os_free(resp_buf.csi_buf);
209+ return -1;
210+ }
211+
212+ mt76_csi_to_json(fname, &resp_buf);
213+
214+ os_free(resp_buf.csi_buf);
215+ return 0;
216+}
217+
218 static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
219 char *buf, char *reply,
220 int reply_size,
developer05f3b2b2024-08-19 19:17:34 +0800221@@ -5724,6 +5911,12 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
developer66e89bc2024-04-23 14:50:01 +0800222 } else if (os_strncmp(buf, "NO_BEACON ", 10) == 0) {
223 reply_len = hostapd_ctrl_iface_disable_beacon(hapd, buf + 10, reply,
224 reply_size);
225+ } else if (os_strncmp(buf, "SET_CSI ", 7) == 0) {
226+ reply_len = hostapd_ctrl_iface_set_csi(hapd, buf + 8,
227+ reply, reply_size);
228+ } else if (os_strncmp(buf, "DUMP_CSI ", 8) == 0) {
229+ reply_len = hostapd_ctrl_iface_dump_csi(hapd, buf + 9,
230+ reply, reply_size);
231 } else {
232 os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
233 reply_len = 16;
234diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
developer05f3b2b2024-08-19 19:17:34 +0800235index a98f76eee..f54fa9997 100644
developer66e89bc2024-04-23 14:50:01 +0800236--- a/hostapd/hostapd_cli.c
237+++ b/hostapd/hostapd_cli.c
developer05f3b2b2024-08-19 19:17:34 +0800238@@ -1744,6 +1744,18 @@ static int hostapd_cli_cmd_dump_amnt(struct wpa_ctrl *ctrl, int argc,
developer66e89bc2024-04-23 14:50:01 +0800239 return hostapd_cli_cmd(ctrl, "DUMP_AMNT", 1, argc, argv);
240 }
241
242+static int hostapd_cli_cmd_set_csi(struct wpa_ctrl *ctrl, int argc,
243+ char *argv[])
244+{
245+ return hostapd_cli_cmd(ctrl, "SET_CSI", 1, argc, argv);
246+}
247+
248+static int hostapd_cli_cmd_dump_csi(struct wpa_ctrl *ctrl, int argc,
249+ char *argv[])
250+{
251+ return hostapd_cli_cmd(ctrl, "DUMP_CSI", 1, argc, argv);
252+}
253+
254 struct hostapd_cli_cmd {
255 const char *cmd;
256 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
developer05f3b2b2024-08-19 19:17:34 +0800257@@ -1992,6 +2004,10 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
developer66e89bc2024-04-23 14:50:01 +0800258 " = Set Station index and mac to monitor"},
259 { "dump_amnt", hostapd_cli_cmd_dump_amnt, NULL,
260 " = Dump RSSI of monitoring Station"},
261+ { "set_csi", hostapd_cli_cmd_set_csi, NULL,
262+ " = Set csi configuaration"},
263+ { "dump_csi", hostapd_cli_cmd_dump_csi, NULL,
264+ " = Dump csi data to a json file"},
265 { NULL, NULL, NULL, NULL }
266 };
267
268diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
developer05f3b2b2024-08-19 19:17:34 +0800269index c7635cae6..a26a3f45d 100644
developer66e89bc2024-04-23 14:50:01 +0800270--- a/src/ap/ap_drv_ops.c
271+++ b/src/ap/ap_drv_ops.c
developer05f3b2b2024-08-19 19:17:34 +0800272@@ -1445,3 +1445,16 @@ int hostapd_drv_beacon_ctrl(struct hostapd_data *hapd, u8 beacon_mode)
developer66e89bc2024-04-23 14:50:01 +0800273 return hapd->driver->beacon_ctrl(hapd->drv_priv, beacon_mode);
274 }
275
276+int hostapd_drv_csi_set(struct hostapd_data *hapd, u8 mode, u8 cfg, u8 v1, u32 v2, u8 *mac)
277+{
278+ if (!hapd->driver || !hapd->driver->csi_set)
279+ return 0;
developer05f3b2b2024-08-19 19:17:34 +0800280+ return hapd->driver->csi_set(hapd->drv_priv, hapd->iconf->band_idx, mode, cfg, v1, v2, mac);
developer66e89bc2024-04-23 14:50:01 +0800281+}
282+
283+int hostapd_drv_csi_dump(struct hostapd_data *hapd, void *dump_buf)
284+{
285+ if (!hapd->driver || !hapd->driver->csi_dump)
286+ return 0;
developer05f3b2b2024-08-19 19:17:34 +0800287+ return hapd->driver->csi_dump(hapd->drv_priv, hapd->iconf->band_idx, dump_buf);
developer66e89bc2024-04-23 14:50:01 +0800288+}
289diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
developer05f3b2b2024-08-19 19:17:34 +0800290index 8c783610c..9f2e86a9b 100644
developer66e89bc2024-04-23 14:50:01 +0800291--- a/src/ap/ap_drv_ops.h
292+++ b/src/ap/ap_drv_ops.h
developer05f3b2b2024-08-19 19:17:34 +0800293@@ -174,6 +174,8 @@ int hostapd_drv_amnt_dump(struct hostapd_data *hapd, u8 amnt_idx, u8 *amnt_dump_
developer66e89bc2024-04-23 14:50:01 +0800294 int hostapd_drv_background_radar_mode(struct hostapd_data *hapd);
295 int hostapd_drv_pp_mode_set(struct hostapd_data *hapd);
296 int hostapd_drv_beacon_ctrl(struct hostapd_data *hapd, u8 beacon_mode);
297+int hostapd_drv_csi_set(struct hostapd_data *hapd, u8 mode, u8 cfg, u8 v1, u32 v2, u8 *mac);
298+int hostapd_drv_csi_dump(struct hostapd_data *hapd, void *dump_buf);
299
300 #include "drivers/driver.h"
301
302diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
developer05f3b2b2024-08-19 19:17:34 +0800303index 9b054ef43..ce3a2ad9a 100644
developer66e89bc2024-04-23 14:50:01 +0800304--- a/src/common/mtk_vendor.h
305+++ b/src/common/mtk_vendor.h
developer05f3b2b2024-08-19 19:17:34 +0800306@@ -73,12 +73,13 @@ enum mtk_vendor_attr_csi_ctrl {
developer66e89bc2024-04-23 14:50:01 +0800307 MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL1,
308 MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL2,
309 MTK_VENDOR_ATTR_CSI_CTRL_MAC_ADDR,
310- MTK_VENDOR_ATTR_CSI_CTRL_INTERVAL,
311
312 MTK_VENDOR_ATTR_CSI_CTRL_DUMP_NUM,
313
developer05f3b2b2024-08-19 19:17:34 +0800314 MTK_VENDOR_ATTR_CSI_CTRL_DATA,
315
316+ MTK_VENDOR_ATTR_CSI_CTRL_BAND_IDX,
317+
318 /* keep last */
319 NUM_MTK_VENDOR_ATTRS_CSI_CTRL,
320 MTK_VENDOR_ATTR_CSI_CTRL_MAX =
321@@ -96,6 +97,7 @@ enum mtk_vendor_attr_csi_data {
developer66e89bc2024-04-23 14:50:01 +0800322 MTK_VENDOR_ATTR_CSI_DATA_BW,
323 MTK_VENDOR_ATTR_CSI_DATA_CH_IDX,
324 MTK_VENDOR_ATTR_CSI_DATA_TA,
325+ MTK_VENDOR_ATTR_CSI_DATA_NUM,
326 MTK_VENDOR_ATTR_CSI_DATA_I,
327 MTK_VENDOR_ATTR_CSI_DATA_Q,
328 MTK_VENDOR_ATTR_CSI_DATA_INFO,
developer05f3b2b2024-08-19 19:17:34 +0800329@@ -106,7 +108,7 @@ enum mtk_vendor_attr_csi_data {
developer66e89bc2024-04-23 14:50:01 +0800330 MTK_VENDOR_ATTR_CSI_DATA_TX_ANT,
331 MTK_VENDOR_ATTR_CSI_DATA_RX_ANT,
332 MTK_VENDOR_ATTR_CSI_DATA_MODE,
333- MTK_VENDOR_ATTR_CSI_DATA_H_IDX,
334+ MTK_VENDOR_ATTR_CSI_DATA_CHAIN_INFO,
335
336 /* keep last */
337 NUM_MTK_VENDOR_ATTRS_CSI_DATA,
developer05f3b2b2024-08-19 19:17:34 +0800338@@ -284,23 +286,40 @@ enum mtk_vendor_attr_beacon_ctrl {
developer66e89bc2024-04-23 14:50:01 +0800339 NUM_MTK_VENDOR_ATTRS_BEACON_CTRL - 1
340 };
341
342-#define CSI_MAX_COUNT 256
343+#define CSI_BW20_DATA_COUNT 64
344+#define CSI_BW40_DATA_COUNT 128
345+#define CSI_BW80_DATA_COUNT 256
346+#define CSI_BW160_DATA_COUNT 512
347+#define CSI_BW320_DATA_COUNT 1024
348 #define ETH_ALEN 6
349
350 struct csi_data {
351- s16 data_i[CSI_MAX_COUNT];
352- s16 data_q[CSI_MAX_COUNT];
353+ u8 ch_bw;
354+ u16 data_num;
355+ s16 data_i[CSI_BW320_DATA_COUNT];
356+ s16 data_q[CSI_BW320_DATA_COUNT];
357+ u8 band;
358 s8 rssi;
359 u8 snr;
360 u32 ts;
361 u8 data_bw;
362 u8 pri_ch_idx;
363 u8 ta[ETH_ALEN];
364- u32 info;
365+ u32 ext_info;
366 u8 rx_mode;
367- u32 h_idx;
368+ u32 chain_info;
369 u16 tx_idx;
370 u16 rx_idx;
371+ u32 segment_num;
372+ u8 remain_last;
373+ u16 pkt_sn;
374+ u8 tr_stream;
375+};
376+
377+struct csi_resp_data {
378+ u16 usr_need_cnt;
379+ u16 buf_cnt;
380+ struct csi_data *csi_buf;
381 };
382
383 #define AIR_MONITOR_MAX_ENTRY 16
384diff --git a/src/drivers/driver.h b/src/drivers/driver.h
developer05f3b2b2024-08-19 19:17:34 +0800385index ec00c36e4..48cb93cfd 100644
developer66e89bc2024-04-23 14:50:01 +0800386--- a/src/drivers/driver.h
387+++ b/src/drivers/driver.h
developer05f3b2b2024-08-19 19:17:34 +0800388@@ -5369,6 +5369,24 @@ struct wpa_driver_ops {
developer66e89bc2024-04-23 14:50:01 +0800389 #ifdef CONFIG_IEEE80211BE
390 int (*get_mld_addr)(void *priv, u8 *addr);
391 #endif
392+ /**
393+ * csi_set - Set csi related mode and parameter
394+ * @priv: Private driver interface data
developer05f3b2b2024-08-19 19:17:34 +0800395+ * @band_idx: band idx
developer66e89bc2024-04-23 14:50:01 +0800396+ * @mode: Csi mode parameter
397+ * @cfg: Csi config parameter
398+ * @v1: Value1
399+ * @v2: Value2
400+ * @mac: Station mac for station filter
401+ */
developer05f3b2b2024-08-19 19:17:34 +0800402+ int (*csi_set)(void *priv, u8 band_idx, u8 mode, u8 cfg, u8 v1, u32 v2, u8 *mac);
developer66e89bc2024-04-23 14:50:01 +0800403+ /**
404+ * csi_dump - Dump csi data to json file
405+ * @priv: Private driver interface data
developer05f3b2b2024-08-19 19:17:34 +0800406+ * @band_idx: band idx
developer66e89bc2024-04-23 14:50:01 +0800407+ * @dump_buf: Dump_struct that store csi data and related info
408+ */
developer05f3b2b2024-08-19 19:17:34 +0800409+ int (*csi_dump)(void *priv, u8 band_idx, void *dump_buf);
developer66e89bc2024-04-23 14:50:01 +0800410 };
411
412 /**
413diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
developer05f3b2b2024-08-19 19:17:34 +0800414index 8f7215d62..afb068091 100644
developer66e89bc2024-04-23 14:50:01 +0800415--- a/src/drivers/driver_nl80211.c
416+++ b/src/drivers/driver_nl80211.c
developer05f3b2b2024-08-19 19:17:34 +0800417@@ -161,6 +161,36 @@ pp_ctrl_policy[NUM_MTK_VENDOR_ATTRS_PP_CTRL] = {
developer66e89bc2024-04-23 14:50:01 +0800418 [MTK_VENDOR_ATTR_PP_MODE] = { .type = NLA_U8 },
419 };
420
421+static struct nla_policy csi_ctrl_policy[NUM_MTK_VENDOR_ATTRS_CSI_CTRL] = {
developer05f3b2b2024-08-19 19:17:34 +0800422+ [MTK_VENDOR_ATTR_CSI_CTRL_BAND_IDX] = { .type = NLA_U8 },
developer66e89bc2024-04-23 14:50:01 +0800423+ [MTK_VENDOR_ATTR_CSI_CTRL_CFG] = { .type = NLA_NESTED },
424+ [MTK_VENDOR_ATTR_CSI_CTRL_CFG_MODE] = { .type = NLA_U8 },
425+ [MTK_VENDOR_ATTR_CSI_CTRL_CFG_TYPE] = { .type = NLA_U8 },
426+ [MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL1] = { .type = NLA_U8 },
427+ [MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL2] = { .type = NLA_U32 },
428+ [MTK_VENDOR_ATTR_CSI_CTRL_MAC_ADDR] = { .type = NLA_NESTED },
429+ [MTK_VENDOR_ATTR_CSI_CTRL_DUMP_NUM] = { .type = NLA_U16 },
430+ [MTK_VENDOR_ATTR_CSI_CTRL_DATA] = { .type = NLA_NESTED },
431+};
432+
433+static struct nla_policy csi_data_policy[NUM_MTK_VENDOR_ATTRS_CSI_DATA] = {
434+ [MTK_VENDOR_ATTR_CSI_DATA_VER] = { .type = NLA_U8 },
435+ [MTK_VENDOR_ATTR_CSI_DATA_TS] = { .type = NLA_U32 },
436+ [MTK_VENDOR_ATTR_CSI_DATA_RSSI] = { .type = NLA_U8 },
437+ [MTK_VENDOR_ATTR_CSI_DATA_SNR] = { .type = NLA_U8 },
438+ [MTK_VENDOR_ATTR_CSI_DATA_BW] = { .type = NLA_U8 },
439+ [MTK_VENDOR_ATTR_CSI_DATA_CH_IDX] = { .type = NLA_U8 },
440+ [MTK_VENDOR_ATTR_CSI_DATA_TA] = { .type = NLA_NESTED },
441+ [MTK_VENDOR_ATTR_CSI_DATA_NUM] = { .type = NLA_U32 },
442+ [MTK_VENDOR_ATTR_CSI_DATA_I] = { .type = NLA_NESTED },
443+ [MTK_VENDOR_ATTR_CSI_DATA_Q] = { .type = NLA_NESTED },
444+ [MTK_VENDOR_ATTR_CSI_DATA_INFO] = { .type = NLA_U32 },
445+ [MTK_VENDOR_ATTR_CSI_DATA_TX_ANT] = { .type = NLA_U8 },
446+ [MTK_VENDOR_ATTR_CSI_DATA_RX_ANT] = { .type = NLA_U8 },
447+ [MTK_VENDOR_ATTR_CSI_DATA_MODE] = { .type = NLA_U8 },
448+ [MTK_VENDOR_ATTR_CSI_DATA_CHAIN_INFO] = { .type = NLA_U32 },
449+};
450+
451 static struct nl_sock * nl_create_handle(struct nl_cb *cb, const char *dbg)
452 {
453 struct nl_sock *handle;
developer05f3b2b2024-08-19 19:17:34 +0800454@@ -15220,6 +15250,213 @@ static int nl80211_get_mld_addr(void *priv, u8 *addr)
developer66e89bc2024-04-23 14:50:01 +0800455 }
456 #endif
457
458+static int
developer05f3b2b2024-08-19 19:17:34 +0800459+nl80211_csi_set(void *priv, u8 band_idx, u8 mode, u8 cfg, u8 v1, u32 v2, u8 *mac)
developer66e89bc2024-04-23 14:50:01 +0800460+{
461+ struct i802_bss *bss = priv;
462+ struct wpa_driver_nl80211_data *drv = bss->drv;
463+ struct nl_msg *msg;
464+ struct nlattr *data;
465+ void *tb1, *tb2;
466+ int ret, i;
467+
468+ if (!drv->mtk_csi_vendor_cmd_avail) {
469+ wpa_printf(MSG_ERROR,
470+ "nl80211: Driver does not support csi");
471+ return 0;
472+ }
473+
474+ msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
475+ if (!msg)
476+ goto fail;
477+
478+ if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
479+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
480+ MTK_NL80211_VENDOR_SUBCMD_CSI_CTRL))
481+ goto fail;
482+
483+ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA | NLA_F_NESTED);
484+ if (!data)
485+ goto fail;
486+
developer05f3b2b2024-08-19 19:17:34 +0800487+ nla_put_u8(msg, MTK_VENDOR_ATTR_CSI_CTRL_BAND_IDX, band_idx);
488+
developer66e89bc2024-04-23 14:50:01 +0800489+ tb1 = nla_nest_start(msg, MTK_VENDOR_ATTR_CSI_CTRL_CFG | NLA_F_NESTED);
490+ if (!tb1)
491+ goto fail;
492+
493+ nla_put_u8(msg, MTK_VENDOR_ATTR_CSI_CTRL_CFG_MODE, mode);
494+ nla_put_u8(msg, MTK_VENDOR_ATTR_CSI_CTRL_CFG_TYPE, cfg);
495+ nla_put_u8(msg, MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL1, v1);
496+ nla_put_u32(msg, MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL2, v2);
497+
498+ nla_nest_end(msg, tb1);
499+
500+ if (mac) {
501+ tb2 = nla_nest_start(msg, MTK_VENDOR_ATTR_CSI_CTRL_MAC_ADDR | NLA_F_NESTED);
502+ if (!tb2)
503+ goto fail;
504+
505+ for (i = 0; i < ETH_ALEN; i++)
506+ nla_put_u8(msg, i, mac[i]);
507+
508+ nla_nest_end(msg, tb2);
509+ }
510+
511+ nla_nest_end(msg, data);
512+
513+ ret = send_and_recv_cmd(drv, msg);
514+
515+ if (ret)
516+ wpa_printf(MSG_ERROR, "Failed to set csi. ret=%d (%s)",
517+ ret, strerror(-ret));
518+
519+ return ret;
520+
521+fail:
522+ nlmsg_free(msg);
523+ return -ENOBUFS;
524+
525+}
526+
527+static int
528+mt76_csi_dump_cb(struct nl_msg *msg, void *arg)
529+{
530+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
531+ struct nlattr *tb1[NUM_MTK_VENDOR_ATTRS_CSI_CTRL];
532+ struct nlattr *tb2[NUM_MTK_VENDOR_ATTRS_CSI_DATA];
533+ struct nlattr *attr, *cur, *data;
534+ int len = 0, rem, idx;
535+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
536+ struct csi_resp_data *csi_resp = (struct csi_resp_data *)arg;
537+ struct csi_data *c = csi_resp->csi_buf;
538+
539+ c += csi_resp->buf_cnt;
540+
541+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
542+ genlmsg_attrlen(gnlh, 0), NULL);
543+
544+ attr = tb[NL80211_ATTR_VENDOR_DATA];
545+ if (!attr)
546+ return NL_SKIP;
547+
548+ nla_parse_nested(tb1, MTK_VENDOR_ATTR_CSI_CTRL_MAX,
549+ attr, csi_ctrl_policy);
550+
551+ if (!tb1[MTK_VENDOR_ATTR_CSI_CTRL_DATA])
552+ return NL_SKIP;
553+
554+ nla_parse_nested(tb2, MTK_VENDOR_ATTR_CSI_DATA_MAX,
555+ tb1[MTK_VENDOR_ATTR_CSI_CTRL_DATA], csi_data_policy);
556+
557+ if (!(tb2[MTK_VENDOR_ATTR_CSI_DATA_VER] &&
558+ tb2[MTK_VENDOR_ATTR_CSI_DATA_TS] &&
559+ tb2[MTK_VENDOR_ATTR_CSI_DATA_RSSI] &&
560+ tb2[MTK_VENDOR_ATTR_CSI_DATA_SNR] &&
561+ tb2[MTK_VENDOR_ATTR_CSI_DATA_BW] &&
562+ tb2[MTK_VENDOR_ATTR_CSI_DATA_CH_IDX] &&
563+ tb2[MTK_VENDOR_ATTR_CSI_DATA_TA] &&
564+ tb2[MTK_VENDOR_ATTR_CSI_DATA_I] &&
565+ tb2[MTK_VENDOR_ATTR_CSI_DATA_Q] &&
566+ tb2[MTK_VENDOR_ATTR_CSI_DATA_INFO] &&
567+ tb2[MTK_VENDOR_ATTR_CSI_DATA_MODE] &&
568+ tb2[MTK_VENDOR_ATTR_CSI_DATA_CHAIN_INFO])) {
569+ fprintf(stderr, "Attributes error for CSI data\n");
570+ return NL_SKIP;
571+ }
572+
573+ c->rssi = nla_get_u8(tb2[MTK_VENDOR_ATTR_CSI_DATA_RSSI]);
574+ c->snr = nla_get_u8(tb2[MTK_VENDOR_ATTR_CSI_DATA_SNR]);
575+ c->data_bw = nla_get_u8(tb2[MTK_VENDOR_ATTR_CSI_DATA_BW]);
576+ c->pri_ch_idx = nla_get_u8(tb2[MTK_VENDOR_ATTR_CSI_DATA_CH_IDX]);
577+ c->rx_mode = nla_get_u8(tb2[MTK_VENDOR_ATTR_CSI_DATA_MODE]);
578+
579+ c->tx_idx = nla_get_u16(tb2[MTK_VENDOR_ATTR_CSI_DATA_TX_ANT]);
580+ c->rx_idx = nla_get_u16(tb2[MTK_VENDOR_ATTR_CSI_DATA_RX_ANT]);
581+
582+ c->ext_info = nla_get_u32(tb2[MTK_VENDOR_ATTR_CSI_DATA_INFO]);
583+ c->chain_info = nla_get_u32(tb2[MTK_VENDOR_ATTR_CSI_DATA_CHAIN_INFO]);
584+
585+ c->ts = nla_get_u32(tb2[MTK_VENDOR_ATTR_CSI_DATA_TS]);
586+
587+ c->data_num = nla_get_u32(tb2[MTK_VENDOR_ATTR_CSI_DATA_NUM]);
588+
589+ idx = 0;
590+ nla_for_each_nested(cur, tb2[MTK_VENDOR_ATTR_CSI_DATA_TA], rem) {
591+ if (idx < ETH_ALEN)
592+ c->ta[idx++] = nla_get_u8(cur);
593+ }
594+
595+ idx = 0;
596+ nla_for_each_nested(cur, tb2[MTK_VENDOR_ATTR_CSI_DATA_I], rem) {
597+ if (idx < c->data_num)
598+ c->data_i[idx++] = nla_get_u16(cur);
599+ }
600+
601+ idx = 0;
602+ nla_for_each_nested(cur, tb2[MTK_VENDOR_ATTR_CSI_DATA_Q], rem) {
603+ if (idx < c->data_num)
604+ c->data_q[idx++] = nla_get_u16(cur);
605+ }
606+
607+ csi_resp->buf_cnt++;
608+
609+ return NL_SKIP;
610+}
611+
612+static int
developer05f3b2b2024-08-19 19:17:34 +0800613+nl80211_csi_dump(void *priv, u8 band_idx, void *dump_buf)
developer66e89bc2024-04-23 14:50:01 +0800614+{
615+ struct i802_bss *bss = priv;
616+ struct wpa_driver_nl80211_data *drv = bss->drv;
617+ struct nl_msg *msg;
618+ struct nlattr *data;
619+ int ret;
620+ struct csi_resp_data *csi_resp;
621+ u16 pkt_num, i;
622+
623+ if (!drv->mtk_csi_vendor_cmd_avail) {
624+ wpa_printf(MSG_INFO,
625+ "nl80211: Driver does not support csi");
626+ return 0;
627+ }
628+
629+ csi_resp = (struct csi_resp_data *)dump_buf;
630+ pkt_num = csi_resp->usr_need_cnt;
631+
632+ if (pkt_num > 3000)
633+ return -EINVAL;
634+
635+#define CSI_DUMP_PER_NUM 3
636+ for (i = 0; i < pkt_num / CSI_DUMP_PER_NUM; i++) {
637+ msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_VENDOR);
638+ if (!msg)
639+ goto fail;
640+
641+ if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
642+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
643+ MTK_NL80211_VENDOR_SUBCMD_CSI_CTRL))
644+ goto fail;
645+
646+ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA | NLA_F_NESTED);
647+ if (!data)
648+ goto fail;
649+
developer05f3b2b2024-08-19 19:17:34 +0800650+ nla_put_u8(msg, MTK_VENDOR_ATTR_CSI_CTRL_BAND_IDX, band_idx);
developer66e89bc2024-04-23 14:50:01 +0800651+ nla_put_u16(msg, MTK_VENDOR_ATTR_CSI_CTRL_DUMP_NUM, CSI_DUMP_PER_NUM);
652+
653+ nla_nest_end(msg, data);
654+
655+ ret = send_and_recv_resp(drv, msg, mt76_csi_dump_cb, dump_buf);
656+ }
657+
658+ return ret;
659+
660+fail:
661+ nlmsg_free(msg);
662+ return -ENOBUFS;
663+}
664+
665 const struct wpa_driver_ops wpa_driver_nl80211_ops = {
666 .name = "nl80211",
667 .desc = "Linux nl80211/cfg80211",
developer05f3b2b2024-08-19 19:17:34 +0800668@@ -15403,4 +15640,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
developer66e89bc2024-04-23 14:50:01 +0800669 #ifdef CONFIG_IEEE80211BE
670 .get_mld_addr = nl80211_get_mld_addr,
671 #endif
672+ .csi_set = nl80211_csi_set,
673+ .csi_dump = nl80211_csi_dump,
674 };
675diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
676index a0a62e536..b710b50cd 100644
677--- a/src/drivers/driver_nl80211.h
678+++ b/src/drivers/driver_nl80211.h
679@@ -212,6 +212,7 @@ struct wpa_driver_nl80211_data {
680 unsigned int mtk_background_radar_vendor_cmd_avail:1;
681 unsigned int mtk_pp_vendor_cmd_avail:1;
682 unsigned int mtk_beacon_ctrl_vendor_cmd_avail:1;
683+ unsigned int mtk_csi_vendor_cmd_avail:1;
684
685 u32 ignore_next_local_disconnect;
686 u32 ignore_next_local_deauth;
687diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
developer05f3b2b2024-08-19 19:17:34 +0800688index 30f89b687..5a53700d1 100644
developer66e89bc2024-04-23 14:50:01 +0800689--- a/src/drivers/driver_nl80211_capa.c
690+++ b/src/drivers/driver_nl80211_capa.c
691@@ -1173,6 +1173,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
692 case MTK_NL80211_VENDOR_SUBCMD_BEACON_CTRL :
693 drv->mtk_beacon_ctrl_vendor_cmd_avail = 1;
694 break;
695+ case MTK_NL80211_VENDOR_SUBCMD_CSI_CTRL:
696+ drv->mtk_csi_vendor_cmd_avail = 1;
697+ break;
698 }
699 }
700
701--
developer05f3b2b2024-08-19 19:17:34 +08007022.18.0
developer66e89bc2024-04-23 14:50:01 +0800703