Commit | Line | Data |
---|---|---|
94a79942 LF |
1 | /****************************************************************************** |
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 | * | |
94a79942 LF |
9 | * The full GNU General Public License is included in this distribution in the |
10 | * file called LICENSE. | |
11 | * | |
12 | * Contact Information: | |
13 | * wlanfae <wlanfae@realtek.com> | |
14 | ******************************************************************************/ | |
15 | ||
16 | #include <linux/string.h> | |
17 | #include "rtl_core.h" | |
5169af23 | 18 | #include "rtl_wx.h" |
94a79942 | 19 | |
94a79942 | 20 | #define RATE_COUNT 12 |
49aab5fd | 21 | static u32 rtl8192_rates[] = { |
08d348a0 LF |
22 | 1000000, 2000000, 5500000, 11000000, 6000000, 9000000, 12000000, |
23 | 18000000, 24000000, 36000000, 48000000, 54000000 | |
24 | }; | |
94a79942 LF |
25 | |
26 | #ifndef ENETDOWN | |
27 | #define ENETDOWN 1 | |
28 | #endif | |
94a79942 | 29 | |
d1bae81a MK |
30 | static int _rtl92e_wx_get_freq(struct net_device *dev, |
31 | struct iw_request_info *a, | |
32 | union iwreq_data *wrqu, char *b) | |
94a79942 LF |
33 | { |
34 | struct r8192_priv *priv = rtllib_priv(dev); | |
35 | ||
08d348a0 | 36 | return rtllib_wx_get_freq(priv->rtllib, a, wrqu, b); |
94a79942 LF |
37 | } |
38 | ||
39 | ||
062cd9b4 MK |
40 | static int _rtl92e_wx_get_mode(struct net_device *dev, |
41 | struct iw_request_info *a, | |
42 | union iwreq_data *wrqu, char *b) | |
94a79942 | 43 | { |
08d348a0 | 44 | struct r8192_priv *priv = rtllib_priv(dev); |
94a79942 | 45 | |
08d348a0 | 46 | return rtllib_wx_get_mode(priv->rtllib, a, wrqu, b); |
94a79942 LF |
47 | } |
48 | ||
5be1e1ff MK |
49 | static int _rtl92e_wx_get_rate(struct net_device *dev, |
50 | struct iw_request_info *info, | |
51 | union iwreq_data *wrqu, char *extra) | |
94a79942 LF |
52 | { |
53 | struct r8192_priv *priv = rtllib_priv(dev); | |
3a6b70c3 | 54 | |
08d348a0 | 55 | return rtllib_wx_get_rate(priv->rtllib, info, wrqu, extra); |
94a79942 LF |
56 | } |
57 | ||
ad6a5412 MK |
58 | static int _rtl92e_wx_set_rate(struct net_device *dev, |
59 | struct iw_request_info *info, | |
60 | union iwreq_data *wrqu, char *extra) | |
94a79942 LF |
61 | { |
62 | int ret; | |
63 | struct r8192_priv *priv = rtllib_priv(dev); | |
64 | ||
44acc6b5 | 65 | if (priv->bHwRadioOff) |
94a79942 LF |
66 | return 0; |
67 | ||
3044975f | 68 | mutex_lock(&priv->wx_mutex); |
94a79942 | 69 | |
08d348a0 | 70 | ret = rtllib_wx_set_rate(priv->rtllib, info, wrqu, extra); |
94a79942 | 71 | |
3044975f | 72 | mutex_unlock(&priv->wx_mutex); |
94a79942 LF |
73 | |
74 | return ret; | |
75 | } | |
76 | ||
c90ee2fc MK |
77 | static int _rtl92e_wx_set_rts(struct net_device *dev, |
78 | struct iw_request_info *info, | |
79 | union iwreq_data *wrqu, char *extra) | |
94a79942 LF |
80 | { |
81 | int ret; | |
82 | struct r8192_priv *priv = rtllib_priv(dev); | |
83 | ||
44acc6b5 | 84 | if (priv->bHwRadioOff) |
94a79942 LF |
85 | return 0; |
86 | ||
3044975f | 87 | mutex_lock(&priv->wx_mutex); |
94a79942 | 88 | |
08d348a0 | 89 | ret = rtllib_wx_set_rts(priv->rtllib, info, wrqu, extra); |
94a79942 | 90 | |
3044975f | 91 | mutex_unlock(&priv->wx_mutex); |
94a79942 LF |
92 | |
93 | return ret; | |
94 | } | |
95 | ||
e19794b1 MK |
96 | static int _rtl92e_wx_get_rts(struct net_device *dev, |
97 | struct iw_request_info *info, | |
98 | union iwreq_data *wrqu, char *extra) | |
94a79942 LF |
99 | { |
100 | struct r8192_priv *priv = rtllib_priv(dev); | |
3a6b70c3 | 101 | |
08d348a0 | 102 | return rtllib_wx_get_rts(priv->rtllib, info, wrqu, extra); |
94a79942 LF |
103 | } |
104 | ||
f2e90185 MK |
105 | static int _rtl92e_wx_set_power(struct net_device *dev, |
106 | struct iw_request_info *info, | |
107 | union iwreq_data *wrqu, char *extra) | |
94a79942 LF |
108 | { |
109 | int ret; | |
110 | struct r8192_priv *priv = rtllib_priv(dev); | |
111 | ||
44acc6b5 | 112 | if (priv->bHwRadioOff) { |
3b4140af MK |
113 | netdev_warn(dev, "%s(): Can't set Power: Radio is Off.\n", |
114 | __func__); | |
94a79942 LF |
115 | return 0; |
116 | } | |
3044975f | 117 | mutex_lock(&priv->wx_mutex); |
94a79942 | 118 | |
08d348a0 | 119 | ret = rtllib_wx_set_power(priv->rtllib, info, wrqu, extra); |
94a79942 | 120 | |
3044975f | 121 | mutex_unlock(&priv->wx_mutex); |
94a79942 LF |
122 | |
123 | return ret; | |
124 | } | |
125 | ||
b821768a MK |
126 | static int _rtl92e_wx_get_power(struct net_device *dev, |
127 | struct iw_request_info *info, | |
128 | union iwreq_data *wrqu, char *extra) | |
94a79942 LF |
129 | { |
130 | struct r8192_priv *priv = rtllib_priv(dev); | |
3a6b70c3 | 131 | |
08d348a0 | 132 | return rtllib_wx_get_power(priv->rtllib, info, wrqu, extra); |
94a79942 LF |
133 | } |
134 | ||
31183234 MK |
135 | static int _rtl92e_wx_set_rawtx(struct net_device *dev, |
136 | struct iw_request_info *info, | |
137 | union iwreq_data *wrqu, char *extra) | |
94a79942 LF |
138 | { |
139 | struct r8192_priv *priv = rtllib_priv(dev); | |
140 | int ret; | |
141 | ||
44acc6b5 | 142 | if (priv->bHwRadioOff) |
94a79942 LF |
143 | return 0; |
144 | ||
3044975f | 145 | mutex_lock(&priv->wx_mutex); |
94a79942 LF |
146 | |
147 | ret = rtllib_wx_set_rawtx(priv->rtllib, info, wrqu, extra); | |
148 | ||
3044975f | 149 | mutex_unlock(&priv->wx_mutex); |
94a79942 LF |
150 | |
151 | return ret; | |
152 | ||
153 | } | |
154 | ||
042f05eb MK |
155 | static int _rtl92e_wx_force_reset(struct net_device *dev, |
156 | struct iw_request_info *info, | |
157 | union iwreq_data *wrqu, char *extra) | |
94a79942 LF |
158 | { |
159 | struct r8192_priv *priv = rtllib_priv(dev); | |
160 | ||
3044975f | 161 | mutex_lock(&priv->wx_mutex); |
94a79942 | 162 | |
08d348a0 LF |
163 | RT_TRACE(COMP_DBG, "%s(): force reset ! extra is %d\n", |
164 | __func__, *extra); | |
94a79942 | 165 | priv->force_reset = *extra; |
3044975f | 166 | mutex_unlock(&priv->wx_mutex); |
94a79942 LF |
167 | return 0; |
168 | ||
169 | } | |
170 | ||
ac9e5e73 MK |
171 | static int _rtl92e_wx_adapter_power_status(struct net_device *dev, |
172 | struct iw_request_info *info, | |
173 | union iwreq_data *wrqu, char *extra) | |
94a79942 LF |
174 | { |
175 | struct r8192_priv *priv = rtllib_priv(dev); | |
08d348a0 LF |
176 | struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *) |
177 | (&(priv->rtllib->PowerSaveControl)); | |
178 | struct rtllib_device *ieee = priv->rtllib; | |
94a79942 | 179 | |
3044975f | 180 | mutex_lock(&priv->wx_mutex); |
94a79942 | 181 | |
08d348a0 LF |
182 | RT_TRACE(COMP_POWER, "%s(): %s\n", __func__, (*extra == 6) ? |
183 | "DC power" : "AC power"); | |
94a79942 LF |
184 | if (*extra || priv->force_lps) { |
185 | priv->ps_force = false; | |
186 | pPSC->bLeisurePs = true; | |
187 | } else { | |
188 | if (priv->rtllib->state == RTLLIB_LINKED) | |
9c4a55d1 | 189 | rtl92e_leisure_ps_leave(dev); |
94a79942 LF |
190 | |
191 | priv->ps_force = true; | |
192 | pPSC->bLeisurePs = false; | |
193 | ieee->ps = *extra; | |
194 | } | |
195 | ||
3044975f | 196 | mutex_unlock(&priv->wx_mutex); |
94a79942 LF |
197 | |
198 | return 0; | |
199 | } | |
200 | ||
0a263fcf MK |
201 | static int _rtl92e_wx_set_lps_awake_interval(struct net_device *dev, |
202 | struct iw_request_info *info, | |
203 | union iwreq_data *wrqu, | |
204 | char *extra) | |
94a79942 | 205 | { |
08d348a0 LF |
206 | struct r8192_priv *priv = rtllib_priv(dev); |
207 | struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *) | |
208 | (&(priv->rtllib->PowerSaveControl)); | |
94a79942 | 209 | |
3044975f | 210 | mutex_lock(&priv->wx_mutex); |
94a79942 | 211 | |
d69d2054 MK |
212 | netdev_info(dev, "%s(): set lps awake interval ! extra is %d\n", |
213 | __func__, *extra); | |
94a79942 | 214 | |
08d348a0 | 215 | pPSC->RegMaxLPSAwakeIntvl = *extra; |
3044975f | 216 | mutex_unlock(&priv->wx_mutex); |
08d348a0 | 217 | return 0; |
94a79942 LF |
218 | } |
219 | ||
84e4dc10 MK |
220 | static int _rtl92e_wx_set_force_lps(struct net_device *dev, |
221 | struct iw_request_info *info, | |
222 | union iwreq_data *wrqu, char *extra) | |
94a79942 LF |
223 | { |
224 | struct r8192_priv *priv = rtllib_priv(dev); | |
225 | ||
3044975f | 226 | mutex_lock(&priv->wx_mutex); |
94a79942 | 227 | |
d69d2054 MK |
228 | netdev_info(dev, |
229 | "%s(): force LPS ! extra is %d (1 is open 0 is close)\n", | |
230 | __func__, *extra); | |
94a79942 | 231 | priv->force_lps = *extra; |
3044975f | 232 | mutex_unlock(&priv->wx_mutex); |
94a79942 LF |
233 | return 0; |
234 | ||
235 | } | |
236 | ||
d373a0ce MK |
237 | static int _rtl92e_wx_set_debug(struct net_device *dev, |
238 | struct iw_request_info *info, | |
239 | union iwreq_data *wrqu, char *extra) | |
94a79942 LF |
240 | { |
241 | struct r8192_priv *priv = rtllib_priv(dev); | |
242 | u8 c = *extra; | |
243 | ||
44acc6b5 | 244 | if (priv->bHwRadioOff) |
94a79942 LF |
245 | return 0; |
246 | ||
d69d2054 MK |
247 | netdev_info(dev, "=====>%s(), *extra:%x, debugflag:%x\n", __func__, |
248 | *extra, rt_global_debug_component); | |
08d348a0 | 249 | if (c > 0) |
94a79942 | 250 | rt_global_debug_component |= (1<<c); |
08d348a0 | 251 | else |
94a79942 | 252 | rt_global_debug_component &= BIT31; |
94a79942 LF |
253 | return 0; |
254 | } | |
255 | ||
89528d6c MK |
256 | static int _rtl92e_wx_set_mode(struct net_device *dev, |
257 | struct iw_request_info *a, | |
258 | union iwreq_data *wrqu, char *b) | |
94a79942 LF |
259 | { |
260 | struct r8192_priv *priv = rtllib_priv(dev); | |
08d348a0 | 261 | struct rtllib_device *ieee = netdev_priv_rsl(dev); |
94a79942 | 262 | |
de7c885a | 263 | enum rt_rf_power_state rtState; |
94a79942 LF |
264 | int ret; |
265 | ||
44acc6b5 | 266 | if (priv->bHwRadioOff) |
94a79942 LF |
267 | return 0; |
268 | rtState = priv->rtllib->eRFPowerState; | |
3044975f | 269 | mutex_lock(&priv->wx_mutex); |
08d348a0 LF |
270 | if (wrqu->mode == IW_MODE_ADHOC || wrqu->mode == IW_MODE_MONITOR || |
271 | ieee->bNetPromiscuousMode) { | |
272 | if (priv->rtllib->PowerSaveControl.bInactivePs) { | |
273 | if (rtState == eRfOff) { | |
274 | if (priv->rtllib->RfOffReason > | |
275 | RF_CHANGE_BY_IPS) { | |
3b4140af MK |
276 | netdev_warn(dev, "%s(): RF is OFF.\n", |
277 | __func__); | |
3044975f | 278 | mutex_unlock(&priv->wx_mutex); |
94a79942 | 279 | return -1; |
94a79942 | 280 | } |
2ab2aba2 MK |
281 | netdev_info(dev, |
282 | "=========>%s(): rtl92e_ips_leave\n", | |
285b7c00 | 283 | __func__); |
38bee763 | 284 | mutex_lock(&priv->rtllib->ips_mutex); |
2ab2aba2 | 285 | rtl92e_ips_leave(dev); |
38bee763 | 286 | mutex_unlock(&priv->rtllib->ips_mutex); |
94a79942 LF |
287 | } |
288 | } | |
289 | } | |
08d348a0 | 290 | ret = rtllib_wx_set_mode(priv->rtllib, a, wrqu, b); |
94a79942 | 291 | |
3044975f | 292 | mutex_unlock(&priv->wx_mutex); |
94a79942 LF |
293 | return ret; |
294 | } | |
295 | ||
08d348a0 LF |
296 | struct iw_range_with_scan_capa { |
297 | /* Informative stuff (to choose between different interface) */ | |
298 | __u32 throughput; /* To give an idea... */ | |
299 | /* In theory this value should be the maximum benchmarked | |
300 | * TCP/IP throughput, because with most of these devices the | |
301 | * bit rate is meaningless (overhead an co) to estimate how | |
302 | * fast the connection will go and pick the fastest one. | |
303 | * I suggest people to play with Netperf or any benchmark... | |
304 | */ | |
305 | ||
306 | /* NWID (or domain id) */ | |
307 | __u32 min_nwid; /* Minimal NWID we are able to set */ | |
308 | __u32 max_nwid; /* Maximal NWID we are able to set */ | |
309 | ||
310 | /* Old Frequency (backward compat - moved lower ) */ | |
311 | __u16 old_num_channels; | |
312 | __u8 old_num_frequency; | |
313 | ||
314 | /* Scan capabilities */ | |
315 | __u8 scan_capa; | |
94a79942 LF |
316 | }; |
317 | ||
a1252b09 | 318 | static int _rtl92e_wx_get_range(struct net_device *dev, |
94a79942 LF |
319 | struct iw_request_info *info, |
320 | union iwreq_data *wrqu, char *extra) | |
321 | { | |
322 | struct iw_range *range = (struct iw_range *)extra; | |
323 | struct r8192_priv *priv = rtllib_priv(dev); | |
324 | u16 val; | |
325 | int i; | |
326 | ||
327 | wrqu->data.length = sizeof(*range); | |
328 | memset(range, 0, sizeof(*range)); | |
329 | ||
330 | /* ~130 Mb/s real (802.11n) */ | |
331 | range->throughput = 130 * 1000 * 1000; | |
332 | ||
e1b32e1e | 333 | if (priv->rf_set_sens != NULL) |
08d348a0 LF |
334 | /* signal level threshold range */ |
335 | range->sensitivity = priv->max_sens; | |
94a79942 LF |
336 | |
337 | range->max_qual.qual = 100; | |
338 | range->max_qual.level = 0; | |
339 | range->max_qual.noise = 0; | |
340 | range->max_qual.updated = 7; /* Updated all three */ | |
341 | ||
342 | range->avg_qual.qual = 70; /* > 8% missed beacons is 'bad' */ | |
343 | range->avg_qual.level = 0; | |
344 | range->avg_qual.noise = 0; | |
345 | range->avg_qual.updated = 7; /* Updated all three */ | |
346 | ||
347 | range->num_bitrates = min(RATE_COUNT, IW_MAX_BITRATES); | |
348 | ||
08d348a0 | 349 | for (i = 0; i < range->num_bitrates; i++) |
94a79942 | 350 | range->bitrate[i] = rtl8192_rates[i]; |
94a79942 LF |
351 | |
352 | range->max_rts = DEFAULT_RTS_THRESHOLD; | |
353 | range->min_frag = MIN_FRAG_THRESHOLD; | |
354 | range->max_frag = MAX_FRAG_THRESHOLD; | |
355 | ||
356 | range->min_pmp = 0; | |
357 | range->max_pmp = 5000000; | |
358 | range->min_pmt = 0; | |
359 | range->max_pmt = 65535*1000; | |
360 | range->pmp_flags = IW_POWER_PERIOD; | |
361 | range->pmt_flags = IW_POWER_TIMEOUT; | |
362 | range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R; | |
363 | range->we_version_compiled = WIRELESS_EXT; | |
364 | range->we_version_source = 18; | |
365 | ||
366 | for (i = 0, val = 0; i < 14; i++) { | |
367 | if ((priv->rtllib->active_channel_map)[i+1]) { | |
08d348a0 LF |
368 | range->freq[val].i = i + 1; |
369 | range->freq[val].m = rtllib_wlan_frequencies[i] * | |
370 | 100000; | |
94a79942 LF |
371 | range->freq[val].e = 1; |
372 | val++; | |
94a79942 LF |
373 | } |
374 | ||
375 | if (val == IW_MAX_FREQUENCIES) | |
08d348a0 | 376 | break; |
94a79942 LF |
377 | } |
378 | range->num_frequency = val; | |
379 | range->num_channels = val; | |
94a79942 LF |
380 | range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2| |
381 | IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP; | |
94a79942 LF |
382 | range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE; |
383 | ||
08d348a0 | 384 | /* Event capability (kernel + driver) */ |
94a79942 LF |
385 | |
386 | return 0; | |
387 | } | |
388 | ||
fe13d010 MK |
389 | static int _rtl92e_wx_set_scan(struct net_device *dev, |
390 | struct iw_request_info *a, | |
391 | union iwreq_data *wrqu, char *b) | |
94a79942 LF |
392 | { |
393 | struct r8192_priv *priv = rtllib_priv(dev); | |
08d348a0 | 394 | struct rtllib_device *ieee = priv->rtllib; |
de7c885a | 395 | enum rt_rf_power_state rtState; |
94a79942 LF |
396 | int ret; |
397 | ||
08d348a0 LF |
398 | if (!(ieee->softmac_features & IEEE_SOFTMAC_SCAN)) { |
399 | if ((ieee->state >= RTLLIB_ASSOCIATING) && | |
400 | (ieee->state <= RTLLIB_ASSOCIATING_AUTHENTICATED)) | |
94a79942 | 401 | return 0; |
08d348a0 LF |
402 | if ((priv->rtllib->state == RTLLIB_LINKED) && |
403 | (priv->rtllib->CntAfterLink < 2)) | |
94a79942 | 404 | return 0; |
94a79942 LF |
405 | } |
406 | ||
44acc6b5 | 407 | if (priv->bHwRadioOff) { |
d69d2054 MK |
408 | netdev_info(dev, "================>%s(): hwradio off\n", |
409 | __func__); | |
94a79942 LF |
410 | return 0; |
411 | } | |
412 | rtState = priv->rtllib->eRFPowerState; | |
08d348a0 LF |
413 | if (!priv->up) |
414 | return -ENETDOWN; | |
94a79942 LF |
415 | if (priv->rtllib->LinkDetectInfo.bBusyTraffic == true) |
416 | return -EAGAIN; | |
417 | ||
08d348a0 LF |
418 | if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { |
419 | struct iw_scan_req *req = (struct iw_scan_req *)b; | |
3a6b70c3 | 420 | |
08d348a0 | 421 | if (req->essid_len) { |
94a79942 | 422 | ieee->current_network.ssid_len = req->essid_len; |
08d348a0 LF |
423 | memcpy(ieee->current_network.ssid, req->essid, |
424 | req->essid_len); | |
94a79942 LF |
425 | } |
426 | } | |
94a79942 | 427 | |
3044975f | 428 | mutex_lock(&priv->wx_mutex); |
94a79942 LF |
429 | |
430 | priv->rtllib->FirstIe_InScan = true; | |
431 | ||
08d348a0 LF |
432 | if (priv->rtllib->state != RTLLIB_LINKED) { |
433 | if (priv->rtllib->PowerSaveControl.bInactivePs) { | |
434 | if (rtState == eRfOff) { | |
435 | if (priv->rtllib->RfOffReason > | |
436 | RF_CHANGE_BY_IPS) { | |
3b4140af MK |
437 | netdev_warn(dev, "%s(): RF is OFF.\n", |
438 | __func__); | |
3044975f | 439 | mutex_unlock(&priv->wx_mutex); |
94a79942 | 440 | return -1; |
94a79942 | 441 | } |
2ab2aba2 MK |
442 | RT_TRACE(COMP_PS, |
443 | "=========>%s(): rtl92e_ips_leave\n", | |
285b7c00 | 444 | __func__); |
38bee763 | 445 | mutex_lock(&priv->rtllib->ips_mutex); |
2ab2aba2 | 446 | rtl92e_ips_leave(dev); |
38bee763 | 447 | mutex_unlock(&priv->rtllib->ips_mutex); |
94a79942 LF |
448 | } |
449 | } | |
450 | rtllib_stop_scan(priv->rtllib); | |
451 | if (priv->rtllib->LedControlHandler) | |
08d348a0 LF |
452 | priv->rtllib->LedControlHandler(dev, |
453 | LED_CTL_SITE_SURVEY); | |
94a79942 | 454 | |
08d348a0 | 455 | if (priv->rtllib->eRFPowerState != eRfOff) { |
94a79942 LF |
456 | priv->rtllib->actscanning = true; |
457 | ||
458 | if (ieee->ScanOperationBackupHandler) | |
08d348a0 LF |
459 | ieee->ScanOperationBackupHandler(ieee->dev, |
460 | SCAN_OPT_BACKUP); | |
94a79942 LF |
461 | |
462 | rtllib_start_scan_syncro(priv->rtllib, 0); | |
463 | ||
464 | if (ieee->ScanOperationBackupHandler) | |
08d348a0 LF |
465 | ieee->ScanOperationBackupHandler(ieee->dev, |
466 | SCAN_OPT_RESTORE); | |
467 | } | |
94a79942 LF |
468 | ret = 0; |
469 | } else { | |
470 | priv->rtllib->actscanning = true; | |
08d348a0 | 471 | ret = rtllib_wx_set_scan(priv->rtllib, a, wrqu, b); |
94a79942 LF |
472 | } |
473 | ||
3044975f | 474 | mutex_unlock(&priv->wx_mutex); |
94a79942 LF |
475 | return ret; |
476 | } | |
477 | ||
478 | ||
4d7b35c7 MK |
479 | static int _rtl92e_wx_get_scan(struct net_device *dev, |
480 | struct iw_request_info *a, | |
481 | union iwreq_data *wrqu, char *b) | |
94a79942 LF |
482 | { |
483 | ||
484 | int ret; | |
485 | struct r8192_priv *priv = rtllib_priv(dev); | |
486 | ||
08d348a0 LF |
487 | if (!priv->up) |
488 | return -ENETDOWN; | |
94a79942 | 489 | |
44acc6b5 | 490 | if (priv->bHwRadioOff) |
94a79942 LF |
491 | return 0; |
492 | ||
493 | ||
3044975f | 494 | mutex_lock(&priv->wx_mutex); |
94a79942 | 495 | |
08d348a0 | 496 | ret = rtllib_wx_get_scan(priv->rtllib, a, wrqu, b); |
94a79942 | 497 | |
3044975f | 498 | mutex_unlock(&priv->wx_mutex); |
94a79942 LF |
499 | |
500 | return ret; | |
501 | } | |
502 | ||
03550af0 MK |
503 | static int _rtl92e_wx_set_essid(struct net_device *dev, |
504 | struct iw_request_info *a, | |
505 | union iwreq_data *wrqu, char *b) | |
94a79942 LF |
506 | { |
507 | struct r8192_priv *priv = rtllib_priv(dev); | |
508 | int ret; | |
509 | ||
44acc6b5 | 510 | if (priv->bHwRadioOff) { |
d69d2054 MK |
511 | netdev_info(dev, |
512 | "=========>%s():hw radio off,or Rf state is eRfOff, return\n", | |
513 | __func__); | |
94a79942 LF |
514 | return 0; |
515 | } | |
3044975f | 516 | mutex_lock(&priv->wx_mutex); |
08d348a0 | 517 | ret = rtllib_wx_set_essid(priv->rtllib, a, wrqu, b); |
94a79942 | 518 | |
3044975f | 519 | mutex_unlock(&priv->wx_mutex); |
94a79942 LF |
520 | |
521 | return ret; | |
522 | } | |
523 | ||
c630d42a MK |
524 | static int _rtl92e_wx_get_essid(struct net_device *dev, |
525 | struct iw_request_info *a, | |
526 | union iwreq_data *wrqu, char *b) | |
94a79942 LF |
527 | { |
528 | int ret; | |
529 | struct r8192_priv *priv = rtllib_priv(dev); | |
530 | ||
3044975f | 531 | mutex_lock(&priv->wx_mutex); |
94a79942 LF |
532 | |
533 | ret = rtllib_wx_get_essid(priv->rtllib, a, wrqu, b); | |
534 | ||
3044975f | 535 | mutex_unlock(&priv->wx_mutex); |
94a79942 LF |
536 | |
537 | return ret; | |
538 | } | |
539 | ||
06a0b5c2 MK |
540 | static int _rtl92e_wx_set_nick(struct net_device *dev, |
541 | struct iw_request_info *info, | |
542 | union iwreq_data *wrqu, char *extra) | |
94a79942 LF |
543 | { |
544 | struct r8192_priv *priv = rtllib_priv(dev); | |
545 | ||
546 | if (wrqu->data.length > IW_ESSID_MAX_SIZE) | |
547 | return -E2BIG; | |
3044975f | 548 | mutex_lock(&priv->wx_mutex); |
35e33b04 MK |
549 | wrqu->data.length = min_t(size_t, wrqu->data.length, |
550 | sizeof(priv->nick)); | |
94a79942 LF |
551 | memset(priv->nick, 0, sizeof(priv->nick)); |
552 | memcpy(priv->nick, extra, wrqu->data.length); | |
3044975f | 553 | mutex_unlock(&priv->wx_mutex); |
94a79942 LF |
554 | return 0; |
555 | ||
556 | } | |
557 | ||
1341a077 MK |
558 | static int _rtl92e_wx_get_nick(struct net_device *dev, |
559 | struct iw_request_info *info, | |
560 | union iwreq_data *wrqu, char *extra) | |
94a79942 LF |
561 | { |
562 | struct r8192_priv *priv = rtllib_priv(dev); | |
563 | ||
3044975f | 564 | mutex_lock(&priv->wx_mutex); |
94a79942 LF |
565 | wrqu->data.length = strlen(priv->nick); |
566 | memcpy(extra, priv->nick, wrqu->data.length); | |
567 | wrqu->data.flags = 1; /* active */ | |
3044975f | 568 | mutex_unlock(&priv->wx_mutex); |
94a79942 LF |
569 | return 0; |
570 | } | |
571 | ||
a1f1c8b0 MK |
572 | static int _rtl92e_wx_set_freq(struct net_device *dev, |
573 | struct iw_request_info *a, | |
574 | union iwreq_data *wrqu, char *b) | |
94a79942 LF |
575 | { |
576 | int ret; | |
577 | struct r8192_priv *priv = rtllib_priv(dev); | |
578 | ||
44acc6b5 | 579 | if (priv->bHwRadioOff) |
94a79942 LF |
580 | return 0; |
581 | ||
3044975f | 582 | mutex_lock(&priv->wx_mutex); |
94a79942 LF |
583 | |
584 | ret = rtllib_wx_set_freq(priv->rtllib, a, wrqu, b); | |
585 | ||
3044975f | 586 | mutex_unlock(&priv->wx_mutex); |
94a79942 LF |
587 | return ret; |
588 | } | |
589 | ||
17bbe986 MK |
590 | static int _rtl92e_wx_get_name(struct net_device *dev, |
591 | struct iw_request_info *info, | |
592 | union iwreq_data *wrqu, char *extra) | |
94a79942 LF |
593 | { |
594 | struct r8192_priv *priv = rtllib_priv(dev); | |
3a6b70c3 | 595 | |
94a79942 LF |
596 | return rtllib_wx_get_name(priv->rtllib, info, wrqu, extra); |
597 | } | |
598 | ||
599 | ||
c9128ca2 MK |
600 | static int _rtl92e_wx_set_frag(struct net_device *dev, |
601 | struct iw_request_info *info, | |
602 | union iwreq_data *wrqu, char *extra) | |
94a79942 LF |
603 | { |
604 | struct r8192_priv *priv = rtllib_priv(dev); | |
605 | ||
44acc6b5 | 606 | if (priv->bHwRadioOff) |
94a79942 LF |
607 | return 0; |
608 | ||
609 | if (wrqu->frag.disabled) | |
610 | priv->rtllib->fts = DEFAULT_FRAG_THRESHOLD; | |
611 | else { | |
612 | if (wrqu->frag.value < MIN_FRAG_THRESHOLD || | |
613 | wrqu->frag.value > MAX_FRAG_THRESHOLD) | |
614 | return -EINVAL; | |
615 | ||
616 | priv->rtllib->fts = wrqu->frag.value & ~0x1; | |
617 | } | |
618 | ||
619 | return 0; | |
620 | } | |
621 | ||
622 | ||
bd2213da MK |
623 | static int _rtl92e_wx_get_frag(struct net_device *dev, |
624 | struct iw_request_info *info, | |
625 | union iwreq_data *wrqu, char *extra) | |
94a79942 LF |
626 | { |
627 | struct r8192_priv *priv = rtllib_priv(dev); | |
628 | ||
629 | wrqu->frag.value = priv->rtllib->fts; | |
630 | wrqu->frag.fixed = 0; /* no auto select */ | |
631 | wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD); | |
632 | ||
633 | return 0; | |
634 | } | |
635 | ||
636 | ||
291bf50d MK |
637 | static int _rtl92e_wx_set_wap(struct net_device *dev, |
638 | struct iw_request_info *info, | |
639 | union iwreq_data *awrq, char *extra) | |
94a79942 | 640 | { |
94a79942 LF |
641 | int ret; |
642 | struct r8192_priv *priv = rtllib_priv(dev); | |
643 | ||
44acc6b5 | 644 | if (priv->bHwRadioOff) |
94a79942 LF |
645 | return 0; |
646 | ||
3044975f | 647 | mutex_lock(&priv->wx_mutex); |
94a79942 | 648 | |
08d348a0 | 649 | ret = rtllib_wx_set_wap(priv->rtllib, info, awrq, extra); |
94a79942 | 650 | |
3044975f | 651 | mutex_unlock(&priv->wx_mutex); |
94a79942 LF |
652 | |
653 | return ret; | |
654 | ||
655 | } | |
656 | ||
657 | ||
7cd40ae4 MK |
658 | static int _rtl92e_wx_get_wap(struct net_device *dev, |
659 | struct iw_request_info *info, | |
660 | union iwreq_data *wrqu, char *extra) | |
94a79942 LF |
661 | { |
662 | struct r8192_priv *priv = rtllib_priv(dev); | |
663 | ||
08d348a0 | 664 | return rtllib_wx_get_wap(priv->rtllib, info, wrqu, extra); |
94a79942 LF |
665 | } |
666 | ||
667 | ||
00496b54 MK |
668 | static int _rtl92e_wx_get_enc(struct net_device *dev, |
669 | struct iw_request_info *info, | |
670 | union iwreq_data *wrqu, char *key) | |
94a79942 LF |
671 | { |
672 | struct r8192_priv *priv = rtllib_priv(dev); | |
673 | ||
674 | return rtllib_wx_get_encode(priv->rtllib, info, wrqu, key); | |
675 | } | |
676 | ||
57aac1ce MK |
677 | static int _rtl92e_wx_set_enc(struct net_device *dev, |
678 | struct iw_request_info *info, | |
679 | union iwreq_data *wrqu, char *key) | |
94a79942 LF |
680 | { |
681 | struct r8192_priv *priv = rtllib_priv(dev); | |
682 | int ret; | |
683 | ||
684 | struct rtllib_device *ieee = priv->rtllib; | |
08d348a0 LF |
685 | u32 hwkey[4] = {0, 0, 0, 0}; |
686 | u8 mask = 0xff; | |
687 | u32 key_idx = 0; | |
688 | u8 zero_addr[4][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, | |
689 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, | |
690 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, | |
691 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} }; | |
94a79942 LF |
692 | int i; |
693 | ||
44acc6b5 | 694 | if (priv->bHwRadioOff) |
94a79942 LF |
695 | return 0; |
696 | ||
08d348a0 LF |
697 | if (!priv->up) |
698 | return -ENETDOWN; | |
94a79942 | 699 | |
08d348a0 | 700 | priv->rtllib->wx_set_enc = 1; |
38bee763 | 701 | mutex_lock(&priv->rtllib->ips_mutex); |
2ab2aba2 | 702 | rtl92e_ips_leave(dev); |
38bee763 | 703 | mutex_unlock(&priv->rtllib->ips_mutex); |
3044975f | 704 | mutex_lock(&priv->wx_mutex); |
94a79942 LF |
705 | |
706 | RT_TRACE(COMP_SEC, "Setting SW wep key"); | |
08d348a0 | 707 | ret = rtllib_wx_set_encode(priv->rtllib, info, wrqu, key); |
3044975f | 708 | mutex_unlock(&priv->wx_mutex); |
94a79942 LF |
709 | |
710 | ||
711 | if (wrqu->encoding.flags & IW_ENCODE_DISABLED) { | |
712 | ieee->pairwise_key_type = ieee->group_key_type = KEY_TYPE_NA; | |
358e4ee1 | 713 | rtl92e_cam_reset(dev); |
08d348a0 LF |
714 | memset(priv->rtllib->swcamtable, 0, |
715 | sizeof(struct sw_cam_table) * 32); | |
94a79942 LF |
716 | goto end_hw_sec; |
717 | } | |
08d348a0 | 718 | if (wrqu->encoding.length != 0) { |
94a79942 | 719 | |
08d348a0 | 720 | for (i = 0; i < 4; i++) { |
94a79942 | 721 | hwkey[i] |= key[4*i+0]&mask; |
08d348a0 LF |
722 | if (i == 1 && (4 * i + 1) == wrqu->encoding.length) |
723 | mask = 0x00; | |
724 | if (i == 3 && (4 * i + 1) == wrqu->encoding.length) | |
725 | mask = 0x00; | |
726 | hwkey[i] |= (key[4 * i + 1] & mask) << 8; | |
727 | hwkey[i] |= (key[4 * i + 2] & mask) << 16; | |
728 | hwkey[i] |= (key[4 * i + 3] & mask) << 24; | |
94a79942 LF |
729 | } |
730 | ||
08d348a0 LF |
731 | switch (wrqu->encoding.flags & IW_ENCODE_INDEX) { |
732 | case 0: | |
0ddcf5fd | 733 | key_idx = ieee->crypt_info.tx_keyidx; |
08d348a0 LF |
734 | break; |
735 | case 1: | |
736 | key_idx = 0; | |
737 | break; | |
738 | case 2: | |
739 | key_idx = 1; | |
740 | break; | |
741 | case 3: | |
742 | key_idx = 2; | |
743 | break; | |
744 | case 4: | |
745 | key_idx = 3; | |
746 | break; | |
747 | default: | |
748 | break; | |
94a79942 | 749 | } |
08d348a0 | 750 | if (wrqu->encoding.length == 0x5) { |
94a79942 | 751 | ieee->pairwise_key_type = KEY_TYPE_WEP40; |
37420932 | 752 | rtl92e_enable_hw_security_config(dev); |
94a79942 LF |
753 | } |
754 | ||
08d348a0 | 755 | else if (wrqu->encoding.length == 0xd) { |
94a79942 | 756 | ieee->pairwise_key_type = KEY_TYPE_WEP104; |
37420932 | 757 | rtl92e_enable_hw_security_config(dev); |
408bd7b7 MK |
758 | rtl92e_set_key(dev, key_idx, key_idx, KEY_TYPE_WEP104, |
759 | zero_addr[key_idx], 0, hwkey); | |
aae7e72e MK |
760 | rtl92e_set_swcam(dev, key_idx, key_idx, KEY_TYPE_WEP104, |
761 | zero_addr[key_idx], 0, hwkey, 0); | |
94a79942 | 762 | } else { |
d69d2054 MK |
763 | netdev_info(dev, |
764 | "wrong type in WEP, not WEP40 and WEP104\n"); | |
94a79942 LF |
765 | } |
766 | } | |
767 | ||
768 | end_hw_sec: | |
769 | priv->rtllib->wx_set_enc = 0; | |
770 | return ret; | |
771 | } | |
772 | ||
11f24fd1 MK |
773 | static int _rtl92e_wx_set_scan_type(struct net_device *dev, |
774 | struct iw_request_info *aa, | |
775 | union iwreq_data *wrqu, char *p) | |
08d348a0 | 776 | { |
94a79942 | 777 | struct r8192_priv *priv = rtllib_priv(dev); |
08d348a0 LF |
778 | int *parms = (int *)p; |
779 | int mode = parms[0]; | |
94a79942 | 780 | |
44acc6b5 | 781 | if (priv->bHwRadioOff) |
94a79942 LF |
782 | return 0; |
783 | ||
784 | priv->rtllib->active_scan = mode; | |
785 | ||
786 | return 1; | |
787 | } | |
788 | ||
789 | ||
790 | ||
791 | #define R8192_MAX_RETRY 255 | |
f761ee68 | 792 | static int _rtl92e_wx_set_retry(struct net_device *dev, |
94a79942 LF |
793 | struct iw_request_info *info, |
794 | union iwreq_data *wrqu, char *extra) | |
795 | { | |
796 | struct r8192_priv *priv = rtllib_priv(dev); | |
797 | int err = 0; | |
798 | ||
44acc6b5 | 799 | if (priv->bHwRadioOff) |
94a79942 LF |
800 | return 0; |
801 | ||
3044975f | 802 | mutex_lock(&priv->wx_mutex); |
94a79942 LF |
803 | |
804 | if (wrqu->retry.flags & IW_RETRY_LIFETIME || | |
08d348a0 | 805 | wrqu->retry.disabled) { |
94a79942 LF |
806 | err = -EINVAL; |
807 | goto exit; | |
808 | } | |
08d348a0 | 809 | if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) { |
94a79942 LF |
810 | err = -EINVAL; |
811 | goto exit; | |
812 | } | |
813 | ||
08d348a0 LF |
814 | if (wrqu->retry.value > R8192_MAX_RETRY) { |
815 | err = -EINVAL; | |
94a79942 LF |
816 | goto exit; |
817 | } | |
a2e681fa | 818 | if (wrqu->retry.flags & IW_RETRY_MAX) |
94a79942 | 819 | priv->retry_rts = wrqu->retry.value; |
a2e681fa | 820 | else |
94a79942 | 821 | priv->retry_data = wrqu->retry.value; |
94a79942 | 822 | |
bc4f2cc9 | 823 | rtl92e_commit(dev); |
94a79942 | 824 | exit: |
3044975f | 825 | mutex_unlock(&priv->wx_mutex); |
94a79942 LF |
826 | |
827 | return err; | |
828 | } | |
829 | ||
e0c21945 | 830 | static int _rtl92e_wx_get_retry(struct net_device *dev, |
94a79942 LF |
831 | struct iw_request_info *info, |
832 | union iwreq_data *wrqu, char *extra) | |
833 | { | |
834 | struct r8192_priv *priv = rtllib_priv(dev); | |
835 | ||
836 | ||
837 | wrqu->retry.disabled = 0; /* can't be disabled */ | |
838 | ||
839 | if ((wrqu->retry.flags & IW_RETRY_TYPE) == | |
840 | IW_RETRY_LIFETIME) | |
841 | return -EINVAL; | |
842 | ||
843 | if (wrqu->retry.flags & IW_RETRY_MAX) { | |
6fe86440 | 844 | wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX; |
94a79942 LF |
845 | wrqu->retry.value = priv->retry_rts; |
846 | } else { | |
6fe86440 | 847 | wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN; |
94a79942 LF |
848 | wrqu->retry.value = priv->retry_data; |
849 | } | |
94a79942 LF |
850 | return 0; |
851 | } | |
852 | ||
fbeb3594 MK |
853 | static int _rtl92e_wx_get_sens(struct net_device *dev, |
854 | struct iw_request_info *info, | |
855 | union iwreq_data *wrqu, char *extra) | |
94a79942 LF |
856 | { |
857 | struct r8192_priv *priv = rtllib_priv(dev); | |
3a6b70c3 | 858 | |
94a79942 LF |
859 | if (priv->rf_set_sens == NULL) |
860 | return -1; /* we have not this support for this radio */ | |
861 | wrqu->sens.value = priv->sens; | |
862 | return 0; | |
863 | } | |
864 | ||
865 | ||
e7c82165 MK |
866 | static int _rtl92e_wx_set_sens(struct net_device *dev, |
867 | struct iw_request_info *info, | |
868 | union iwreq_data *wrqu, char *extra) | |
94a79942 LF |
869 | { |
870 | ||
871 | struct r8192_priv *priv = rtllib_priv(dev); | |
872 | ||
873 | short err = 0; | |
874 | ||
44acc6b5 | 875 | if (priv->bHwRadioOff) |
94a79942 LF |
876 | return 0; |
877 | ||
3044975f | 878 | mutex_lock(&priv->wx_mutex); |
94a79942 | 879 | if (priv->rf_set_sens == NULL) { |
08d348a0 | 880 | err = -1; /* we have not this support for this radio */ |
94a79942 LF |
881 | goto exit; |
882 | } | |
883 | if (priv->rf_set_sens(dev, wrqu->sens.value) == 0) | |
884 | priv->sens = wrqu->sens.value; | |
885 | else | |
08d348a0 | 886 | err = -EINVAL; |
94a79942 LF |
887 | |
888 | exit: | |
3044975f | 889 | mutex_unlock(&priv->wx_mutex); |
94a79942 LF |
890 | |
891 | return err; | |
892 | } | |
893 | ||
e197821f MK |
894 | static int _rtl92e_wx_set_encode_ext(struct net_device *dev, |
895 | struct iw_request_info *info, | |
896 | union iwreq_data *wrqu, char *extra) | |
94a79942 | 897 | { |
08d348a0 | 898 | int ret = 0; |
94a79942 | 899 | struct r8192_priv *priv = rtllib_priv(dev); |
08d348a0 | 900 | struct rtllib_device *ieee = priv->rtllib; |
94a79942 | 901 | |
44acc6b5 | 902 | if (priv->bHwRadioOff) |
94a79942 LF |
903 | return 0; |
904 | ||
3044975f | 905 | mutex_lock(&priv->wx_mutex); |
94a79942 | 906 | |
08d348a0 | 907 | priv->rtllib->wx_set_enc = 1; |
38bee763 | 908 | mutex_lock(&priv->rtllib->ips_mutex); |
2ab2aba2 | 909 | rtl92e_ips_leave(dev); |
38bee763 | 910 | mutex_unlock(&priv->rtllib->ips_mutex); |
94a79942 LF |
911 | |
912 | ret = rtllib_wx_set_encode_ext(ieee, info, wrqu, extra); | |
94a79942 | 913 | { |
06c11107 MK |
914 | const u8 broadcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
915 | const u8 zero[ETH_ALEN] = {0}; | |
94a79942 LF |
916 | u32 key[4] = {0}; |
917 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; | |
918 | struct iw_point *encoding = &wrqu->encoding; | |
919 | u8 idx = 0, alg = 0, group = 0; | |
3a6b70c3 | 920 | |
94a79942 | 921 | if ((encoding->flags & IW_ENCODE_DISABLED) || |
08d348a0 LF |
922 | ext->alg == IW_ENCODE_ALG_NONE) { |
923 | ieee->pairwise_key_type = ieee->group_key_type | |
924 | = KEY_TYPE_NA; | |
358e4ee1 | 925 | rtl92e_cam_reset(dev); |
08d348a0 LF |
926 | memset(priv->rtllib->swcamtable, 0, |
927 | sizeof(struct sw_cam_table) * 32); | |
94a79942 LF |
928 | goto end_hw_sec; |
929 | } | |
08d348a0 LF |
930 | alg = (ext->alg == IW_ENCODE_ALG_CCMP) ? KEY_TYPE_CCMP : |
931 | ext->alg; | |
94a79942 LF |
932 | idx = encoding->flags & IW_ENCODE_INDEX; |
933 | if (idx) | |
08d348a0 | 934 | idx--; |
94a79942 LF |
935 | group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY; |
936 | ||
4c29207a | 937 | if ((!group) || (ieee->iw_mode == IW_MODE_ADHOC) || |
08d348a0 LF |
938 | (alg == KEY_TYPE_WEP40)) { |
939 | if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40)) | |
94a79942 LF |
940 | alg = KEY_TYPE_WEP104; |
941 | ieee->pairwise_key_type = alg; | |
37420932 | 942 | rtl92e_enable_hw_security_config(dev); |
94a79942 | 943 | } |
08d348a0 | 944 | memcpy((u8 *)key, ext->key, 16); |
94a79942 | 945 | |
08d348a0 | 946 | if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode != 2)) { |
94a79942 LF |
947 | if (ext->key_len == 13) |
948 | ieee->pairwise_key_type = alg = KEY_TYPE_WEP104; | |
408bd7b7 | 949 | rtl92e_set_key(dev, idx, idx, alg, zero, 0, key); |
aae7e72e | 950 | rtl92e_set_swcam(dev, idx, idx, alg, zero, 0, key, 0); |
08d348a0 | 951 | } else if (group) { |
94a79942 | 952 | ieee->group_key_type = alg; |
408bd7b7 MK |
953 | rtl92e_set_key(dev, idx, idx, alg, broadcast_addr, 0, |
954 | key); | |
aae7e72e MK |
955 | rtl92e_set_swcam(dev, idx, idx, alg, broadcast_addr, 0, |
956 | key, 0); | |
08d348a0 LF |
957 | } else { |
958 | if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) && | |
959 | ieee->pHTInfo->bCurrentHTSupport) | |
d8ae1967 | 960 | rtl92e_writeb(dev, 0x173, 1); |
408bd7b7 MK |
961 | rtl92e_set_key(dev, 4, idx, alg, |
962 | (u8 *)ieee->ap_mac_addr, 0, key); | |
aae7e72e MK |
963 | rtl92e_set_swcam(dev, 4, idx, alg, |
964 | (u8 *)ieee->ap_mac_addr, 0, key, 0); | |
94a79942 LF |
965 | } |
966 | ||
967 | ||
968 | } | |
969 | ||
970 | end_hw_sec: | |
08d348a0 | 971 | priv->rtllib->wx_set_enc = 0; |
3044975f | 972 | mutex_unlock(&priv->wx_mutex); |
94a79942 LF |
973 | return ret; |
974 | ||
975 | } | |
99f1859f MK |
976 | |
977 | static int _rtl92e_wx_set_auth(struct net_device *dev, | |
978 | struct iw_request_info *info, | |
979 | union iwreq_data *data, char *extra) | |
94a79942 | 980 | { |
08d348a0 | 981 | int ret = 0; |
94a79942 LF |
982 | |
983 | struct r8192_priv *priv = rtllib_priv(dev); | |
984 | ||
44acc6b5 | 985 | if (priv->bHwRadioOff) |
94a79942 LF |
986 | return 0; |
987 | ||
3044975f | 988 | mutex_lock(&priv->wx_mutex); |
94a79942 | 989 | ret = rtllib_wx_set_auth(priv->rtllib, info, &(data->param), extra); |
3044975f | 990 | mutex_unlock(&priv->wx_mutex); |
94a79942 LF |
991 | return ret; |
992 | } | |
993 | ||
cdd105f8 MK |
994 | static int _rtl92e_wx_set_mlme(struct net_device *dev, |
995 | struct iw_request_info *info, | |
996 | union iwreq_data *wrqu, char *extra) | |
94a79942 LF |
997 | { |
998 | ||
08d348a0 | 999 | int ret = 0; |
94a79942 LF |
1000 | |
1001 | struct r8192_priv *priv = rtllib_priv(dev); | |
1002 | ||
44acc6b5 | 1003 | if (priv->bHwRadioOff) |
94a79942 LF |
1004 | return 0; |
1005 | ||
3044975f | 1006 | mutex_lock(&priv->wx_mutex); |
94a79942 | 1007 | ret = rtllib_wx_set_mlme(priv->rtllib, info, wrqu, extra); |
3044975f | 1008 | mutex_unlock(&priv->wx_mutex); |
94a79942 LF |
1009 | return ret; |
1010 | } | |
94a79942 | 1011 | |
49d650e7 MK |
1012 | static int _rtl92e_wx_set_gen_ie(struct net_device *dev, |
1013 | struct iw_request_info *info, | |
1014 | union iwreq_data *data, char *extra) | |
94a79942 LF |
1015 | { |
1016 | int ret = 0; | |
1017 | ||
08d348a0 | 1018 | struct r8192_priv *priv = rtllib_priv(dev); |
94a79942 | 1019 | |
44acc6b5 | 1020 | if (priv->bHwRadioOff) |
94a79942 LF |
1021 | return 0; |
1022 | ||
3044975f | 1023 | mutex_lock(&priv->wx_mutex); |
08d348a0 | 1024 | ret = rtllib_wx_set_gen_ie(priv->rtllib, extra, data->data.length); |
3044975f | 1025 | mutex_unlock(&priv->wx_mutex); |
08d348a0 | 1026 | return ret; |
94a79942 LF |
1027 | } |
1028 | ||
d343ed7f MK |
1029 | static int _rtl92e_wx_get_gen_ie(struct net_device *dev, |
1030 | struct iw_request_info *info, | |
1031 | union iwreq_data *data, char *extra) | |
94a79942 LF |
1032 | { |
1033 | int ret = 0; | |
08d348a0 LF |
1034 | struct r8192_priv *priv = rtllib_priv(dev); |
1035 | struct rtllib_device *ieee = priv->rtllib; | |
94a79942 LF |
1036 | |
1037 | if (ieee->wpa_ie_len == 0 || ieee->wpa_ie == NULL) { | |
1038 | data->data.length = 0; | |
1039 | return 0; | |
1040 | } | |
1041 | ||
08d348a0 | 1042 | if (data->data.length < ieee->wpa_ie_len) |
94a79942 | 1043 | return -E2BIG; |
94a79942 LF |
1044 | |
1045 | data->data.length = ieee->wpa_ie_len; | |
1046 | memcpy(extra, ieee->wpa_ie, ieee->wpa_ie_len); | |
08d348a0 | 1047 | return ret; |
94a79942 LF |
1048 | } |
1049 | ||
1050 | #define OID_RT_INTEL_PROMISCUOUS_MODE 0xFF0101F6 | |
1051 | ||
d987a158 MK |
1052 | static int _rtl92e_wx_set_promisc_mode(struct net_device *dev, |
1053 | struct iw_request_info *info, | |
1054 | union iwreq_data *wrqu, char *extra) | |
94a79942 LF |
1055 | { |
1056 | struct r8192_priv *priv = rtllib_priv(dev); | |
08d348a0 | 1057 | struct rtllib_device *ieee = priv->rtllib; |
94a79942 | 1058 | |
db4d7173 | 1059 | u32 info_buf[3]; |
94a79942 | 1060 | |
db4d7173 DB |
1061 | u32 oid; |
1062 | u32 bPromiscuousOn; | |
1063 | u32 bFilterSourceStationFrame; | |
1064 | ||
1065 | if (copy_from_user(info_buf, wrqu->data.pointer, sizeof(info_buf))) | |
1066 | return -EFAULT; | |
1067 | ||
1068 | oid = info_buf[0]; | |
1069 | bPromiscuousOn = info_buf[1]; | |
1070 | bFilterSourceStationFrame = info_buf[2]; | |
94a79942 | 1071 | |
4c29207a | 1072 | if (oid == OID_RT_INTEL_PROMISCUOUS_MODE) { |
94a79942 | 1073 | ieee->IntelPromiscuousModeInfo.bPromiscuousOn = |
08d348a0 | 1074 | (bPromiscuousOn) ? (true) : (false); |
94a79942 | 1075 | ieee->IntelPromiscuousModeInfo.bFilterSourceStationFrame = |
08d348a0 LF |
1076 | (bFilterSourceStationFrame) ? (true) : (false); |
1077 | (bPromiscuousOn) ? | |
1078 | (rtllib_EnableIntelPromiscuousMode(dev, false)) : | |
1079 | (rtllib_DisableIntelPromiscuousMode(dev, false)); | |
94a79942 | 1080 | |
d69d2054 MK |
1081 | netdev_info(dev, |
1082 | "=======>%s(), on = %d, filter src sta = %d\n", | |
1083 | __func__, bPromiscuousOn, | |
1084 | bFilterSourceStationFrame); | |
94a79942 LF |
1085 | } else { |
1086 | return -1; | |
1087 | } | |
1088 | ||
1089 | return 0; | |
1090 | } | |
1091 | ||
1092 | ||
e792cf88 MK |
1093 | static int _rtl92e_wx_get_promisc_mode(struct net_device *dev, |
1094 | struct iw_request_info *info, | |
1095 | union iwreq_data *wrqu, char *extra) | |
94a79942 LF |
1096 | { |
1097 | struct r8192_priv *priv = rtllib_priv(dev); | |
08d348a0 | 1098 | struct rtllib_device *ieee = priv->rtllib; |
94a79942 | 1099 | |
3044975f | 1100 | mutex_lock(&priv->wx_mutex); |
94a79942 | 1101 | |
08d348a0 LF |
1102 | snprintf(extra, 45, "PromiscuousMode:%d, FilterSrcSTAFrame:%d", |
1103 | ieee->IntelPromiscuousModeInfo.bPromiscuousOn, | |
1104 | ieee->IntelPromiscuousModeInfo.bFilterSourceStationFrame); | |
1105 | wrqu->data.length = strlen(extra) + 1; | |
94a79942 | 1106 | |
3044975f | 1107 | mutex_unlock(&priv->wx_mutex); |
94a79942 LF |
1108 | |
1109 | return 0; | |
1110 | } | |
1111 | ||
1112 | ||
976a06cc | 1113 | #define IW_IOCTL(x) ((x) - SIOCSIWCOMMIT) |
08d348a0 | 1114 | static iw_handler r8192_wx_handlers[] = { |
17bbe986 | 1115 | [IW_IOCTL(SIOCGIWNAME)] = _rtl92e_wx_get_name, |
a1f1c8b0 | 1116 | [IW_IOCTL(SIOCSIWFREQ)] = _rtl92e_wx_set_freq, |
d1bae81a | 1117 | [IW_IOCTL(SIOCGIWFREQ)] = _rtl92e_wx_get_freq, |
89528d6c | 1118 | [IW_IOCTL(SIOCSIWMODE)] = _rtl92e_wx_set_mode, |
062cd9b4 | 1119 | [IW_IOCTL(SIOCGIWMODE)] = _rtl92e_wx_get_mode, |
e7c82165 | 1120 | [IW_IOCTL(SIOCSIWSENS)] = _rtl92e_wx_set_sens, |
fbeb3594 | 1121 | [IW_IOCTL(SIOCGIWSENS)] = _rtl92e_wx_get_sens, |
a1252b09 | 1122 | [IW_IOCTL(SIOCGIWRANGE)] = _rtl92e_wx_get_range, |
291bf50d | 1123 | [IW_IOCTL(SIOCSIWAP)] = _rtl92e_wx_set_wap, |
7cd40ae4 | 1124 | [IW_IOCTL(SIOCGIWAP)] = _rtl92e_wx_get_wap, |
fe13d010 | 1125 | [IW_IOCTL(SIOCSIWSCAN)] = _rtl92e_wx_set_scan, |
4d7b35c7 | 1126 | [IW_IOCTL(SIOCGIWSCAN)] = _rtl92e_wx_get_scan, |
03550af0 | 1127 | [IW_IOCTL(SIOCSIWESSID)] = _rtl92e_wx_set_essid, |
c630d42a | 1128 | [IW_IOCTL(SIOCGIWESSID)] = _rtl92e_wx_get_essid, |
06a0b5c2 | 1129 | [IW_IOCTL(SIOCSIWNICKN)] = _rtl92e_wx_set_nick, |
1341a077 | 1130 | [IW_IOCTL(SIOCGIWNICKN)] = _rtl92e_wx_get_nick, |
ad6a5412 | 1131 | [IW_IOCTL(SIOCSIWRATE)] = _rtl92e_wx_set_rate, |
5be1e1ff | 1132 | [IW_IOCTL(SIOCGIWRATE)] = _rtl92e_wx_get_rate, |
c90ee2fc | 1133 | [IW_IOCTL(SIOCSIWRTS)] = _rtl92e_wx_set_rts, |
e19794b1 | 1134 | [IW_IOCTL(SIOCGIWRTS)] = _rtl92e_wx_get_rts, |
c9128ca2 | 1135 | [IW_IOCTL(SIOCSIWFRAG)] = _rtl92e_wx_set_frag, |
bd2213da | 1136 | [IW_IOCTL(SIOCGIWFRAG)] = _rtl92e_wx_get_frag, |
f761ee68 | 1137 | [IW_IOCTL(SIOCSIWRETRY)] = _rtl92e_wx_set_retry, |
e0c21945 | 1138 | [IW_IOCTL(SIOCGIWRETRY)] = _rtl92e_wx_get_retry, |
57aac1ce | 1139 | [IW_IOCTL(SIOCSIWENCODE)] = _rtl92e_wx_set_enc, |
00496b54 | 1140 | [IW_IOCTL(SIOCGIWENCODE)] = _rtl92e_wx_get_enc, |
f2e90185 | 1141 | [IW_IOCTL(SIOCSIWPOWER)] = _rtl92e_wx_set_power, |
b821768a | 1142 | [IW_IOCTL(SIOCGIWPOWER)] = _rtl92e_wx_get_power, |
49d650e7 | 1143 | [IW_IOCTL(SIOCSIWGENIE)] = _rtl92e_wx_set_gen_ie, |
d343ed7f | 1144 | [IW_IOCTL(SIOCGIWGENIE)] = _rtl92e_wx_get_gen_ie, |
cdd105f8 | 1145 | [IW_IOCTL(SIOCSIWMLME)] = _rtl92e_wx_set_mlme, |
99f1859f | 1146 | [IW_IOCTL(SIOCSIWAUTH)] = _rtl92e_wx_set_auth, |
e197821f | 1147 | [IW_IOCTL(SIOCSIWENCODEEXT)] = _rtl92e_wx_set_encode_ext, |
94a79942 LF |
1148 | }; |
1149 | ||
14b40d92 | 1150 | /* the following rule need to be following, |
94a79942 LF |
1151 | * Odd : get (world access), |
1152 | * even : set (root access) | |
14b40d92 | 1153 | */ |
94a79942 LF |
1154 | static const struct iw_priv_args r8192_private_args[] = { |
1155 | { | |
1156 | SIOCIWFIRSTPRIV + 0x0, | |
1157 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_debugflag" | |
08d348a0 | 1158 | }, { |
94a79942 LF |
1159 | SIOCIWFIRSTPRIV + 0x1, |
1160 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan" | |
08d348a0 | 1161 | }, { |
94a79942 LF |
1162 | SIOCIWFIRSTPRIV + 0x2, |
1163 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx" | |
08d348a0 | 1164 | }, { |
94a79942 LF |
1165 | SIOCIWFIRSTPRIV + 0x3, |
1166 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset" | |
08d348a0 | 1167 | }, { |
94a79942 LF |
1168 | SIOCIWFIRSTPRIV + 0x6, |
1169 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE, | |
1170 | "set_power" | |
08d348a0 | 1171 | }, { |
94a79942 LF |
1172 | SIOCIWFIRSTPRIV + 0xa, |
1173 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE, | |
1174 | "lps_interv" | |
08d348a0 | 1175 | }, { |
94a79942 LF |
1176 | SIOCIWFIRSTPRIV + 0xb, |
1177 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE, | |
1178 | "lps_force" | |
08d348a0 | 1179 | }, { |
94a79942 | 1180 | SIOCIWFIRSTPRIV + 0x16, |
08d348a0 LF |
1181 | IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "setpromisc" |
1182 | }, { | |
94a79942 | 1183 | SIOCIWFIRSTPRIV + 0x17, |
08d348a0 | 1184 | 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 45, "getpromisc" |
94a79942 LF |
1185 | } |
1186 | ||
1187 | }; | |
1188 | ||
1189 | static iw_handler r8192_private_handler[] = { | |
d373a0ce | 1190 | (iw_handler)_rtl92e_wx_set_debug, /*SIOCIWSECONDPRIV*/ |
11f24fd1 | 1191 | (iw_handler)_rtl92e_wx_set_scan_type, |
31183234 | 1192 | (iw_handler)_rtl92e_wx_set_rawtx, |
042f05eb | 1193 | (iw_handler)_rtl92e_wx_force_reset, |
0beee3ba MK |
1194 | (iw_handler)NULL, |
1195 | (iw_handler)NULL, | |
ac9e5e73 | 1196 | (iw_handler)_rtl92e_wx_adapter_power_status, |
94a79942 LF |
1197 | (iw_handler)NULL, |
1198 | (iw_handler)NULL, | |
0beee3ba | 1199 | (iw_handler)NULL, |
0a263fcf | 1200 | (iw_handler)_rtl92e_wx_set_lps_awake_interval, |
84e4dc10 | 1201 | (iw_handler)_rtl92e_wx_set_force_lps, |
0beee3ba | 1202 | (iw_handler)NULL, |
94a79942 | 1203 | (iw_handler)NULL, |
94a79942 LF |
1204 | (iw_handler)NULL, |
1205 | (iw_handler)NULL, | |
1206 | (iw_handler)NULL, | |
1207 | (iw_handler)NULL, | |
1208 | (iw_handler)NULL, | |
1209 | (iw_handler)NULL, | |
1210 | (iw_handler)NULL, | |
1211 | (iw_handler)NULL, | |
d987a158 | 1212 | (iw_handler)_rtl92e_wx_set_promisc_mode, |
e792cf88 | 1213 | (iw_handler)_rtl92e_wx_get_promisc_mode, |
94a79942 LF |
1214 | }; |
1215 | ||
e830e0dc | 1216 | static struct iw_statistics *_rtl92e_get_wireless_stats(struct net_device *dev) |
94a79942 | 1217 | { |
08d348a0 LF |
1218 | struct r8192_priv *priv = rtllib_priv(dev); |
1219 | struct rtllib_device *ieee = priv->rtllib; | |
1220 | struct iw_statistics *wstats = &priv->wstats; | |
94a79942 LF |
1221 | int tmp_level = 0; |
1222 | int tmp_qual = 0; | |
1223 | int tmp_noise = 0; | |
3a6b70c3 | 1224 | |
08d348a0 | 1225 | if (ieee->state < RTLLIB_LINKED) { |
94a79942 LF |
1226 | wstats->qual.qual = 10; |
1227 | wstats->qual.level = 0; | |
86dc65b3 | 1228 | wstats->qual.noise = 0x100 - 100; /* -100 dBm */ |
94a79942 LF |
1229 | wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; |
1230 | return wstats; | |
1231 | } | |
1232 | ||
08d348a0 | 1233 | tmp_level = (&ieee->current_network)->stats.rssi; |
94a79942 LF |
1234 | tmp_qual = (&ieee->current_network)->stats.signal; |
1235 | tmp_noise = (&ieee->current_network)->stats.noise; | |
1236 | ||
1237 | wstats->qual.level = tmp_level; | |
1238 | wstats->qual.qual = tmp_qual; | |
1239 | wstats->qual.noise = tmp_noise; | |
1240 | wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; | |
1241 | return wstats; | |
1242 | } | |
1243 | ||
5169af23 | 1244 | const struct iw_handler_def r8192_wx_handlers_def = { |
94a79942 | 1245 | .standard = r8192_wx_handlers, |
b330f606 | 1246 | .num_standard = ARRAY_SIZE(r8192_wx_handlers), |
94a79942 | 1247 | .private = r8192_private_handler, |
b330f606 | 1248 | .num_private = ARRAY_SIZE(r8192_private_handler), |
08d348a0 LF |
1249 | .num_private_args = sizeof(r8192_private_args) / |
1250 | sizeof(struct iw_priv_args), | |
e830e0dc | 1251 | .get_wireless_stats = _rtl92e_get_wireless_stats, |
94a79942 LF |
1252 | .private_args = (struct iw_priv_args *)r8192_private_args, |
1253 | }; |