@@ -2630,6 +2630,98 @@ static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params,
#endif /* NEED_AP_MLME */
+#ifdef CONFIG_IEEE80211AX
+static int hostapd_ctrl_iface_color_change(struct hostapd_iface *iface,
+ char *pos)
+{
+#ifdef NEED_AP_MLME
+ struct cca_settings settings;
+ struct hostapd_data *hapd = iface->bss[0];
+ int ret, color;
+ unsigned int i;
+ char *end;
+
+ os_memset(&settings, 0, sizeof(settings));
+
+ color = strtol(pos, &end, 10);
+ if (pos == end || color < 0 || color > 63) {
+ wpa_printf(MSG_ERROR, "color_change: invalid color provided");
+ return -1;
+ }
+
+ /* color value is expected to be [1-63]. If 0 comes, assumption is
+ * user wants to disable the color. In this case no need to do CCA,
+ * just changing beacon is sufficient
+ */
+ if (color == 0) {
+ if (iface->conf->he_op.he_bss_color_disabled) {
+ wpa_printf(MSG_ERROR, "color_change: color is already disabled");
+ return -1;
+ }
+
+ iface->conf->he_op.he_bss_color_disabled = 1;
+
+ for (i = 0; i < iface->num_bss; i++)
+ ieee802_11_set_beacon(iface->bss[i]);
+
+ return 0;
+ }
+
+ if (color == iface->conf->he_op.he_bss_color) {
+ if (!iface->conf->he_op.he_bss_color_disabled) {
+ wpa_printf(MSG_ERROR, "color_change: provided color is already set");
+ return -1;
+ }
+
+ iface->conf->he_op.he_bss_color_disabled = 0;
+
+ for (i = 0; i < iface->num_bss; i++)
+ ieee802_11_set_beacon(iface->bss[i]);
+
+ return 0;
+ }
+
+ if (hapd->cca_in_progress) {
+ wpa_printf(MSG_ERROR, "color_change: CCA is already in progress");
+ return -1;
+ }
+
+ iface->conf->he_op.he_bss_color_disabled = 0;
+
+ for (i = 0; i < iface->num_bss; i++) {
+ struct hostapd_data *bss = iface->bss[i];
+
+ hostapd_cleanup_cca_params(bss);
+
+ bss->cca_color = color;
+ bss->cca_count = 10;
+
+ if (hostapd_fill_cca_settings(bss, &settings)) {
+ wpa_printf(MSG_DEBUG,
+ "hostapd fill cca settings failed for color: %d\n",
+ color);
+ hostapd_cleanup_cca_params(bss);
+ continue;
+ }
+
+ wpa_printf(MSG_DEBUG, "Setting user selected color: %d", color);
+ ret = hostapd_drv_switch_color(bss, &settings);
+
+ if (ret)
+ hostapd_cleanup_cca_params(bss);
+
+ free_beacon_data(&settings.beacon_cca);
+ free_beacon_data(&settings.beacon_after);
+ }
+
+ return 0;
+#else /* NEED_AP_MLME */
+ return -1;
+#endif /* NEED_AP_MLME */
+}
+#endif /* CONFIG_IEEE80211AX */
+
+
static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
char *pos)
{
@@ -4154,6 +4246,11 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
reply_len = -1;
+#ifdef CONFIG_IEEE80211AX
+ } else if (os_strncmp(buf, "COLOR_CHANGE ", 12) == 0) {
+ if (hostapd_ctrl_iface_color_change(hapd->iface, buf + 12))
+ reply_len = -1;
+#endif /* CONFIG_IEEE80211AX */
} else if (os_strncmp(buf, "NOTIFY_CW_CHANGE ", 17) == 0) {
if (hostapd_ctrl_iface_notify_cw_change(hapd, buf + 17))
reply_len = -1;
@@ -1168,6 +1168,31 @@ static int hostapd_cli_cmd_fst(struct wpa_ctrl *ctrl, int argc, char *argv[])
#endif /* CONFIG_FST */
+#ifdef CONFIG_IEEE80211AX
+static int hostapd_cli_cmd_color_change(struct wpa_ctrl *ctrl,
+ int argc, char *argv[])
+{
+ char cmd[256];
+ int res;
+
+ if (argc < 1) {
+ printf("Invalid color_change command: no argument given \n"
+ "usage: <color> \n");
+ return -1;
+ }
+
+ res = os_snprintf(cmd, sizeof(cmd), "COLOR_CHANGE %s",
+ argv[0]);
+ if (os_snprintf_error(sizeof(cmd), res)) {
+ printf("Too long CHAN_CHANGE command\n");
+ return -1;
+ }
+
+ return wpa_ctrl_command(ctrl, cmd);
+}
+#endif /* CONFIG_IEEE80211AX */
+
+
static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
int argc, char *argv[])
{
@@ -1746,6 +1771,11 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
"<cs_count> <freq> [sec_channel_offset=] [center_freq1=]\n"
" [center_freq2=] [bandwidth=] [blocktx] [ht|vht]\n"
" = initiate channel switch announcement" },
+#ifdef CONFIG_IEEE80211AX
+ { "color_change", hostapd_cli_cmd_color_change, NULL,
+ "<color> = initiate BSS color change to set user color\n"
+ "Value 0 will disable the color\n"},
+#endif /* CONFIG_IEEE80211AX */
{ "notify_cw_change", hostapd_cli_cmd_notify_cw_change, NULL,
"<channel_width> = 0 - 20 MHz, 1 - 40 MHz, 2 - 80 MHz, 3 - 160 MHz" },
{ "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif, NULL,
@@ -4088,7 +4088,7 @@ int hostapd_csa_in_progress(struct hostapd_iface *iface)
#ifdef NEED_AP_MLME
-static void free_beacon_data(struct beacon_data *beacon)
+void free_beacon_data(struct beacon_data *beacon)
{
os_free(beacon->head);
beacon->head = NULL;
@@ -4535,8 +4535,8 @@ void hostapd_cleanup_cca_params(struct hostapd_data *hapd)
}
-static int hostapd_fill_cca_settings(struct hostapd_data *hapd,
- struct cca_settings *settings)
+int hostapd_fill_cca_settings(struct hostapd_data *hapd,
+ struct cca_settings *settings)
{
struct hostapd_iface *iface = hapd->iface;
u8 old_color;
@@ -823,6 +823,9 @@ int hostapd_mld_add_link(struct hostapd_data *hapd);
int hostapd_mld_remove_link(struct hostapd_data *hapd);
struct hostapd_data * hostapd_mld_get_first_bss(struct hostapd_data *hapd);
+void free_beacon_data(struct beacon_data *beacon);
+int hostapd_fill_cca_settings(struct hostapd_data *hapd,
+ struct cca_settings *settings);
#ifdef CONFIG_IEEE80211BE
bool hostapd_mld_is_first_bss(struct hostapd_data *hapd);
Add hostapd_cli command "color_change <color>" to change BSS color in run time. hostapd_cli status can be used to check the updated color. Usage: hostapd_cli -i <interface> color_change <color> If 0 value is given, HE BSS color would be disabled. Same or a non-zero value between [1-63] can be given to enable color again. Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com> --- hostapd/ctrl_iface.c | 97 +++++++++++++++++++++++++++++++++++++++++++ hostapd/hostapd_cli.c | 30 +++++++++++++ src/ap/hostapd.c | 6 +-- src/ap/hostapd.h | 3 ++ 4 files changed, 133 insertions(+), 3 deletions(-)