Merge git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / ath6kl / os / linux / wireless_ext.c
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
35 static void ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi);
36 extern unsigned int wmitimeout;
37 extern 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 */
44 static u_int
45 encode_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
67 static A_UINT8
68 get_bss_phy_capability(bss_t *bss)
69 {
70 A_UINT8 capability = 0;
71 struct ieee80211_common_ie *cie = &bss->ni_cie;
72 #define CHAN_IS_11A(x) (!((x >= 2412) && (x <= 2484)))
73 if (CHAN_IS_11A(cie->ie_chan)) {
74 if (cie->ie_htcap) {
75 capability = WMI_11NA_CAPABILITY;
76 } else {
77 capability = WMI_11A_CAPABILITY;
78 }
79 } else if ((cie->ie_erp) || (cie->ie_xrates)) {
80 if (cie->ie_htcap) {
81 capability = WMI_11NG_CAPABILITY;
82 } else {
83 capability = WMI_11G_CAPABILITY;
84 }
85 }
86 return capability;
87 }
88
89 void
90 ar6000_scan_node(void *arg, bss_t *ni)
91 {
92 struct iw_event iwe;
93 #if WIRELESS_EXT > 14
94 char buf[256];
95 #endif
96 struct ar_giwscan_param *param;
97 A_CHAR *current_ev;
98 A_CHAR *end_buf;
99 struct ieee80211_common_ie *cie;
100 A_CHAR *current_val;
101 A_INT32 j;
102 A_UINT32 rate_len, data_len = 0;
103
104 param = (struct ar_giwscan_param *)arg;
105
106 current_ev = param->current_ev;
107 end_buf = param->end_buf;
108
109 cie = &ni->ni_cie;
110
111 if ((end_buf - current_ev) > IW_EV_ADDR_LEN)
112 {
113 A_MEMZERO(&iwe, sizeof(iwe));
114 iwe.cmd = SIOCGIWAP;
115 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
116 A_MEMCPY(iwe.u.ap_addr.sa_data, ni->ni_macaddr, 6);
117 current_ev = IWE_STREAM_ADD_EVENT(param->info, current_ev, end_buf,
118 &iwe, IW_EV_ADDR_LEN);
119 }
120 param->bytes_needed += IW_EV_ADDR_LEN;
121
122 data_len = cie->ie_ssid[1] + IW_EV_POINT_LEN;
123 if ((end_buf - current_ev) > data_len)
124 {
125 A_MEMZERO(&iwe, sizeof(iwe));
126 iwe.cmd = SIOCGIWESSID;
127 iwe.u.data.flags = 1;
128 iwe.u.data.length = cie->ie_ssid[1];
129 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
130 &iwe, (char*)&cie->ie_ssid[2]);
131 }
132 param->bytes_needed += data_len;
133
134 if (cie->ie_capInfo & (IEEE80211_CAPINFO_ESS|IEEE80211_CAPINFO_IBSS)) {
135 if ((end_buf - current_ev) > IW_EV_UINT_LEN)
136 {
137 A_MEMZERO(&iwe, sizeof(iwe));
138 iwe.cmd = SIOCGIWMODE;
139 iwe.u.mode = cie->ie_capInfo & IEEE80211_CAPINFO_ESS ?
140 IW_MODE_MASTER : IW_MODE_ADHOC;
141 current_ev = IWE_STREAM_ADD_EVENT(param->info, current_ev, end_buf,
142 &iwe, IW_EV_UINT_LEN);
143 }
144 param->bytes_needed += IW_EV_UINT_LEN;
145 }
146
147 if ((end_buf - current_ev) > IW_EV_FREQ_LEN)
148 {
149 A_MEMZERO(&iwe, sizeof(iwe));
150 iwe.cmd = SIOCGIWFREQ;
151 iwe.u.freq.m = cie->ie_chan * 100000;
152 iwe.u.freq.e = 1;
153 current_ev = IWE_STREAM_ADD_EVENT(param->info, current_ev, end_buf,
154 &iwe, IW_EV_FREQ_LEN);
155 }
156 param->bytes_needed += IW_EV_FREQ_LEN;
157
158 if ((end_buf - current_ev) > IW_EV_QUAL_LEN)
159 {
160 A_MEMZERO(&iwe, sizeof(iwe));
161 iwe.cmd = IWEVQUAL;
162 ar6000_set_quality(&iwe.u.qual, ni->ni_snr);
163 current_ev = IWE_STREAM_ADD_EVENT(param->info, current_ev, end_buf,
164 &iwe, IW_EV_QUAL_LEN);
165 }
166 param->bytes_needed += IW_EV_QUAL_LEN;
167
168 if ((end_buf - current_ev) > IW_EV_POINT_LEN)
169 {
170 A_MEMZERO(&iwe, sizeof(iwe));
171 iwe.cmd = SIOCGIWENCODE;
172 if (cie->ie_capInfo & IEEE80211_CAPINFO_PRIVACY) {
173 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
174 } else {
175 iwe.u.data.flags = IW_ENCODE_DISABLED;
176 }
177 iwe.u.data.length = 0;
178 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
179 &iwe, "");
180 }
181 param->bytes_needed += IW_EV_POINT_LEN;
182
183 /* supported bit rate */
184 A_MEMZERO(&iwe, sizeof(iwe));
185 iwe.cmd = SIOCGIWRATE;
186 iwe.u.bitrate.fixed = 0;
187 iwe.u.bitrate.disabled = 0;
188 iwe.u.bitrate.value = 0;
189 current_val = current_ev + IW_EV_LCP_LEN;
190 param->bytes_needed += IW_EV_LCP_LEN;
191
192 if (cie->ie_rates != NULL) {
193 rate_len = cie->ie_rates[1];
194 data_len = (rate_len * (IW_EV_PARAM_LEN - IW_EV_LCP_LEN));
195 if ((end_buf - current_ev) > data_len)
196 {
197 for (j = 0; j < rate_len; j++) {
198 unsigned char val;
199 val = cie->ie_rates[2 + j];
200 iwe.u.bitrate.value =
201 (val >= 0x80)? ((val - 0x80) * 500000): (val * 500000);
202 current_val = IWE_STREAM_ADD_VALUE(param->info, current_ev,
203 current_val, end_buf,
204 &iwe, IW_EV_PARAM_LEN);
205 }
206 }
207 param->bytes_needed += data_len;
208 }
209
210 if (cie->ie_xrates != NULL) {
211 rate_len = cie->ie_xrates[1];
212 data_len = (rate_len * (IW_EV_PARAM_LEN - IW_EV_LCP_LEN));
213 if ((end_buf - current_ev) > data_len)
214 {
215 for (j = 0; j < rate_len; j++) {
216 unsigned char val;
217 val = cie->ie_xrates[2 + j];
218 iwe.u.bitrate.value =
219 (val >= 0x80)? ((val - 0x80) * 500000): (val * 500000);
220 current_val = IWE_STREAM_ADD_VALUE(param->info, current_ev,
221 current_val, end_buf,
222 &iwe, IW_EV_PARAM_LEN);
223 }
224 }
225 param->bytes_needed += data_len;
226 }
227 /* remove fixed header if no rates were added */
228 if ((current_val - current_ev) > IW_EV_LCP_LEN)
229 current_ev = current_val;
230
231 #if WIRELESS_EXT >= 18
232 /* IE */
233 if (cie->ie_wpa != NULL) {
234 data_len = cie->ie_wpa[1] + 2 + IW_EV_POINT_LEN;
235 if ((end_buf - current_ev) > data_len)
236 {
237 A_MEMZERO(&iwe, sizeof(iwe));
238 iwe.cmd = IWEVGENIE;
239 iwe.u.data.length = cie->ie_wpa[1] + 2;
240 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
241 &iwe, (char*)cie->ie_wpa);
242 }
243 param->bytes_needed += data_len;
244 }
245
246 if (cie->ie_rsn != NULL && cie->ie_rsn[0] == IEEE80211_ELEMID_RSN) {
247 data_len = cie->ie_rsn[1] + 2 + IW_EV_POINT_LEN;
248 if ((end_buf - current_ev) > data_len)
249 {
250 A_MEMZERO(&iwe, sizeof(iwe));
251 iwe.cmd = IWEVGENIE;
252 iwe.u.data.length = cie->ie_rsn[1] + 2;
253 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
254 &iwe, (char*)cie->ie_rsn);
255 }
256 param->bytes_needed += data_len;
257 }
258
259 #endif /* WIRELESS_EXT >= 18 */
260
261 if ((end_buf - current_ev) > IW_EV_CHAR_LEN)
262 {
263 /* protocol */
264 A_MEMZERO(&iwe, sizeof(iwe));
265 iwe.cmd = SIOCGIWNAME;
266 switch (get_bss_phy_capability(ni)) {
267 case WMI_11A_CAPABILITY:
268 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11a");
269 break;
270 case WMI_11G_CAPABILITY:
271 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
272 break;
273 case WMI_11NA_CAPABILITY:
274 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11na");
275 break;
276 case WMI_11NG_CAPABILITY:
277 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11ng");
278 break;
279 default:
280 snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
281 break;
282 }
283 current_ev = IWE_STREAM_ADD_EVENT(param->info, current_ev, end_buf,
284 &iwe, IW_EV_CHAR_LEN);
285 }
286 param->bytes_needed += IW_EV_CHAR_LEN;
287
288 #if WIRELESS_EXT > 14
289 A_MEMZERO(&iwe, sizeof(iwe));
290 iwe.cmd = IWEVCUSTOM;
291 iwe.u.data.length = snprintf(buf, sizeof(buf), "bcn_int=%d", cie->ie_beaconInt);
292 data_len = iwe.u.data.length + IW_EV_POINT_LEN;
293 if ((end_buf - current_ev) > data_len)
294 {
295 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
296 &iwe, buf);
297 }
298 param->bytes_needed += data_len;
299
300 #if WIRELESS_EXT < 18
301 if (cie->ie_wpa != NULL) {
302 static const char wpa_leader[] = "wpa_ie=";
303 data_len = (sizeof(wpa_leader) - 1) + ((cie->ie_wpa[1]+2) * 2) + IW_EV_POINT_LEN;
304 if ((end_buf - current_ev) > data_len)
305 {
306 A_MEMZERO(&iwe, sizeof(iwe));
307 iwe.cmd = IWEVCUSTOM;
308 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wpa,
309 cie->ie_wpa[1]+2,
310 wpa_leader, sizeof(wpa_leader)-1);
311
312 if (iwe.u.data.length != 0) {
313 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev,
314 end_buf, &iwe, buf);
315 }
316 }
317 param->bytes_needed += data_len;
318 }
319
320 if (cie->ie_rsn != NULL && cie->ie_rsn[0] == IEEE80211_ELEMID_RSN) {
321 static const char rsn_leader[] = "rsn_ie=";
322 data_len = (sizeof(rsn_leader) - 1) + ((cie->ie_rsn[1]+2) * 2) + IW_EV_POINT_LEN;
323 if ((end_buf - current_ev) > data_len)
324 {
325 A_MEMZERO(&iwe, sizeof(iwe));
326 iwe.cmd = IWEVCUSTOM;
327 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_rsn,
328 cie->ie_rsn[1]+2,
329 rsn_leader, sizeof(rsn_leader)-1);
330
331 if (iwe.u.data.length != 0) {
332 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev,
333 end_buf, &iwe, buf);
334 }
335 }
336 param->bytes_needed += data_len;
337 }
338 #endif /* WIRELESS_EXT < 18 */
339
340 if (cie->ie_wmm != NULL) {
341 static const char wmm_leader[] = "wmm_ie=";
342 data_len = (sizeof(wmm_leader) - 1) + ((cie->ie_wmm[1]+2) * 2) + IW_EV_POINT_LEN;
343 if ((end_buf - current_ev) > data_len)
344 {
345 A_MEMZERO(&iwe, sizeof(iwe));
346 iwe.cmd = IWEVCUSTOM;
347 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wmm,
348 cie->ie_wmm[1]+2,
349 wmm_leader, sizeof(wmm_leader)-1);
350 if (iwe.u.data.length != 0) {
351 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev,
352 end_buf, &iwe, buf);
353 }
354 }
355 param->bytes_needed += data_len;
356 }
357
358 if (cie->ie_ath != NULL) {
359 static const char ath_leader[] = "ath_ie=";
360 data_len = (sizeof(ath_leader) - 1) + ((cie->ie_ath[1]+2) * 2) + IW_EV_POINT_LEN;
361 if ((end_buf - current_ev) > data_len)
362 {
363 A_MEMZERO(&iwe, sizeof(iwe));
364 iwe.cmd = IWEVCUSTOM;
365 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_ath,
366 cie->ie_ath[1]+2,
367 ath_leader, sizeof(ath_leader)-1);
368 if (iwe.u.data.length != 0) {
369 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev,
370 end_buf, &iwe, buf);
371 }
372 }
373 param->bytes_needed += data_len;
374 }
375
376 #ifdef WAPI_ENABLE
377 if (cie->ie_wapi != NULL) {
378 static const char wapi_leader[] = "wapi_ie=";
379 data_len = (sizeof(wapi_leader) - 1) + ((cie->ie_wapi[1] + 2) * 2) + IW_EV_POINT_LEN;
380 if ((end_buf - current_ev) > data_len) {
381 A_MEMZERO(&iwe, sizeof(iwe));
382 iwe.cmd = IWEVCUSTOM;
383 iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wapi,
384 cie->ie_wapi[1] + 2,
385 wapi_leader, sizeof(wapi_leader) - 1);
386 if (iwe.u.data.length != 0) {
387 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev,
388 end_buf, &iwe, buf);
389 }
390 }
391 param->bytes_needed += data_len;
392 }
393 #endif /* WAPI_ENABLE */
394
395 #endif /* WIRELESS_EXT > 14 */
396
397 #if WIRELESS_EXT >= 18
398 if (cie->ie_wsc != NULL) {
399 data_len = (cie->ie_wsc[1] + 2) + IW_EV_POINT_LEN;
400 if ((end_buf - current_ev) > data_len)
401 {
402 A_MEMZERO(&iwe, sizeof(iwe));
403 iwe.cmd = IWEVGENIE;
404 iwe.u.data.length = cie->ie_wsc[1] + 2;
405 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
406 &iwe, (char*)cie->ie_wsc);
407 }
408 param->bytes_needed += data_len;
409 }
410 #endif /* WIRELESS_EXT >= 18 */
411
412 param->current_ev = current_ev;
413 }
414
415 int
416 ar6000_ioctl_giwscan(struct net_device *dev,
417 struct iw_request_info *info,
418 struct iw_point *data, char *extra)
419 {
420 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
421 struct ar_giwscan_param param;
422
423 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
424 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
425 return -EOPNOTSUPP;
426 }
427
428 if (ar->arWlanState == WLAN_DISABLED) {
429 return -EIO;
430 }
431
432 if (ar->arWmiReady == FALSE) {
433 return -EIO;
434 }
435
436 param.current_ev = extra;
437 param.end_buf = extra + data->length;
438 param.bytes_needed = 0;
439 param.info = info;
440
441 /* Translate data to WE format */
442 wmi_iterate_nodes(ar->arWmi, ar6000_scan_node, &param);
443
444 /* check if bytes needed is greater than bytes consumed */
445 if (param.bytes_needed > (param.current_ev - extra))
446 {
447 /* Request one byte more than needed, because when "data->length" equals bytes_needed,
448 it is not possible to add the last event data as all iwe_stream_add_xxxxx() functions
449 checks whether (cur_ptr + ev_len) < end_ptr, due to this one more retry would happen*/
450 data->length = param.bytes_needed + 1;
451
452 return -E2BIG;
453 }
454
455 return 0;
456 }
457
458 extern int reconnect_flag;
459 /* SIOCSIWESSID */
460 static int
461 ar6000_ioctl_siwessid(struct net_device *dev,
462 struct iw_request_info *info,
463 struct iw_point *data, char *ssid)
464 {
465 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
466 A_STATUS status;
467 A_UINT8 arNetworkType;
468 A_UINT8 prevMode = ar->arNetworkType;
469
470 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
471 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
472 return -EOPNOTSUPP;
473 }
474
475 if (ar->bIsDestroyProgress) {
476 return -EBUSY;
477 }
478
479 if (ar->arWlanState == WLAN_DISABLED) {
480 return -EIO;
481 }
482
483 if (ar->arWmiReady == FALSE) {
484 return -EIO;
485 }
486
487 #if defined(WIRELESS_EXT)
488 if (WIRELESS_EXT >= 20) {
489 data->length += 1;
490 }
491 #endif
492
493 /*
494 * iwconfig passes a null terminated string with length including this
495 * so we need to account for this
496 */
497 if (data->flags && (!data->length || (data->length == 1) ||
498 ((data->length - 1) > sizeof(ar->arSsid))))
499 {
500 /*
501 * ssid is invalid
502 */
503 return -EINVAL;
504 }
505
506 if (ar->arNextMode == AP_NETWORK) {
507 /* SSID change for AP network - Will take effect on commit */
508 if(A_MEMCMP(ar->arSsid,ssid,32) != 0) {
509 ar->arSsidLen = data->length - 1;
510 A_MEMCPY(ar->arSsid, ssid, ar->arSsidLen);
511 ar->ap_profile_flag = 1; /* There is a change in profile */
512 }
513 return 0;
514 } else if(ar->arNetworkType == AP_NETWORK) {
515 A_UINT8 ctr;
516 struct sk_buff *skb;
517
518 /* We are switching from AP to STA | IBSS mode, cleanup the AP state */
519 for (ctr=0; ctr < AP_MAX_NUM_STA; ctr++) {
520 remove_sta(ar, ar->sta_list[ctr].mac, 0);
521 }
522 A_MUTEX_LOCK(&ar->mcastpsqLock);
523 while (!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) {
524 skb = A_NETBUF_DEQUEUE(&ar->mcastpsq);
525 A_NETBUF_FREE(skb);
526 }
527 A_MUTEX_UNLOCK(&ar->mcastpsqLock);
528 }
529
530 /* Added for bug 25178, return an IOCTL error instead of target returning
531 Illegal parameter error when either the BSSID or channel is missing
532 and we cannot scan during connect.
533 */
534 if (data->flags) {
535 if (ar->arSkipScan == TRUE &&
536 (ar->arChannelHint == 0 ||
537 (!ar->arReqBssid[0] && !ar->arReqBssid[1] && !ar->arReqBssid[2] &&
538 !ar->arReqBssid[3] && !ar->arReqBssid[4] && !ar->arReqBssid[5])))
539 {
540 return -EINVAL;
541 }
542 }
543
544 if (down_interruptible(&ar->arSem)) {
545 return -ERESTARTSYS;
546 }
547
548 if (ar->bIsDestroyProgress || ar->arWlanState == WLAN_DISABLED) {
549 up(&ar->arSem);
550 return -EBUSY;
551 }
552
553 if (ar->arTxPending[wmi_get_control_ep(ar->arWmi)]) {
554 /*
555 * sleep until the command queue drains
556 */
557 wait_event_interruptible_timeout(arEvent,
558 ar->arTxPending[wmi_get_control_ep(ar->arWmi)] == 0, wmitimeout * HZ);
559 if (signal_pending(current)) {
560 return -EINTR;
561 }
562 }
563
564 if (!data->flags) {
565 arNetworkType = ar->arNetworkType;
566 #ifdef ATH6K_CONFIG_CFG80211
567 if (ar->arConnected) {
568 #endif /* ATH6K_CONFIG_CFG80211 */
569 ar6000_init_profile_info(ar);
570 #ifdef ATH6K_CONFIG_CFG80211
571 }
572 #endif /* ATH6K_CONFIG_CFG80211 */
573 ar->arNetworkType = arNetworkType;
574 }
575
576 /* Update the arNetworkType */
577 ar->arNetworkType = ar->arNextMode;
578
579
580 if ((prevMode != AP_NETWORK) &&
581 ((ar->arSsidLen) || ((ar->arSsidLen == 0) && ar->arConnected) || (!data->flags)))
582 {
583 if ((!data->flags) ||
584 (A_MEMCMP(ar->arSsid, ssid, ar->arSsidLen) != 0) ||
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 */
595 if (ar->arWmiReady == TRUE) {
596 reconnect_flag = 0;
597 status = wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, 0);
598 status = wmi_disconnect_cmd(ar->arWmi);
599 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
600 ar->arSsidLen = 0;
601 if (ar->arSkipScan == FALSE) {
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 */
620 if((ar->arConnected == TRUE) && (ar->arWmiReady == TRUE))
621 {
622 reconnect_flag = TRUE;
623 status = wmi_reconnect_cmd(ar->arWmi,ar->arReqBssid,
624 ar->arChannelHint);
625 up(&ar->arSem);
626 if (status != A_OK) {
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;
644 A_MEMCPY(ar->arSsid, ssid, ar->arSsidLen);
645
646 if (ar6000_connect_to_ap(ar)!= A_OK) {
647 up(&ar->arSem);
648 return -EIO;
649 }else{
650 up(&ar->arSem);
651 }
652 return 0;
653 }
654
655 /* SIOCGIWESSID */
656 static int
657 ar6000_ioctl_giwessid(struct net_device *dev,
658 struct iw_request_info *info,
659 struct iw_point *data, char *essid)
660 {
661 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
662
663 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
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;
678 A_MEMCPY(essid, ar->arSsid, ar->arSsidLen);
679
680 return 0;
681 }
682
683
684 void ar6000_install_static_wep_keys(AR_SOFTC_T *ar)
685 {
686 A_UINT8 index;
687 A_UINT8 keyUsage;
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 */
710 int
711 ar6000_ioctl_siwrate(struct net_device *dev,
712 struct iw_request_info *info,
713 struct iw_param *rrq, char *extra)
714 {
715 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
716 A_UINT32 kbps;
717 A_INT8 rate_idx;
718
719 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
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 }
729 if(kbps != -1 && wmi_validate_bitrate(ar->arWmi, kbps, &rate_idx) != A_OK)
730 {
731 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BitRate is not Valid %d\n", kbps));
732 return -EINVAL;
733 }
734 ar->arBitRate = kbps;
735 if(ar->arWmiReady == TRUE)
736 {
737 if (wmi_set_bitrate_cmd(ar->arWmi, kbps, -1, -1) != A_OK) {
738 return -EINVAL;
739 }
740 }
741 return 0;
742 }
743
744 /*
745 * SIOCGIWRATE
746 */
747 int
748 ar6000_ioctl_giwrate(struct net_device *dev,
749 struct iw_request_info *info,
750 struct iw_param *rrq, char *extra)
751 {
752 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
753 int ret = 0;
754
755 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
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
768 if ((ar->arNextMode != AP_NETWORK && !ar->arConnected) || ar->arWmiReady == FALSE) {
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;
783 if (wmi_get_bitrate_cmd(ar->arWmi) != A_OK) {
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) {
795 rrq->fixed = TRUE;
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 */
810 static int
811 ar6000_ioctl_siwtxpow(struct net_device *dev,
812 struct iw_request_info *info,
813 struct iw_param *rrq, char *extra)
814 {
815 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
816 A_UINT8 dbM;
817
818 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
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;
836 ar->arTxPwrSet = TRUE;
837 } else {
838 ar->arTxPwr = dbM = 0;
839 ar->arTxPwrSet = FALSE;
840 }
841 if(ar->arWmiReady == TRUE)
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 */
852 int
853 ar6000_ioctl_giwtxpow(struct net_device *dev,
854 struct iw_request_info *info,
855 struct iw_param *rrq, char *extra)
856 {
857 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
858 int ret = 0;
859
860 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
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
882 if((ar->arWmiReady == TRUE) && (ar->arConnected == TRUE))
883 {
884 ar->arTxPwr = 0;
885
886 if (wmi_get_txPwr_cmd(ar->arWmi) != A_OK) {
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) {
901 if (ar->arTxPwrSet == TRUE) {
902 rrq->fixed = TRUE;
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 */
922 static int
923 ar6000_ioctl_siwretry(struct net_device *dev,
924 struct iw_request_info *info,
925 struct iw_param *rrq, char *extra)
926 {
927 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
928
929 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
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 }
949 if(ar->arWmiReady == TRUE)
950 {
951 if (wmi_set_retry_limits_cmd(ar->arWmi, DATA_FRAMETYPE, WMM_AC_BE,
952 rrq->value, 0) != A_OK){
953 return -EINVAL;
954 }
955 }
956 ar->arMaxRetries = rrq->value;
957 return 0;
958 }
959
960 /*
961 * SIOCGIWRETRY
962 */
963 static int
964 ar6000_ioctl_giwretry(struct net_device *dev,
965 struct iw_request_info *info,
966 struct iw_param *rrq, char *extra)
967 {
968 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
969
970 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
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 */
1004 static int
1005 ar6000_ioctl_siwencode(struct net_device *dev,
1006 struct iw_request_info *info,
1007 struct iw_point *erq, char *keybuf)
1008 {
1009 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1010 int index;
1011 A_INT32 auth = 0;
1012
1013 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
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));
1083 A_MEMCPY(ar->arWepKeyList[index].arKey, keybuf, erq->length);
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
1120 static int
1121 ar6000_ioctl_giwencode(struct net_device *dev,
1122 struct iw_request_info *info,
1123 struct iw_point *erq, char *key)
1124 {
1125 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1126 A_UINT8 keyIndex;
1127 struct ar_wep_key *wk;
1128
1129 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
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) {
1161 A_MEMCPY(key, wk->arKey, erq->length);
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) {
1168 A_MEMCPY(key, ar->user_saved_keys.ucast_ik.ik_keydata, erq->length);
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 */
1190 static int
1191 ar6000_ioctl_siwgenie(struct net_device *dev,
1192 struct iw_request_info *info,
1193 struct iw_point *erq, char *extra)
1194 {
1195 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1196
1197 #ifdef WAPI_ENABLE
1198 A_UINT8 *ie = erq->pointer;
1199 A_UINT8 ie_type = ie[0];
1200 A_UINT16 ie_length = erq->length;
1201 A_UINT8 wapi_ie[128];
1202 #endif
1203
1204 if (ar->arWmiReady == FALSE) {
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 */
1226 static int
1227 ar6000_ioctl_giwgenie(struct net_device *dev,
1228 struct iw_request_info *info,
1229 struct iw_point *erq, char *extra)
1230 {
1231 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1232
1233 if (ar->arWmiReady == FALSE) {
1234 return -EIO;
1235 }
1236 erq->length = 0;
1237 erq->flags = 0;
1238
1239 return 0;
1240 }
1241
1242 /*
1243 * SIOCSIWAUTH
1244 */
1245 static int
1246 ar6000_ioctl_siwauth(struct net_device *dev,
1247 struct iw_request_info *info,
1248 struct iw_param *data, char *extra)
1249 {
1250 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1251
1252 A_BOOL profChanged;
1253 A_UINT16 param;
1254 A_INT32 ret;
1255 A_INT32 value;
1256
1257 if (ar->arWmiReady == FALSE) {
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;
1267 profChanged = TRUE;
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;
1280 profChanged = FALSE;
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;
1301 profChanged = FALSE;
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;
1322 profChanged = FALSE;
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);
1340 profChanged = FALSE;
1341 break;
1342 case IW_AUTH_DROP_UNENCRYPTED:
1343 profChanged = FALSE;
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;
1358 profChanged = FALSE;
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:
1377 profChanged = FALSE;
1378 break;
1379 case IW_AUTH_ROAMING_CONTROL:
1380 profChanged = FALSE;
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;
1397 profChanged = FALSE;
1398 break;
1399 }
1400
1401 if (profChanged == TRUE) {
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 */
1416 static int
1417 ar6000_ioctl_giwauth(struct net_device *dev,
1418 struct iw_request_info *info,
1419 struct iw_param *data, char *extra)
1420 {
1421 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1422 A_UINT16 param;
1423 A_INT32 ret;
1424
1425 if (ar->arWmiReady == FALSE) {
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 */
1544 static int
1545 ar6000_ioctl_siwpmksa(struct net_device *dev,
1546 struct iw_request_info *info,
1547 struct iw_point *data, char *extra)
1548 {
1549 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1550 A_INT32 ret;
1551 A_STATUS status;
1552 struct iw_pmksa *pmksa;
1553
1554 pmksa = (struct iw_pmksa *)extra;
1555
1556 if (ar->arWmiReady == FALSE) {
1557 return -EIO;
1558 }
1559
1560 ret = 0;
1561 status = A_OK;
1562
1563 switch (pmksa->cmd) {
1564 case IW_PMKSA_ADD:
1565 status = wmi_setPmkid_cmd(ar->arWmi, (A_UINT8*)pmksa->bssid.sa_data, pmksa->pmkid, TRUE);
1566 break;
1567 case IW_PMKSA_REMOVE:
1568 status = wmi_setPmkid_cmd(ar->arWmi, (A_UINT8*)pmksa->bssid.sa_data, pmksa->pmkid, FALSE);
1569 break;
1570 case IW_PMKSA_FLUSH:
1571 if (ar->arConnected == TRUE) {
1572 status = wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, 0);
1573 }
1574 break;
1575 default:
1576 ret=-1;
1577 break;
1578 }
1579 if (status != A_OK) {
1580 ret = -1;
1581 }
1582
1583 return ret;
1584 }
1585
1586 #ifdef WAPI_ENABLE
1587
1588 #define PN_INIT 0x5c365c36
1589
1590 static int ar6000_set_wapi_key(struct net_device *dev,
1591 struct iw_request_info *info,
1592 struct iw_point *erq, char *extra)
1593 {
1594 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1595 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1596 KEY_USAGE keyUsage = 0;
1597 A_INT32 keyLen;
1598 A_UINT8 *keyData;
1599 A_INT32 index;
1600 A_UINT32 *PN;
1601 A_INT32 i;
1602 A_STATUS status;
1603 A_UINT8 wapiKeyRsc[16];
1604 CRYPTO_TYPE keyType = WAPI_CRYPT;
1605 const A_UINT8 broadcastMac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
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 }
1617 keyData = (A_UINT8 *)(ext + 1);
1618 keyLen = erq->length - sizeof(struct iw_encode_ext);
1619 A_MEMCPY(wapiKeyRsc, ext->tx_seq, sizeof(wapiKeyRsc));
1620
1621 if (A_MEMCMP(ext->addr.sa_data, broadcastMac, sizeof(broadcastMac)) == 0) {
1622 keyUsage |= GROUP_USAGE;
1623 PN = (A_UINT32 *)wapiKeyRsc;
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);
1640 if (A_OK != status) {
1641 return -EIO;
1642 }
1643 return 0;
1644 }
1645
1646 #endif
1647
1648 /*
1649 * SIOCSIWENCODEEXT
1650 */
1651 static int
1652 ar6000_ioctl_siwencodeext(struct net_device *dev,
1653 struct iw_request_info *info,
1654 struct iw_point *erq, char *extra)
1655 {
1656 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1657 A_INT32 index;
1658 struct iw_encode_ext *ext;
1659 KEY_USAGE keyUsage;
1660 A_INT32 keyLen;
1661 A_UINT8 *keyData;
1662 A_UINT8 keyRsc[8];
1663 A_STATUS status;
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
1674 ar->user_saved_keys.keyOk = FALSE;
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 */
1724 keyData = (A_UINT8 *)(ext + 1);
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));
1740 A_MEMCPY(ar->arWepKeyList[index].arKey, keyData, keyLen);
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) {
1781 A_MEMCPY(keyRsc, ext->rx_seq, sizeof(keyRsc));
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,
1795 (A_UINT8*)ext->addr.sa_data,
1796 SYNC_BOTH_WMIFLAG);
1797 if (status != A_OK) {
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 }
1814 ar->user_saved_keys.keyOk = TRUE;
1815 #endif /* USER_KEYS */
1816 }
1817
1818
1819 return 0;
1820 }
1821
1822 /*
1823 * SIOCGIWENCODEEXT
1824 */
1825 static int
1826 ar6000_ioctl_giwencodeext(struct net_device *dev,
1827 struct iw_request_info *info,
1828 struct iw_point *erq, char *extra)
1829 {
1830 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
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
1848 static 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
1853 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1854 WMI_POWER_MODE power_mode;
1855
1856 if (ar->arWmiReady == FALSE) {
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
1875 static int ar6000_ioctl_giwpower(struct net_device *dev,
1876 struct iw_request_info *info,
1877 union iwreq_data *wrqu, char *extra)
1878 {
1879 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1880 WMI_POWER_MODE power_mode;
1881
1882 if (ar->arWmiReady == FALSE) {
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 */
1904 int
1905 ar6000_ioctl_giwname(struct net_device *dev,
1906 struct iw_request_info *info,
1907 char *name, char *extra)
1908 {
1909 A_UINT8 capability;
1910 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1911
1912 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
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 */
1959 int
1960 ar6000_ioctl_siwfreq(struct net_device *dev,
1961 struct iw_request_info *info,
1962 struct iw_freq *freq, char *extra)
1963 {
1964 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
1965
1966 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
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 */
2004 int
2005 ar6000_ioctl_giwfreq(struct net_device *dev,
2006 struct iw_request_info *info,
2007 struct iw_freq *freq, char *extra)
2008 {
2009 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2010
2011 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
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 {
2029 if (ar->arConnected != TRUE) {
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 */
2044 int
2045 ar6000_ioctl_siwmode(struct net_device *dev,
2046 struct iw_request_info *info,
2047 __u32 *mode, char *extra)
2048 {
2049 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2050
2051 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
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 */
2063 if(!(ar->arNetworkType == (((*mode) == IW_MODE_INFRA) ? INFRA_NETWORK : ADHOC_NETWORK)) && (ar->arConnected == TRUE) ){
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 */
2115 int
2116 ar6000_ioctl_giwmode(struct net_device *dev,
2117 struct iw_request_info *info,
2118 __u32 *mode, char *extra)
2119 {
2120 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2121
2122 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
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 */
2150 int
2151 ar6000_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 */
2161 int
2162 ar6000_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 */
2175 int
2176 ar6000_ioctl_giwrange(struct net_device *dev,
2177 struct iw_request_info *info,
2178 struct iw_point *data, char *extra)
2179 {
2180 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2181 struct iw_range *range = (struct iw_range *) extra;
2182 int i, ret = 0;
2183
2184 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
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
2193 if (ar->arWmiReady == FALSE) {
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
2209 if (wmi_get_channelList_cmd(ar->arWmi) != A_OK) {
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 */
2298 int
2299 ar6000_ioctl_siwap(struct net_device *dev,
2300 struct iw_request_info *info,
2301 struct sockaddr *ap_addr, char *extra)
2302 {
2303 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2304
2305 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
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
2318 if (A_MEMCMP(&ap_addr->sa_data, bcast_mac, AR6000_ETH_ADDR_LEN) == 0) {
2319 A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
2320 } else {
2321 A_MEMCPY(ar->arReqBssid, &ap_addr->sa_data, sizeof(ar->arReqBssid));
2322 }
2323
2324 return 0;
2325 }
2326
2327 /*
2328 * SIOCGIWAP
2329 */
2330 int
2331 ar6000_ioctl_giwap(struct net_device *dev,
2332 struct iw_request_info *info,
2333 struct sockaddr *ap_addr, char *extra)
2334 {
2335 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2336
2337 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
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) {
2347 A_MEMCPY(&ap_addr->sa_data, dev->dev_addr, ATH_MAC_LEN);
2348 ap_addr->sa_family = ARPHRD_ETHER;
2349 return 0;
2350 }
2351
2352 if (ar->arConnected != TRUE) {
2353 return -EINVAL;
2354 }
2355
2356 A_MEMCPY(&ap_addr->sa_data, ar->arBssid, sizeof(ar->arBssid));
2357 ap_addr->sa_family = ARPHRD_ETHER;
2358
2359 return 0;
2360 }
2361
2362 #if (WIRELESS_EXT >= 18)
2363 /*
2364 * SIOCSIWMLME
2365 */
2366 int
2367 ar6000_ioctl_siwmlme(struct net_device *dev,
2368 struct iw_request_info *info,
2369 struct iw_point *data, char *extra)
2370 {
2371 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2372
2373 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
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
2386 if (ar->arWmiReady == FALSE) {
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
2396 A_UINT8 arNetworkType;
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:
2407 if ((ar->arConnected != TRUE) ||
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;
2418 wmi_disconnect_cmd(ar->arWmi);
2419 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
2420 ar->arSsidLen = 0;
2421 if (ar->arSkipScan == FALSE) {
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 */
2444 int
2445 ar6000_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 */
2455 int
2456 ar6000_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
2463 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2464 int ret = 0;
2465
2466 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2467 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2468 return -EOPNOTSUPP;
2469 }
2470
2471 if (ar->arWmiReady == FALSE) {
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) {
2491 if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != A_OK) {
2492 return -EIO;
2493 }
2494 }
2495
2496 if (ar->arConnected) {
2497 if (wmi_get_stats_cmd(ar->arWmi) != A_OK) {
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;
2511 if (wmi_probedSsid_cmd(ar->arWmi, 1, SPECIFIC_SSID_FLAG, req.essid_len, req.essid) != A_OK)
2512 return -EIO;
2513 ar->scanSpecificSsid = 1;
2514 }
2515 else
2516 {
2517 if (ar->scanSpecificSsid) {
2518 if (wmi_probedSsid_cmd(ar->arWmi, 1, DISABLE_SSID_FLAG, 0, NULL) != A_OK)
2519 return -EIO;
2520 ar->scanSpecificSsid = 0;
2521 }
2522 }
2523 }
2524 else
2525 {
2526 if (ar->scanSpecificSsid) {
2527 if (wmi_probedSsid_cmd(ar->arWmi, 1, DISABLE_SSID_FLAG, 0, NULL) != A_OK)
2528 return -EIO;
2529 ar->scanSpecificSsid = 0;
2530 }
2531 }
2532 #endif
2533 #endif /* ANDROID_ENV */
2534
2535 if (wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, FALSE, FALSE, \
2536 0, 0, 0, NULL) != A_OK) {
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 */
2567 static void
2568 ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi)
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
2586 int
2587 ar6000_ioctl_siwcommit(struct net_device *dev,
2588 struct iw_request_info *info,
2589 struct iw_point *data, char *extra)
2590 {
2591 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
2592
2593 if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
2594 A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
2595 return -EOPNOTSUPP;
2596 }
2597
2598 if (ar->arWmiReady == FALSE) {
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) {
2618 ar->arConnectPending = FALSE;
2619 ar->arConnected = FALSE;
2620 /* Stop getting pkts from upper stack */
2621 netif_stop_queue(ar->arNetDev);
2622 A_MEMZERO(ar->arBssid, sizeof(ar->arBssid));
2623 ar->arBssChannel = 0;
2624 ar->arBeaconInterval = 0;
2625
2626 /* Flush the Tx queues */
2627 ar6000_TxDataCleanup(ar);
2628
2629 /* Start getting pkts from upper stack */
2630 netif_wake_queue(ar->arNetDev);
2631 }
2632
2633 return 0;
2634 }
2635
2636 #define W_PROTO(_x) wait_ ## _x
2637 #define WAIT_HANDLER_IMPL(_x, type) \
2638 int wait_ ## _x (struct net_device *dev, struct iw_request_info *info, type wrqu, char *extra) {\
2639 int ret; \
2640 dev_hold(dev); \
2641 rtnl_unlock(); \
2642 ret = _x(dev, info, wrqu, extra); \
2643 rtnl_lock(); \
2644 dev_put(dev); \
2645 return ret;\
2646 }
2647
2648 WAIT_HANDLER_IMPL(ar6000_ioctl_siwessid, struct iw_point *)
2649 WAIT_HANDLER_IMPL(ar6000_ioctl_giwrate, struct iw_param *)
2650 WAIT_HANDLER_IMPL(ar6000_ioctl_giwtxpow, struct iw_param *)
2651 WAIT_HANDLER_IMPL(ar6000_ioctl_giwrange, struct iw_point*)
2652
2653 /* Structures to export the Wireless Handlers */
2654 static const iw_handler ath_handlers[] = {
2655 (iw_handler) ar6000_ioctl_siwcommit, /* SIOCSIWCOMMIT */
2656 (iw_handler) ar6000_ioctl_giwname, /* SIOCGIWNAME */
2657 (iw_handler) NULL, /* SIOCSIWNWID */
2658 (iw_handler) NULL, /* SIOCGIWNWID */
2659 (iw_handler) ar6000_ioctl_siwfreq, /* SIOCSIWFREQ */
2660 (iw_handler) ar6000_ioctl_giwfreq, /* SIOCGIWFREQ */
2661 (iw_handler) ar6000_ioctl_siwmode, /* SIOCSIWMODE */
2662 (iw_handler) ar6000_ioctl_giwmode, /* SIOCGIWMODE */
2663 (iw_handler) ar6000_ioctl_siwsens, /* SIOCSIWSENS */
2664 (iw_handler) ar6000_ioctl_giwsens, /* SIOCGIWSENS */
2665 (iw_handler) NULL /* not _used */, /* SIOCSIWRANGE */
2666 (iw_handler) W_PROTO(ar6000_ioctl_giwrange),/* SIOCGIWRANGE */
2667 (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */
2668 (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
2669 (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */
2670 (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */
2671 (iw_handler) NULL, /* SIOCSIWSPY */
2672 (iw_handler) NULL, /* SIOCGIWSPY */
2673 (iw_handler) NULL, /* SIOCSIWTHRSPY */
2674 (iw_handler) NULL, /* SIOCGIWTHRSPY */
2675 (iw_handler) ar6000_ioctl_siwap, /* SIOCSIWAP */
2676 (iw_handler) ar6000_ioctl_giwap, /* SIOCGIWAP */
2677 #if (WIRELESS_EXT >= 18)
2678 (iw_handler) ar6000_ioctl_siwmlme, /* SIOCSIWMLME */
2679 #else
2680 (iw_handler) NULL, /* -- hole -- */
2681 #endif /* WIRELESS_EXT >= 18 */
2682 (iw_handler) ar6000_ioctl_iwaplist, /* SIOCGIWAPLIST */
2683 (iw_handler) ar6000_ioctl_siwscan, /* SIOCSIWSCAN */
2684 (iw_handler) ar6000_ioctl_giwscan, /* SIOCGIWSCAN */
2685 (iw_handler) W_PROTO(ar6000_ioctl_siwessid),/* SIOCSIWESSID */
2686 (iw_handler) ar6000_ioctl_giwessid, /* SIOCGIWESSID */
2687 (iw_handler) NULL, /* SIOCSIWNICKN */
2688 (iw_handler) NULL, /* SIOCGIWNICKN */
2689 (iw_handler) NULL, /* -- hole -- */
2690 (iw_handler) NULL, /* -- hole -- */
2691 (iw_handler) ar6000_ioctl_siwrate, /* SIOCSIWRATE */
2692 (iw_handler) W_PROTO(ar6000_ioctl_giwrate), /* SIOCGIWRATE */
2693 (iw_handler) NULL, /* SIOCSIWRTS */
2694 (iw_handler) NULL, /* SIOCGIWRTS */
2695 (iw_handler) NULL, /* SIOCSIWFRAG */
2696 (iw_handler) NULL, /* SIOCGIWFRAG */
2697 (iw_handler) ar6000_ioctl_siwtxpow, /* SIOCSIWTXPOW */
2698 (iw_handler) W_PROTO(ar6000_ioctl_giwtxpow),/* SIOCGIWTXPOW */
2699 (iw_handler) ar6000_ioctl_siwretry, /* SIOCSIWRETRY */
2700 (iw_handler) ar6000_ioctl_giwretry, /* SIOCGIWRETRY */
2701 (iw_handler) ar6000_ioctl_siwencode, /* SIOCSIWENCODE */
2702 (iw_handler) ar6000_ioctl_giwencode, /* SIOCGIWENCODE */
2703 #if WIRELESS_EXT > 20
2704 (iw_handler) ar6000_ioctl_siwpower, /* SIOCSIWPOWER */
2705 (iw_handler) ar6000_ioctl_giwpower, /* SIOCGIWPOWER */
2706 #endif // WIRELESS_EXT > 20
2707 #if WIRELESS_EXT >= 18
2708 (iw_handler) NULL, /* -- hole -- */
2709 (iw_handler) NULL, /* -- hole -- */
2710 (iw_handler) ar6000_ioctl_siwgenie, /* SIOCSIWGENIE */
2711 (iw_handler) ar6000_ioctl_giwgenie, /* SIOCGIWGENIE */
2712 (iw_handler) ar6000_ioctl_siwauth, /* SIOCSIWAUTH */
2713 (iw_handler) ar6000_ioctl_giwauth, /* SIOCGIWAUTH */
2714 (iw_handler) ar6000_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */
2715 (iw_handler) ar6000_ioctl_giwencodeext, /* SIOCGIWENCODEEXT */
2716 (iw_handler) ar6000_ioctl_siwpmksa, /* SIOCSIWPMKSA */
2717 #endif // WIRELESS_EXT >= 18
2718 };
2719
2720 struct iw_handler_def ath_iw_handler_def = {
2721 .standard = (iw_handler *)ath_handlers,
2722 .num_standard = ARRAY_SIZE(ath_handlers),
2723 .private = NULL,
2724 .num_private = 0,
2725 };