1 /******************************************************************************
2 *
3 * Copyright(c) 2009-2010 - 2017 Realtek Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 *****************************************************************************/
15
16 #include <drv_types.h>
17
18 #ifdef CONFIG_IOCTL_CFG80211
rtw_regd_apply_flags(struct wiphy * wiphy)19 void rtw_regd_apply_flags(struct wiphy *wiphy)
20 {
21 struct dvobj_priv *dvobj = wiphy_to_dvobj(wiphy);
22 struct rf_ctl_t *rfctl = dvobj_to_rfctl(dvobj);
23 RT_CHANNEL_INFO *channel_set = rfctl->channel_set;
24 u8 max_chan_nums = rfctl->max_chan_nums;
25
26 struct ieee80211_supported_band *sband;
27 struct ieee80211_channel *ch;
28 unsigned int i, j;
29 u16 channel;
30 u32 freq;
31
32 /* all channels disable */
33 for (i = 0; i < NUM_NL80211_BANDS; i++) {
34 sband = wiphy->bands[i];
35 if (!sband)
36 continue;
37 for (j = 0; j < sband->n_channels; j++) {
38 ch = &sband->channels[j];
39 if (!ch)
40 continue;
41 ch->flags = IEEE80211_CHAN_DISABLED;
42 }
43 }
44
45 /* channels apply by channel plans. */
46 for (i = 0; i < max_chan_nums; i++) {
47 channel = channel_set[i].ChannelNum;
48 freq = rtw_ch2freq(channel);
49 ch = ieee80211_get_channel(wiphy, freq);
50 if (!ch)
51 continue;
52
53 /* enable */
54 ch->flags = 0;
55
56 if (channel_set[i].dfs) {
57 /*
58 * before integrating with nl80211 flow
59 * bypass IEEE80211_CHAN_RADAR when configured with radar detection
60 * to prevent from hostapd blocking DFS channels
61 */
62 if (rtw_rfctl_dfs_domain_unknown(rfctl))
63 ch->flags |= IEEE80211_CHAN_RADAR;
64 }
65
66 if (channel_set[i].ScanType == SCAN_PASSIVE) {
67 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
68 ch->flags |= IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_PASSIVE_SCAN;
69 #else
70 ch->flags |= IEEE80211_CHAN_NO_IR;
71 #endif
72 }
73 }
74 }
75
rtw_reg_notifier(struct wiphy * wiphy,struct regulatory_request * request)76 static void rtw_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
77 {
78 switch (request->initiator) {
79 case NL80211_REGDOM_SET_BY_DRIVER:
80 RTW_INFO("%s: %s\n", __func__, "NL80211_REGDOM_SET_BY_DRIVER");
81 break;
82 case NL80211_REGDOM_SET_BY_CORE:
83 RTW_INFO("%s: %s\n", __func__, "NL80211_REGDOM_SET_BY_CORE");
84 break;
85 case NL80211_REGDOM_SET_BY_USER:
86 RTW_INFO("%s: %s alpha2:%c%c\n", __func__, "NL80211_REGDOM_SET_BY_USER"
87 , request->alpha2[0], request->alpha2[1]);
88 rtw_set_country(wiphy_to_adapter(wiphy), request->alpha2);
89 break;
90 case NL80211_REGDOM_SET_BY_COUNTRY_IE:
91 RTW_INFO("%s: %s\n", __func__, "NL80211_REGDOM_SET_BY_COUNTRY_IE");
92 break;
93 }
94
95 rtw_regd_apply_flags(wiphy);
96 }
97
98 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
rtw_reg_notifier_return(struct wiphy * wiphy,struct regulatory_request * request)99 static int rtw_reg_notifier_return(struct wiphy *wiphy, struct regulatory_request *request)
100 {
101 rtw_reg_notifier(wiphy, request);
102 return 0;
103 }
104 #endif
105
rtw_regd_init(struct wiphy * wiphy)106 int rtw_regd_init(struct wiphy *wiphy)
107 {
108 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
109 wiphy->reg_notifier = rtw_reg_notifier_return;
110 #else
111 wiphy->reg_notifier = rtw_reg_notifier;
112 #endif
113
114 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
115 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
116 wiphy->flags &= ~WIPHY_FLAG_STRICT_REGULATORY;
117 wiphy->flags &= ~WIPHY_FLAG_DISABLE_BEACON_HINTS;
118 #else
119 wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
120 wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG;
121 wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS;
122 #endif
123
124 rtw_regd_apply_flags(wiphy);
125
126 return 0;
127 }
128 #endif /* CONFIG_IOCTL_CFG80211 */
129