root/drivers/staging/rtl8723bs/os_dep/wifi_regd.c
// SPDX-License-Identifier: GPL-2.0
/******************************************************************************
 *
 * Copyright(c) 2009-2010  Realtek Corporation.
 *
 *****************************************************************************/

#include <drv_types.h>

#include <rtw_wifi_regd.h>

/*
 * REG_RULE(freq start, freq end, bandwidth, max gain, eirp, reg_flags)
 */

/*
 * Only these channels all allow active
 * scan on all world regulatory domains
 */

/* 2G chan 01 - chan 11 */
#define RTW_2GHZ_CH01_11        \
        REG_RULE(2412 - 10, 2462 + 10, 40, 0, 20, 0)

/*
 * We enable active scan on these a case
 * by case basis by regulatory domain
 */

/* 2G chan 12 - chan 13, PASSIV SCAN */
#define RTW_2GHZ_CH12_13        \
        REG_RULE(2467 - 10, 2472 + 10, 40, 0, 20,       \
        NL80211_RRF_PASSIVE_SCAN)

static const struct ieee80211_regdomain rtw_regdom_rd = {
        .n_reg_rules = 2,
        .alpha2 = "99",
        .reg_rules = {
                RTW_2GHZ_CH01_11,
                RTW_2GHZ_CH12_13,
        }
};

static void _rtw_reg_apply_flags(struct wiphy *wiphy)
{
        struct adapter *padapter = wiphy_to_adapter(wiphy);
        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
        struct rt_channel_info *channel_set = pmlmeext->channel_set;
        u8 max_chan_nums = pmlmeext->max_chan_nums;

        struct ieee80211_supported_band *sband;
        struct ieee80211_channel *ch;
        unsigned int i, j;
        u16 channel;
        u32 freq;

        /* all channels disable */
        for (i = 0; i < NUM_NL80211_BANDS; i++) {
                sband = wiphy->bands[i];

                if (sband) {
                        for (j = 0; j < sband->n_channels; j++) {
                                ch = &sband->channels[j];

                                if (ch)
                                        ch->flags = IEEE80211_CHAN_DISABLED;
                        }
                }
        }

        /* channels apply by channel plans. */
        for (i = 0; i < max_chan_nums; i++) {
                channel = channel_set[i].ChannelNum;
                freq = rtw_ieee80211_channel_to_frequency(channel);
                ch = ieee80211_get_channel(wiphy, freq);
                if (ch) {
                        if (channel_set[i].ScanType == SCAN_PASSIVE)
                                ch->flags = IEEE80211_CHAN_NO_IR;
                        else
                                ch->flags = 0;
                }
        }
}

static int _rtw_reg_notifier_apply(struct wiphy *wiphy,
                                   struct regulatory_request *request)
{
        /* Hard code flags */
        _rtw_reg_apply_flags(wiphy);
        return 0;
}

static const struct ieee80211_regdomain *_rtw_regdomain_select(void)
{
        return &rtw_regdom_rd;
}

static void _rtw_regd_init_wiphy(struct wiphy *wiphy,
                                 void (*reg_notifier)(struct wiphy *wiphy,
                                                      struct
                                                      regulatory_request *
                                                      request))
{
        const struct ieee80211_regdomain *regd;

        wiphy->reg_notifier = reg_notifier;

        wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
        wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG;
        wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS;

        regd = _rtw_regdomain_select();
        wiphy_apply_custom_regulatory(wiphy, regd);

        /* Hard code flags */
        _rtw_reg_apply_flags(wiphy);
}

void rtw_regd_init(struct wiphy *wiphy,
                   void (*reg_notifier)(struct wiphy *wiphy,
                                        struct regulatory_request *request))
{
        _rtw_regd_init_wiphy(wiphy, reg_notifier);
}

void rtw_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
{
        _rtw_reg_notifier_apply(wiphy, request);
}