Skip to content

Commit bcd2fc7

Browse files
Krishna Tcarlescufi
authored andcommitted
[nrf fromtree] net: wifi: Add support for regulatory domain configuration
Wi-Fi bands are regulated by a governing body depending on operating country, add support for the user to provide a country of operation as a hint to the Wi-Fi chipset. Ideally if the chipset supports, this is all handled internally, in that case "get" is useful. But for testing and other use cases add a "set" as well, similar to "iw reg set" or "country_code=" configuration in hostapd/wpa_supplicant in Linux world. This add a new offload API operation "reg_domain" that can be used to either get or set the regulatory information. The validation is left to the underlying chipset, shell only does basic validation (XY/00). This is just a regulatory hint to the chipset, there could be other regulatory hints e.g., beacon that can override this configuration, so, an additional option to force this setting, despite other hints, is useful for testing purposes. FYI, the standard database used is [1]. [1] - https://git.kernel.org/pub/scm/linux/kernel/git/sforshee/wireless-regdb.git/tree/db.txt Signed-off-by: Krishna T <[email protected]> (cherry picked from commit fadb1fd)
1 parent aa5def0 commit bcd2fc7

File tree

4 files changed

+109
-0
lines changed

4 files changed

+109
-0
lines changed

include/zephyr/net/wifi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#ifndef ZEPHYR_INCLUDE_NET_WIFI_H_
1313
#define ZEPHYR_INCLUDE_NET_WIFI_H_
1414

15+
#define WIFI_COUNTRY_CODE_LEN 2
16+
1517
/* Not having support for legacy types is deliberate to enforce
1618
* higher security.
1719
*/

include/zephyr/net/wifi_mgmt.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ enum net_request_wifi_cmd {
4040
NET_REQUEST_WIFI_CMD_PS_MODE,
4141
NET_REQUEST_WIFI_CMD_TWT,
4242
NET_REQUEST_WIFI_CMD_PS_CONFIG,
43+
NET_REQUEST_WIFI_CMD_REG_DOMAIN,
4344
};
4445

4546
#define NET_REQUEST_WIFI_SCAN \
@@ -91,6 +92,10 @@ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_TWT);
9192
(_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_PS_CONFIG)
9293

9394
NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_PS_CONFIG);
95+
#define NET_REQUEST_WIFI_REG_DOMAIN \
96+
(_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_REG_DOMAIN)
97+
98+
NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_REG_DOMAIN);
9499

