Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6
[pandora-kernel.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 };