blob: af7b31e83a1b67f510f1bf50916d0a773502625e [file] [log] [blame]
developer8fb759f2022-02-21 16:39:38 +08001/* Copyright (C) 2021 Mediatek Inc. */
2#define _GNU_SOURCE
3
4#include <net/if.h>
5
6#include "mtk_vendor_nl80211.h"
7#include "mt76-vendor.h"
8#include "iwpriv_compat.h"
9#include "mwctl.h"
10
11static const char *progname;
12struct unl unl;
13
14int (*registered_handler)(struct nl_msg *, void *);
15void *registered_handler_data;
16
17void register_handler(int (*handler)(struct nl_msg *, void *), void *data)
18{
19 registered_handler = handler;
20 registered_handler_data = data;
21}
22
23int valid_handler(struct nl_msg *msg, void *arg)
24{
25 if (registered_handler)
26 return registered_handler(msg, registered_handler_data);
27
28 return NL_OK;
29}
30
31extern struct cmd *__start___cmd[];
32extern struct cmd *__stop___cmd;
33
34#define for_each_cmd(_cmd, i) \
35 for (i = 0; i < &__stop___cmd - __start___cmd; i++) \
36 if ((_cmd = __start___cmd[i]))
37
38void usage(void)
39{
40 static const char *const commands[] = {
41 "set csi ctrl=<opt1>,<opt2>,<opt3>,<opt4> (macaddr=<macaddr>)",
42 "set csi interval=<interval (us)>",
43 "dump csi <packet num> <filename>",
44
45 "set amnt <index>(0x0~0xf) <mac addr>(xx:xx:xx:xx:xx:xx)",
46 "dump amnt <index> (0x0~0xf or 0xff)",
47
48 "set ap_rfeatures he_gi=<val>",
49 "set ap_rfeatures he_ltf=<val>",
50 "set ap_rfeatures trig_type=<enable>,<val> (val: 0-7)",
51 "set ap_rfeatures ack_policy=<val> (val: 0-4)",
52 "set ap_wireless fixed_mcs=<val>",
53 "set ap_wireless ofdma=<val> (0: disable, 1: DL, 2: UL)",
54 "set ap_wireless nusers_ofdma=<val>",
55 "set ap_wireless ppdu_type=<val> (0: SU, 1: MU, 4: LEGACY)",
56 "set ap_wireless add_ba_req_bufsize=<val>",
57 "set ap_wireless mimo=<val> (0: DL, 1: UL)",
58 "set ap_wireless ampdu=<enable>",
59 "set ap_wireless amsdu=<enable>",
60 "set ap_wireless cert=<enable>",
61 };
62 int i;
63
64 fprintf(stderr, "Usage:\n");
65 for (i = 0; i < ARRAY_SIZE(commands); i++)
66 printf(" %s wlanX %s\n", progname, commands[i]);
67
68 exit(1);
69}
70SECTION(dump);
71
72int main(int argc, char **argv)
73{
74 int if_idx, ret = 0;
75 const struct cmd *cmd, *match = NULL, *sectcmd;
76 const char *command, *section;
77 enum command_identify_by command_idby = CIB_NONE;
78 int err, i;
79 struct nl_msg *msg;
80
81 progname = argv[0];
82
developer99968cd2022-03-01 18:19:02 +080083 if(argv[1])
84 if_idx = if_nametoindex(argv[1]);
85 else {
86 fprintf(stderr, "wrong argument\n");
87 usage();
88 }
89
developer8fb759f2022-02-21 16:39:38 +080090 if (!if_idx) {
91 fprintf(stderr, "%s\n", strerror(errno));
92 return 2;
93 }
94
95 argc -= 2;
96 argv += 2;
97
98#if 0
99 if (!strncmp(cmd_str, "dump", 4)) {
100 if (!strncmp(subcmd, "csi", 3))
101 ret = mt76_csi_dump(if_idx, argc, argv);
102 else if (!strncmp(subcmd, "amnt", 4))
103 ret = mt76_amnt_dump(if_idx, argc, argv);
104 } else if (!strncmp(cmd_str, "set", 3)) {
105 if (!strncmp(subcmd, "csi", 3))
106 ret = mt76_csi_set(if_idx, argc, argv);
107 else if (!strncmp(subcmd, "amnt", 4))
108 ret = mt76_amnt_set(if_idx, argc, argv);
109 else if (!strncmp(subcmd, "ap_rfeatures", 12))
110 ret = mt76_ap_rfeatures_set(if_idx, argc, argv);
111 else if (!strncmp(subcmd, "ap_wireless", 11))
112 ret = mt76_ap_wireless_set(if_idx, argc, argv);
113 } else {
114 usage();
115 }
116#endif
117
118 command_idby = CIB_NETDEV;
119 section = *argv;
120 argc--;
121 argv++;
122
123 for_each_cmd(sectcmd, i) {
124 if (sectcmd->parent)
125 continue;
126 /* ok ... bit of a hack for the dupe 'info' section */
127 if (match && sectcmd->idby != command_idby)
128 continue;
129 if (strcmp(sectcmd->name, section) == 0)
130 match = sectcmd;
131 }
132
133 sectcmd = match;
134 match = NULL;
135 if (!sectcmd)
136 return 1;
137
138 if (argc > 0) {
139 command = *argv;
140
141 for_each_cmd(cmd, i) {
142 if (!cmd->handler)
143 continue;
144 if (cmd->parent != sectcmd)
145 continue;
146 /*
147 * ignore mismatch id by, but allow WDEV
148 * in place of NETDEV
149 */
150 if (cmd->idby != command_idby &&
151 !(cmd->idby == CIB_NETDEV &&
152 command_idby == CIB_WDEV))
153 continue;
154 if (strcmp(cmd->name, command))
155 continue;
156 if (argc > 1 && !cmd->args)
157 continue;
158 match = cmd;
159 break;
160 }
161
162 if (match) {
163 argc--;
164 argv++;
165 }
166 }
167
168
169 if (match)
170 cmd = match;
171 else {
172 /* Use the section itself, if possible. */
173 cmd = sectcmd;
174 if (argc && !cmd->args)
175 return 1;
176 if (cmd->idby != command_idby &&
177 !(cmd->idby == CIB_NETDEV && command_idby == CIB_WDEV))
178 return 1;
179 if (!cmd->handler)
180 return 1;
181 }
182
183 if (unl_genl_init(&unl, "nl80211") < 0) {
184 fprintf(stderr, "Failed to connect to nl80211\n");
185 return 2;
186 }
187
188 msg = unl_genl_msg(&unl, NL80211_CMD_VENDOR, false);
189
190 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_idx) ||
191 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, MTK_NL80211_VENDOR_ID) ||
192 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, cmd->cmd)) {
193 nlmsg_free(msg);
194 goto out;
195 }
196
197 err = cmd->handler(msg, argc, argv, (void*)&if_idx);
198 if (err) {
199 nlmsg_free(msg);
200 goto out;
201 }
202
203 ret = unl_genl_request(&unl, msg, valid_handler, NULL);
204 if (ret)
205 fprintf(stderr, "nl80211 call failed: %s\n", strerror(-ret));
206out:
207 unl_free(&unl);
208
209 return ret;
210}