95100
enum net_event_wifi_cmd {
96101
NET_EVENT_WIFI_CMD_SCAN_RESULT = 1,
@@ -231,6 +236,19 @@ struct wifi_ps_config {
231236
char num_twt_flows;
232237
};
233238

239+
/* Generic get/set operation for any command*/
240+
enum wifi_mgmt_op {
241+
WIFI_MGMT_GET = 0,
242+
WIFI_MGMT_SET = 1,
243+
};
244+
245+
struct wifi_reg_domain {
246+
enum wifi_mgmt_op oper;
247+
/* Ignore all other regulatory hints */
248+
bool force;
249+
uint8_t country_code[WIFI_COUNTRY_CODE_LEN];
250+
};
251+
234252
#include <zephyr/net/net_if.h>
235253

236254
typedef void (*scan_result_cb_t)(struct net_if *iface, int status,
@@ -268,6 +286,7 @@ struct net_wifi_mgmt_offload {
268286
int (*set_power_save_mode)(const struct device *dev, struct wifi_ps_mode_params *params);
269287
int (*set_twt)(const struct device *dev, struct wifi_twt_params *params);
270288
int (*get_power_save_config)(const struct device *dev, struct wifi_ps_config *config);
289+
int (*reg_domain)(const struct device *dev, struct wifi_reg_domain *reg_domain);
271290
};
272291

273292
/* Make sure that the network interface API is properly setup inside

subsys/net/l2/wifi/wifi_mgmt.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,3 +312,24 @@ void wifi_mgmt_raise_twt_event(struct net_if *iface, struct wifi_twt_params *twt
312312
iface, twt_params,
313313
sizeof(struct wifi_twt_params));
314314
}
315+
316+
static int wifi_reg_domain(uint32_t mgmt_request, struct net_if *iface,
317+
void *data, size_t len)
318+
{
319+
const struct device *dev = net_if_get_device(iface);
320+
struct net_wifi_mgmt_offload *off_api =
321+
(struct net_wifi_mgmt_offload *) dev->api;
322+
struct wifi_reg_domain *reg_domain = data;
323+
324+
if (off_api == NULL || off_api->reg_domain == NULL) {
325+
return -ENOTSUP;
326+
}
327+
328+
if (!data || len != sizeof(*reg_domain)) {
329+
return -EINVAL;
330+
}
331+
332+
return off_api->reg_domain(dev, reg_domain);
333+
}
334+
335+
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_REG_DOMAIN, wifi_reg_domain);

subsys/net/l2/wifi/wifi_shell.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,67 @@ static int cmd_wifi_ap_disable(const struct shell *sh, size_t argc,
685685
return 0;
686686
}
687687

688+
689+
static int cmd_wifi_reg_domain(const struct shell *sh, size_t argc,
690+
char *argv[])
691+
{
692+
struct net_if *iface = net_if_get_default();
693+
struct wifi_reg_domain regd = {0};
694+
int ret;
695+
696+
if (argc == 1) {
697+
regd.oper = WIFI_MGMT_GET;
698+
} else if (argc >= 2 && argc <= 3) {
699+
regd.oper = WIFI_MGMT_SET;
700+
if (strlen(argv[1]) != 2) {
701+
shell_fprintf(sh, SHELL_WARNING,
702+
"Invalid reg domain: Length should be two letters/digits\n");
703+
return -ENOEXEC;
704+
}
705+
706+
/* Two letter country code with special case of 00 for WORLD */
707+
if (((argv[1][0] < 'A' || argv[1][0] > 'Z') ||
708+
(argv[1][1] < 'A' || argv[1][1] > 'Z')) &&
709+
(argv[1][0] != '0' || argv[1][1] != '0')) {
710+
shell_fprintf(sh, SHELL_WARNING, "Invalid reg domain %c%c\n", argv[1][0],
711+
argv[1][1]);
712+
return -ENOEXEC;
713+
}
714+
regd.country_code[0] = argv[1][0];
715+
regd.country_code[1] = argv[1][1];
716+
717+
if (argc == 3) {
718+
if (strncmp(argv[2], "-f", 2) == 0) {
719+
regd.force = true;
720+
} else {
721+
shell_fprintf(sh, SHELL_WARNING, "Invalid option %s\n", argv[2]);
722+
return -ENOEXEC;
723+
}
724+
}
725+
} else {
726+
shell_help(sh);
727+
return -ENOEXEC;
728+
}
729+
730+
ret = net_mgmt(NET_REQUEST_WIFI_REG_DOMAIN, iface,
731+
&regd, sizeof(regd));
732+
if (ret) {
733+
shell_fprintf(sh, SHELL_WARNING, "Cannot %s Regulatory domain: %d\n",
734+
regd.oper == WIFI_MGMT_GET ? "get" : "set", ret);
735+
return -ENOEXEC;
736+
}
737+
738+
if (regd.oper == WIFI_MGMT_GET) {
739+
shell_fprintf(sh, SHELL_NORMAL, "Wi-Fi Regulatory domain is: %c%c\n",
740+
regd.country_code[0], regd.country_code[1]);
741+
} else {
742+
shell_fprintf(sh, SHELL_NORMAL, "Wi-Fi Regulatory domain set to: %c%c\n",
743+
regd.country_code[0], regd.country_code[1]);
744+
}
745+
746+
return 0;
747+
}
748+
688749
SHELL_STATIC_SUBCMD_SET_CREATE(wifi_cmd_ap,
689750
SHELL_CMD(enable, NULL, "<SSID> <SSID length> [channel] [PSK]",
690751
cmd_wifi_ap_enable),
@@ -732,6 +793,12 @@ SHELL_STATIC_SUBCMD_SET_CREATE(wifi_commands,
732793
SHELL_CMD(ps_mode, NULL, "Configure Wi-Fi power save mode legacy/wmm", cmd_wifi_ps_mode),
733794
SHELL_CMD(twt, &wifi_twt_ops, "Manage TWT flows", NULL),
734795
SHELL_CMD(ap, &wifi_cmd_ap, "Access Point mode commands", NULL),
796+
SHELL_CMD(reg_domain, NULL,
797+
"Set or Get Wi-Fi regulatory domain\n"
798+
"Usage: wifi reg_domain [ISO/IEC 3166-1 alpha2] [-f]\n"
799+
"-f: Force to use this regulatory hint over any other regulatory hints\n"
800+
"Note: This may cause regulatory compliance issues, use it at your own risk.",
801+
cmd_wifi_reg_domain),
735802
SHELL_SUBCMD_SET_END
736803
);
737804

0 commit comments

Comments
 (0)