Fix common misspellings
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / ath6kl / os / linux / wireless_ext.c
CommitLineData
30295c89
VM
1//------------------------------------------------------------------------------
2// Copyright (c) 2004-2010 Atheros Communications Inc.
3// All rights reserved.
4//
5//
6//
7// Permission to use, copy, modify, and/or distribute this software for any
8// purpose with or without fee is hereby granted, provided that the above
9// copyright notice and this permission notice appear in all copies.
10//
11// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18//
19//
20//
21// Author(s): ="Atheros"
22//------------------------------------------------------------------------------
23
24#include "ar6000_drv.h"
25
26#define IWE_STREAM_ADD_EVENT(p1, p2, p3, p4, p5) \
27 iwe_stream_add_event((p1), (p2), (p3), (p4), (p5))
28
29#define IWE_STREAM_ADD_POINT(p1, p2, p3, p4, p5) \
30 iwe_stream_add_point((p1), (p2), (p3), (p4), (p5))
31
32#define IWE_STREAM_ADD_VALUE(p1, p2, p3, p4, p5, p6) \
33 iwe_stream_add_value((p1), (p2), (p3), (p4), (p5), (p6))
34
f2ab1275 35static void ar6000_set_quality(struct iw_quality *iq, s8 rssi);
30295c89
VM
36extern unsigned int wmitimeout;
37extern A_WAITQUEUE_HEAD arEvent;
38
39#if WIRELESS_EXT > 14
40/*
41 * Encode a WPA or RSN information element as a custom
42 * element using the hostap format.
43 */
44static u_int
45encode_ie(void *buf, size_t bufsize,
46 const u_int8_t *ie, size_t ielen,
47 const char *leader, size_t leader_len)
48{
49 u_int8_t *p;
50 int i;
51
52 if (bufsize < leader_len)
53 return 0;
54 p = buf;
55 memcpy(p, leader, leader_len);
56 bufsize -= leader_len;
57 p += leader_len;
58 for (i = 0; i < ielen && bufsize > 2; i++)
59 {
60 p += sprintf((char*)p, "%02x", ie[i]);
61 bufsize -= 2;
62 }
63 return (i == ielen ? p - (u_int8_t *)buf : 0);
64}
65#endif /* WIRELESS_EXT > 14 */
66
ab3655da 67static u8 get_bss_phy_capability(bss_t *bss)
30295c89 68{
ab3655da 69 u8 capability = 0;
30295c89
VM
70 struct ieee80211_common_ie *cie = &bss->ni_cie;
71#define CHAN_IS_11A(x) (!((x >= 2412) && (x <= 2484)))
72 if (CHAN_IS_11A(cie->ie_chan)) {
73 if (cie->ie_htcap) {
74 capability = WMI_11NA_CAPABILITY;
75 } else {
76 capability = WMI_11A_CAPABILITY;
77 }
78 } else if ((cie->ie_erp) || (cie->ie_xrates)) {
79 if (cie->ie_htcap) {
80 capability = WMI_11NG_CAPABILITY;
81 } else {
82 capability = WMI_11G_CAPABILITY;
83 }
84 }
85 return capability;
86}
87
88void
89ar6000_scan_node(void *arg, bss_t *ni)
90{
91 struct iw_event iwe;
92#if WIRELESS_EXT > 14
93 char buf[256];
94#endif
95 struct ar_giwscan_param *param;
4c42080f
JP
96 char *current_ev;
97 char *end_buf;
30295c89 98 struct ieee80211_common_ie *cie;
4c42080f 99 char *current_val;
f68057e6 100 s32 j;
e1ce2a3a 101 u32 rate_len, data_len = 0;
30295c89
VM
102
103 param = (struct ar_giwscan_param *)arg;
104
105 current_ev = param->current_ev;
106 end_buf = param->end_buf;
107
108 cie = &ni->ni_cie;
109
110 if ((end_buf - current_ev) > IW_EV_ADDR_LEN)
111 {
112 A_MEMZERO(&iwe, sizeof(iwe));
113 iwe.cmd = SIOCGIWAP;
114 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
05209262 115 memcpy(iwe.u.ap_addr.sa_data, ni->ni_macaddr, 6);
30295c89
VM
116 current_ev = IWE_STREAM_ADD_EVENT(param->info, current_ev, end_buf,
117 &iwe, IW_EV_ADDR_LEN);
118 }
119 param->bytes_needed += IW_EV_ADDR_LEN;
120
121 data_len = cie->ie_ssid[1] + IW_EV_POINT_LEN;
122 if ((end_buf - current_ev) > data_len)
123 {
124 A_MEMZERO(&iwe, sizeof(iwe));
125 iwe.cmd = SIOCGIWESSID;
126 iwe.u.data.flags = 1;
127 iwe.u.data.length = cie->ie_ssid[1];
128 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
129 &iwe, (char*)&cie->ie_ssid[2]);
130 }
131 param->bytes_needed += data_len;
132
133 if (cie->ie_capInfo & (IEEE80211_CAPINFO_ESS|IEEE80211_CAPINFO_IBSS)) {
134 if ((end_buf - current_ev) > IW_EV_UINT_LEN)
135 {
136 A_MEMZERO(&iwe, sizeof(iwe));
137 iwe.cmd = SIOCGIWMODE;
138 iwe.u.mode = cie->ie_capInfo & IEEE80211_CAPINFO_ESS ?
139 IW_MODE_MASTER : IW_MODE_ADHOC;
140 current_ev = IWE_STREAM_ADD_EVENT(param->info, current_ev, end_buf,
141 &iwe, IW_EV_UINT_LEN);
142 }
143 param->bytes_needed += IW_EV_UINT_LEN;
144 }
145
146 if ((end_buf - current_ev) > IW_EV_FREQ_LEN)
147 {
148 A_MEMZERO(&iwe, sizeof(iwe));
149 iwe.cmd = SIOCGIWFREQ;
150 iwe.u.freq.m = cie->ie_chan * 100000;
151 iwe.u.freq.e = 1;
152 current_ev = IWE_STREAM_ADD_EVENT(param->info, current_ev, end_buf,
153 &iwe, IW_EV_FREQ_LEN);
154 }
155 param->bytes_needed += IW_EV_FREQ_LEN;
156
157 if ((end_buf - current_ev) > IW_EV_QUAL_LEN)
158 {
159 A_MEMZERO(&iwe, sizeof(iwe));
160 iwe.cmd = IWEVQUAL;
161 ar6000_set_quality(&iwe.u.qual, ni->ni_snr);
162 current_ev = IWE_STREAM_ADD_EVENT(param->info, current_ev, end_buf,
163 &iwe, IW_EV_QUAL_LEN);
164 }
165 param->bytes_needed += IW_EV_QUAL_LEN;
166
167 if ((end_buf - current_ev) > IW_EV_POINT_LEN)
168 {
169 A_MEMZERO(&iwe, sizeof(iwe));
170 iwe.cmd = SIOCGIWENCODE;
171 if (cie->ie_capInfo & IEEE80211_CAPINFO_PRIVACY) {
172 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
173 } else {
174 iwe.u.data.flags = IW_ENCODE_DISABLED;
175 }
176 iwe.u.data.length = 0;
177 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
178 &iwe, "");
179 }
180 param->bytes_needed += IW_EV_POINT_LEN;
181
182 /* supported bit rate */
183 A_MEMZERO(&iwe, sizeof(iwe));
184 iwe.cmd = SIOCGIWRATE;
185 iwe.u.bitrate.fixed = 0;
186 iwe.u.bitrate.disabled = 0;
187 iwe.u.bitrate.value = 0;
188 current_val = current_ev + IW_EV_LCP_LEN;
189 param->bytes_needed += IW_EV_LCP_LEN;
190
191 if (cie->ie_rates != NULL) {
192 rate_len = cie->ie_rates[1];
193 data_len = (rate_len * (IW_EV_PARAM_LEN - IW_EV_LCP_LEN));
194 if ((end_buf - current_ev) > data_len)
195 {
196 for (j = 0; j < rate_len; j++) {
197 unsigned char val;
198 val = cie->ie_rates[2 + j];
199 iwe.u.bitrate.value =
200 (val >= 0x80)? ((val - 0x80) * 500000): (val * 500000);
201 current_val = IWE_STREAM_ADD_VALUE(param->info, current_ev,
202 current_val, end_buf,
203 &iwe, IW_EV_PARAM_LEN);
204 }
205 }
206 param->bytes_needed += data_len;
207 }
208
209 if (cie->ie_xrates != NULL) {
210 rate_len = cie->ie_xrates[1];
211 data_len = (rate_len * (IW_EV_PARAM_LEN - IW_EV_LCP_LEN));
212 if ((end_buf - current_ev) > data_len)
213 {
214 for (j = 0; j < rate_len; j++) {
215 unsigned char val;
216 val = cie->ie_xrates[2 + j];
217 iwe.u.bitrate.value =
218 (val >= 0x80)? ((val - 0x80) * 500000): (val * 500000);
219 current_val = IWE_STREAM_ADD_VALUE(param->info, current_ev,
220 current_val, end_buf,
221 &iwe, IW_EV_PARAM_LEN);
222 }
223 }
224 param->bytes_needed += data_len;
225 }
226 /* remove fixed header if no rates were added */
227 if ((current_val - current_ev) > IW_EV_LCP_LEN)
228 current_ev = current_val;
229
230#if WIRELESS_EXT >= 18
231 /* IE */
232 if (cie->ie_wpa != NULL) {
233 data_len = cie->ie_wpa[1] + 2 + IW_EV_POINT_LEN;
234 if ((end_buf - current_ev) > data_len)
235 {
236 A_MEMZERO(&iwe, sizeof(iwe));
237 iwe.cmd = IWEVGENIE;
238 iwe.u.data.length = cie->ie_wpa[1] + 2;
239 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
240 &iwe, (char*)cie->ie_wpa);
241 }
242 param->bytes_needed += data_len;
243 }
244
245 if (cie->ie_rsn != NULL && cie->ie_rsn[0] == IEEE80211_ELEMID_RSN) {
246 data_len = cie->ie_rsn[1] + 2 + IW_EV_POINT_LEN;
247 if ((end_buf - current_ev) > data_len)
248 {
249 A_MEMZERO(&iwe, sizeof(iwe));
250 iwe.cmd = IWEVGENIE;
251 iwe.u.data.length = cie->ie_rsn[1] + 2;
252 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
253 &iwe, (char*)cie->ie_rsn);
254 }
255 param->bytes_needed += data_len;
256 }
257
258#endif /* WIRELESS_EXT >= 18 */
259
260 if ((end_buf - current_ev) > IW_EV_CHAR_LEN)
261 {
262 /* protocol */
263 A_MEMZERO(&iwe, sizeof(iwe));
264 iwe.cmd = SIOCGIWNAME;
265 switch (get_bss_phy_capability(ni)) {
266 case WMI_11A_CAPABILITY:
267 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11a");
268 break;
269 case WMI_11G_CAPABILITY:
270 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
271 break;
272 case WMI_11NA_CAPABILITY:
273 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11na");
274 break;
275 case WMI_11NG_CAPABILITY:
276 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11ng");
277 break;
278 default:
279 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
280 break;
281 }
282 current_ev = IWE_STREAM_ADD_EVENT(param->info, current_ev, end_buf,
283 &iwe, IW_EV_CHAR_LEN);
284 }
285 param->bytes_needed += IW_EV_CHAR_LEN;
286
287#if WIRELESS_EXT > 14
288 A_MEMZERO(&iwe, sizeof(iwe));
289 iwe.cmd = IWEVCUSTOM;
290 iwe.u.data.length = snprintf(buf, sizeof(buf), "bcn_int=%d", cie->ie_beaconInt);
291 data_len = iwe.u.data.length + IW_EV_POINT_LEN;
292 if ((end_buf - current_ev) > data_len)
293 {
294 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
295 &iwe, buf);
296 }
297 param->bytes_needed += data_len;
298
299#if WIRELESS_EXT < 18
300 if (cie->ie_wpa != NULL) {
301 static const char wpa_leader[] = "wpa_ie=";
302 data_len = (sizeof(wpa_leader) - 1) + ((cie->ie_wpa[1]+2) * 2) + IW_EV_POINT_LEN;
303 if ((end_buf - current_ev) > data_len)
304 {
305 A_MEMZERO(&iwe, sizeof(iwe));
306 iwe.cmd = IWEVCUSTOM;
307 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wpa,
308 cie->ie_wpa[1]+2,
309 wpa_leader, sizeof(wpa_leader)-1);
310
311 if (iwe.u.data.length != 0) {
312 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev,
313 end_buf, &iwe, buf);
314 }
315 }
316 param->bytes_needed += data_len;
317 }
318
319 if (cie->ie_rsn != NULL && cie->ie_rsn[0] == IEEE80211_ELEMID_RSN) {
320 static const char rsn_leader[] = "rsn_ie=";
321 data_len = (sizeof(rsn_leader) - 1) + ((cie->ie_rsn[1]+2) * 2) + IW_EV_POINT_LEN;
322 if ((end_buf - current_ev) > data_len)
323 {
324 A_MEMZERO(&iwe, sizeof(iwe));
325 iwe.cmd = IWEVCUSTOM;
326 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_rsn,
327 cie->ie_rsn[1]+2,
328 rsn_leader, sizeof(rsn_leader)-1);
329
330 if (iwe.u.data.length != 0) {
331 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev,
332 end_buf, &iwe, buf);
333 }
334 }
335 param->bytes_needed += data_len;
336 }
337#endif /* WIRELESS_EXT < 18 */
338
339 if (cie->ie_wmm != NULL) {
340 static const char wmm_leader[] = "wmm_ie=";
341 data_len = (sizeof(wmm_leader) - 1) + ((cie->ie_wmm[1]+2) * 2) + IW_EV_POINT_LEN;
342 if ((end_buf - current_ev) > data_len)
343 {
344 A_MEMZERO(&iwe, sizeof(iwe));
345 iwe.cmd = IWEVCUSTOM;
346 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wmm,
347 cie->ie_wmm[1]+2,
348 wmm_leader, sizeof(wmm_leader)-1);
349 if (iwe.u.data.length != 0) {
350 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev,
351 end_buf, &iwe, buf);
352 }
353 }
354 param->bytes_needed += data_len;
355 }
356
357 if (cie->ie_ath != NULL) {
358 static const char ath_leader[] = "ath_ie=";
359 data_len = (sizeof(ath_leader) - 1) + ((cie->ie_ath[1]+2) * 2) + IW_EV_POINT_LEN;
360 if ((end_buf - current_ev) > data_len)
361 {
362 A_MEMZERO(&iwe, sizeof(iwe));
363 iwe.cmd = IWEVCUSTOM;
364 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_ath,
365 cie->ie_ath[1]+2,
366 ath_leader, sizeof(ath_leader)-1);
367 if (iwe.u.data.length != 0) {
368 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev,
369 end_buf, &iwe, buf);
370 }
371 }
372 param->bytes_needed += data_len;
373 }
374
375#ifdef WAPI_ENABLE
376 if (cie->ie_wapi != NULL) {
377 static const char wapi_leader[] = "wapi_ie=";
378 data_len = (sizeof(wapi_leader) - 1) + ((cie->ie_wapi[1] + 2) * 2) + IW_EV_POINT_LEN;
379 if ((end_buf - current_ev) > data_len) {
380 A_MEMZERO(&iwe, sizeof(iwe));
381 iwe.cmd = IWEVCUSTOM;
382 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wapi,
383 cie->ie_wapi[1] + 2,
384 wapi_leader, sizeof(wapi_leader) - 1);
385 if (iwe.u.data.length != 0) {
386 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev,
387 end_buf, &iwe, buf);
388 }
389 }
390 param->bytes_needed += data_len;
391 }
392#endif /* WAPI_ENABLE */
393
394#endif /* WIRELESS_EXT > 14 */
395
396#if WIRELESS_EXT >= 18
397 if (cie->ie_wsc != NULL) {
398 data_len = (cie->ie_wsc[1] + 2) + IW_EV_POINT_LEN;
399 if ((end_buf - current_ev) > data_len)
400 {
401 A_MEMZERO(&iwe, sizeof(iwe));
402 iwe.cmd = IWEVGENIE;
403 iwe.u.data.length = cie->ie_wsc[1] + 2;
404 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
405 &iwe, (char*)cie->ie_wsc);
406 }
407 param->bytes_needed += data_len;
408 }
409#endif /* WIRELESS_EXT >= 18 */
410
411 param->current_ev = current_ev;
412}
413
414int
415ar6000_ioctl_giwscan(struct net_device *dev,
416 struct iw_request_info *info,
417 struct iw_point *data, char *extra)
418{
a71f0bf6 419 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89
VM
420 struct ar_giwscan_param param;
421
4f69cef0 422 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
30295c89
VM
423 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
424 return -EOPNOTSUPP;
425 }
426
427 if (ar->arWlanState == WLAN_DISABLED) {
428 return -EIO;
429 }
430
1071a134 431 if (ar->arWmiReady == false) {
30295c89
VM
432 return -EIO;
433 }
434
435 param.current_ev = extra;
436 param.end_buf = extra + data->length;
437 param.bytes_needed = 0;
438 param.info = info;
439
440 /* Translate data to WE format */
441 wmi_iterate_nodes(ar->arWmi, ar6000_scan_node, &param);
442
443 /* check if bytes needed is greater than bytes consumed */
444 if (param.bytes_needed > (param.current_ev - extra))
445 {
446 /* Request one byte more than needed, because when "data->length" equals bytes_needed,
447 it is not possible to add the last event data as all iwe_stream_add_xxxxx() functions
448 checks whether (cur_ptr + ev_len) < end_ptr, due to this one more retry would happen*/
449 data->length = param.bytes_needed + 1;
450
451 return -E2BIG;
452 }
453
454 return 0;
455}
456
457extern int reconnect_flag;
458/* SIOCSIWESSID */
459static int
460ar6000_ioctl_siwessid(struct net_device *dev,
461 struct iw_request_info *info,
462 struct iw_point *data, char *ssid)
463{
a71f0bf6 464 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1f4c34bd 465 int status;
ab3655da
JP
466 u8 arNetworkType;
467 u8 prevMode = ar->arNetworkType;
30295c89 468
4f69cef0 469 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
30295c89
VM
470 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
471 return -EOPNOTSUPP;
472 }
473
474 if (ar->bIsDestroyProgress) {
475 return -EBUSY;
476 }
477
478 if (ar->arWlanState == WLAN_DISABLED) {
479 return -EIO;
480 }
481
1071a134 482 if (ar->arWmiReady == false) {
30295c89
VM
483 return -EIO;
484 }
485
486#if defined(WIRELESS_EXT)
487 if (WIRELESS_EXT >= 20) {
488 data->length += 1;
489 }
490#endif
491
492 /*
493 * iwconfig passes a null terminated string with length including this
494 * so we need to account for this
495 */
496 if (data->flags && (!data->length || (data->length == 1) ||
497 ((data->length - 1) > sizeof(ar->arSsid))))
498 {
499 /*
500 * ssid is invalid
501 */
502 return -EINVAL;
503 }
504
505 if (ar->arNextMode == AP_NETWORK) {
506 /* SSID change for AP network - Will take effect on commit */
395e1cae 507 if(memcmp(ar->arSsid,ssid,32) != 0) {
30295c89 508 ar->arSsidLen = data->length - 1;
05209262 509 memcpy(ar->arSsid, ssid, ar->arSsidLen);
30295c89
VM
510 ar->ap_profile_flag = 1; /* There is a change in profile */
511 }
512 return 0;
513 } else if(ar->arNetworkType == AP_NETWORK) {
ab3655da 514 u8 ctr;
30295c89
VM
515 struct sk_buff *skb;
516
517 /* We are switching from AP to STA | IBSS mode, cleanup the AP state */
518 for (ctr=0; ctr < AP_MAX_NUM_STA; ctr++) {
519 remove_sta(ar, ar->sta_list[ctr].mac, 0);
520 }
521 A_MUTEX_LOCK(&ar->mcastpsqLock);
522 while (!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) {
523 skb = A_NETBUF_DEQUEUE(&ar->mcastpsq);
524 A_NETBUF_FREE(skb);
525 }
526 A_MUTEX_UNLOCK(&ar->mcastpsqLock);
527 }
528
529 /* Added for bug 25178, return an IOCTL error instead of target returning
530 Illegal parameter error when either the BSSID or channel is missing
531 and we cannot scan during connect.
532 */
533 if (data->flags) {
1071a134 534 if (ar->arSkipScan == true &&
30295c89
VM
535 (ar->arChannelHint == 0 ||
536 (!ar->arReqBssid[0] && !ar->arReqBssid[1] && !ar->arReqBssid[2] &&
537 !ar->arReqBssid[3] && !ar->arReqBssid[4] && !ar->arReqBssid[5])))
538 {
539 return -EINVAL;
540 }
541 }
542
543 if (down_interruptible(&ar->arSem)) {
544 return -ERESTARTSYS;
545 }
546
547 if (ar->bIsDestroyProgress || ar->arWlanState == WLAN_DISABLED) {
548 up(&ar->arSem);
549 return -EBUSY;
550 }
551
552 if (ar->arTxPending[wmi_get_control_ep(ar->arWmi)]) {
553 /*
554 * sleep until the command queue drains
555 */
556 wait_event_interruptible_timeout(arEvent,
557 ar->arTxPending[wmi_get_control_ep(ar->arWmi)] == 0, wmitimeout * HZ);
558 if (signal_pending(current)) {
559 return -EINTR;
560 }
561 }
562
563 if (!data->flags) {
564 arNetworkType = ar->arNetworkType;
565#ifdef ATH6K_CONFIG_CFG80211
566 if (ar->arConnected) {
567#endif /* ATH6K_CONFIG_CFG80211 */
568 ar6000_init_profile_info(ar);
569#ifdef ATH6K_CONFIG_CFG80211
570 }
571#endif /* ATH6K_CONFIG_CFG80211 */
572 ar->arNetworkType = arNetworkType;
573 }
574
575 /* Update the arNetworkType */
576 ar->arNetworkType = ar->arNextMode;
577
30295c89 578 if ((prevMode != AP_NETWORK) &&
83195cc8
VM
579 ((ar->arSsidLen) ||
580 ((ar->arSsidLen == 0) && (ar->arConnected || ar->arConnectPending)) ||
581 (!data->flags)))
30295c89
VM
582 {
583 if ((!data->flags) ||
395e1cae 584 (memcmp(ar->arSsid, ssid, ar->arSsidLen) != 0) ||
30295c89
VM
585 (ar->arSsidLen != (data->length - 1)))
586 {
587 /*
588 * SSID set previously or essid off has been issued.
589 *
590 * Disconnect Command is issued in two cases after wmi is ready
591 * (1) ssid is different from the previous setting
592 * (2) essid off has been issued
593 *
594 */
1071a134 595 if (ar->arWmiReady == true) {
30295c89
VM
596 reconnect_flag = 0;
597 status = wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, 0);
83195cc8 598 ar6000_disconnect(ar);
30295c89
VM
599 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
600 ar->arSsidLen = 0;
1071a134 601 if (ar->arSkipScan == false) {
30295c89
VM
602 A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
603 }
604 if (!data->flags) {
605 up(&ar->arSem);
606 return 0;
607 }
608 } else {
609 up(&ar->arSem);
610 }
611 }
612 else
613 {
614 /*
615 * SSID is same, so we assume profile hasn't changed.
616 * If the interface is up and wmi is ready, we issue
617 * a reconnect cmd. Issue a reconnect only we are already
618 * connected.
619 */
1071a134 620 if((ar->arConnected == true) && (ar->arWmiReady == true))
30295c89 621 {
1071a134 622 reconnect_flag = true;
30295c89
VM
623 status = wmi_reconnect_cmd(ar->arWmi,ar->arReqBssid,
624 ar->arChannelHint);
625 up(&ar->arSem);
a1d46529 626 if (status) {
30295c89
VM
627 return -EIO;
628 }
629 return 0;
630 }
631 else{
632 /*
633 * Dont return if connect is pending.
634 */
635 if(!(ar->arConnectPending)) {
636 up(&ar->arSem);
637 return 0;
638 }
639 }
640 }
641 }
642
643 ar->arSsidLen = data->length - 1;
05209262 644 memcpy(ar->arSsid, ssid, ar->arSsidLen);
30295c89 645
4f69cef0 646 if (ar6000_connect_to_ap(ar)!= 0) {
30295c89
VM
647 up(&ar->arSem);
648 return -EIO;
649 }else{
650 up(&ar->arSem);
651 }
652 return 0;
653}
654
655/* SIOCGIWESSID */
656static int
657ar6000_ioctl_giwessid(struct net_device *dev,
658 struct iw_request_info *info,
659 struct iw_point *data, char *essid)
660{
a71f0bf6 661 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89 662
4f69cef0 663 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
30295c89
VM
664 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
665 return -EOPNOTSUPP;
666 }
667
668 if (ar->arWlanState == WLAN_DISABLED) {
669 return -EIO;
670 }
671
672 if (!ar->arSsidLen) {
673 return -EINVAL;
674 }
675
676 data->flags = 1;
677 data->length = ar->arSsidLen;
05209262 678 memcpy(essid, ar->arSsid, ar->arSsidLen);
30295c89
VM
679
680 return 0;
681}
682
683
a71f0bf6 684void ar6000_install_static_wep_keys(struct ar6_softc *ar)
30295c89 685{
ab3655da
JP
686 u8 index;
687 u8 keyUsage;
30295c89
VM
688
689 for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) {
690 if (ar->arWepKeyList[index].arKeyLen) {
691 keyUsage = GROUP_USAGE;
692 if (index == ar->arDefTxKeyIndex) {
693 keyUsage |= TX_USAGE;
694 }
695 wmi_addKey_cmd(ar->arWmi,
696 index,
697 WEP_CRYPT,
698 keyUsage,
699 ar->arWepKeyList[index].arKeyLen,
700 NULL,
701 ar->arWepKeyList[index].arKey, KEY_OP_INIT_VAL, NULL,
702 NO_SYNC_WMIFLAG);
703 }
704 }
705}
706
707/*
708 * SIOCSIWRATE
709 */
710int
711ar6000_ioctl_siwrate(struct net_device *dev,
712 struct iw_request_info *info,
713 struct iw_param *rrq, char *extra)
714{
a71f0bf6 715 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
e1ce2a3a 716 u32 kbps;
f2ab1275 717 s8 rate_idx;
30295c89 718
4f69cef0 719 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
30295c89
VM
720 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
721 return -EOPNOTSUPP;
722 }
723
724 if (rrq->fixed) {
725 kbps = rrq->value / 1000; /* rrq->value is in bps */
726 } else {
727 kbps = -1; /* -1 indicates auto rate */
728 }
4f69cef0 729 if(kbps != -1 && wmi_validate_bitrate(ar->arWmi, kbps, &rate_idx) != 0)
30295c89
VM
730 {
731 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BitRate is not Valid %d\n", kbps));
732 return -EINVAL;
733 }
734 ar->arBitRate = kbps;
1071a134 735 if(ar->arWmiReady == true)
30295c89 736 {
4f69cef0 737 if (wmi_set_bitrate_cmd(ar->arWmi, kbps, -1, -1) != 0) {
30295c89
VM
738 return -EINVAL;
739 }
740 }
741 return 0;
742}
743
744/*
745 * SIOCGIWRATE
746 */
747int
748ar6000_ioctl_giwrate(struct net_device *dev,
749 struct iw_request_info *info,
750 struct iw_param *rrq, char *extra)
751{
a71f0bf6 752 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89
VM
753 int ret = 0;
754
4f69cef0 755 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
30295c89
VM
756 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
757 return -EOPNOTSUPP;
758 }
759
760 if (ar->bIsDestroyProgress) {
761 return -EBUSY;
762 }
763
764 if (ar->arWlanState == WLAN_DISABLED) {
765 return -EIO;
766 }
767
1071a134 768 if ((ar->arNextMode != AP_NETWORK && !ar->arConnected) || ar->arWmiReady == false) {
30295c89
VM
769 rrq->value = 1000 * 1000;
770 return 0;
771 }
772
773 if (down_interruptible(&ar->arSem)) {
774 return -ERESTARTSYS;
775 }
776
777 if (ar->bIsDestroyProgress || ar->arWlanState == WLAN_DISABLED) {
778 up(&ar->arSem);
779 return -EBUSY;
780 }
781
782 ar->arBitRate = 0xFFFF;
4f69cef0 783 if (wmi_get_bitrate_cmd(ar->arWmi) != 0) {
30295c89
VM
784 up(&ar->arSem);
785 return -EIO;
786 }
787 wait_event_interruptible_timeout(arEvent, ar->arBitRate != 0xFFFF, wmitimeout * HZ);
788 if (signal_pending(current)) {
789 ret = -EINTR;
790 }
791 /* If the interface is down or wmi is not ready or the target is not
792 connected - return the value stored in the device structure */
793 if (!ret) {
794 if (ar->arBitRate == -1) {
1071a134 795 rrq->fixed = true;
30295c89
VM
796 rrq->value = 0;
797 } else {
798 rrq->value = ar->arBitRate * 1000;
799 }
800 }
801
802 up(&ar->arSem);
803
804 return ret;
805}
806
807/*
808 * SIOCSIWTXPOW
809 */
810static int
811ar6000_ioctl_siwtxpow(struct net_device *dev,
812 struct iw_request_info *info,
813 struct iw_param *rrq, char *extra)
814{
a71f0bf6 815 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
ab3655da 816 u8 dbM;
30295c89 817
4f69cef0 818 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
30295c89
VM
819 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
820 return -EOPNOTSUPP;
821 }
822
823 if (ar->arWlanState == WLAN_DISABLED) {
824 return -EIO;
825 }
826
827 if (rrq->disabled) {
828 return -EOPNOTSUPP;
829 }
830
831 if (rrq->fixed) {
832 if (rrq->flags != IW_TXPOW_DBM) {
833 return -EOPNOTSUPP;
834 }
835 ar->arTxPwr= dbM = rrq->value;
1071a134 836 ar->arTxPwrSet = true;
30295c89
VM
837 } else {
838 ar->arTxPwr = dbM = 0;
1071a134 839 ar->arTxPwrSet = false;
30295c89 840 }
1071a134 841 if(ar->arWmiReady == true)
30295c89
VM
842 {
843 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("Set tx pwr cmd %d dbM\n", dbM));
844 wmi_set_txPwr_cmd(ar->arWmi, dbM);
845 }
846 return 0;
847}
848
849/*
850 * SIOCGIWTXPOW
851 */
852int
853ar6000_ioctl_giwtxpow(struct net_device *dev,
854 struct iw_request_info *info,
855 struct iw_param *rrq, char *extra)
856{
a71f0bf6 857 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89
VM
858 int ret = 0;
859
4f69cef0 860 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
30295c89
VM
861 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
862 return -EOPNOTSUPP;
863 }
864
865 if (ar->bIsDestroyProgress) {
866 return -EBUSY;
867 }
868
869 if (ar->arWlanState == WLAN_DISABLED) {
870 return -EIO;
871 }
872
873 if (down_interruptible(&ar->arSem)) {
874 return -ERESTARTSYS;
875 }
876
877 if (ar->bIsDestroyProgress) {
878 up(&ar->arSem);
879 return -EBUSY;
880 }
881
1071a134 882 if((ar->arWmiReady == true) && (ar->arConnected == true))
30295c89
VM
883 {
884 ar->arTxPwr = 0;
885
4f69cef0 886 if (wmi_get_txPwr_cmd(ar->arWmi) != 0) {
30295c89
VM
887 up(&ar->arSem);
888 return -EIO;
889 }
890
891 wait_event_interruptible_timeout(arEvent, ar->arTxPwr != 0, wmitimeout * HZ);
892
893 if (signal_pending(current)) {
894 ret = -EINTR;
895 }
896 }
897 /* If the interace is down or wmi is not ready or target is not connected
898 then return value stored in the device structure */
899
900 if (!ret) {
1071a134
JP
901 if (ar->arTxPwrSet == true) {
902 rrq->fixed = true;
30295c89
VM
903 }
904 rrq->value = ar->arTxPwr;
905 rrq->flags = IW_TXPOW_DBM;
906 //
907 // IWLIST need this flag to get TxPower
908 //
909 rrq->disabled = 0;
910 }
911
912 up(&ar->arSem);
913
914 return ret;
915}
916
917/*
918 * SIOCSIWRETRY
919 * since iwconfig only provides us with one max retry value, we use it
920 * to apply to data frames of the BE traffic class.
921 */
922static int
923ar6000_ioctl_siwretry(struct net_device *dev,
924 struct iw_request_info *info,
925 struct iw_param *rrq, char *extra)
926{
a71f0bf6 927 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89 928
4f69cef0 929 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
30295c89
VM
930 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
931 return -EOPNOTSUPP;
932 }
933
934 if (ar->arWlanState == WLAN_DISABLED) {
935 return -EIO;
936 }
937
938 if (rrq->disabled) {
939 return -EOPNOTSUPP;
940 }
941
942 if ((rrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) {
943 return -EOPNOTSUPP;
944 }
945
946 if ( !(rrq->value >= WMI_MIN_RETRIES) || !(rrq->value <= WMI_MAX_RETRIES)) {
947 return - EINVAL;
948 }
1071a134 949 if(ar->arWmiReady == true)
30295c89
VM
950 {
951 if (wmi_set_retry_limits_cmd(ar->arWmi, DATA_FRAMETYPE, WMM_AC_BE,
4f69cef0 952 rrq->value, 0) != 0){
30295c89
VM
953 return -EINVAL;
954 }
955 }
956 ar->arMaxRetries = rrq->value;
957 return 0;
958}
959
960/*
961 * SIOCGIWRETRY
962 */
963static int
964ar6000_ioctl_giwretry(struct net_device *dev,
965 struct iw_request_info *info,
966 struct iw_param *rrq, char *extra)
967{
a71f0bf6 968 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89 969
4f69cef0 970 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
30295c89
VM
971 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
972 return -EOPNOTSUPP;
973 }
974
975 if (ar->arWlanState == WLAN_DISABLED) {
976 return -EIO;
977 }
978
979 rrq->disabled = 0;
980 switch (rrq->flags & IW_RETRY_TYPE) {
981 case IW_RETRY_LIFETIME:
982 return -EOPNOTSUPP;
983 break;
984 case IW_RETRY_LIMIT:
985 rrq->flags = IW_RETRY_LIMIT;
986 switch (rrq->flags & IW_RETRY_MODIFIER) {
987 case IW_RETRY_MIN:
988 rrq->flags |= IW_RETRY_MIN;
989 rrq->value = WMI_MIN_RETRIES;
990 break;
991 case IW_RETRY_MAX:
992 rrq->flags |= IW_RETRY_MAX;
993 rrq->value = ar->arMaxRetries;
994 break;
995 }
996 break;
997 }
998 return 0;
999}
1000
1001/*
1002 * SIOCSIWENCODE
1003 */
1004static int
1005ar6000_ioctl_siwencode(struct net_device *dev,
1006 struct iw_request_info *info,
1007 struct iw_point *erq, char *keybuf)
1008{
a71f0bf6 1009 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89 1010 int index;
f68057e6 1011 s32 auth = 0;
30295c89 1012
4f69cef0 1013 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
30295c89
VM
1014 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
1015 return -EOPNOTSUPP;
1016 }
1017
1018 if(ar->arNextMode != AP_NETWORK) {
1019 /*
1020 * Static WEP Keys should be configured before setting the SSID
1021 */
1022 if (ar->arSsid[0] && erq->length) {
1023 return -EIO;
1024 }
1025 }
1026
1027 if (ar->arWlanState == WLAN_DISABLED) {
1028 return -EIO;
1029 }
1030
1031 index = erq->flags & IW_ENCODE_INDEX;
1032
1033 if (index && (((index - 1) < WMI_MIN_KEY_INDEX) ||
1034 ((index - 1) > WMI_MAX_KEY_INDEX)))
1035 {
1036 return -EIO;
1037 }
1038
1039 if (erq->flags & IW_ENCODE_DISABLED) {
1040 /*
1041 * Encryption disabled
1042 */
1043 if (index) {
1044 /*
1045 * If key index was specified then clear the specified key
1046 */
1047 index--;
1048 A_MEMZERO(ar->arWepKeyList[index].arKey,
1049 sizeof(ar->arWepKeyList[index].arKey));
1050 ar->arWepKeyList[index].arKeyLen = 0;
1051 }
1052 ar->arDot11AuthMode = OPEN_AUTH;
1053 ar->arPairwiseCrypto = NONE_CRYPT;
1054 ar->arGroupCrypto = NONE_CRYPT;
1055 ar->arAuthMode = NONE_AUTH;
1056 } else {
1057 /*
1058 * Enabling WEP encryption
1059 */
1060 if (index) {
1061 index--; /* keyindex is off base 1 in iwconfig */
1062 }
1063
1064 if (erq->flags & IW_ENCODE_OPEN) {
1065 auth |= OPEN_AUTH;
1066 ar->arDefTxKeyIndex = index;
1067 }
1068 if (erq->flags & IW_ENCODE_RESTRICTED) {
1069 auth |= SHARED_AUTH;
1070 }
1071
1072 if (!auth) {
1073 auth = OPEN_AUTH;
1074 }
1075
1076 if (erq->length) {
1077 if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(erq->length)) {
1078 return -EIO;
1079 }
1080
1081 A_MEMZERO(ar->arWepKeyList[index].arKey,
1082 sizeof(ar->arWepKeyList[index].arKey));
05209262 1083 memcpy(ar->arWepKeyList[index].arKey, keybuf, erq->length);
30295c89
VM
1084 ar->arWepKeyList[index].arKeyLen = erq->length;
1085 ar->arDot11AuthMode = auth;
1086 } else {
1087 if (ar->arWepKeyList[index].arKeyLen == 0) {
1088 return -EIO;
1089 }
1090 ar->arDefTxKeyIndex = index;
1091
1092 if(ar->arSsidLen && ar->arWepKeyList[index].arKeyLen) {
1093 wmi_addKey_cmd(ar->arWmi,
1094 index,
1095 WEP_CRYPT,
1096 GROUP_USAGE | TX_USAGE,
1097 ar->arWepKeyList[index].arKeyLen,
1098 NULL,
1099 ar->arWepKeyList[index].arKey, KEY_OP_INIT_VAL, NULL,
1100 NO_SYNC_WMIFLAG);
1101 }
1102 }
1103
1104 ar->arPairwiseCrypto = WEP_CRYPT;
1105 ar->arGroupCrypto = WEP_CRYPT;
1106 ar->arAuthMode = NONE_AUTH;
1107 }
1108
1109 if(ar->arNextMode != AP_NETWORK) {
1110 /*
1111 * profile has changed. Erase ssid to signal change
1112 */
1113 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
1114 ar->arSsidLen = 0;
1115 }
1116 ar->ap_profile_flag = 1; /* There is a change in profile */
1117 return 0;
1118}
1119
1120static int
1121ar6000_ioctl_giwencode(struct net_device *dev,
1122 struct iw_request_info *info,
1123 struct iw_point *erq, char *key)
1124{
a71f0bf6 1125 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
ab3655da 1126 u8 keyIndex;
30295c89
VM
1127 struct ar_wep_key *wk;
1128
4f69cef0 1129 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
30295c89
VM
1130 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
1131 return -EOPNOTSUPP;
1132 }
1133
1134 if (ar->arWlanState == WLAN_DISABLED) {
1135 return -EIO;
1136 }
1137
1138 if (ar->arPairwiseCrypto == NONE_CRYPT) {
1139 erq->length = 0;
1140 erq->flags = IW_ENCODE_DISABLED;
1141 } else {
1142 if (ar->arPairwiseCrypto == WEP_CRYPT) {
1143 /* get the keyIndex */
1144 keyIndex = erq->flags & IW_ENCODE_INDEX;
1145 if (0 == keyIndex) {
1146 keyIndex = ar->arDefTxKeyIndex;
1147 } else if ((keyIndex - 1 < WMI_MIN_KEY_INDEX) ||
1148 (keyIndex - 1 > WMI_MAX_KEY_INDEX))
1149 {
1150 keyIndex = WMI_MIN_KEY_INDEX;
1151 } else {
1152 keyIndex--;
1153 }
1154 erq->flags = keyIndex + 1;
1155 erq->flags &= ~IW_ENCODE_DISABLED;
1156 wk = &ar->arWepKeyList[keyIndex];
1157 if (erq->length > wk->arKeyLen) {
1158 erq->length = wk->arKeyLen;
1159 }
1160 if (wk->arKeyLen) {
05209262 1161 memcpy(key, wk->arKey, erq->length);
30295c89
VM
1162 }
1163 } else {
1164 erq->flags &= ~IW_ENCODE_DISABLED;
1165 if (ar->user_saved_keys.keyOk) {
1166 erq->length = ar->user_saved_keys.ucast_ik.ik_keylen;
1167 if (erq->length) {
05209262 1168 memcpy(key, ar->user_saved_keys.ucast_ik.ik_keydata, erq->length);
30295c89
VM
1169 }
1170 } else {
1171 erq->length = 1; // not really printing any key but let iwconfig know enc is on
1172 }
1173 }
1174
1175 if (ar->arDot11AuthMode & OPEN_AUTH) {
1176 erq->flags |= IW_ENCODE_OPEN;
1177 }
1178 if (ar->arDot11AuthMode & SHARED_AUTH) {
1179 erq->flags |= IW_ENCODE_RESTRICTED;
1180 }
1181 }
1182
1183 return 0;
1184}
1185
1186#if WIRELESS_EXT >= 18
1187/*
1188 * SIOCSIWGENIE
1189 */
1190static int
1191ar6000_ioctl_siwgenie(struct net_device *dev,
1192 struct iw_request_info *info,
1193 struct iw_point *erq, char *extra)
1194{
a71f0bf6 1195 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89
VM
1196
1197#ifdef WAPI_ENABLE
ab3655da
JP
1198 u8 *ie = erq->pointer;
1199 u8 ie_type = ie[0];
4853ac05 1200 u16 ie_length = erq->length;
ab3655da 1201 u8 wapi_ie[128];
30295c89
VM
1202#endif
1203
1071a134 1204 if (ar->arWmiReady == false) {
30295c89
VM
1205 return -EIO;
1206 }
1207#ifdef WAPI_ENABLE
1208 if (ie_type == IEEE80211_ELEMID_WAPI) {
1209 if (ie_length > 0) {
1210 if (copy_from_user(wapi_ie, ie, ie_length)) {
1211 return -EIO;
1212 }
1213 }
1214 wmi_set_appie_cmd(ar->arWmi, WMI_FRAME_ASSOC_REQ, ie_length, wapi_ie);
1215 } else if (ie_length == 0) {
1216 wmi_set_appie_cmd(ar->arWmi, WMI_FRAME_ASSOC_REQ, ie_length, wapi_ie);
1217 }
1218#endif
1219 return 0;
1220}
1221
1222
1223/*
1224 * SIOCGIWGENIE
1225 */
1226static int
1227ar6000_ioctl_giwgenie(struct net_device *dev,
1228 struct iw_request_info *info,
1229 struct iw_point *erq, char *extra)
1230{
a71f0bf6 1231 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89 1232
1071a134 1233 if (ar->arWmiReady == false) {
30295c89
VM
1234 return -EIO;
1235 }
1236 erq->length = 0;
1237 erq->flags = 0;
1238
1239 return 0;
1240}
1241
1242/*
1243 * SIOCSIWAUTH
1244 */
1245static int
1246ar6000_ioctl_siwauth(struct net_device *dev,
1247 struct iw_request_info *info,
1248 struct iw_param *data, char *extra)
1249{
a71f0bf6 1250 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89 1251
1071a134 1252 bool profChanged;
4853ac05 1253 u16 param;
f68057e6
JP
1254 s32 ret;
1255 s32 value;
30295c89 1256
1071a134 1257 if (ar->arWmiReady == false) {
30295c89
VM
1258 return -EIO;
1259 }
1260
1261 if (ar->arWlanState == WLAN_DISABLED) {
1262 return -EIO;
1263 }
1264
1265 param = data->flags & IW_AUTH_INDEX;
1266 value = data->value;
1071a134 1267 profChanged = true;
30295c89
VM
1268 ret = 0;
1269
1270 switch (param) {
1271 case IW_AUTH_WPA_VERSION:
1272 if (value & IW_AUTH_WPA_VERSION_DISABLED) {
1273 ar->arAuthMode = NONE_AUTH;
1274 } else if (value & IW_AUTH_WPA_VERSION_WPA) {
1275 ar->arAuthMode = WPA_AUTH;
1276 } else if (value & IW_AUTH_WPA_VERSION_WPA2) {
1277 ar->arAuthMode = WPA2_AUTH;
1278 } else {
1279 ret = -1;
1071a134 1280 profChanged = false;
30295c89
VM
1281 }
1282 break;
1283 case IW_AUTH_CIPHER_PAIRWISE:
1284 if (value & IW_AUTH_CIPHER_NONE) {
1285 ar->arPairwiseCrypto = NONE_CRYPT;
1286 ar->arPairwiseCryptoLen = 0;
1287 } else if (value & IW_AUTH_CIPHER_WEP40) {
1288 ar->arPairwiseCrypto = WEP_CRYPT;
1289 ar->arPairwiseCryptoLen = 5;
1290 } else if (value & IW_AUTH_CIPHER_TKIP) {
1291 ar->arPairwiseCrypto = TKIP_CRYPT;
1292 ar->arPairwiseCryptoLen = 0;
1293 } else if (value & IW_AUTH_CIPHER_CCMP) {
1294 ar->arPairwiseCrypto = AES_CRYPT;
1295 ar->arPairwiseCryptoLen = 0;
1296 } else if (value & IW_AUTH_CIPHER_WEP104) {
1297 ar->arPairwiseCrypto = WEP_CRYPT;
1298 ar->arPairwiseCryptoLen = 13;
1299 } else {
1300 ret = -1;
1071a134 1301 profChanged = false;
30295c89
VM
1302 }
1303 break;
1304 case IW_AUTH_CIPHER_GROUP:
1305 if (value & IW_AUTH_CIPHER_NONE) {
1306 ar->arGroupCrypto = NONE_CRYPT;
1307 ar->arGroupCryptoLen = 0;
1308 } else if (value & IW_AUTH_CIPHER_WEP40) {
1309 ar->arGroupCrypto = WEP_CRYPT;
1310 ar->arGroupCryptoLen = 5;
1311 } else if (value & IW_AUTH_CIPHER_TKIP) {
1312 ar->arGroupCrypto = TKIP_CRYPT;
1313 ar->arGroupCryptoLen = 0;
1314 } else if (value & IW_AUTH_CIPHER_CCMP) {
1315 ar->arGroupCrypto = AES_CRYPT;
1316 ar->arGroupCryptoLen = 0;
1317 } else if (value & IW_AUTH_CIPHER_WEP104) {
1318 ar->arGroupCrypto = WEP_CRYPT;
1319 ar->arGroupCryptoLen = 13;
1320 } else {
1321 ret = -1;
1071a134 1322 profChanged = false;
30295c89
VM
1323 }
1324 break;
1325 case IW_AUTH_KEY_MGMT:
1326 if (value & IW_AUTH_KEY_MGMT_PSK) {
1327 if (WPA_AUTH == ar->arAuthMode) {
1328 ar->arAuthMode = WPA_PSK_AUTH;
1329 } else if (WPA2_AUTH == ar->arAuthMode) {
1330 ar->arAuthMode = WPA2_PSK_AUTH;
1331 } else {
1332 ret = -1;
1333 }
1334 } else if (!(value & IW_AUTH_KEY_MGMT_802_1X)) {
1335 ar->arAuthMode = NONE_AUTH;
1336 }
1337 break;
1338 case IW_AUTH_TKIP_COUNTERMEASURES:
1339 wmi_set_tkip_countermeasures_cmd(ar->arWmi, value);
1071a134 1340 profChanged = false;
30295c89
VM
1341 break;
1342 case IW_AUTH_DROP_UNENCRYPTED:
1071a134 1343 profChanged = false;
30295c89
VM
1344 break;
1345 case IW_AUTH_80211_AUTH_ALG:
1346 ar->arDot11AuthMode = 0;
1347 if (value & IW_AUTH_ALG_OPEN_SYSTEM) {
1348 ar->arDot11AuthMode |= OPEN_AUTH;
1349 }
1350 if (value & IW_AUTH_ALG_SHARED_KEY) {
1351 ar->arDot11AuthMode |= SHARED_AUTH;
1352 }
1353 if (value & IW_AUTH_ALG_LEAP) {
1354 ar->arDot11AuthMode = LEAP_AUTH;
1355 }
1356 if(ar->arDot11AuthMode == 0) {
1357 ret = -1;
1071a134 1358 profChanged = false;
30295c89
VM
1359 }
1360 break;
1361 case IW_AUTH_WPA_ENABLED:
1362 if (!value) {
1363 ar->arAuthMode = NONE_AUTH;
1364 /* when the supplicant is stopped, it calls this
1365 * handler with value=0. The followings need to be
1366 * reset if the STA were to connect again
1367 * without security
1368 */
1369 ar->arDot11AuthMode = OPEN_AUTH;
1370 ar->arPairwiseCrypto = NONE_CRYPT;
1371 ar->arPairwiseCryptoLen = 0;
1372 ar->arGroupCrypto = NONE_CRYPT;
1373 ar->arGroupCryptoLen = 0;
1374 }
1375 break;
1376 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1071a134 1377 profChanged = false;
30295c89
VM
1378 break;
1379 case IW_AUTH_ROAMING_CONTROL:
1071a134 1380 profChanged = false;
30295c89
VM
1381 break;
1382 case IW_AUTH_PRIVACY_INVOKED:
1383 if (!value) {
1384 ar->arPairwiseCrypto = NONE_CRYPT;
1385 ar->arPairwiseCryptoLen = 0;
1386 ar->arGroupCrypto = NONE_CRYPT;
1387 ar->arGroupCryptoLen = 0;
1388 }
1389 break;
1390#ifdef WAPI_ENABLE
1391 case IW_AUTH_WAPI_ENABLED:
1392 ar->arWapiEnable = value;
1393 break;
1394#endif
1395 default:
1396 ret = -1;
1071a134 1397 profChanged = false;
30295c89
VM
1398 break;
1399 }
1400
1071a134 1401 if (profChanged == true) {
30295c89
VM
1402 /*
1403 * profile has changed. Erase ssid to signal change
1404 */
1405 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
1406 ar->arSsidLen = 0;
1407 }
1408
1409 return ret;
1410}
1411
1412
1413/*
1414 * SIOCGIWAUTH
1415 */
1416static int
1417ar6000_ioctl_giwauth(struct net_device *dev,
1418 struct iw_request_info *info,
1419 struct iw_param *data, char *extra)
1420{
a71f0bf6 1421 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
4853ac05 1422 u16 param;
f68057e6 1423 s32 ret;
30295c89 1424
1071a134 1425 if (ar->arWmiReady == false) {
30295c89
VM
1426 return -EIO;
1427 }
1428
1429 if (ar->arWlanState == WLAN_DISABLED) {
1430 return -EIO;
1431 }
1432
1433 param = data->flags & IW_AUTH_INDEX;
1434 ret = 0;
1435 data->value = 0;
1436
1437
1438 switch (param) {
1439 case IW_AUTH_WPA_VERSION:
1440 if (ar->arAuthMode == NONE_AUTH) {
1441 data->value |= IW_AUTH_WPA_VERSION_DISABLED;
1442 } else if (ar->arAuthMode == WPA_AUTH) {
1443 data->value |= IW_AUTH_WPA_VERSION_WPA;
1444 } else if (ar->arAuthMode == WPA2_AUTH) {
1445 data->value |= IW_AUTH_WPA_VERSION_WPA2;
1446 } else {
1447 ret = -1;
1448 }
1449 break;
1450 case IW_AUTH_CIPHER_PAIRWISE:
1451 if (ar->arPairwiseCrypto == NONE_CRYPT) {
1452 data->value |= IW_AUTH_CIPHER_NONE;
1453 } else if (ar->arPairwiseCrypto == WEP_CRYPT) {
1454 if (ar->arPairwiseCryptoLen == 13) {
1455 data->value |= IW_AUTH_CIPHER_WEP104;
1456 } else {
1457 data->value |= IW_AUTH_CIPHER_WEP40;
1458 }
1459 } else if (ar->arPairwiseCrypto == TKIP_CRYPT) {
1460 data->value |= IW_AUTH_CIPHER_TKIP;
1461 } else if (ar->arPairwiseCrypto == AES_CRYPT) {
1462 data->value |= IW_AUTH_CIPHER_CCMP;
1463 } else {
1464 ret = -1;
1465 }
1466 break;
1467 case IW_AUTH_CIPHER_GROUP:
1468 if (ar->arGroupCrypto == NONE_CRYPT) {
1469 data->value |= IW_AUTH_CIPHER_NONE;
1470 } else if (ar->arGroupCrypto == WEP_CRYPT) {
1471 if (ar->arGroupCryptoLen == 13) {
1472 data->value |= IW_AUTH_CIPHER_WEP104;
1473 } else {
1474 data->value |= IW_AUTH_CIPHER_WEP40;
1475 }
1476 } else if (ar->arGroupCrypto == TKIP_CRYPT) {
1477 data->value |= IW_AUTH_CIPHER_TKIP;
1478 } else if (ar->arGroupCrypto == AES_CRYPT) {
1479 data->value |= IW_AUTH_CIPHER_CCMP;
1480 } else {
1481 ret = -1;
1482 }
1483 break;
1484 case IW_AUTH_KEY_MGMT:
1485 if ((ar->arAuthMode == WPA_PSK_AUTH) ||
1486 (ar->arAuthMode == WPA2_PSK_AUTH)) {
1487 data->value |= IW_AUTH_KEY_MGMT_PSK;
1488 } else if ((ar->arAuthMode == WPA_AUTH) ||
1489 (ar->arAuthMode == WPA2_AUTH)) {
1490 data->value |= IW_AUTH_KEY_MGMT_802_1X;
1491 }
1492 break;
1493 case IW_AUTH_TKIP_COUNTERMEASURES:
1494 // TODO. Save countermeassure enable/disable
1495 data->value = 0;
1496 break;
1497 case IW_AUTH_DROP_UNENCRYPTED:
1498 break;
1499 case IW_AUTH_80211_AUTH_ALG:
1500 if (ar->arDot11AuthMode == OPEN_AUTH) {
1501 data->value |= IW_AUTH_ALG_OPEN_SYSTEM;
1502 } else if (ar->arDot11AuthMode == SHARED_AUTH) {
1503 data->value |= IW_AUTH_ALG_SHARED_KEY;
1504 } else if (ar->arDot11AuthMode == LEAP_AUTH) {
1505 data->value |= IW_AUTH_ALG_LEAP;
1506 } else {
1507 ret = -1;
1508 }
1509 break;
1510 case IW_AUTH_WPA_ENABLED:
1511 if (ar->arAuthMode == NONE_AUTH) {
1512 data->value = 0;
1513 } else {
1514 data->value = 1;
1515 }
1516 break;
1517 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1518 break;
1519 case IW_AUTH_ROAMING_CONTROL:
1520 break;
1521 case IW_AUTH_PRIVACY_INVOKED:
1522 if (ar->arPairwiseCrypto == NONE_CRYPT) {
1523 data->value = 0;
1524 } else {
1525 data->value = 1;
1526 }
1527 break;
1528#ifdef WAPI_ENABLE
1529 case IW_AUTH_WAPI_ENABLED:
1530 data->value = ar->arWapiEnable;
1531 break;
1532#endif
1533 default:
1534 ret = -1;
1535 break;
1536 }
1537
1538 return 0;
1539}
1540
1541/*
1542 * SIOCSIWPMKSA
1543 */
1544static int
1545ar6000_ioctl_siwpmksa(struct net_device *dev,
1546 struct iw_request_info *info,
1547 struct iw_point *data, char *extra)
1548{
a71f0bf6 1549 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
f68057e6 1550 s32 ret;
1f4c34bd 1551 int status;
30295c89
VM
1552 struct iw_pmksa *pmksa;
1553
1554 pmksa = (struct iw_pmksa *)extra;
1555
1071a134 1556 if (ar->arWmiReady == false) {
30295c89
VM
1557 return -EIO;
1558 }
1559
1560 ret = 0;
4f69cef0 1561 status = 0;
30295c89
VM
1562
1563 switch (pmksa->cmd) {
1564 case IW_PMKSA_ADD:
ab3655da 1565 status = wmi_setPmkid_cmd(ar->arWmi, (u8 *)pmksa->bssid.sa_data, pmksa->pmkid, true);
30295c89
VM
1566 break;
1567 case IW_PMKSA_REMOVE:
ab3655da 1568 status = wmi_setPmkid_cmd(ar->arWmi, (u8 *)pmksa->bssid.sa_data, pmksa->pmkid, false);
30295c89
VM
1569 break;
1570 case IW_PMKSA_FLUSH:
1071a134 1571 if (ar->arConnected == true) {
30295c89
VM
1572 status = wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, 0);
1573 }
1574 break;
1575 default:
1576 ret=-1;
1577 break;
1578 }
a1d46529 1579 if (status) {
30295c89
VM
1580 ret = -1;
1581 }
1582
1583 return ret;
1584}
1585
1586#ifdef WAPI_ENABLE
1587
1588#define PN_INIT 0x5c365c36
1589
1590static int ar6000_set_wapi_key(struct net_device *dev,
1591 struct iw_request_info *info,
1592 struct iw_point *erq, char *extra)
1593{
a71f0bf6 1594 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89
VM
1595 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1596 KEY_USAGE keyUsage = 0;
f68057e6 1597 s32 keyLen;
ab3655da 1598 u8 *keyData;
f68057e6 1599 s32 index;
e1ce2a3a 1600 u32 *PN;
f68057e6 1601 s32 i;
1f4c34bd 1602 int status;
ab3655da 1603 u8 wapiKeyRsc[16];
30295c89 1604 CRYPTO_TYPE keyType = WAPI_CRYPT;
ab3655da 1605 const u8 broadcastMac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
30295c89
VM
1606
1607 index = erq->flags & IW_ENCODE_INDEX;
1608 if (index && (((index - 1) < WMI_MIN_KEY_INDEX) ||
1609 ((index - 1) > WMI_MAX_KEY_INDEX))) {
1610 return -EIO;
1611 }
1612
1613 index--;
1614 if (index < 0 || index > 4) {
1615 return -EIO;
1616 }
ab3655da 1617 keyData = (u8 *)(ext + 1);
30295c89 1618 keyLen = erq->length - sizeof(struct iw_encode_ext);
05209262 1619 memcpy(wapiKeyRsc, ext->tx_seq, sizeof(wapiKeyRsc));
30295c89 1620
395e1cae 1621 if (memcmp(ext->addr.sa_data, broadcastMac, sizeof(broadcastMac)) == 0) {
30295c89 1622 keyUsage |= GROUP_USAGE;
e1ce2a3a 1623 PN = (u32 *)wapiKeyRsc;
30295c89
VM
1624 for (i = 0; i < 4; i++) {
1625 PN[i] = PN_INIT;
1626 }
1627 } else {
1628 keyUsage |= PAIRWISE_USAGE;
1629 }
1630 status = wmi_addKey_cmd(ar->arWmi,
1631 index,
1632 keyType,
1633 keyUsage,
1634 keyLen,
1635 wapiKeyRsc,
1636 keyData,
1637 KEY_OP_INIT_WAPIPN,
1638 NULL,
1639 SYNC_BEFORE_WMIFLAG);
4f69cef0 1640 if (0 != status) {
30295c89
VM
1641 return -EIO;
1642 }
1643 return 0;
1644}
1645
1646#endif
1647
1648/*
1649 * SIOCSIWENCODEEXT
1650 */
1651static int
1652ar6000_ioctl_siwencodeext(struct net_device *dev,
1653 struct iw_request_info *info,
1654 struct iw_point *erq, char *extra)
1655{
a71f0bf6 1656 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
f68057e6 1657 s32 index;
30295c89
VM
1658 struct iw_encode_ext *ext;
1659 KEY_USAGE keyUsage;
f68057e6 1660 s32 keyLen;
ab3655da
JP
1661 u8 *keyData;
1662 u8 keyRsc[8];
1f4c34bd 1663 int status;
30295c89
VM
1664 CRYPTO_TYPE keyType;
1665#ifdef USER_KEYS
1666 struct ieee80211req_key ik;
1667#endif /* USER_KEYS */
1668
1669 if (ar->arWlanState == WLAN_DISABLED) {
1670 return -EIO;
1671 }
1672
1673#ifdef USER_KEYS
1071a134 1674 ar->user_saved_keys.keyOk = false;
30295c89
VM
1675#endif /* USER_KEYS */
1676
1677 index = erq->flags & IW_ENCODE_INDEX;
1678
1679 if (index && (((index - 1) < WMI_MIN_KEY_INDEX) ||
1680 ((index - 1) > WMI_MAX_KEY_INDEX)))
1681 {
1682 return -EIO;
1683 }
1684
1685 ext = (struct iw_encode_ext *)extra;
1686 if (erq->flags & IW_ENCODE_DISABLED) {
1687 /*
1688 * Encryption disabled
1689 */
1690 if (index) {
1691 /*
1692 * If key index was specified then clear the specified key
1693 */
1694 index--;
1695 A_MEMZERO(ar->arWepKeyList[index].arKey,
1696 sizeof(ar->arWepKeyList[index].arKey));
1697 ar->arWepKeyList[index].arKeyLen = 0;
1698 }
1699 } else {
1700 /*
1701 * Enabling WEP encryption
1702 */
1703 if (index) {
1704 index--; /* keyindex is off base 1 in iwconfig */
1705 }
1706
1707 keyUsage = 0;
1708 keyLen = erq->length - sizeof(struct iw_encode_ext);
1709
1710 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
1711 keyUsage = TX_USAGE;
1712 ar->arDefTxKeyIndex = index;
1713 // Just setting the key index
1714 if (keyLen == 0) {
1715 return 0;
1716 }
1717 }
1718
1719 if (keyLen <= 0) {
1720 return -EIO;
1721 }
1722
1723 /* key follows iw_encode_ext */
ab3655da 1724 keyData = (u8 *)(ext + 1);
30295c89
VM
1725
1726 switch (ext->alg) {
1727 case IW_ENCODE_ALG_WEP:
1728 keyType = WEP_CRYPT;
1729#ifdef USER_KEYS
1730 ik.ik_type = IEEE80211_CIPHER_WEP;
1731#endif /* USER_KEYS */
1732 if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(keyLen)) {
1733 return -EIO;
1734 }
1735
1736 /* Check whether it is static wep. */
1737 if (!ar->arConnected) {
1738 A_MEMZERO(ar->arWepKeyList[index].arKey,
1739 sizeof(ar->arWepKeyList[index].arKey));
05209262 1740 memcpy(ar->arWepKeyList[index].arKey, keyData, keyLen);
30295c89
VM
1741 ar->arWepKeyList[index].arKeyLen = keyLen;
1742
1743 return 0;
1744 }
1745 break;
1746 case IW_ENCODE_ALG_TKIP:
1747 keyType = TKIP_CRYPT;
1748#ifdef USER_KEYS
1749 ik.ik_type = IEEE80211_CIPHER_TKIP;
1750#endif /* USER_KEYS */
1751 break;
1752 case IW_ENCODE_ALG_CCMP:
1753 keyType = AES_CRYPT;
1754#ifdef USER_KEYS
1755 ik.ik_type = IEEE80211_CIPHER_AES_CCM;
1756#endif /* USER_KEYS */
1757 break;
1758#ifdef WAPI_ENABLE
1759 case IW_ENCODE_ALG_SM4:
1760 if (ar->arWapiEnable) {
1761 return ar6000_set_wapi_key(dev, info, erq, extra);
1762 } else {
1763 return -EIO;
1764 }
1765#endif
1766 case IW_ENCODE_ALG_PMK:
1767 ar->arConnectCtrlFlags |= CONNECT_DO_WPA_OFFLOAD;
1768 return wmi_set_pmk_cmd(ar->arWmi, keyData);
1769 default:
1770 return -EIO;
1771 }
1772
1773
1774 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1775 keyUsage |= GROUP_USAGE;
1776 } else {
1777 keyUsage |= PAIRWISE_USAGE;
1778 }
1779
1780 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
05209262 1781 memcpy(keyRsc, ext->rx_seq, sizeof(keyRsc));
30295c89
VM
1782 } else {
1783 A_MEMZERO(keyRsc, sizeof(keyRsc));
1784 }
1785
1786 if (((WPA_PSK_AUTH == ar->arAuthMode) || (WPA2_PSK_AUTH == ar->arAuthMode)) &&
1787 (GROUP_USAGE & keyUsage))
1788 {
1789 A_UNTIMEOUT(&ar->disconnect_timer);
1790 }
1791
1792 status = wmi_addKey_cmd(ar->arWmi, index, keyType, keyUsage,
1793 keyLen, keyRsc,
1794 keyData, KEY_OP_INIT_VAL,
ab3655da 1795 (u8 *)ext->addr.sa_data,
30295c89 1796 SYNC_BOTH_WMIFLAG);
a1d46529 1797 if (status) {
30295c89
VM
1798 return -EIO;
1799 }
1800
1801#ifdef USER_KEYS
1802 ik.ik_keyix = index;
1803 ik.ik_keylen = keyLen;
1804 memcpy(ik.ik_keydata, keyData, keyLen);
1805 memcpy(&ik.ik_keyrsc, keyRsc, sizeof(keyRsc));
1806 memcpy(ik.ik_macaddr, ext->addr.sa_data, ETH_ALEN);
1807 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1808 memcpy(&ar->user_saved_keys.bcast_ik, &ik,
1809 sizeof(struct ieee80211req_key));
1810 } else {
1811 memcpy(&ar->user_saved_keys.ucast_ik, &ik,
1812 sizeof(struct ieee80211req_key));
1813 }
1071a134 1814 ar->user_saved_keys.keyOk = true;
30295c89
VM
1815#endif /* USER_KEYS */
1816 }
1817
1818
1819 return 0;
1820}
1821
1822/*
1823 * SIOCGIWENCODEEXT
1824 */
1825static int
1826ar6000_ioctl_giwencodeext(struct net_device *dev,
1827 struct iw_request_info *info,
1828 struct iw_point *erq, char *extra)
1829{
a71f0bf6 1830 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89
VM
1831
1832 if (ar->arWlanState == WLAN_DISABLED) {
1833 return -EIO;
1834 }
1835
1836 if (ar->arPairwiseCrypto == NONE_CRYPT) {
1837 erq->length = 0;
1838 erq->flags = IW_ENCODE_DISABLED;
1839 } else {
1840 erq->length = 0;
1841 }
1842
1843 return 0;
1844}
1845#endif // WIRELESS_EXT >= 18
1846
1847#if WIRELESS_EXT > 20
1848static int ar6000_ioctl_siwpower(struct net_device *dev,
1849 struct iw_request_info *info,
1850 union iwreq_data *wrqu, char *extra)
1851{
1852#ifndef ATH6K_CONFIG_OTA_MODE
a71f0bf6 1853 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89
VM
1854 WMI_POWER_MODE power_mode;
1855
1071a134 1856 if (ar->arWmiReady == false) {
30295c89
VM
1857 return -EIO;
1858 }
1859
1860 if (ar->arWlanState == WLAN_DISABLED) {
1861 return -EIO;
1862 }
1863
1864 if (wrqu->power.disabled)
1865 power_mode = MAX_PERF_POWER;
1866 else
1867 power_mode = REC_POWER;
1868
1869 if (wmi_powermode_cmd(ar->arWmi, power_mode) < 0)
1870 return -EIO;
1871#endif
1872 return 0;
1873}
1874
1875static int ar6000_ioctl_giwpower(struct net_device *dev,
1876 struct iw_request_info *info,
1877 union iwreq_data *wrqu, char *extra)
1878{
a71f0bf6 1879 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89
VM
1880 WMI_POWER_MODE power_mode;
1881
1071a134 1882 if (ar->arWmiReady == false) {
30295c89
VM
1883 return -EIO;
1884 }
1885
1886 if (ar->arWlanState == WLAN_DISABLED) {
1887 return -EIO;
1888 }
1889
1890 power_mode = wmi_get_power_mode_cmd(ar->arWmi);
1891
1892 if (power_mode == MAX_PERF_POWER)
1893 wrqu->power.disabled = 1;
1894 else
1895 wrqu->power.disabled = 0;
1896
1897 return 0;
1898}
1899#endif // WIRELESS_EXT > 20
1900
1901/*
1902 * SIOCGIWNAME
1903 */
1904int
1905ar6000_ioctl_giwname(struct net_device *dev,
1906 struct iw_request_info *info,
1907 char *name, char *extra)
1908{
ab3655da 1909 u8 capability;
a71f0bf6 1910 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89 1911
4f69cef0 1912 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
30295c89
VM
1913 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
1914 return -EOPNOTSUPP;
1915 }
1916
1917 if (ar->arWlanState == WLAN_DISABLED) {
1918 return -EIO;
1919 }
1920
1921 capability = ar->arPhyCapability;
1922 if(ar->arNetworkType == INFRA_NETWORK && ar->arConnected) {
1923 bss_t *bss = wmi_find_node(ar->arWmi, ar->arBssid);
1924 if (bss) {
1925 capability = get_bss_phy_capability(bss);
1926 wmi_node_return(ar->arWmi, bss);
1927 }
1928 }
1929 switch (capability) {
1930 case (WMI_11A_CAPABILITY):
1931 strncpy(name, "AR6000 802.11a", IFNAMSIZ);
1932 break;
1933 case (WMI_11G_CAPABILITY):
1934 strncpy(name, "AR6000 802.11g", IFNAMSIZ);
1935 break;
1936 case (WMI_11AG_CAPABILITY):
1937 strncpy(name, "AR6000 802.11ag", IFNAMSIZ);
1938 break;
1939 case (WMI_11NA_CAPABILITY):
1940 strncpy(name, "AR6000 802.11na", IFNAMSIZ);
1941 break;
1942 case (WMI_11NG_CAPABILITY):
1943 strncpy(name, "AR6000 802.11ng", IFNAMSIZ);
1944 break;
1945 case (WMI_11NAG_CAPABILITY):
1946 strncpy(name, "AR6000 802.11nag", IFNAMSIZ);
1947 break;
1948 default:
1949 strncpy(name, "AR6000 802.11b", IFNAMSIZ);
1950 break;
1951 }
1952
1953 return 0;
1954}
1955
1956/*
1957 * SIOCSIWFREQ
1958 */
1959int
1960ar6000_ioctl_siwfreq(struct net_device *dev,
1961 struct iw_request_info *info,
1962 struct iw_freq *freq, char *extra)
1963{
a71f0bf6 1964 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89 1965
4f69cef0 1966 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
30295c89
VM
1967 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
1968 return -EOPNOTSUPP;
1969 }
1970
1971 if (ar->arWlanState == WLAN_DISABLED) {
1972 return -EIO;
1973 }
1974
1975 /*
1976 * We support limiting the channels via wmiconfig.
1977 *
1978 * We use this command to configure the channel hint for the connect cmd
1979 * so it is possible the target will end up connecting to a different
1980 * channel.
1981 */
1982 if (freq->e > 1) {
1983 return -EINVAL;
1984 } else if (freq->e == 1) {
1985 ar->arChannelHint = freq->m / 100000;
1986 } else {
1987 if(freq->m) {
1988 ar->arChannelHint = wlan_ieee2freq(freq->m);
1989 } else {
1990 /* Auto Channel Selection */
1991 ar->arChannelHint = 0;
1992 }
1993 }
1994
1995 ar->ap_profile_flag = 1; /* There is a change in profile */
1996
1997 A_PRINTF("channel hint set to %d\n", ar->arChannelHint);
1998 return 0;
1999}
2000
2001/*
2002 * SIOCGIWFREQ
2003 */
2004int
2005ar6000_ioctl_giwfreq(struct net_device *dev,
2006 struct iw_request_info *info,
2007 struct iw_freq *freq, char *extra)
2008{
a71f0bf6 2009 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89 2010
4f69cef0 2011 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
30295c89
VM
2012 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2013 return -EOPNOTSUPP;
2014 }
2015
2016 if (ar->arWlanState == WLAN_DISABLED) {
2017 return -EIO;
2018 }
2019
2020 if (ar->arNetworkType == AP_NETWORK) {
2021 if(ar->arChannelHint) {
2022 freq->m = ar->arChannelHint * 100000;
2023 } else if(ar->arACS) {
2024 freq->m = ar->arACS * 100000;
2025 } else {
2026 return -EINVAL;
2027 }
2028 } else {
1071a134 2029 if (ar->arConnected != true) {
30295c89
VM
2030 return -EINVAL;
2031 } else {
2032 freq->m = ar->arBssChannel * 100000;
2033 }
2034 }
2035
2036 freq->e = 1;
2037
2038 return 0;
2039}
2040
2041/*
2042 * SIOCSIWMODE
2043 */
2044int
2045ar6000_ioctl_siwmode(struct net_device *dev,
2046 struct iw_request_info *info,
2047 __u32 *mode, char *extra)
2048{
a71f0bf6 2049 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89 2050
4f69cef0 2051 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
30295c89
VM
2052 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2053 return -EOPNOTSUPP;
2054 }
2055
2056 if (ar->arWlanState == WLAN_DISABLED) {
2057 return -EIO;
2058 }
2059
2060 /*
2061 * clear SSID during mode switch in connected state
2062 */
1071a134 2063 if(!(ar->arNetworkType == (((*mode) == IW_MODE_INFRA) ? INFRA_NETWORK : ADHOC_NETWORK)) && (ar->arConnected == true) ){
30295c89
VM
2064 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
2065 ar->arSsidLen = 0;
2066 }
2067
2068 switch (*mode) {
2069 case IW_MODE_INFRA:
2070 ar->arNextMode = INFRA_NETWORK;
2071 break;
2072 case IW_MODE_ADHOC:
2073 ar->arNextMode = ADHOC_NETWORK;
2074 break;
2075 case IW_MODE_MASTER:
2076 ar->arNextMode = AP_NETWORK;
2077 break;
2078 default:
2079 return -EINVAL;
2080 }
2081
2082 /* clear all shared parameters between AP and STA|IBSS modes when we
2083 * switch between them. Switch between STA & IBSS modes does'nt clear
2084 * the shared profile. This is as per the original design for switching
2085 * between STA & IBSS.
2086 */
2087 if (ar->arNetworkType == AP_NETWORK || ar->arNextMode == AP_NETWORK) {
2088 ar->arDot11AuthMode = OPEN_AUTH;
2089 ar->arAuthMode = NONE_AUTH;
2090 ar->arPairwiseCrypto = NONE_CRYPT;
2091 ar->arPairwiseCryptoLen = 0;
2092 ar->arGroupCrypto = NONE_CRYPT;
2093 ar->arGroupCryptoLen = 0;
2094 ar->arChannelHint = 0;
2095 ar->arBssChannel = 0;
2096 A_MEMZERO(ar->arBssid, sizeof(ar->arBssid));
2097 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
2098 ar->arSsidLen = 0;
2099 }
2100
2101 /* SSID has to be cleared to trigger a profile change while switching
2102 * between STA & IBSS modes having the same SSID
2103 */
2104 if (ar->arNetworkType != ar->arNextMode) {
2105 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
2106 ar->arSsidLen = 0;
2107 }
2108
2109 return 0;
2110}
2111
2112/*
2113 * SIOCGIWMODE
2114 */
2115int
2116ar6000_ioctl_giwmode(struct net_device *dev,
2117 struct iw_request_info *info,
2118 __u32 *mode, char *extra)
2119{
a71f0bf6 2120 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89 2121
4f69cef0 2122 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
30295c89
VM
2123 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2124 return -EOPNOTSUPP;
2125 }
2126
2127 if (ar->arWlanState == WLAN_DISABLED) {
2128 return -EIO;
2129 }
2130
2131 switch (ar->arNetworkType) {
2132 case INFRA_NETWORK:
2133 *mode = IW_MODE_INFRA;
2134 break;
2135 case ADHOC_NETWORK:
2136 *mode = IW_MODE_ADHOC;
2137 break;
2138 case AP_NETWORK:
2139 *mode = IW_MODE_MASTER;
2140 break;
2141 default:
2142 return -EIO;
2143 }
2144 return 0;
2145}
2146
2147/*
2148 * SIOCSIWSENS
2149 */
2150int
2151ar6000_ioctl_siwsens(struct net_device *dev,
2152 struct iw_request_info *info,
2153 struct iw_param *sens, char *extra)
2154{
2155 return 0;
2156}
2157
2158/*
2159 * SIOCGIWSENS
2160 */
2161int
2162ar6000_ioctl_giwsens(struct net_device *dev,
2163 struct iw_request_info *info,
2164 struct iw_param *sens, char *extra)
2165{
2166 sens->value = 0;
2167 sens->fixed = 1;
2168
2169 return 0;
2170}
2171
2172/*
2173 * SIOCGIWRANGE
2174 */
2175int
2176ar6000_ioctl_giwrange(struct net_device *dev,
2177 struct iw_request_info *info,
2178 struct iw_point *data, char *extra)
2179{
a71f0bf6 2180 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89
VM
2181 struct iw_range *range = (struct iw_range *) extra;
2182 int i, ret = 0;
2183
4f69cef0 2184 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
30295c89
VM
2185 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2186 return -EOPNOTSUPP;
2187 }
2188
2189 if (ar->bIsDestroyProgress) {
2190 return -EBUSY;
2191 }
2192
1071a134 2193 if (ar->arWmiReady == false) {
30295c89
VM
2194 return -EIO;
2195 }
2196
2197 if (down_interruptible(&ar->arSem)) {
2198 return -ERESTARTSYS;
2199 }
2200
2201 if (ar->bIsDestroyProgress) {
2202 up(&ar->arSem);
2203 return -EBUSY;
2204 }
2205
2206 ar->arNumChannels = -1;
2207 A_MEMZERO(ar->arChannelList, sizeof (ar->arChannelList));
2208
4f69cef0 2209 if (wmi_get_channelList_cmd(ar->arWmi) != 0) {
30295c89
VM
2210 up(&ar->arSem);
2211 return -EIO;
2212 }
2213
2214 wait_event_interruptible_timeout(arEvent, ar->arNumChannels != -1, wmitimeout * HZ);
2215
2216 if (signal_pending(current)) {
2217 up(&ar->arSem);
2218 return -EINTR;
2219 }
2220
2221 data->length = sizeof(struct iw_range);
2222 A_MEMZERO(range, sizeof(struct iw_range));
2223
2224 range->txpower_capa = 0;
2225
2226 range->min_pmp = 1 * 1024;
2227 range->max_pmp = 65535 * 1024;
2228 range->min_pmt = 1 * 1024;
2229 range->max_pmt = 1000 * 1024;
2230 range->pmp_flags = IW_POWER_PERIOD;
2231 range->pmt_flags = IW_POWER_TIMEOUT;
2232 range->pm_capa = 0;
2233
2234 range->we_version_compiled = WIRELESS_EXT;
2235 range->we_version_source = 13;
2236
2237 range->retry_capa = IW_RETRY_LIMIT;
2238 range->retry_flags = IW_RETRY_LIMIT;
2239 range->min_retry = 0;
2240 range->max_retry = 255;
2241
2242 range->num_frequency = range->num_channels = ar->arNumChannels;
2243 for (i = 0; i < ar->arNumChannels; i++) {
2244 range->freq[i].i = wlan_freq2ieee(ar->arChannelList[i]);
2245 range->freq[i].m = ar->arChannelList[i] * 100000;
2246 range->freq[i].e = 1;
2247 /*
2248 * Linux supports max of 32 channels, bail out once you
2249 * reach the max.
2250 */
2251 if (i == IW_MAX_FREQUENCIES) {
2252 break;
2253 }
2254 }
2255
2256 /* Max quality is max field value minus noise floor */
2257 range->max_qual.qual = 0xff - 161;
2258
2259 /*
2260 * In order to use dBm measurements, 'level' must be lower
2261 * than any possible measurement (see iw_print_stats() in
2262 * wireless tools). It's unclear how this is meant to be
2263 * done, but setting zero in these values forces dBm and
2264 * the actual numbers are not used.
2265 */
2266 range->max_qual.level = 0;
2267 range->max_qual.noise = 0;
2268
2269 range->sensitivity = 3;
2270
2271 range->max_encoding_tokens = 4;
2272 /* XXX query driver to find out supported key sizes */
2273 range->num_encoding_sizes = 3;
2274 range->encoding_size[0] = 5; /* 40-bit */
2275 range->encoding_size[1] = 13; /* 104-bit */
2276 range->encoding_size[2] = 16; /* 128-bit */
2277
2278 range->num_bitrates = 0;
2279
2280 /* estimated maximum TCP throughput values (bps) */
2281 range->throughput = 22000000;
2282
2283 range->min_rts = 0;
2284 range->max_rts = 2347;
2285 range->min_frag = 256;
2286 range->max_frag = 2346;
2287
2288 up(&ar->arSem);
2289
2290 return ret;
2291}
2292
2293
2294/*
2295 * SIOCSIWAP
2296 * This ioctl is used to set the desired bssid for the connect command.
2297 */
2298int
2299ar6000_ioctl_siwap(struct net_device *dev,
2300 struct iw_request_info *info,
2301 struct sockaddr *ap_addr, char *extra)
2302{
a71f0bf6 2303 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89 2304
4f69cef0 2305 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
30295c89
VM
2306 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2307 return -EOPNOTSUPP;
2308 }
2309
2310 if (ar->arWlanState == WLAN_DISABLED) {
2311 return -EIO;
2312 }
2313
2314 if (ap_addr->sa_family != ARPHRD_ETHER) {
2315 return -EIO;
2316 }
2317
395e1cae 2318 if (memcmp(&ap_addr->sa_data, bcast_mac, AR6000_ETH_ADDR_LEN) == 0) {
30295c89
VM
2319 A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
2320 } else {
05209262 2321 memcpy(ar->arReqBssid, &ap_addr->sa_data, sizeof(ar->arReqBssid));
30295c89
VM
2322 }
2323
2324 return 0;
2325}
2326
2327/*
2328 * SIOCGIWAP
2329 */
2330int
2331ar6000_ioctl_giwap(struct net_device *dev,
2332 struct iw_request_info *info,
2333 struct sockaddr *ap_addr, char *extra)
2334{
a71f0bf6 2335 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89 2336
4f69cef0 2337 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
30295c89
VM
2338 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2339 return -EOPNOTSUPP;
2340 }
2341
2342 if (ar->arWlanState == WLAN_DISABLED) {
2343 return -EIO;
2344 }
2345
2346 if (ar->arNetworkType == AP_NETWORK) {
05209262 2347 memcpy(&ap_addr->sa_data, dev->dev_addr, ATH_MAC_LEN);
30295c89
VM
2348 ap_addr->sa_family = ARPHRD_ETHER;
2349 return 0;
2350 }
2351
1071a134 2352 if (ar->arConnected != true) {
30295c89
VM
2353 return -EINVAL;
2354 }
2355
05209262 2356 memcpy(&ap_addr->sa_data, ar->arBssid, sizeof(ar->arBssid));
30295c89
VM
2357 ap_addr->sa_family = ARPHRD_ETHER;
2358
2359 return 0;
2360}
2361
2362#if (WIRELESS_EXT >= 18)
2363/*
2364 * SIOCSIWMLME
2365 */
2366int
2367ar6000_ioctl_siwmlme(struct net_device *dev,
2368 struct iw_request_info *info,
2369 struct iw_point *data, char *extra)
2370{
a71f0bf6 2371 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89 2372
4f69cef0 2373 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
30295c89
VM
2374 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2375 return -EOPNOTSUPP;
2376 }
2377
2378 if (ar->bIsDestroyProgress) {
2379 return -EBUSY;
2380 }
2381
2382 if (ar->arWlanState == WLAN_DISABLED) {
2383 return -EIO;
2384 }
2385
1071a134 2386 if (ar->arWmiReady == false) {
30295c89
VM
2387 return -EIO;
2388 }
2389
2390 if (down_interruptible(&ar->arSem)) {
2391 return -ERESTARTSYS;
2392 }
2393
2394 if (data->pointer && data->length == sizeof(struct iw_mlme)) {
2395
ab3655da 2396 u8 arNetworkType;
30295c89
VM
2397 struct iw_mlme mlme;
2398
2399 if (copy_from_user(&mlme, data->pointer, sizeof(struct iw_mlme)))
2400 return -EIO;
2401
2402 switch (mlme.cmd) {
2403
2404 case IW_MLME_DEAUTH:
2405 /* fall through */
2406 case IW_MLME_DISASSOC:
1071a134 2407 if ((ar->arConnected != true) ||
30295c89
VM
2408 (memcmp(ar->arBssid, mlme.addr.sa_data, 6) != 0)) {
2409
2410 up(&ar->arSem);
2411 return -EINVAL;
2412 }
2413 wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, 0);
2414 arNetworkType = ar->arNetworkType;
2415 ar6000_init_profile_info(ar);
2416 ar->arNetworkType = arNetworkType;
2417 reconnect_flag = 0;
83195cc8 2418 ar6000_disconnect(ar);
30295c89
VM
2419 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
2420 ar->arSsidLen = 0;
1071a134 2421 if (ar->arSkipScan == false) {
30295c89
VM
2422 A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
2423 }
2424 break;
2425
2426 case IW_MLME_AUTH:
2427 /* fall through */
2428 case IW_MLME_ASSOC:
2429 /* fall through */
2430 default:
2431 up(&ar->arSem);
2432 return -EOPNOTSUPP;
2433 }
2434 }
2435
2436 up(&ar->arSem);
2437 return 0;
2438}
2439#endif /* WIRELESS_EXT >= 18 */
2440
2441/*
2442 * SIOCGIWAPLIST
2443 */
2444int
2445ar6000_ioctl_iwaplist(struct net_device *dev,
2446 struct iw_request_info *info,
2447 struct iw_point *data, char *extra)
2448{
2449 return -EIO; /* for now */
2450}
2451
2452/*
2453 * SIOCSIWSCAN
2454 */
2455int
2456ar6000_ioctl_siwscan(struct net_device *dev,
2457 struct iw_request_info *info,
2458 struct iw_point *data, char *extra)
2459{
2460#define ACT_DWELLTIME_DEFAULT 105
2461#define HOME_TXDRAIN_TIME 100
2462#define SCAN_INT HOME_TXDRAIN_TIME + ACT_DWELLTIME_DEFAULT
a71f0bf6 2463 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89
VM
2464 int ret = 0;
2465
4f69cef0 2466 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
30295c89
VM
2467 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2468 return -EOPNOTSUPP;
2469 }
2470
1071a134 2471 if (ar->arWmiReady == false) {
30295c89
VM
2472 return -EIO;
2473 }
2474
2475 if (ar->arWlanState == WLAN_DISABLED) {
2476 return -EIO;
2477 }
2478
2479 /* If scan is issued in the middle of ongoing scan or connect,
2480 dont issue another one */
2481 if ( ar->scan_triggered > 0 ) {
2482 ++ar->scan_triggered;
2483 if (ar->scan_triggered < 5) {
2484 return 0;
2485 } else {
2486 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,("Scan request is triggered over 5 times. Not scan complete event\n"));
2487 }
2488 }
2489
2490 if (!ar->arUserBssFilter) {
4f69cef0 2491 if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != 0) {
30295c89
VM
2492 return -EIO;
2493 }
2494 }
2495
2496 if (ar->arConnected) {
4f69cef0 2497 if (wmi_get_stats_cmd(ar->arWmi) != 0) {
30295c89
VM
2498 return -EIO;
2499 }
2500 }
2501
2502#ifdef ANDROID_ENV
2503#if WIRELESS_EXT >= 18
2504 if (data->pointer && (data->length == sizeof(struct iw_scan_req)))
2505 {
2506 if ((data->flags & IW_SCAN_THIS_ESSID) == IW_SCAN_THIS_ESSID)
2507 {
2508 struct iw_scan_req req;
2509 if (copy_from_user(&req, data->pointer, sizeof(struct iw_scan_req)))
2510 return -EIO;
4f69cef0 2511 if (wmi_probedSsid_cmd(ar->arWmi, 1, SPECIFIC_SSID_FLAG, req.essid_len, req.essid) != 0)
30295c89 2512 return -EIO;
1071a134 2513 ar->scanSpecificSsid = true;
30295c89
VM
2514 }
2515 else
2516 {
2517 if (ar->scanSpecificSsid) {
4f69cef0 2518 if (wmi_probedSsid_cmd(ar->arWmi, 1, DISABLE_SSID_FLAG, 0, NULL) != 0)
30295c89 2519 return -EIO;
1071a134 2520 ar->scanSpecificSsid = false;
30295c89
VM
2521 }
2522 }
2523 }
2524 else
2525 {
2526 if (ar->scanSpecificSsid) {
4f69cef0 2527 if (wmi_probedSsid_cmd(ar->arWmi, 1, DISABLE_SSID_FLAG, 0, NULL) != 0)
30295c89 2528 return -EIO;
1071a134 2529 ar->scanSpecificSsid = false;
30295c89
VM
2530 }
2531 }
2532#endif
2533#endif /* ANDROID_ENV */
2534
1071a134 2535 if (wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, false, false, \
4f69cef0 2536 0, 0, 0, NULL) != 0) {
30295c89
VM
2537 ret = -EIO;
2538 }
2539
2540 if (ret == 0) {
2541 ar->scan_triggered = 1;
2542 }
2543
2544 return ret;
2545#undef ACT_DWELLTIME_DEFAULT
2546#undef HOME_TXDRAIN_TIME
2547#undef SCAN_INT
2548}
2549
2550
2551/*
2552 * Units are in db above the noise floor. That means the
2553 * rssi values reported in the tx/rx descriptors in the
2554 * driver are the SNR expressed in db.
2555 *
2556 * If you assume that the noise floor is -95, which is an
2557 * excellent assumption 99.5 % of the time, then you can
2558 * derive the absolute signal level (i.e. -95 + rssi).
2559 * There are some other slight factors to take into account
2560 * depending on whether the rssi measurement is from 11b,
2561 * 11g, or 11a. These differences are at most 2db and
2562 * can be documented.
2563 *
2564 * NB: various calculations are based on the orinoco/wavelan
2565 * drivers for compatibility
2566 */
2567static void
f2ab1275 2568ar6000_set_quality(struct iw_quality *iq, s8 rssi)
30295c89
VM
2569{
2570 if (rssi < 0) {
2571 iq->qual = 0;
2572 } else {
2573 iq->qual = rssi;
2574 }
2575
2576 /* NB: max is 94 because noise is hardcoded to 161 */
2577 if (iq->qual > 94)
2578 iq->qual = 94;
2579
2580 iq->noise = 161; /* -95dBm */
2581 iq->level = iq->noise + iq->qual;
2582 iq->updated = 7;
2583}
2584
2585
2586int
2587ar6000_ioctl_siwcommit(struct net_device *dev,
2588 struct iw_request_info *info,
2589 struct iw_point *data, char *extra)
2590{
a71f0bf6 2591 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
30295c89 2592
4f69cef0 2593 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
30295c89
VM
2594 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2595 return -EOPNOTSUPP;
2596 }
2597
1071a134 2598 if (ar->arWmiReady == false) {
30295c89
VM
2599 return -EIO;
2600 }
2601
2602 if (ar->arWlanState == WLAN_DISABLED) {
2603 return -EIO;
2604 }
2605
2606 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("AP: SSID %s freq %d authmode %d dot11 auth %d"\
2607 " PW crypto %d GRP crypto %d\n",
2608 ar->arSsid, ar->arChannelHint,
2609 ar->arAuthMode, ar->arDot11AuthMode,
2610 ar->arPairwiseCrypto, ar->arGroupCrypto));
2611
2612 ar6000_ap_mode_profile_commit(ar);
2613
2614 /* if there is a profile switch from STA|IBSS mode to AP mode,
2615 * update the host driver association state for the STA|IBSS mode.
2616 */
2617 if (ar->arNetworkType != AP_NETWORK && ar->arNextMode == AP_NETWORK) {
30295c89
VM
2618 /* Stop getting pkts from upper stack */
2619 netif_stop_queue(ar->arNetDev);
2620 A_MEMZERO(ar->arBssid, sizeof(ar->arBssid));
2621 ar->arBssChannel = 0;
2622 ar->arBeaconInterval = 0;
2623
2624 /* Flush the Tx queues */
2625 ar6000_TxDataCleanup(ar);
2626
2627 /* Start getting pkts from upper stack */
2628 netif_wake_queue(ar->arNetDev);
2629 }
2630
2631 return 0;
2632}
2633
2634#define W_PROTO(_x) wait_ ## _x
2635#define WAIT_HANDLER_IMPL(_x, type) \
2636int wait_ ## _x (struct net_device *dev, struct iw_request_info *info, type wrqu, char *extra) {\
2637 int ret; \
2638 dev_hold(dev); \
2639 rtnl_unlock(); \
2640 ret = _x(dev, info, wrqu, extra); \
2641 rtnl_lock(); \
2642 dev_put(dev); \
2643 return ret;\
2644}
2645
2646WAIT_HANDLER_IMPL(ar6000_ioctl_siwessid, struct iw_point *)
2647WAIT_HANDLER_IMPL(ar6000_ioctl_giwrate, struct iw_param *)
2648WAIT_HANDLER_IMPL(ar6000_ioctl_giwtxpow, struct iw_param *)
2649WAIT_HANDLER_IMPL(ar6000_ioctl_giwrange, struct iw_point*)
2650
2651/* Structures to export the Wireless Handlers */
2652static const iw_handler ath_handlers[] = {
2653 (iw_handler) ar6000_ioctl_siwcommit, /* SIOCSIWCOMMIT */
2654 (iw_handler) ar6000_ioctl_giwname, /* SIOCGIWNAME */
2655 (iw_handler) NULL, /* SIOCSIWNWID */
2656 (iw_handler) NULL, /* SIOCGIWNWID */
2657 (iw_handler) ar6000_ioctl_siwfreq, /* SIOCSIWFREQ */
2658 (iw_handler) ar6000_ioctl_giwfreq, /* SIOCGIWFREQ */
2659 (iw_handler) ar6000_ioctl_siwmode, /* SIOCSIWMODE */
2660 (iw_handler) ar6000_ioctl_giwmode, /* SIOCGIWMODE */
2661 (iw_handler) ar6000_ioctl_siwsens, /* SIOCSIWSENS */
2662 (iw_handler) ar6000_ioctl_giwsens, /* SIOCGIWSENS */
2663 (iw_handler) NULL /* not _used */, /* SIOCSIWRANGE */
2664 (iw_handler) W_PROTO(ar6000_ioctl_giwrange),/* SIOCGIWRANGE */
2665 (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */
2666 (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
2667 (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */
2668 (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */
2669 (iw_handler) NULL, /* SIOCSIWSPY */
2670 (iw_handler) NULL, /* SIOCGIWSPY */
2671 (iw_handler) NULL, /* SIOCSIWTHRSPY */
2672 (iw_handler) NULL, /* SIOCGIWTHRSPY */
2673 (iw_handler) ar6000_ioctl_siwap, /* SIOCSIWAP */
2674 (iw_handler) ar6000_ioctl_giwap, /* SIOCGIWAP */
2675#if (WIRELESS_EXT >= 18)
2676 (iw_handler) ar6000_ioctl_siwmlme, /* SIOCSIWMLME */
2677#else
2678 (iw_handler) NULL, /* -- hole -- */
2679#endif /* WIRELESS_EXT >= 18 */
2680 (iw_handler) ar6000_ioctl_iwaplist, /* SIOCGIWAPLIST */
2681 (iw_handler) ar6000_ioctl_siwscan, /* SIOCSIWSCAN */
2682 (iw_handler) ar6000_ioctl_giwscan, /* SIOCGIWSCAN */
2683 (iw_handler) W_PROTO(ar6000_ioctl_siwessid),/* SIOCSIWESSID */
2684 (iw_handler) ar6000_ioctl_giwessid, /* SIOCGIWESSID */
2685 (iw_handler) NULL, /* SIOCSIWNICKN */
2686 (iw_handler) NULL, /* SIOCGIWNICKN */
2687 (iw_handler) NULL, /* -- hole -- */
2688 (iw_handler) NULL, /* -- hole -- */
2689 (iw_handler) ar6000_ioctl_siwrate, /* SIOCSIWRATE */
2690 (iw_handler) W_PROTO(ar6000_ioctl_giwrate), /* SIOCGIWRATE */
2691 (iw_handler) NULL, /* SIOCSIWRTS */
2692 (iw_handler) NULL, /* SIOCGIWRTS */
2693 (iw_handler) NULL, /* SIOCSIWFRAG */
2694 (iw_handler) NULL, /* SIOCGIWFRAG */
2695 (iw_handler) ar6000_ioctl_siwtxpow, /* SIOCSIWTXPOW */
2696 (iw_handler) W_PROTO(ar6000_ioctl_giwtxpow),/* SIOCGIWTXPOW */
2697 (iw_handler) ar6000_ioctl_siwretry, /* SIOCSIWRETRY */
2698 (iw_handler) ar6000_ioctl_giwretry, /* SIOCGIWRETRY */
2699 (iw_handler) ar6000_ioctl_siwencode, /* SIOCSIWENCODE */
2700 (iw_handler) ar6000_ioctl_giwencode, /* SIOCGIWENCODE */
2701#if WIRELESS_EXT > 20
2702 (iw_handler) ar6000_ioctl_siwpower, /* SIOCSIWPOWER */
2703 (iw_handler) ar6000_ioctl_giwpower, /* SIOCGIWPOWER */
2704#endif // WIRELESS_EXT > 20
2705#if WIRELESS_EXT >= 18
2706 (iw_handler) NULL, /* -- hole -- */
2707 (iw_handler) NULL, /* -- hole -- */
2708 (iw_handler) ar6000_ioctl_siwgenie, /* SIOCSIWGENIE */
2709 (iw_handler) ar6000_ioctl_giwgenie, /* SIOCGIWGENIE */
2710 (iw_handler) ar6000_ioctl_siwauth, /* SIOCSIWAUTH */
2711 (iw_handler) ar6000_ioctl_giwauth, /* SIOCGIWAUTH */
2712 (iw_handler) ar6000_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */
2713 (iw_handler) ar6000_ioctl_giwencodeext, /* SIOCGIWENCODEEXT */
2714 (iw_handler) ar6000_ioctl_siwpmksa, /* SIOCSIWPMKSA */
2715#endif // WIRELESS_EXT >= 18
2716};
2717
2718struct iw_handler_def ath_iw_handler_def = {
2719 .standard = (iw_handler *)ath_handlers,
2720 .num_standard = ARRAY_SIZE(ath_handlers),
2721 .private = NULL,
2722 .num_private = 0,
2723};