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