blob: 7e3ca7ef997b9f5a5e8a22caf200c7c052e499c2 [file] [log] [blame]
Larry Finger94a79942011-08-23 19:00:42 -05001/******************************************************************************
2 * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
3 *
4 * This program is distributed in the hope that it will be useful, but WITHOUT
5 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
6 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
7 * more details.
8 *
9 * You should have received a copy of the GNU General Public License along with
10 * this program; if not, write to the Free Software Foundation, Inc.,
11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
12 *
13 * The full GNU General Public License is included in this distribution in the
14 * file called LICENSE.
15 *
16 * Contact Information:
17 * wlanfae <wlanfae@realtek.com>
18******************************************************************************/
19
20#include <linux/string.h>
21#include "rtl_core.h"
Joel Pelaez Jorge5169af22014-04-19 22:32:32 -050022#include "rtl_wx.h"
Larry Finger94a79942011-08-23 19:00:42 -050023
Larry Finger94a79942011-08-23 19:00:42 -050024#define RATE_COUNT 12
Larry Finger49aab5f2011-08-25 14:07:05 -050025static u32 rtl8192_rates[] = {
Larry Finger08d348a2011-08-25 11:48:30 -050026 1000000, 2000000, 5500000, 11000000, 6000000, 9000000, 12000000,
27 18000000, 24000000, 36000000, 48000000, 54000000
28};
Larry Finger94a79942011-08-23 19:00:42 -050029
30#ifndef ENETDOWN
31#define ENETDOWN 1
32#endif
Larry Finger94a79942011-08-23 19:00:42 -050033
34static int r8192_wx_get_freq(struct net_device *dev,
35 struct iw_request_info *a,
36 union iwreq_data *wrqu, char *b)
37{
38 struct r8192_priv *priv = rtllib_priv(dev);
39
Larry Finger08d348a2011-08-25 11:48:30 -050040 return rtllib_wx_get_freq(priv->rtllib, a, wrqu, b);
Larry Finger94a79942011-08-23 19:00:42 -050041}
42
43
44static int r8192_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
45 union iwreq_data *wrqu, char *b)
46{
Larry Finger08d348a2011-08-25 11:48:30 -050047 struct r8192_priv *priv = rtllib_priv(dev);
Larry Finger94a79942011-08-23 19:00:42 -050048
Larry Finger08d348a2011-08-25 11:48:30 -050049 return rtllib_wx_get_mode(priv->rtllib, a, wrqu, b);
Larry Finger94a79942011-08-23 19:00:42 -050050}
51
52static int r8192_wx_get_rate(struct net_device *dev,
53 struct iw_request_info *info,
54 union iwreq_data *wrqu, char *extra)
55{
56 struct r8192_priv *priv = rtllib_priv(dev);
Matthew Casey3a6b70c2014-08-22 06:27:52 -040057
Larry Finger08d348a2011-08-25 11:48:30 -050058 return rtllib_wx_get_rate(priv->rtllib, info, wrqu, extra);
Larry Finger94a79942011-08-23 19:00:42 -050059}
60
61
62
63static int r8192_wx_set_rate(struct net_device *dev,
64 struct iw_request_info *info,
65 union iwreq_data *wrqu, char *extra)
66{
67 int ret;
68 struct r8192_priv *priv = rtllib_priv(dev);
69
Cristina Opriceana44acc6b2015-03-13 21:19:24 +020070 if (priv->bHwRadioOff)
Larry Finger94a79942011-08-23 19:00:42 -050071 return 0;
72
73 down(&priv->wx_sem);
74
Larry Finger08d348a2011-08-25 11:48:30 -050075 ret = rtllib_wx_set_rate(priv->rtllib, info, wrqu, extra);
Larry Finger94a79942011-08-23 19:00:42 -050076
77 up(&priv->wx_sem);
78
79 return ret;
80}
81
82
83static int r8192_wx_set_rts(struct net_device *dev,
84 struct iw_request_info *info,
85 union iwreq_data *wrqu, char *extra)
86{
87 int ret;
88 struct r8192_priv *priv = rtllib_priv(dev);
89
Cristina Opriceana44acc6b2015-03-13 21:19:24 +020090 if (priv->bHwRadioOff)
Larry Finger94a79942011-08-23 19:00:42 -050091 return 0;
92
93 down(&priv->wx_sem);
94
Larry Finger08d348a2011-08-25 11:48:30 -050095 ret = rtllib_wx_set_rts(priv->rtllib, info, wrqu, extra);
Larry Finger94a79942011-08-23 19:00:42 -050096
97 up(&priv->wx_sem);
98
99 return ret;
100}
101
102static int r8192_wx_get_rts(struct net_device *dev,
103 struct iw_request_info *info,
104 union iwreq_data *wrqu, char *extra)
105{
106 struct r8192_priv *priv = rtllib_priv(dev);
Matthew Casey3a6b70c2014-08-22 06:27:52 -0400107
Larry Finger08d348a2011-08-25 11:48:30 -0500108 return rtllib_wx_get_rts(priv->rtllib, info, wrqu, extra);
Larry Finger94a79942011-08-23 19:00:42 -0500109}
110
111static int r8192_wx_set_power(struct net_device *dev,
112 struct iw_request_info *info,
113 union iwreq_data *wrqu, char *extra)
114{
115 int ret;
116 struct r8192_priv *priv = rtllib_priv(dev);
117
Cristina Opriceana44acc6b2015-03-13 21:19:24 +0200118 if (priv->bHwRadioOff) {
Mateusz Kulikowski3b4140a2015-05-31 20:19:50 +0200119 netdev_warn(dev, "%s(): Can't set Power: Radio is Off.\n",
120 __func__);
Larry Finger94a79942011-08-23 19:00:42 -0500121 return 0;
122 }
123 down(&priv->wx_sem);
124
Larry Finger08d348a2011-08-25 11:48:30 -0500125 ret = rtllib_wx_set_power(priv->rtllib, info, wrqu, extra);
Larry Finger94a79942011-08-23 19:00:42 -0500126
127 up(&priv->wx_sem);
128
129 return ret;
130}
131
132static int r8192_wx_get_power(struct net_device *dev,
133 struct iw_request_info *info,
134 union iwreq_data *wrqu, char *extra)
135{
136 struct r8192_priv *priv = rtllib_priv(dev);
Matthew Casey3a6b70c2014-08-22 06:27:52 -0400137
Larry Finger08d348a2011-08-25 11:48:30 -0500138 return rtllib_wx_get_power(priv->rtllib, info, wrqu, extra);
Larry Finger94a79942011-08-23 19:00:42 -0500139}
140
141static int r8192_wx_set_rawtx(struct net_device *dev,
Larry Finger08d348a2011-08-25 11:48:30 -0500142 struct iw_request_info *info,
143 union iwreq_data *wrqu, char *extra)
Larry Finger94a79942011-08-23 19:00:42 -0500144{
145 struct r8192_priv *priv = rtllib_priv(dev);
146 int ret;
147
Cristina Opriceana44acc6b2015-03-13 21:19:24 +0200148 if (priv->bHwRadioOff)
Larry Finger94a79942011-08-23 19:00:42 -0500149 return 0;
150
151 down(&priv->wx_sem);
152
153 ret = rtllib_wx_set_rawtx(priv->rtllib, info, wrqu, extra);
154
155 up(&priv->wx_sem);
156
157 return ret;
158
159}
160
161static int r8192_wx_force_reset(struct net_device *dev,
162 struct iw_request_info *info,
163 union iwreq_data *wrqu, char *extra)
164{
165 struct r8192_priv *priv = rtllib_priv(dev);
166
167 down(&priv->wx_sem);
168
Larry Finger08d348a2011-08-25 11:48:30 -0500169 RT_TRACE(COMP_DBG, "%s(): force reset ! extra is %d\n",
170 __func__, *extra);
Larry Finger94a79942011-08-23 19:00:42 -0500171 priv->force_reset = *extra;
172 up(&priv->wx_sem);
173 return 0;
174
175}
176
Larry Finger94a79942011-08-23 19:00:42 -0500177static int r8192_wx_adapter_power_status(struct net_device *dev,
178 struct iw_request_info *info,
179 union iwreq_data *wrqu, char *extra)
180{
181 struct r8192_priv *priv = rtllib_priv(dev);
Larry Finger08d348a2011-08-25 11:48:30 -0500182 struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
183 (&(priv->rtllib->PowerSaveControl));
184 struct rtllib_device *ieee = priv->rtllib;
Larry Finger94a79942011-08-23 19:00:42 -0500185
186 down(&priv->wx_sem);
187
Larry Finger08d348a2011-08-25 11:48:30 -0500188 RT_TRACE(COMP_POWER, "%s(): %s\n", __func__, (*extra == 6) ?
189 "DC power" : "AC power");
Larry Finger94a79942011-08-23 19:00:42 -0500190 if (*extra || priv->force_lps) {
191 priv->ps_force = false;
192 pPSC->bLeisurePs = true;
193 } else {
194 if (priv->rtllib->state == RTLLIB_LINKED)
Mateusz Kulikowski9c4a55d2015-07-19 19:33:50 +0200195 rtl92e_leisure_ps_leave(dev);
Larry Finger94a79942011-08-23 19:00:42 -0500196
197 priv->ps_force = true;
198 pPSC->bLeisurePs = false;
199 ieee->ps = *extra;
200 }
201
202 up(&priv->wx_sem);
203
204 return 0;
205}
206
Larry Finger94a79942011-08-23 19:00:42 -0500207static int r8192se_wx_set_lps_awake_interval(struct net_device *dev,
Larry Finger08d348a2011-08-25 11:48:30 -0500208 struct iw_request_info *info,
209 union iwreq_data *wrqu, char *extra)
Larry Finger94a79942011-08-23 19:00:42 -0500210{
Larry Finger08d348a2011-08-25 11:48:30 -0500211 struct r8192_priv *priv = rtllib_priv(dev);
212 struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
213 (&(priv->rtllib->PowerSaveControl));
Larry Finger94a79942011-08-23 19:00:42 -0500214
Larry Finger08d348a2011-08-25 11:48:30 -0500215 down(&priv->wx_sem);
Larry Finger94a79942011-08-23 19:00:42 -0500216
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +0100217 netdev_info(dev, "%s(): set lps awake interval ! extra is %d\n",
218 __func__, *extra);
Larry Finger94a79942011-08-23 19:00:42 -0500219
Larry Finger08d348a2011-08-25 11:48:30 -0500220 pPSC->RegMaxLPSAwakeIntvl = *extra;
221 up(&priv->wx_sem);
222 return 0;
Larry Finger94a79942011-08-23 19:00:42 -0500223}
224
225static int r8192se_wx_set_force_lps(struct net_device *dev,
226 struct iw_request_info *info,
227 union iwreq_data *wrqu, char *extra)
228{
229 struct r8192_priv *priv = rtllib_priv(dev);
230
231 down(&priv->wx_sem);
232
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +0100233 netdev_info(dev,
234 "%s(): force LPS ! extra is %d (1 is open 0 is close)\n",
235 __func__, *extra);
Larry Finger94a79942011-08-23 19:00:42 -0500236 priv->force_lps = *extra;
237 up(&priv->wx_sem);
238 return 0;
239
240}
241
242static int r8192_wx_set_debugflag(struct net_device *dev,
Larry Finger08d348a2011-08-25 11:48:30 -0500243 struct iw_request_info *info,
244 union iwreq_data *wrqu, char *extra)
Larry Finger94a79942011-08-23 19:00:42 -0500245{
246 struct r8192_priv *priv = rtllib_priv(dev);
247 u8 c = *extra;
248
Cristina Opriceana44acc6b2015-03-13 21:19:24 +0200249 if (priv->bHwRadioOff)
Larry Finger94a79942011-08-23 19:00:42 -0500250 return 0;
251
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +0100252 netdev_info(dev, "=====>%s(), *extra:%x, debugflag:%x\n", __func__,
253 *extra, rt_global_debug_component);
Larry Finger08d348a2011-08-25 11:48:30 -0500254 if (c > 0)
Larry Finger94a79942011-08-23 19:00:42 -0500255 rt_global_debug_component |= (1<<c);
Larry Finger08d348a2011-08-25 11:48:30 -0500256 else
Larry Finger94a79942011-08-23 19:00:42 -0500257 rt_global_debug_component &= BIT31;
Larry Finger94a79942011-08-23 19:00:42 -0500258 return 0;
259}
260
261static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
262 union iwreq_data *wrqu, char *b)
263{
264 struct r8192_priv *priv = rtllib_priv(dev);
Larry Finger08d348a2011-08-25 11:48:30 -0500265 struct rtllib_device *ieee = netdev_priv_rsl(dev);
Larry Finger94a79942011-08-23 19:00:42 -0500266
Larry Fingerde7c8852011-07-19 21:00:33 -0500267 enum rt_rf_power_state rtState;
Larry Finger94a79942011-08-23 19:00:42 -0500268 int ret;
269
Cristina Opriceana44acc6b2015-03-13 21:19:24 +0200270 if (priv->bHwRadioOff)
Larry Finger94a79942011-08-23 19:00:42 -0500271 return 0;
272 rtState = priv->rtllib->eRFPowerState;
273 down(&priv->wx_sem);
Larry Finger08d348a2011-08-25 11:48:30 -0500274 if (wrqu->mode == IW_MODE_ADHOC || wrqu->mode == IW_MODE_MONITOR ||
275 ieee->bNetPromiscuousMode) {
276 if (priv->rtllib->PowerSaveControl.bInactivePs) {
277 if (rtState == eRfOff) {
278 if (priv->rtllib->RfOffReason >
279 RF_CHANGE_BY_IPS) {
Mateusz Kulikowski3b4140a2015-05-31 20:19:50 +0200280 netdev_warn(dev, "%s(): RF is OFF.\n",
281 __func__);
Larry Finger94a79942011-08-23 19:00:42 -0500282 up(&priv->wx_sem);
283 return -1;
Larry Finger94a79942011-08-23 19:00:42 -0500284 }
Mateusz Kulikowski2ab2aba2015-07-19 19:33:47 +0200285 netdev_info(dev,
286 "=========>%s(): rtl92e_ips_leave\n",
Mateusz Kulikowski285b7c02015-04-01 00:24:26 +0200287 __func__);
288 down(&priv->rtllib->ips_sem);
Mateusz Kulikowski2ab2aba2015-07-19 19:33:47 +0200289 rtl92e_ips_leave(dev);
Mateusz Kulikowski285b7c02015-04-01 00:24:26 +0200290 up(&priv->rtllib->ips_sem);
Larry Finger94a79942011-08-23 19:00:42 -0500291 }
292 }
293 }
Larry Finger08d348a2011-08-25 11:48:30 -0500294 ret = rtllib_wx_set_mode(priv->rtllib, a, wrqu, b);
Larry Finger94a79942011-08-23 19:00:42 -0500295
296 up(&priv->wx_sem);
297 return ret;
298}
299
Larry Finger08d348a2011-08-25 11:48:30 -0500300struct iw_range_with_scan_capa {
301 /* Informative stuff (to choose between different interface) */
302 __u32 throughput; /* To give an idea... */
303 /* In theory this value should be the maximum benchmarked
304 * TCP/IP throughput, because with most of these devices the
305 * bit rate is meaningless (overhead an co) to estimate how
306 * fast the connection will go and pick the fastest one.
307 * I suggest people to play with Netperf or any benchmark...
308 */
Larry Finger94a79942011-08-23 19:00:42 -0500309
Larry Finger08d348a2011-08-25 11:48:30 -0500310 /* NWID (or domain id) */
311 __u32 min_nwid; /* Minimal NWID we are able to set */
312 __u32 max_nwid; /* Maximal NWID we are able to set */
Larry Finger94a79942011-08-23 19:00:42 -0500313
Larry Finger08d348a2011-08-25 11:48:30 -0500314 /* Old Frequency (backward compat - moved lower ) */
315 __u16 old_num_channels;
316 __u8 old_num_frequency;
Larry Finger94a79942011-08-23 19:00:42 -0500317
Larry Finger08d348a2011-08-25 11:48:30 -0500318 /* Scan capabilities */
319 __u8 scan_capa;
Larry Finger94a79942011-08-23 19:00:42 -0500320};
321
322static int rtl8192_wx_get_range(struct net_device *dev,
323 struct iw_request_info *info,
324 union iwreq_data *wrqu, char *extra)
325{
326 struct iw_range *range = (struct iw_range *)extra;
327 struct r8192_priv *priv = rtllib_priv(dev);
328 u16 val;
329 int i;
330
331 wrqu->data.length = sizeof(*range);
332 memset(range, 0, sizeof(*range));
333
334 /* ~130 Mb/s real (802.11n) */
335 range->throughput = 130 * 1000 * 1000;
336
Larry Finger08d348a2011-08-25 11:48:30 -0500337 if (priv->rf_set_sens != NULL) {
338 /* signal level threshold range */
339 range->sensitivity = priv->max_sens;
340 }
Larry Finger94a79942011-08-23 19:00:42 -0500341
342 range->max_qual.qual = 100;
343 range->max_qual.level = 0;
344 range->max_qual.noise = 0;
345 range->max_qual.updated = 7; /* Updated all three */
346
347 range->avg_qual.qual = 70; /* > 8% missed beacons is 'bad' */
348 range->avg_qual.level = 0;
349 range->avg_qual.noise = 0;
350 range->avg_qual.updated = 7; /* Updated all three */
351
352 range->num_bitrates = min(RATE_COUNT, IW_MAX_BITRATES);
353
Larry Finger08d348a2011-08-25 11:48:30 -0500354 for (i = 0; i < range->num_bitrates; i++)
Larry Finger94a79942011-08-23 19:00:42 -0500355 range->bitrate[i] = rtl8192_rates[i];
Larry Finger94a79942011-08-23 19:00:42 -0500356
357 range->max_rts = DEFAULT_RTS_THRESHOLD;
358 range->min_frag = MIN_FRAG_THRESHOLD;
359 range->max_frag = MAX_FRAG_THRESHOLD;
360
361 range->min_pmp = 0;
362 range->max_pmp = 5000000;
363 range->min_pmt = 0;
364 range->max_pmt = 65535*1000;
365 range->pmp_flags = IW_POWER_PERIOD;
366 range->pmt_flags = IW_POWER_TIMEOUT;
367 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
368 range->we_version_compiled = WIRELESS_EXT;
369 range->we_version_source = 18;
370
371 for (i = 0, val = 0; i < 14; i++) {
372 if ((priv->rtllib->active_channel_map)[i+1]) {
Larry Finger08d348a2011-08-25 11:48:30 -0500373 range->freq[val].i = i + 1;
374 range->freq[val].m = rtllib_wlan_frequencies[i] *
375 100000;
Larry Finger94a79942011-08-23 19:00:42 -0500376 range->freq[val].e = 1;
377 val++;
Larry Finger94a79942011-08-23 19:00:42 -0500378 }
379
380 if (val == IW_MAX_FREQUENCIES)
Larry Finger08d348a2011-08-25 11:48:30 -0500381 break;
Larry Finger94a79942011-08-23 19:00:42 -0500382 }
383 range->num_frequency = val;
384 range->num_channels = val;
Larry Finger94a79942011-08-23 19:00:42 -0500385 range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2|
386 IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP;
Larry Finger94a79942011-08-23 19:00:42 -0500387 range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE;
388
Larry Finger08d348a2011-08-25 11:48:30 -0500389 /* Event capability (kernel + driver) */
Larry Finger94a79942011-08-23 19:00:42 -0500390
391 return 0;
392}
393
394static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
395 union iwreq_data *wrqu, char *b)
396{
397 struct r8192_priv *priv = rtllib_priv(dev);
Larry Finger08d348a2011-08-25 11:48:30 -0500398 struct rtllib_device *ieee = priv->rtllib;
Larry Fingerde7c8852011-07-19 21:00:33 -0500399 enum rt_rf_power_state rtState;
Larry Finger94a79942011-08-23 19:00:42 -0500400 int ret;
401
Larry Finger08d348a2011-08-25 11:48:30 -0500402 if (!(ieee->softmac_features & IEEE_SOFTMAC_SCAN)) {
403 if ((ieee->state >= RTLLIB_ASSOCIATING) &&
404 (ieee->state <= RTLLIB_ASSOCIATING_AUTHENTICATED))
Larry Finger94a79942011-08-23 19:00:42 -0500405 return 0;
Larry Finger08d348a2011-08-25 11:48:30 -0500406 if ((priv->rtllib->state == RTLLIB_LINKED) &&
407 (priv->rtllib->CntAfterLink < 2))
Larry Finger94a79942011-08-23 19:00:42 -0500408 return 0;
Larry Finger94a79942011-08-23 19:00:42 -0500409 }
410
Cristina Opriceana44acc6b2015-03-13 21:19:24 +0200411 if (priv->bHwRadioOff) {
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +0100412 netdev_info(dev, "================>%s(): hwradio off\n",
413 __func__);
Larry Finger94a79942011-08-23 19:00:42 -0500414 return 0;
415 }
416 rtState = priv->rtllib->eRFPowerState;
Larry Finger08d348a2011-08-25 11:48:30 -0500417 if (!priv->up)
418 return -ENETDOWN;
Larry Finger94a79942011-08-23 19:00:42 -0500419 if (priv->rtllib->LinkDetectInfo.bBusyTraffic == true)
420 return -EAGAIN;
421
Larry Finger08d348a2011-08-25 11:48:30 -0500422 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
423 struct iw_scan_req *req = (struct iw_scan_req *)b;
Matthew Casey3a6b70c2014-08-22 06:27:52 -0400424
Larry Finger08d348a2011-08-25 11:48:30 -0500425 if (req->essid_len) {
Larry Finger94a79942011-08-23 19:00:42 -0500426 ieee->current_network.ssid_len = req->essid_len;
Larry Finger08d348a2011-08-25 11:48:30 -0500427 memcpy(ieee->current_network.ssid, req->essid,
428 req->essid_len);
Larry Finger94a79942011-08-23 19:00:42 -0500429 }
430 }
Larry Finger94a79942011-08-23 19:00:42 -0500431
432 down(&priv->wx_sem);
433
434 priv->rtllib->FirstIe_InScan = true;
435
Larry Finger08d348a2011-08-25 11:48:30 -0500436 if (priv->rtllib->state != RTLLIB_LINKED) {
437 if (priv->rtllib->PowerSaveControl.bInactivePs) {
438 if (rtState == eRfOff) {
439 if (priv->rtllib->RfOffReason >
440 RF_CHANGE_BY_IPS) {
Mateusz Kulikowski3b4140a2015-05-31 20:19:50 +0200441 netdev_warn(dev, "%s(): RF is OFF.\n",
442 __func__);
Larry Finger94a79942011-08-23 19:00:42 -0500443 up(&priv->wx_sem);
444 return -1;
Larry Finger94a79942011-08-23 19:00:42 -0500445 }
Mateusz Kulikowski2ab2aba2015-07-19 19:33:47 +0200446 RT_TRACE(COMP_PS,
447 "=========>%s(): rtl92e_ips_leave\n",
Mateusz Kulikowski285b7c02015-04-01 00:24:26 +0200448 __func__);
449 down(&priv->rtllib->ips_sem);
Mateusz Kulikowski2ab2aba2015-07-19 19:33:47 +0200450 rtl92e_ips_leave(dev);
Mateusz Kulikowski285b7c02015-04-01 00:24:26 +0200451 up(&priv->rtllib->ips_sem);
Larry Finger94a79942011-08-23 19:00:42 -0500452 }
453 }
454 rtllib_stop_scan(priv->rtllib);
455 if (priv->rtllib->LedControlHandler)
Larry Finger08d348a2011-08-25 11:48:30 -0500456 priv->rtllib->LedControlHandler(dev,
457 LED_CTL_SITE_SURVEY);
Larry Finger94a79942011-08-23 19:00:42 -0500458
Larry Finger08d348a2011-08-25 11:48:30 -0500459 if (priv->rtllib->eRFPowerState != eRfOff) {
Larry Finger94a79942011-08-23 19:00:42 -0500460 priv->rtllib->actscanning = true;
461
462 if (ieee->ScanOperationBackupHandler)
Larry Finger08d348a2011-08-25 11:48:30 -0500463 ieee->ScanOperationBackupHandler(ieee->dev,
464 SCAN_OPT_BACKUP);
Larry Finger94a79942011-08-23 19:00:42 -0500465
466 rtllib_start_scan_syncro(priv->rtllib, 0);
467
468 if (ieee->ScanOperationBackupHandler)
Larry Finger08d348a2011-08-25 11:48:30 -0500469 ieee->ScanOperationBackupHandler(ieee->dev,
470 SCAN_OPT_RESTORE);
471 }
Larry Finger94a79942011-08-23 19:00:42 -0500472 ret = 0;
473 } else {
474 priv->rtllib->actscanning = true;
Larry Finger08d348a2011-08-25 11:48:30 -0500475 ret = rtllib_wx_set_scan(priv->rtllib, a, wrqu, b);
Larry Finger94a79942011-08-23 19:00:42 -0500476 }
477
478 up(&priv->wx_sem);
479 return ret;
480}
481
482
483static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
484 union iwreq_data *wrqu, char *b)
485{
486
487 int ret;
488 struct r8192_priv *priv = rtllib_priv(dev);
489
Larry Finger08d348a2011-08-25 11:48:30 -0500490 if (!priv->up)
491 return -ENETDOWN;
Larry Finger94a79942011-08-23 19:00:42 -0500492
Cristina Opriceana44acc6b2015-03-13 21:19:24 +0200493 if (priv->bHwRadioOff)
Larry Finger94a79942011-08-23 19:00:42 -0500494 return 0;
495
496
497 down(&priv->wx_sem);
498
Larry Finger08d348a2011-08-25 11:48:30 -0500499 ret = rtllib_wx_get_scan(priv->rtllib, a, wrqu, b);
Larry Finger94a79942011-08-23 19:00:42 -0500500
501 up(&priv->wx_sem);
502
503 return ret;
504}
505
506static int r8192_wx_set_essid(struct net_device *dev,
507 struct iw_request_info *a,
508 union iwreq_data *wrqu, char *b)
509{
510 struct r8192_priv *priv = rtllib_priv(dev);
511 int ret;
512
Cristina Opriceana44acc6b2015-03-13 21:19:24 +0200513 if (priv->bHwRadioOff) {
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +0100514 netdev_info(dev,
515 "=========>%s():hw radio off,or Rf state is eRfOff, return\n",
516 __func__);
Larry Finger94a79942011-08-23 19:00:42 -0500517 return 0;
518 }
519 down(&priv->wx_sem);
Larry Finger08d348a2011-08-25 11:48:30 -0500520 ret = rtllib_wx_set_essid(priv->rtllib, a, wrqu, b);
Larry Finger94a79942011-08-23 19:00:42 -0500521
522 up(&priv->wx_sem);
523
524 return ret;
525}
526
527static int r8192_wx_get_essid(struct net_device *dev,
528 struct iw_request_info *a,
529 union iwreq_data *wrqu, char *b)
530{
531 int ret;
532 struct r8192_priv *priv = rtllib_priv(dev);
533
534 down(&priv->wx_sem);
535
536 ret = rtllib_wx_get_essid(priv->rtllib, a, wrqu, b);
537
538 up(&priv->wx_sem);
539
540 return ret;
541}
542
543static int r8192_wx_set_nick(struct net_device *dev,
544 struct iw_request_info *info,
545 union iwreq_data *wrqu, char *extra)
546{
547 struct r8192_priv *priv = rtllib_priv(dev);
548
549 if (wrqu->data.length > IW_ESSID_MAX_SIZE)
550 return -E2BIG;
551 down(&priv->wx_sem);
Mateusz Kulikowski35e33b02015-05-31 20:19:40 +0200552 wrqu->data.length = min_t(size_t, wrqu->data.length,
553 sizeof(priv->nick));
Larry Finger94a79942011-08-23 19:00:42 -0500554 memset(priv->nick, 0, sizeof(priv->nick));
555 memcpy(priv->nick, extra, wrqu->data.length);
556 up(&priv->wx_sem);
557 return 0;
558
559}
560
561static int r8192_wx_get_nick(struct net_device *dev,
562 struct iw_request_info *info,
563 union iwreq_data *wrqu, char *extra)
564{
565 struct r8192_priv *priv = rtllib_priv(dev);
566
567 down(&priv->wx_sem);
568 wrqu->data.length = strlen(priv->nick);
569 memcpy(extra, priv->nick, wrqu->data.length);
570 wrqu->data.flags = 1; /* active */
571 up(&priv->wx_sem);
572 return 0;
573}
574
575static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
576 union iwreq_data *wrqu, char *b)
577{
578 int ret;
579 struct r8192_priv *priv = rtllib_priv(dev);
580
Cristina Opriceana44acc6b2015-03-13 21:19:24 +0200581 if (priv->bHwRadioOff)
Larry Finger94a79942011-08-23 19:00:42 -0500582 return 0;
583
584 down(&priv->wx_sem);
585
586 ret = rtllib_wx_set_freq(priv->rtllib, a, wrqu, b);
587
588 up(&priv->wx_sem);
589 return ret;
590}
591
592static int r8192_wx_get_name(struct net_device *dev,
593 struct iw_request_info *info,
594 union iwreq_data *wrqu, char *extra)
595{
596 struct r8192_priv *priv = rtllib_priv(dev);
Matthew Casey3a6b70c2014-08-22 06:27:52 -0400597
Larry Finger94a79942011-08-23 19:00:42 -0500598 return rtllib_wx_get_name(priv->rtllib, info, wrqu, extra);
599}
600
601
602static int r8192_wx_set_frag(struct net_device *dev,
603 struct iw_request_info *info,
604 union iwreq_data *wrqu, char *extra)
605{
606 struct r8192_priv *priv = rtllib_priv(dev);
607
Cristina Opriceana44acc6b2015-03-13 21:19:24 +0200608 if (priv->bHwRadioOff)
Larry Finger94a79942011-08-23 19:00:42 -0500609 return 0;
610
611 if (wrqu->frag.disabled)
612 priv->rtllib->fts = DEFAULT_FRAG_THRESHOLD;
613 else {
614 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
615 wrqu->frag.value > MAX_FRAG_THRESHOLD)
616 return -EINVAL;
617
618 priv->rtllib->fts = wrqu->frag.value & ~0x1;
619 }
620
621 return 0;
622}
623
624
625static int r8192_wx_get_frag(struct net_device *dev,
626 struct iw_request_info *info,
627 union iwreq_data *wrqu, char *extra)
628{
629 struct r8192_priv *priv = rtllib_priv(dev);
630
631 wrqu->frag.value = priv->rtllib->fts;
632 wrqu->frag.fixed = 0; /* no auto select */
633 wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
634
635 return 0;
636}
637
638
639static int r8192_wx_set_wap(struct net_device *dev,
640 struct iw_request_info *info,
641 union iwreq_data *awrq,
642 char *extra)
643{
Larry Finger94a79942011-08-23 19:00:42 -0500644 int ret;
645 struct r8192_priv *priv = rtllib_priv(dev);
646
Cristina Opriceana44acc6b2015-03-13 21:19:24 +0200647 if (priv->bHwRadioOff)
Larry Finger94a79942011-08-23 19:00:42 -0500648 return 0;
649
650 down(&priv->wx_sem);
651
Larry Finger08d348a2011-08-25 11:48:30 -0500652 ret = rtllib_wx_set_wap(priv->rtllib, info, awrq, extra);
Larry Finger94a79942011-08-23 19:00:42 -0500653
654 up(&priv->wx_sem);
655
656 return ret;
657
658}
659
660
661static int r8192_wx_get_wap(struct net_device *dev,
662 struct iw_request_info *info,
663 union iwreq_data *wrqu, char *extra)
664{
665 struct r8192_priv *priv = rtllib_priv(dev);
666
Larry Finger08d348a2011-08-25 11:48:30 -0500667 return rtllib_wx_get_wap(priv->rtllib, info, wrqu, extra);
Larry Finger94a79942011-08-23 19:00:42 -0500668}
669
670
671static int r8192_wx_get_enc(struct net_device *dev,
672 struct iw_request_info *info,
673 union iwreq_data *wrqu, char *key)
674{
675 struct r8192_priv *priv = rtllib_priv(dev);
676
677 return rtllib_wx_get_encode(priv->rtllib, info, wrqu, key);
678}
679
680static int r8192_wx_set_enc(struct net_device *dev,
681 struct iw_request_info *info,
682 union iwreq_data *wrqu, char *key)
683{
684 struct r8192_priv *priv = rtllib_priv(dev);
685 int ret;
686
687 struct rtllib_device *ieee = priv->rtllib;
Larry Finger08d348a2011-08-25 11:48:30 -0500688 u32 hwkey[4] = {0, 0, 0, 0};
689 u8 mask = 0xff;
690 u32 key_idx = 0;
691 u8 zero_addr[4][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
692 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
693 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
694 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} };
Larry Finger94a79942011-08-23 19:00:42 -0500695 int i;
696
Cristina Opriceana44acc6b2015-03-13 21:19:24 +0200697 if (priv->bHwRadioOff)
Larry Finger94a79942011-08-23 19:00:42 -0500698 return 0;
699
Larry Finger08d348a2011-08-25 11:48:30 -0500700 if (!priv->up)
701 return -ENETDOWN;
Larry Finger94a79942011-08-23 19:00:42 -0500702
Larry Finger08d348a2011-08-25 11:48:30 -0500703 priv->rtllib->wx_set_enc = 1;
704 down(&priv->rtllib->ips_sem);
Mateusz Kulikowski2ab2aba2015-07-19 19:33:47 +0200705 rtl92e_ips_leave(dev);
Larry Finger08d348a2011-08-25 11:48:30 -0500706 up(&priv->rtllib->ips_sem);
Larry Finger94a79942011-08-23 19:00:42 -0500707 down(&priv->wx_sem);
708
709 RT_TRACE(COMP_SEC, "Setting SW wep key");
Larry Finger08d348a2011-08-25 11:48:30 -0500710 ret = rtllib_wx_set_encode(priv->rtllib, info, wrqu, key);
Larry Finger94a79942011-08-23 19:00:42 -0500711 up(&priv->wx_sem);
712
713
714 if (wrqu->encoding.flags & IW_ENCODE_DISABLED) {
715 ieee->pairwise_key_type = ieee->group_key_type = KEY_TYPE_NA;
Mateusz Kulikowski358e4ee2015-07-19 19:28:00 +0200716 rtl92e_cam_reset(dev);
Larry Finger08d348a2011-08-25 11:48:30 -0500717 memset(priv->rtllib->swcamtable, 0,
718 sizeof(struct sw_cam_table) * 32);
Larry Finger94a79942011-08-23 19:00:42 -0500719 goto end_hw_sec;
720 }
Larry Finger08d348a2011-08-25 11:48:30 -0500721 if (wrqu->encoding.length != 0) {
Larry Finger94a79942011-08-23 19:00:42 -0500722
Larry Finger08d348a2011-08-25 11:48:30 -0500723 for (i = 0; i < 4; i++) {
Larry Finger94a79942011-08-23 19:00:42 -0500724 hwkey[i] |= key[4*i+0]&mask;
Larry Finger08d348a2011-08-25 11:48:30 -0500725 if (i == 1 && (4 * i + 1) == wrqu->encoding.length)
726 mask = 0x00;
727 if (i == 3 && (4 * i + 1) == wrqu->encoding.length)
728 mask = 0x00;
729 hwkey[i] |= (key[4 * i + 1] & mask) << 8;
730 hwkey[i] |= (key[4 * i + 2] & mask) << 16;
731 hwkey[i] |= (key[4 * i + 3] & mask) << 24;
Larry Finger94a79942011-08-23 19:00:42 -0500732 }
733
Larry Finger08d348a2011-08-25 11:48:30 -0500734 switch (wrqu->encoding.flags & IW_ENCODE_INDEX) {
735 case 0:
Sean MacLennan0ddcf5f2011-12-19 23:21:41 -0500736 key_idx = ieee->crypt_info.tx_keyidx;
Larry Finger08d348a2011-08-25 11:48:30 -0500737 break;
738 case 1:
739 key_idx = 0;
740 break;
741 case 2:
742 key_idx = 1;
743 break;
744 case 3:
745 key_idx = 2;
746 break;
747 case 4:
748 key_idx = 3;
749 break;
750 default:
751 break;
Larry Finger94a79942011-08-23 19:00:42 -0500752 }
Larry Finger08d348a2011-08-25 11:48:30 -0500753 if (wrqu->encoding.length == 0x5) {
Larry Finger94a79942011-08-23 19:00:42 -0500754 ieee->pairwise_key_type = KEY_TYPE_WEP40;
Mateusz Kulikowski37420932015-07-19 19:28:02 +0200755 rtl92e_enable_hw_security_config(dev);
Larry Finger94a79942011-08-23 19:00:42 -0500756 }
757
Larry Finger08d348a2011-08-25 11:48:30 -0500758 else if (wrqu->encoding.length == 0xd) {
Larry Finger94a79942011-08-23 19:00:42 -0500759 ieee->pairwise_key_type = KEY_TYPE_WEP104;
Mateusz Kulikowski37420932015-07-19 19:28:02 +0200760 rtl92e_enable_hw_security_config(dev);
Mateusz Kulikowski408bd7b2015-07-19 19:28:03 +0200761 rtl92e_set_key(dev, key_idx, key_idx, KEY_TYPE_WEP104,
762 zero_addr[key_idx], 0, hwkey);
Mateusz Kulikowskiaae7e722015-07-19 19:28:04 +0200763 rtl92e_set_swcam(dev, key_idx, key_idx, KEY_TYPE_WEP104,
764 zero_addr[key_idx], 0, hwkey, 0);
Larry Finger94a79942011-08-23 19:00:42 -0500765 } else {
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +0100766 netdev_info(dev,
767 "wrong type in WEP, not WEP40 and WEP104\n");
Larry Finger94a79942011-08-23 19:00:42 -0500768 }
769 }
770
771end_hw_sec:
772 priv->rtllib->wx_set_enc = 0;
773 return ret;
774}
775
Larry Finger08d348a2011-08-25 11:48:30 -0500776static int r8192_wx_set_scan_type(struct net_device *dev,
777 struct iw_request_info *aa,
778 union iwreq_data *wrqu, char *p)
779{
Larry Finger94a79942011-08-23 19:00:42 -0500780 struct r8192_priv *priv = rtllib_priv(dev);
Larry Finger08d348a2011-08-25 11:48:30 -0500781 int *parms = (int *)p;
782 int mode = parms[0];
Larry Finger94a79942011-08-23 19:00:42 -0500783
Cristina Opriceana44acc6b2015-03-13 21:19:24 +0200784 if (priv->bHwRadioOff)
Larry Finger94a79942011-08-23 19:00:42 -0500785 return 0;
786
787 priv->rtllib->active_scan = mode;
788
789 return 1;
790}
791
792
793
794#define R8192_MAX_RETRY 255
795static int r8192_wx_set_retry(struct net_device *dev,
796 struct iw_request_info *info,
797 union iwreq_data *wrqu, char *extra)
798{
799 struct r8192_priv *priv = rtllib_priv(dev);
800 int err = 0;
801
Cristina Opriceana44acc6b2015-03-13 21:19:24 +0200802 if (priv->bHwRadioOff)
Larry Finger94a79942011-08-23 19:00:42 -0500803 return 0;
804
805 down(&priv->wx_sem);
806
807 if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
Larry Finger08d348a2011-08-25 11:48:30 -0500808 wrqu->retry.disabled) {
Larry Finger94a79942011-08-23 19:00:42 -0500809 err = -EINVAL;
810 goto exit;
811 }
Larry Finger08d348a2011-08-25 11:48:30 -0500812 if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) {
Larry Finger94a79942011-08-23 19:00:42 -0500813 err = -EINVAL;
814 goto exit;
815 }
816
Larry Finger08d348a2011-08-25 11:48:30 -0500817 if (wrqu->retry.value > R8192_MAX_RETRY) {
818 err = -EINVAL;
Larry Finger94a79942011-08-23 19:00:42 -0500819 goto exit;
820 }
821 if (wrqu->retry.flags & IW_RETRY_MAX) {
822 priv->retry_rts = wrqu->retry.value;
Larry Finger94a79942011-08-23 19:00:42 -0500823
Larry Finger08d348a2011-08-25 11:48:30 -0500824 } else {
Larry Finger94a79942011-08-23 19:00:42 -0500825 priv->retry_data = wrqu->retry.value;
Larry Finger94a79942011-08-23 19:00:42 -0500826 }
827
828
Mateusz Kulikowskibc4f2cc2015-07-19 19:28:12 +0200829 rtl92e_commit(dev);
Larry Finger94a79942011-08-23 19:00:42 -0500830exit:
831 up(&priv->wx_sem);
832
833 return err;
834}
835
836static int r8192_wx_get_retry(struct net_device *dev,
837 struct iw_request_info *info,
838 union iwreq_data *wrqu, char *extra)
839{
840 struct r8192_priv *priv = rtllib_priv(dev);
841
842
843 wrqu->retry.disabled = 0; /* can't be disabled */
844
845 if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
846 IW_RETRY_LIFETIME)
847 return -EINVAL;
848
849 if (wrqu->retry.flags & IW_RETRY_MAX) {
Dan Carpenter6fe86442012-06-09 20:05:16 +0300850 wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
Larry Finger94a79942011-08-23 19:00:42 -0500851 wrqu->retry.value = priv->retry_rts;
852 } else {
Dan Carpenter6fe86442012-06-09 20:05:16 +0300853 wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
Larry Finger94a79942011-08-23 19:00:42 -0500854 wrqu->retry.value = priv->retry_data;
855 }
Larry Finger94a79942011-08-23 19:00:42 -0500856 return 0;
857}
858
859static int r8192_wx_get_sens(struct net_device *dev,
Larry Finger08d348a2011-08-25 11:48:30 -0500860 struct iw_request_info *info,
861 union iwreq_data *wrqu, char *extra)
Larry Finger94a79942011-08-23 19:00:42 -0500862{
863 struct r8192_priv *priv = rtllib_priv(dev);
Matthew Casey3a6b70c2014-08-22 06:27:52 -0400864
Larry Finger94a79942011-08-23 19:00:42 -0500865 if (priv->rf_set_sens == NULL)
866 return -1; /* we have not this support for this radio */
867 wrqu->sens.value = priv->sens;
868 return 0;
869}
870
871
872static int r8192_wx_set_sens(struct net_device *dev,
873 struct iw_request_info *info,
874 union iwreq_data *wrqu, char *extra)
875{
876
877 struct r8192_priv *priv = rtllib_priv(dev);
878
879 short err = 0;
880
Cristina Opriceana44acc6b2015-03-13 21:19:24 +0200881 if (priv->bHwRadioOff)
Larry Finger94a79942011-08-23 19:00:42 -0500882 return 0;
883
884 down(&priv->wx_sem);
885 if (priv->rf_set_sens == NULL) {
Larry Finger08d348a2011-08-25 11:48:30 -0500886 err = -1; /* we have not this support for this radio */
Larry Finger94a79942011-08-23 19:00:42 -0500887 goto exit;
888 }
889 if (priv->rf_set_sens(dev, wrqu->sens.value) == 0)
890 priv->sens = wrqu->sens.value;
891 else
Larry Finger08d348a2011-08-25 11:48:30 -0500892 err = -EINVAL;
Larry Finger94a79942011-08-23 19:00:42 -0500893
894exit:
895 up(&priv->wx_sem);
896
897 return err;
898}
899
Larry Finger94a79942011-08-23 19:00:42 -0500900static int r8192_wx_set_enc_ext(struct net_device *dev,
Larry Finger08d348a2011-08-25 11:48:30 -0500901 struct iw_request_info *info,
902 union iwreq_data *wrqu, char *extra)
Larry Finger94a79942011-08-23 19:00:42 -0500903{
Larry Finger08d348a2011-08-25 11:48:30 -0500904 int ret = 0;
Larry Finger94a79942011-08-23 19:00:42 -0500905 struct r8192_priv *priv = rtllib_priv(dev);
Larry Finger08d348a2011-08-25 11:48:30 -0500906 struct rtllib_device *ieee = priv->rtllib;
Larry Finger94a79942011-08-23 19:00:42 -0500907
Cristina Opriceana44acc6b2015-03-13 21:19:24 +0200908 if (priv->bHwRadioOff)
Larry Finger94a79942011-08-23 19:00:42 -0500909 return 0;
910
911 down(&priv->wx_sem);
912
Larry Finger08d348a2011-08-25 11:48:30 -0500913 priv->rtllib->wx_set_enc = 1;
914 down(&priv->rtllib->ips_sem);
Mateusz Kulikowski2ab2aba2015-07-19 19:33:47 +0200915 rtl92e_ips_leave(dev);
Larry Finger08d348a2011-08-25 11:48:30 -0500916 up(&priv->rtllib->ips_sem);
Larry Finger94a79942011-08-23 19:00:42 -0500917
918 ret = rtllib_wx_set_encode_ext(ieee, info, wrqu, extra);
Larry Finger94a79942011-08-23 19:00:42 -0500919 {
Mateusz Kulikowski06c11102015-05-31 20:19:21 +0200920 const u8 broadcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
921 const u8 zero[ETH_ALEN] = {0};
Larry Finger94a79942011-08-23 19:00:42 -0500922 u32 key[4] = {0};
923 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
924 struct iw_point *encoding = &wrqu->encoding;
925 u8 idx = 0, alg = 0, group = 0;
Matthew Casey3a6b70c2014-08-22 06:27:52 -0400926
Larry Finger94a79942011-08-23 19:00:42 -0500927 if ((encoding->flags & IW_ENCODE_DISABLED) ||
Larry Finger08d348a2011-08-25 11:48:30 -0500928 ext->alg == IW_ENCODE_ALG_NONE) {
929 ieee->pairwise_key_type = ieee->group_key_type
930 = KEY_TYPE_NA;
Mateusz Kulikowski358e4ee2015-07-19 19:28:00 +0200931 rtl92e_cam_reset(dev);
Larry Finger08d348a2011-08-25 11:48:30 -0500932 memset(priv->rtllib->swcamtable, 0,
933 sizeof(struct sw_cam_table) * 32);
Larry Finger94a79942011-08-23 19:00:42 -0500934 goto end_hw_sec;
935 }
Larry Finger08d348a2011-08-25 11:48:30 -0500936 alg = (ext->alg == IW_ENCODE_ALG_CCMP) ? KEY_TYPE_CCMP :
937 ext->alg;
Larry Finger94a79942011-08-23 19:00:42 -0500938 idx = encoding->flags & IW_ENCODE_INDEX;
939 if (idx)
Larry Finger08d348a2011-08-25 11:48:30 -0500940 idx--;
Larry Finger94a79942011-08-23 19:00:42 -0500941 group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
942
Larry Finger08d348a2011-08-25 11:48:30 -0500943 if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) ||
944 (alg == KEY_TYPE_WEP40)) {
945 if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40))
Larry Finger94a79942011-08-23 19:00:42 -0500946 alg = KEY_TYPE_WEP104;
947 ieee->pairwise_key_type = alg;
Mateusz Kulikowski37420932015-07-19 19:28:02 +0200948 rtl92e_enable_hw_security_config(dev);
Larry Finger94a79942011-08-23 19:00:42 -0500949 }
Larry Finger08d348a2011-08-25 11:48:30 -0500950 memcpy((u8 *)key, ext->key, 16);
Larry Finger94a79942011-08-23 19:00:42 -0500951
Larry Finger08d348a2011-08-25 11:48:30 -0500952 if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode != 2)) {
Larry Finger94a79942011-08-23 19:00:42 -0500953 if (ext->key_len == 13)
954 ieee->pairwise_key_type = alg = KEY_TYPE_WEP104;
Mateusz Kulikowski408bd7b2015-07-19 19:28:03 +0200955 rtl92e_set_key(dev, idx, idx, alg, zero, 0, key);
Mateusz Kulikowskiaae7e722015-07-19 19:28:04 +0200956 rtl92e_set_swcam(dev, idx, idx, alg, zero, 0, key, 0);
Larry Finger08d348a2011-08-25 11:48:30 -0500957 } else if (group) {
Larry Finger94a79942011-08-23 19:00:42 -0500958 ieee->group_key_type = alg;
Mateusz Kulikowski408bd7b2015-07-19 19:28:03 +0200959 rtl92e_set_key(dev, idx, idx, alg, broadcast_addr, 0,
960 key);
Mateusz Kulikowskiaae7e722015-07-19 19:28:04 +0200961 rtl92e_set_swcam(dev, idx, idx, alg, broadcast_addr, 0,
962 key, 0);
Larry Finger08d348a2011-08-25 11:48:30 -0500963 } else {
964 if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) &&
965 ieee->pHTInfo->bCurrentHTSupport)
Mateusz Kulikowskid8ae1962015-07-19 19:28:26 +0200966 rtl92e_writeb(dev, 0x173, 1);
Mateusz Kulikowski408bd7b2015-07-19 19:28:03 +0200967 rtl92e_set_key(dev, 4, idx, alg,
968 (u8 *)ieee->ap_mac_addr, 0, key);
Mateusz Kulikowskiaae7e722015-07-19 19:28:04 +0200969 rtl92e_set_swcam(dev, 4, idx, alg,
970 (u8 *)ieee->ap_mac_addr, 0, key, 0);
Larry Finger94a79942011-08-23 19:00:42 -0500971 }
972
973
974 }
975
976end_hw_sec:
Larry Finger08d348a2011-08-25 11:48:30 -0500977 priv->rtllib->wx_set_enc = 0;
Larry Finger94a79942011-08-23 19:00:42 -0500978 up(&priv->wx_sem);
979 return ret;
980
981}
982static int r8192_wx_set_auth(struct net_device *dev,
Larry Finger08d348a2011-08-25 11:48:30 -0500983 struct iw_request_info *info,
984 union iwreq_data *data, char *extra)
Larry Finger94a79942011-08-23 19:00:42 -0500985{
Larry Finger08d348a2011-08-25 11:48:30 -0500986 int ret = 0;
Larry Finger94a79942011-08-23 19:00:42 -0500987
988 struct r8192_priv *priv = rtllib_priv(dev);
989
Cristina Opriceana44acc6b2015-03-13 21:19:24 +0200990 if (priv->bHwRadioOff)
Larry Finger94a79942011-08-23 19:00:42 -0500991 return 0;
992
993 down(&priv->wx_sem);
994 ret = rtllib_wx_set_auth(priv->rtllib, info, &(data->param), extra);
995 up(&priv->wx_sem);
996 return ret;
997}
998
999static int r8192_wx_set_mlme(struct net_device *dev,
Larry Finger08d348a2011-08-25 11:48:30 -05001000 struct iw_request_info *info,
1001 union iwreq_data *wrqu, char *extra)
Larry Finger94a79942011-08-23 19:00:42 -05001002{
1003
Larry Finger08d348a2011-08-25 11:48:30 -05001004 int ret = 0;
Larry Finger94a79942011-08-23 19:00:42 -05001005
1006 struct r8192_priv *priv = rtllib_priv(dev);
1007
Cristina Opriceana44acc6b2015-03-13 21:19:24 +02001008 if (priv->bHwRadioOff)
Larry Finger94a79942011-08-23 19:00:42 -05001009 return 0;
1010
1011 down(&priv->wx_sem);
1012 ret = rtllib_wx_set_mlme(priv->rtllib, info, wrqu, extra);
1013 up(&priv->wx_sem);
1014 return ret;
1015}
Larry Finger94a79942011-08-23 19:00:42 -05001016
1017static int r8192_wx_set_gen_ie(struct net_device *dev,
Larry Finger08d348a2011-08-25 11:48:30 -05001018 struct iw_request_info *info,
1019 union iwreq_data *data, char *extra)
Larry Finger94a79942011-08-23 19:00:42 -05001020{
1021 int ret = 0;
1022
Larry Finger08d348a2011-08-25 11:48:30 -05001023 struct r8192_priv *priv = rtllib_priv(dev);
Larry Finger94a79942011-08-23 19:00:42 -05001024
Cristina Opriceana44acc6b2015-03-13 21:19:24 +02001025 if (priv->bHwRadioOff)
Larry Finger94a79942011-08-23 19:00:42 -05001026 return 0;
1027
Larry Finger08d348a2011-08-25 11:48:30 -05001028 down(&priv->wx_sem);
1029 ret = rtllib_wx_set_gen_ie(priv->rtllib, extra, data->data.length);
1030 up(&priv->wx_sem);
1031 return ret;
Larry Finger94a79942011-08-23 19:00:42 -05001032}
1033
1034static int r8192_wx_get_gen_ie(struct net_device *dev,
Larry Finger08d348a2011-08-25 11:48:30 -05001035 struct iw_request_info *info,
Larry Finger94a79942011-08-23 19:00:42 -05001036 union iwreq_data *data, char *extra)
1037{
1038 int ret = 0;
Larry Finger08d348a2011-08-25 11:48:30 -05001039 struct r8192_priv *priv = rtllib_priv(dev);
1040 struct rtllib_device *ieee = priv->rtllib;
Larry Finger94a79942011-08-23 19:00:42 -05001041
1042 if (ieee->wpa_ie_len == 0 || ieee->wpa_ie == NULL) {
1043 data->data.length = 0;
1044 return 0;
1045 }
1046
Larry Finger08d348a2011-08-25 11:48:30 -05001047 if (data->data.length < ieee->wpa_ie_len)
Larry Finger94a79942011-08-23 19:00:42 -05001048 return -E2BIG;
Larry Finger94a79942011-08-23 19:00:42 -05001049
1050 data->data.length = ieee->wpa_ie_len;
1051 memcpy(extra, ieee->wpa_ie, ieee->wpa_ie_len);
Larry Finger08d348a2011-08-25 11:48:30 -05001052 return ret;
Larry Finger94a79942011-08-23 19:00:42 -05001053}
1054
1055#define OID_RT_INTEL_PROMISCUOUS_MODE 0xFF0101F6
1056
1057static int r8192_wx_set_PromiscuousMode(struct net_device *dev,
Larry Finger08d348a2011-08-25 11:48:30 -05001058 struct iw_request_info *info,
1059 union iwreq_data *wrqu, char *extra)
Larry Finger94a79942011-08-23 19:00:42 -05001060{
1061 struct r8192_priv *priv = rtllib_priv(dev);
Larry Finger08d348a2011-08-25 11:48:30 -05001062 struct rtllib_device *ieee = priv->rtllib;
Larry Finger94a79942011-08-23 19:00:42 -05001063
Dominique van den Broeckdb4d7172014-05-04 16:46:27 +02001064 u32 info_buf[3];
Larry Finger94a79942011-08-23 19:00:42 -05001065
Dominique van den Broeckdb4d7172014-05-04 16:46:27 +02001066 u32 oid;
1067 u32 bPromiscuousOn;
1068 u32 bFilterSourceStationFrame;
1069
1070 if (copy_from_user(info_buf, wrqu->data.pointer, sizeof(info_buf)))
1071 return -EFAULT;
1072
1073 oid = info_buf[0];
1074 bPromiscuousOn = info_buf[1];
1075 bFilterSourceStationFrame = info_buf[2];
Larry Finger94a79942011-08-23 19:00:42 -05001076
Larry Finger08d348a2011-08-25 11:48:30 -05001077 if (OID_RT_INTEL_PROMISCUOUS_MODE == oid) {
Larry Finger94a79942011-08-23 19:00:42 -05001078 ieee->IntelPromiscuousModeInfo.bPromiscuousOn =
Larry Finger08d348a2011-08-25 11:48:30 -05001079 (bPromiscuousOn) ? (true) : (false);
Larry Finger94a79942011-08-23 19:00:42 -05001080 ieee->IntelPromiscuousModeInfo.bFilterSourceStationFrame =
Larry Finger08d348a2011-08-25 11:48:30 -05001081 (bFilterSourceStationFrame) ? (true) : (false);
1082 (bPromiscuousOn) ?
1083 (rtllib_EnableIntelPromiscuousMode(dev, false)) :
1084 (rtllib_DisableIntelPromiscuousMode(dev, false));
Larry Finger94a79942011-08-23 19:00:42 -05001085
Mateusz Kulikowskid69d2052015-03-17 00:00:52 +01001086 netdev_info(dev,
1087 "=======>%s(), on = %d, filter src sta = %d\n",
1088 __func__, bPromiscuousOn,
1089 bFilterSourceStationFrame);
Larry Finger94a79942011-08-23 19:00:42 -05001090 } else {
1091 return -1;
1092 }
1093
1094 return 0;
1095}
1096
1097
1098static int r8192_wx_get_PromiscuousMode(struct net_device *dev,
Larry Finger08d348a2011-08-25 11:48:30 -05001099 struct iw_request_info *info,
1100 union iwreq_data *wrqu, char *extra)
Larry Finger94a79942011-08-23 19:00:42 -05001101{
1102 struct r8192_priv *priv = rtllib_priv(dev);
Larry Finger08d348a2011-08-25 11:48:30 -05001103 struct rtllib_device *ieee = priv->rtllib;
Larry Finger94a79942011-08-23 19:00:42 -05001104
Larry Finger08d348a2011-08-25 11:48:30 -05001105 down(&priv->wx_sem);
Larry Finger94a79942011-08-23 19:00:42 -05001106
Larry Finger08d348a2011-08-25 11:48:30 -05001107 snprintf(extra, 45, "PromiscuousMode:%d, FilterSrcSTAFrame:%d",
1108 ieee->IntelPromiscuousModeInfo.bPromiscuousOn,
1109 ieee->IntelPromiscuousModeInfo.bFilterSourceStationFrame);
1110 wrqu->data.length = strlen(extra) + 1;
Larry Finger94a79942011-08-23 19:00:42 -05001111
Larry Finger08d348a2011-08-25 11:48:30 -05001112 up(&priv->wx_sem);
Larry Finger94a79942011-08-23 19:00:42 -05001113
1114 return 0;
1115}
1116
1117
Mateusz Kulikowski976a06c2015-07-28 23:31:45 +02001118#define IW_IOCTL(x) ((x) - SIOCSIWCOMMIT)
Larry Finger08d348a2011-08-25 11:48:30 -05001119static iw_handler r8192_wx_handlers[] = {
Mateusz Kulikowski976a06c2015-07-28 23:31:45 +02001120 [IW_IOCTL(SIOCGIWNAME)] = r8192_wx_get_name,
1121 [IW_IOCTL(SIOCSIWFREQ)] = r8192_wx_set_freq,
1122 [IW_IOCTL(SIOCGIWFREQ)] = r8192_wx_get_freq,
1123 [IW_IOCTL(SIOCSIWMODE)] = r8192_wx_set_mode,
1124 [IW_IOCTL(SIOCGIWMODE)] = r8192_wx_get_mode,
1125 [IW_IOCTL(SIOCSIWSENS)] = r8192_wx_set_sens,
1126 [IW_IOCTL(SIOCGIWSENS)] = r8192_wx_get_sens,
1127 [IW_IOCTL(SIOCGIWRANGE)] = rtl8192_wx_get_range,
1128 [IW_IOCTL(SIOCSIWAP)] = r8192_wx_set_wap,
1129 [IW_IOCTL(SIOCGIWAP)] = r8192_wx_get_wap,
1130 [IW_IOCTL(SIOCSIWSCAN)] = r8192_wx_set_scan,
1131 [IW_IOCTL(SIOCGIWSCAN)] = r8192_wx_get_scan,
1132 [IW_IOCTL(SIOCSIWESSID)] = r8192_wx_set_essid,
1133 [IW_IOCTL(SIOCGIWESSID)] = r8192_wx_get_essid,
1134 [IW_IOCTL(SIOCSIWNICKN)] = r8192_wx_set_nick,
1135 [IW_IOCTL(SIOCGIWNICKN)] = r8192_wx_get_nick,
1136 [IW_IOCTL(SIOCSIWRATE)] = r8192_wx_set_rate,
1137 [IW_IOCTL(SIOCGIWRATE)] = r8192_wx_get_rate,
1138 [IW_IOCTL(SIOCSIWRTS)] = r8192_wx_set_rts,
1139 [IW_IOCTL(SIOCGIWRTS)] = r8192_wx_get_rts,
1140 [IW_IOCTL(SIOCSIWFRAG)] = r8192_wx_set_frag,
1141 [IW_IOCTL(SIOCGIWFRAG)] = r8192_wx_get_frag,
1142 [IW_IOCTL(SIOCSIWRETRY)] = r8192_wx_set_retry,
1143 [IW_IOCTL(SIOCGIWRETRY)] = r8192_wx_get_retry,
1144 [IW_IOCTL(SIOCSIWENCODE)] = r8192_wx_set_enc,
1145 [IW_IOCTL(SIOCGIWENCODE)] = r8192_wx_get_enc,
1146 [IW_IOCTL(SIOCSIWPOWER)] = r8192_wx_set_power,
1147 [IW_IOCTL(SIOCGIWPOWER)] = r8192_wx_get_power,
1148 [IW_IOCTL(SIOCSIWGENIE)] = r8192_wx_set_gen_ie,
1149 [IW_IOCTL(SIOCGIWGENIE)] = r8192_wx_get_gen_ie,
1150 [IW_IOCTL(SIOCSIWMLME)] = r8192_wx_set_mlme,
1151 [IW_IOCTL(SIOCSIWAUTH)] = r8192_wx_set_auth,
1152 [IW_IOCTL(SIOCSIWENCODEEXT)] = r8192_wx_set_enc_ext,
Larry Finger94a79942011-08-23 19:00:42 -05001153};
1154
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +02001155/* the following rule need to be following,
Larry Finger94a79942011-08-23 19:00:42 -05001156 * Odd : get (world access),
1157 * even : set (root access)
Mateusz Kulikowski14b40d92015-04-01 00:24:37 +02001158 */
Larry Finger94a79942011-08-23 19:00:42 -05001159static const struct iw_priv_args r8192_private_args[] = {
1160 {
1161 SIOCIWFIRSTPRIV + 0x0,
1162 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_debugflag"
Larry Finger08d348a2011-08-25 11:48:30 -05001163 }, {
Larry Finger94a79942011-08-23 19:00:42 -05001164 SIOCIWFIRSTPRIV + 0x1,
1165 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
Larry Finger08d348a2011-08-25 11:48:30 -05001166 }, {
Larry Finger94a79942011-08-23 19:00:42 -05001167 SIOCIWFIRSTPRIV + 0x2,
1168 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
Larry Finger08d348a2011-08-25 11:48:30 -05001169 }, {
Larry Finger94a79942011-08-23 19:00:42 -05001170 SIOCIWFIRSTPRIV + 0x3,
1171 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
Larry Finger08d348a2011-08-25 11:48:30 -05001172 }, {
Larry Finger94a79942011-08-23 19:00:42 -05001173 SIOCIWFIRSTPRIV + 0x6,
1174 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE,
1175 "set_power"
Larry Finger08d348a2011-08-25 11:48:30 -05001176 }, {
Larry Finger94a79942011-08-23 19:00:42 -05001177 SIOCIWFIRSTPRIV + 0xa,
1178 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE,
1179 "lps_interv"
Larry Finger08d348a2011-08-25 11:48:30 -05001180 }, {
Larry Finger94a79942011-08-23 19:00:42 -05001181 SIOCIWFIRSTPRIV + 0xb,
1182 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE,
1183 "lps_force"
Larry Finger08d348a2011-08-25 11:48:30 -05001184 }, {
Larry Finger94a79942011-08-23 19:00:42 -05001185 SIOCIWFIRSTPRIV + 0x16,
Larry Finger08d348a2011-08-25 11:48:30 -05001186 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "setpromisc"
1187 }, {
Larry Finger94a79942011-08-23 19:00:42 -05001188 SIOCIWFIRSTPRIV + 0x17,
Larry Finger08d348a2011-08-25 11:48:30 -05001189 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 45, "getpromisc"
Larry Finger94a79942011-08-23 19:00:42 -05001190 }
1191
1192};
1193
1194static iw_handler r8192_private_handler[] = {
1195 (iw_handler)r8192_wx_set_debugflag, /*SIOCIWSECONDPRIV*/
1196 (iw_handler)r8192_wx_set_scan_type,
1197 (iw_handler)r8192_wx_set_rawtx,
1198 (iw_handler)r8192_wx_force_reset,
Mateusz Kulikowski0beee3b2015-05-31 20:19:42 +02001199 (iw_handler)NULL,
1200 (iw_handler)NULL,
Larry Finger94a79942011-08-23 19:00:42 -05001201 (iw_handler)r8192_wx_adapter_power_status,
1202 (iw_handler)NULL,
1203 (iw_handler)NULL,
Mateusz Kulikowski0beee3b2015-05-31 20:19:42 +02001204 (iw_handler)NULL,
Larry Finger94a79942011-08-23 19:00:42 -05001205 (iw_handler)r8192se_wx_set_lps_awake_interval,
1206 (iw_handler)r8192se_wx_set_force_lps,
Mateusz Kulikowski0beee3b2015-05-31 20:19:42 +02001207 (iw_handler)NULL,
Larry Finger94a79942011-08-23 19:00:42 -05001208 (iw_handler)NULL,
Larry Finger94a79942011-08-23 19:00:42 -05001209 (iw_handler)NULL,
1210 (iw_handler)NULL,
1211 (iw_handler)NULL,
1212 (iw_handler)NULL,
1213 (iw_handler)NULL,
1214 (iw_handler)NULL,
1215 (iw_handler)NULL,
1216 (iw_handler)NULL,
Larry Finger94a79942011-08-23 19:00:42 -05001217 (iw_handler)r8192_wx_set_PromiscuousMode,
1218 (iw_handler)r8192_wx_get_PromiscuousMode,
1219};
1220
Larry Finger49aab5f2011-08-25 14:07:05 -05001221static struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
Larry Finger94a79942011-08-23 19:00:42 -05001222{
Larry Finger08d348a2011-08-25 11:48:30 -05001223 struct r8192_priv *priv = rtllib_priv(dev);
1224 struct rtllib_device *ieee = priv->rtllib;
1225 struct iw_statistics *wstats = &priv->wstats;
Larry Finger94a79942011-08-23 19:00:42 -05001226 int tmp_level = 0;
1227 int tmp_qual = 0;
1228 int tmp_noise = 0;
Matthew Casey3a6b70c2014-08-22 06:27:52 -04001229
Larry Finger08d348a2011-08-25 11:48:30 -05001230 if (ieee->state < RTLLIB_LINKED) {
Larry Finger94a79942011-08-23 19:00:42 -05001231 wstats->qual.qual = 10;
1232 wstats->qual.level = 0;
1233 wstats->qual.noise = -100;
1234 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
1235 return wstats;
1236 }
1237
Larry Finger08d348a2011-08-25 11:48:30 -05001238 tmp_level = (&ieee->current_network)->stats.rssi;
Larry Finger94a79942011-08-23 19:00:42 -05001239 tmp_qual = (&ieee->current_network)->stats.signal;
1240 tmp_noise = (&ieee->current_network)->stats.noise;
1241
1242 wstats->qual.level = tmp_level;
1243 wstats->qual.qual = tmp_qual;
1244 wstats->qual.noise = tmp_noise;
1245 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
1246 return wstats;
1247}
1248
Joel Pelaez Jorge5169af22014-04-19 22:32:32 -05001249const struct iw_handler_def r8192_wx_handlers_def = {
Larry Finger94a79942011-08-23 19:00:42 -05001250 .standard = r8192_wx_handlers,
Jim Cromieb330f602012-04-10 16:06:41 -06001251 .num_standard = ARRAY_SIZE(r8192_wx_handlers),
Larry Finger94a79942011-08-23 19:00:42 -05001252 .private = r8192_private_handler,
Jim Cromieb330f602012-04-10 16:06:41 -06001253 .num_private = ARRAY_SIZE(r8192_private_handler),
Larry Finger08d348a2011-08-25 11:48:30 -05001254 .num_private_args = sizeof(r8192_private_args) /
1255 sizeof(struct iw_priv_args),
Larry Finger94a79942011-08-23 19:00:42 -05001256 .get_wireless_stats = r8192_get_wireless_stats,
Larry Finger94a79942011-08-23 19:00:42 -05001257 .private_args = (struct iw_priv_args *)r8192_private_args,
1258};