// 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 int rtw_ieee80211_channel_to_frequency(int chan, int band)
{
/* NL80211_BAND_2GHZ */
if (chan == 14)
return 2484;
else if (chan < 14)
return 2407 + chan * 5;
else
return 0; /* not supported */
}
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,
NL80211_BAND_2GHZ);
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,
struct rtw_regulatory *reg)
{
/* Hard code flags */
_rtw_reg_apply_flags(wiphy);
return 0;
}
static const struct ieee80211_regdomain *_rtw_regdomain_select(struct
rtw_regulatory
*reg)
{
return &rtw_regdom_rd;
}
static void _rtw_regd_init_wiphy(struct rtw_regulatory *reg,
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(reg);
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(NULL, wiphy, reg_notifier);
}
void rtw_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
{
struct rtw_regulatory *reg = NULL;
_rtw_reg_notifier_apply(wiphy, request, reg);
}