1 /******************************************************************************
2  *
3  * Copyright(c) 2009-2010  Realtek Corporation.
4  *
5  *****************************************************************************/
6 
7 #include <drv_types.h>
8 #include <rtw_debug.h>
9 
10 #include <rtw_wifi_regd.h>
11 
12 /*
13  * REG_RULE(freq start, freq end, bandwidth, max gain, eirp, reg_flags)
14  */
15 
16 /*
17  *Only these channels all allow active
18  *scan on all world regulatory domains
19  */
20 
21 /* 2G chan 01 - chan 11 */
22 #define RTW_2GHZ_CH01_11	\
23 	REG_RULE(2412-10, 2462+10, 40, 0, 20, 0)
24 
25 /*
26  *We enable active scan on these a case
27  *by case basis by regulatory domain
28  */
29 
30 /* 2G chan 12 - chan 13, PASSIV SCAN */
31 #define RTW_2GHZ_CH12_13	\
32 	REG_RULE(2467-10, 2472+10, 40, 0, 20,	\
33 	NL80211_RRF_PASSIVE_SCAN)
34 
35 /* 2G chan 14, PASSIVS SCAN, NO OFDM (B only) */
36 #define RTW_2GHZ_CH14	\
37 	REG_RULE(2484-10, 2484+10, 40, 0, 20,	\
38 	NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM)
39 
40 static const struct ieee80211_regdomain rtw_regdom_rd = {
41 	.n_reg_rules = 3,
42 	.alpha2 = "99",
43 	.reg_rules = {
44 		      RTW_2GHZ_CH01_11,
45 		      RTW_2GHZ_CH12_13,
46 		      }
47 };
48 
49 static int rtw_ieee80211_channel_to_frequency(int chan, int band)
50 {
51 	/* see 802.11 17.3.8.3.2 and Annex J
52 	 * there are overlapping channel numbers in 5GHz and 2GHz bands */
53 
54 	/* NL80211_BAND_2GHZ */
55 	if (chan == 14)
56 		return 2484;
57 	else if (chan < 14)
58 		return 2407 + chan * 5;
59 	else
60 		return 0;	/* not supported */
61 }
62 
63 static void _rtw_reg_apply_flags(struct wiphy *wiphy)
64 {
65 	struct adapter *padapter = wiphy_to_adapter(wiphy);
66 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
67 	RT_CHANNEL_INFO *channel_set = pmlmeext->channel_set;
68 	u8 max_chan_nums = pmlmeext->max_chan_nums;
69 
70 	struct ieee80211_supported_band *sband;
71 	struct ieee80211_channel *ch;
72 	unsigned int i, j;
73 	u16 channel;
74 	u32 freq;
75 
76 	/*  all channels disable */
77 	for (i = 0; i < NUM_NL80211_BANDS; i++) {
78 		sband = wiphy->bands[i];
79 
80 		if (sband) {
81 			for (j = 0; j < sband->n_channels; j++) {
82 				ch = &sband->channels[j];
83 
84 				if (ch)
85 					ch->flags = IEEE80211_CHAN_DISABLED;
86 			}
87 		}
88 	}
89 
90 	/*  channels apply by channel plans. */
91 	for (i = 0; i < max_chan_nums; i++) {
92 		channel = channel_set[i].ChannelNum;
93 		freq =
94 		    rtw_ieee80211_channel_to_frequency(channel,
95 						       NL80211_BAND_2GHZ);
96 
97 		ch = ieee80211_get_channel(wiphy, freq);
98 		if (ch) {
99 			if (channel_set[i].ScanType == SCAN_PASSIVE) {
100 				ch->flags = IEEE80211_CHAN_NO_IR;
101 			}
102 			else {
103 				ch->flags = 0;
104 			}
105 		}
106 	}
107 }
108 
109 static int _rtw_reg_notifier_apply(struct wiphy *wiphy,
110 				   struct regulatory_request *request,
111 				   struct rtw_regulatory *reg)
112 {
113 	/* Hard code flags */
114 	_rtw_reg_apply_flags(wiphy);
115 	return 0;
116 }
117 
118 static const struct ieee80211_regdomain *_rtw_regdomain_select(struct
119 							       rtw_regulatory
120 							       *reg)
121 {
122 	return &rtw_regdom_rd;
123 }
124 
125 static void _rtw_regd_init_wiphy(struct rtw_regulatory *reg,
126 				struct wiphy *wiphy,
127 				void (*reg_notifier) (struct wiphy * wiphy,
128 						     struct regulatory_request *
129 						     request))
130 {
131 	const struct ieee80211_regdomain *regd;
132 
133 	wiphy->reg_notifier = reg_notifier;
134 
135 	wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
136 	wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG;
137 	wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS;
138 
139 	regd = _rtw_regdomain_select(reg);
140 	wiphy_apply_custom_regulatory(wiphy, regd);
141 
142 	/* Hard code flags */
143 	_rtw_reg_apply_flags(wiphy);
144 }
145 
146 int rtw_regd_init(struct adapter *padapter,
147 		  void (*reg_notifier) (struct wiphy * wiphy,
148 				       struct regulatory_request *request))
149 {
150 	/* struct registry_priv  *registrypriv = &padapter->registrypriv; */
151 	struct wiphy *wiphy = padapter->rtw_wdev->wiphy;
152 	_rtw_regd_init_wiphy(NULL, wiphy, reg_notifier);
153 
154 	return 0;
155 }
156 
157 void rtw_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
158 {
159 	struct rtw_regulatory *reg = NULL;
160 
161 	DBG_8192C("%s\n", __func__);
162 
163 	_rtw_reg_notifier_apply(wiphy, request, reg);
164 }
165