ath6kl: remove-typedef AR_SOFTC_T
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / ath6kl / os / linux / wireless_ext.c
blob4b779434956f2c2037251375e689c02aa94ed465
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.
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.
21 // Author(s): ="Atheros"
22 //------------------------------------------------------------------------------
24 #include "ar6000_drv.h"
26 #define IWE_STREAM_ADD_EVENT(p1, p2, p3, p4, p5) \
27 iwe_stream_add_event((p1), (p2), (p3), (p4), (p5))
29 #define IWE_STREAM_ADD_POINT(p1, p2, p3, p4, p5) \
30 iwe_stream_add_point((p1), (p2), (p3), (p4), (p5))
32 #define IWE_STREAM_ADD_VALUE(p1, p2, p3, p4, p5, p6) \
33 iwe_stream_add_value((p1), (p2), (p3), (p4), (p5), (p6))
35 static void ar6000_set_quality(struct iw_quality *iq, s8 rssi);
36 extern unsigned int wmitimeout;
37 extern A_WAITQUEUE_HEAD arEvent;
39 #if WIRELESS_EXT > 14
41 * Encode a WPA or RSN information element as a custom
42 * element using the hostap format.
44 static u_int
45 encode_ie(void *buf, size_t bufsize,
46 const u_int8_t *ie, size_t ielen,
47 const char *leader, size_t leader_len)
49 u_int8_t *p;
50 int i;
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++)
60 p += sprintf((char*)p, "%02x", ie[i]);
61 bufsize -= 2;
63 return (i == ielen ? p - (u_int8_t *)buf : 0);
65 #endif /* WIRELESS_EXT > 14 */
67 static u8 get_bss_phy_capability(bss_t *bss)
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;
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;
85 return capability;
88 void
89 ar6000_scan_node(void *arg, bss_t *ni)
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;
103 param = (struct ar_giwscan_param *)arg;
105 current_ev = param->current_ev;
106 end_buf = param->end_buf;
108 cie = &ni->ni_cie;
110 if ((end_buf - current_ev) > IW_EV_ADDR_LEN)
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);
119 param->bytes_needed += IW_EV_ADDR_LEN;
121 data_len = cie->ie_ssid[1] + IW_EV_POINT_LEN;
122 if ((end_buf - current_ev) > data_len)
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]);
131 param->bytes_needed += data_len;
133 if (cie->ie_capInfo & (IEEE80211_CAPINFO_ESS|IEEE80211_CAPINFO_IBSS)) {
134 if ((end_buf - current_ev) > IW_EV_UINT_LEN)
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);
143 param->bytes_needed += IW_EV_UINT_LEN;
146 if ((end_buf - current_ev) > IW_EV_FREQ_LEN)
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);
155 param->bytes_needed += IW_EV_FREQ_LEN;
157 if ((end_buf - current_ev) > IW_EV_QUAL_LEN)
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);
165 param->bytes_needed += IW_EV_QUAL_LEN;
167 if ((end_buf - current_ev) > IW_EV_POINT_LEN)
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;
176 iwe.u.data.length = 0;
177 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
178 &iwe, "");
180 param->bytes_needed += IW_EV_POINT_LEN;
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;
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)
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);
206 param->bytes_needed += data_len;
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)
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);
224 param->bytes_needed += data_len;
226 /* remove fixed header if no rates were added */
227 if ((current_val - current_ev) > IW_EV_LCP_LEN)
228 current_ev = current_val;
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)
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);
242 param->bytes_needed += data_len;
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)
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);
255 param->bytes_needed += data_len;
258 #endif /* WIRELESS_EXT >= 18 */
260 if ((end_buf - current_ev) > IW_EV_CHAR_LEN)
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;
282 current_ev = IWE_STREAM_ADD_EVENT(param->info, current_ev, end_buf,
283 &iwe, IW_EV_CHAR_LEN);
285 param->bytes_needed += IW_EV_CHAR_LEN;
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)
294 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev, end_buf,
295 &iwe, buf);
297 param->bytes_needed += data_len;
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)
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);
311 if (iwe.u.data.length != 0) {
312 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev,
313 end_buf, &iwe, buf);
316 param->bytes_needed += data_len;
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)
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);
330 if (iwe.u.data.length != 0) {
331 current_ev = IWE_STREAM_ADD_POINT(param->info, current_ev,
332 end_buf, &iwe, buf);
335 param->bytes_needed += data_len;
337 #endif /* WIRELESS_EXT < 18 */
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)
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);
354 param->bytes_needed += data_len;
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)
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);
372 param->bytes_needed += data_len;
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);
390 param->bytes_needed += data_len;
392 #endif /* WAPI_ENABLE */
394 #endif /* WIRELESS_EXT > 14 */
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)
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);
407 param->bytes_needed += data_len;
409 #endif /* WIRELESS_EXT >= 18 */
411 param->current_ev = current_ev;
415 ar6000_ioctl_giwscan(struct net_device *dev,
416 struct iw_request_info *info,
417 struct iw_point *data, char *extra)
419 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
420 struct ar_giwscan_param param;
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;
427 if (ar->arWlanState == WLAN_DISABLED) {
428 return -EIO;
431 if (ar->arWmiReady == false) {
432 return -EIO;
435 param.current_ev = extra;
436 param.end_buf = extra + data->length;
437 param.bytes_needed = 0;
438 param.info = info;
440 /* Translate data to WE format */
441 wmi_iterate_nodes(ar->arWmi, ar6000_scan_node, &param);
443 /* check if bytes needed is greater than bytes consumed */
444 if (param.bytes_needed > (param.current_ev - extra))
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;
451 return -E2BIG;
454 return 0;
457 extern int reconnect_flag;
458 /* SIOCSIWESSID */
459 static int
460 ar6000_ioctl_siwessid(struct net_device *dev,
461 struct iw_request_info *info,
462 struct iw_point *data, char *ssid)
464 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
465 int status;
466 u8 arNetworkType;
467 u8 prevMode = ar->arNetworkType;
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;
474 if (ar->bIsDestroyProgress) {
475 return -EBUSY;
478 if (ar->arWlanState == WLAN_DISABLED) {
479 return -EIO;
482 if (ar->arWmiReady == false) {
483 return -EIO;
486 #if defined(WIRELESS_EXT)
487 if (WIRELESS_EXT >= 20) {
488 data->length += 1;
490 #endif
493 * iwconfig passes a null terminated string with length including this
494 * so we need to account for this
496 if (data->flags && (!data->length || (data->length == 1) ||
497 ((data->length - 1) > sizeof(ar->arSsid))))
500 * ssid is invalid
502 return -EINVAL;
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 */
512 return 0;
513 } else if(ar->arNetworkType == AP_NETWORK) {
514 u8 ctr;
515 struct sk_buff *skb;
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);
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);
526 A_MUTEX_UNLOCK(&ar->mcastpsqLock);
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.
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])))
539 return -EINVAL;
543 if (down_interruptible(&ar->arSem)) {
544 return -ERESTARTSYS;
547 if (ar->bIsDestroyProgress || ar->arWlanState == WLAN_DISABLED) {
548 up(&ar->arSem);
549 return -EBUSY;
552 if (ar->arTxPending[wmi_get_control_ep(ar->arWmi)]) {
554 * sleep until the command queue drains
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;
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
571 #endif /* ATH6K_CONFIG_CFG80211 */
572 ar->arNetworkType = arNetworkType;
575 /* Update the arNetworkType */
576 ar->arNetworkType = ar->arNextMode;
578 if ((prevMode != AP_NETWORK) &&
579 ((ar->arSsidLen) ||
580 ((ar->arSsidLen == 0) && (ar->arConnected || ar->arConnectPending)) ||
581 (!data->flags)))
583 if ((!data->flags) ||
584 (memcmp(ar->arSsid, ssid, ar->arSsidLen) != 0) ||
585 (ar->arSsidLen != (data->length - 1)))
588 * SSID set previously or essid off has been issued.
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
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));
604 if (!data->flags) {
605 up(&ar->arSem);
606 return 0;
608 } else {
609 up(&ar->arSem);
612 else
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.
620 if((ar->arConnected == true) && (ar->arWmiReady == true))
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;
629 return 0;
631 else{
633 * Dont return if connect is pending.
635 if(!(ar->arConnectPending)) {
636 up(&ar->arSem);
637 return 0;
643 ar->arSsidLen = data->length - 1;
644 memcpy(ar->arSsid, ssid, ar->arSsidLen);
646 if (ar6000_connect_to_ap(ar)!= 0) {
647 up(&ar->arSem);
648 return -EIO;
649 }else{
650 up(&ar->arSem);
652 return 0;
655 /* SIOCGIWESSID */
656 static int
657 ar6000_ioctl_giwessid(struct net_device *dev,
658 struct iw_request_info *info,
659 struct iw_point *data, char *essid)
661 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
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;
668 if (ar->arWlanState == WLAN_DISABLED) {
669 return -EIO;
672 if (!ar->arSsidLen) {
673 return -EINVAL;
676 data->flags = 1;
677 data->length = ar->arSsidLen;
678 memcpy(essid, ar->arSsid, ar->arSsidLen);
680 return 0;
684 void ar6000_install_static_wep_keys(struct ar6_softc *ar)
686 u8 index;
687 u8 keyUsage;
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;
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);
708 * SIOCSIWRATE
711 ar6000_ioctl_siwrate(struct net_device *dev,
712 struct iw_request_info *info,
713 struct iw_param *rrq, char *extra)
715 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
716 u32 kbps;
717 s8 rate_idx;
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;
724 if (rrq->fixed) {
725 kbps = rrq->value / 1000; /* rrq->value is in bps */
726 } else {
727 kbps = -1; /* -1 indicates auto rate */
729 if(kbps != -1 && wmi_validate_bitrate(ar->arWmi, kbps, &rate_idx) != 0)
731 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BitRate is not Valid %d\n", kbps));
732 return -EINVAL;
734 ar->arBitRate = kbps;
735 if(ar->arWmiReady == true)
737 if (wmi_set_bitrate_cmd(ar->arWmi, kbps, -1, -1) != 0) {
738 return -EINVAL;
741 return 0;
745 * SIOCGIWRATE
748 ar6000_ioctl_giwrate(struct net_device *dev,
749 struct iw_request_info *info,
750 struct iw_param *rrq, char *extra)
752 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
753 int ret = 0;
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;
760 if (ar->bIsDestroyProgress) {
761 return -EBUSY;
764 if (ar->arWlanState == WLAN_DISABLED) {
765 return -EIO;
768 if ((ar->arNextMode != AP_NETWORK && !ar->arConnected) || ar->arWmiReady == false) {
769 rrq->value = 1000 * 1000;
770 return 0;
773 if (down_interruptible(&ar->arSem)) {
774 return -ERESTARTSYS;
777 if (ar->bIsDestroyProgress || ar->arWlanState == WLAN_DISABLED) {
778 up(&ar->arSem);
779 return -EBUSY;
782 ar->arBitRate = 0xFFFF;
783 if (wmi_get_bitrate_cmd(ar->arWmi) != 0) {
784 up(&ar->arSem);
785 return -EIO;
787 wait_event_interruptible_timeout(arEvent, ar->arBitRate != 0xFFFF, wmitimeout * HZ);
788 if (signal_pending(current)) {
789 ret = -EINTR;
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;
802 up(&ar->arSem);
804 return ret;
808 * SIOCSIWTXPOW
810 static int
811 ar6000_ioctl_siwtxpow(struct net_device *dev,
812 struct iw_request_info *info,
813 struct iw_param *rrq, char *extra)
815 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
816 u8 dbM;
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;
823 if (ar->arWlanState == WLAN_DISABLED) {
824 return -EIO;
827 if (rrq->disabled) {
828 return -EOPNOTSUPP;
831 if (rrq->fixed) {
832 if (rrq->flags != IW_TXPOW_DBM) {
833 return -EOPNOTSUPP;
835 ar->arTxPwr= dbM = rrq->value;
836 ar->arTxPwrSet = true;
837 } else {
838 ar->arTxPwr = dbM = 0;
839 ar->arTxPwrSet = false;
841 if(ar->arWmiReady == true)
843 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("Set tx pwr cmd %d dbM\n", dbM));
844 wmi_set_txPwr_cmd(ar->arWmi, dbM);
846 return 0;
850 * SIOCGIWTXPOW
853 ar6000_ioctl_giwtxpow(struct net_device *dev,
854 struct iw_request_info *info,
855 struct iw_param *rrq, char *extra)
857 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
858 int ret = 0;
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;
865 if (ar->bIsDestroyProgress) {
866 return -EBUSY;
869 if (ar->arWlanState == WLAN_DISABLED) {
870 return -EIO;
873 if (down_interruptible(&ar->arSem)) {
874 return -ERESTARTSYS;
877 if (ar->bIsDestroyProgress) {
878 up(&ar->arSem);
879 return -EBUSY;
882 if((ar->arWmiReady == true) && (ar->arConnected == true))
884 ar->arTxPwr = 0;
886 if (wmi_get_txPwr_cmd(ar->arWmi) != 0) {
887 up(&ar->arSem);
888 return -EIO;
891 wait_event_interruptible_timeout(arEvent, ar->arTxPwr != 0, wmitimeout * HZ);
893 if (signal_pending(current)) {
894 ret = -EINTR;
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 */
900 if (!ret) {
901 if (ar->arTxPwrSet == true) {
902 rrq->fixed = true;
904 rrq->value = ar->arTxPwr;
905 rrq->flags = IW_TXPOW_DBM;
907 // IWLIST need this flag to get TxPower
909 rrq->disabled = 0;
912 up(&ar->arSem);
914 return ret;
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.
922 static int
923 ar6000_ioctl_siwretry(struct net_device *dev,
924 struct iw_request_info *info,
925 struct iw_param *rrq, char *extra)
927 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
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;
934 if (ar->arWlanState == WLAN_DISABLED) {
935 return -EIO;
938 if (rrq->disabled) {
939 return -EOPNOTSUPP;
942 if ((rrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) {
943 return -EOPNOTSUPP;
946 if ( !(rrq->value >= WMI_MIN_RETRIES) || !(rrq->value <= WMI_MAX_RETRIES)) {
947 return - EINVAL;
949 if(ar->arWmiReady == true)
951 if (wmi_set_retry_limits_cmd(ar->arWmi, DATA_FRAMETYPE, WMM_AC_BE,
952 rrq->value, 0) != 0){
953 return -EINVAL;
956 ar->arMaxRetries = rrq->value;
957 return 0;
961 * SIOCGIWRETRY
963 static int
964 ar6000_ioctl_giwretry(struct net_device *dev,
965 struct iw_request_info *info,
966 struct iw_param *rrq, char *extra)
968 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
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;
975 if (ar->arWlanState == WLAN_DISABLED) {
976 return -EIO;
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;
996 break;
998 return 0;
1002 * SIOCSIWENCODE
1004 static int
1005 ar6000_ioctl_siwencode(struct net_device *dev,
1006 struct iw_request_info *info,
1007 struct iw_point *erq, char *keybuf)
1009 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1010 int index;
1011 s32 auth = 0;
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;
1018 if(ar->arNextMode != AP_NETWORK) {
1020 * Static WEP Keys should be configured before setting the SSID
1022 if (ar->arSsid[0] && erq->length) {
1023 return -EIO;
1027 if (ar->arWlanState == WLAN_DISABLED) {
1028 return -EIO;
1031 index = erq->flags & IW_ENCODE_INDEX;
1033 if (index && (((index - 1) < WMI_MIN_KEY_INDEX) ||
1034 ((index - 1) > WMI_MAX_KEY_INDEX)))
1036 return -EIO;
1039 if (erq->flags & IW_ENCODE_DISABLED) {
1041 * Encryption disabled
1043 if (index) {
1045 * If key index was specified then clear the specified key
1047 index--;
1048 A_MEMZERO(ar->arWepKeyList[index].arKey,
1049 sizeof(ar->arWepKeyList[index].arKey));
1050 ar->arWepKeyList[index].arKeyLen = 0;
1052 ar->arDot11AuthMode = OPEN_AUTH;
1053 ar->arPairwiseCrypto = NONE_CRYPT;
1054 ar->arGroupCrypto = NONE_CRYPT;
1055 ar->arAuthMode = NONE_AUTH;
1056 } else {
1058 * Enabling WEP encryption
1060 if (index) {
1061 index--; /* keyindex is off base 1 in iwconfig */
1064 if (erq->flags & IW_ENCODE_OPEN) {
1065 auth |= OPEN_AUTH;
1066 ar->arDefTxKeyIndex = index;
1068 if (erq->flags & IW_ENCODE_RESTRICTED) {
1069 auth |= SHARED_AUTH;
1072 if (!auth) {
1073 auth = OPEN_AUTH;
1076 if (erq->length) {
1077 if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(erq->length)) {
1078 return -EIO;
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;
1090 ar->arDefTxKeyIndex = index;
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);
1104 ar->arPairwiseCrypto = WEP_CRYPT;
1105 ar->arGroupCrypto = WEP_CRYPT;
1106 ar->arAuthMode = NONE_AUTH;
1109 if(ar->arNextMode != AP_NETWORK) {
1111 * profile has changed. Erase ssid to signal change
1113 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
1114 ar->arSsidLen = 0;
1116 ar->ap_profile_flag = 1; /* There is a change in profile */
1117 return 0;
1120 static int
1121 ar6000_ioctl_giwencode(struct net_device *dev,
1122 struct iw_request_info *info,
1123 struct iw_point *erq, char *key)
1125 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1126 u8 keyIndex;
1127 struct ar_wep_key *wk;
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;
1134 if (ar->arWlanState == WLAN_DISABLED) {
1135 return -EIO;
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))
1150 keyIndex = WMI_MIN_KEY_INDEX;
1151 } else {
1152 keyIndex--;
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;
1160 if (wk->arKeyLen) {
1161 memcpy(key, wk->arKey, erq->length);
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);
1170 } else {
1171 erq->length = 1; // not really printing any key but let iwconfig know enc is on
1175 if (ar->arDot11AuthMode & OPEN_AUTH) {
1176 erq->flags |= IW_ENCODE_OPEN;
1178 if (ar->arDot11AuthMode & SHARED_AUTH) {
1179 erq->flags |= IW_ENCODE_RESTRICTED;
1183 return 0;
1186 #if WIRELESS_EXT >= 18
1188 * SIOCSIWGENIE
1190 static int
1191 ar6000_ioctl_siwgenie(struct net_device *dev,
1192 struct iw_request_info *info,
1193 struct iw_point *erq, char *extra)
1195 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
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
1204 if (ar->arWmiReady == false) {
1205 return -EIO;
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;
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);
1218 #endif
1219 return 0;
1224 * SIOCGIWGENIE
1226 static int
1227 ar6000_ioctl_giwgenie(struct net_device *dev,
1228 struct iw_request_info *info,
1229 struct iw_point *erq, char *extra)
1231 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1233 if (ar->arWmiReady == false) {
1234 return -EIO;
1236 erq->length = 0;
1237 erq->flags = 0;
1239 return 0;
1243 * SIOCSIWAUTH
1245 static int
1246 ar6000_ioctl_siwauth(struct net_device *dev,
1247 struct iw_request_info *info,
1248 struct iw_param *data, char *extra)
1250 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1252 bool profChanged;
1253 u16 param;
1254 s32 ret;
1255 s32 value;
1257 if (ar->arWmiReady == false) {
1258 return -EIO;
1261 if (ar->arWlanState == WLAN_DISABLED) {
1262 return -EIO;
1265 param = data->flags & IW_AUTH_INDEX;
1266 value = data->value;
1267 profChanged = true;
1268 ret = 0;
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;
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;
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;
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;
1334 } else if (!(value & IW_AUTH_KEY_MGMT_802_1X)) {
1335 ar->arAuthMode = NONE_AUTH;
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;
1350 if (value & IW_AUTH_ALG_SHARED_KEY) {
1351 ar->arDot11AuthMode |= SHARED_AUTH;
1353 if (value & IW_AUTH_ALG_LEAP) {
1354 ar->arDot11AuthMode = LEAP_AUTH;
1356 if(ar->arDot11AuthMode == 0) {
1357 ret = -1;
1358 profChanged = false;
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
1369 ar->arDot11AuthMode = OPEN_AUTH;
1370 ar->arPairwiseCrypto = NONE_CRYPT;
1371 ar->arPairwiseCryptoLen = 0;
1372 ar->arGroupCrypto = NONE_CRYPT;
1373 ar->arGroupCryptoLen = 0;
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;
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;
1401 if (profChanged == true) {
1403 * profile has changed. Erase ssid to signal change
1405 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
1406 ar->arSsidLen = 0;
1409 return ret;
1414 * SIOCGIWAUTH
1416 static int
1417 ar6000_ioctl_giwauth(struct net_device *dev,
1418 struct iw_request_info *info,
1419 struct iw_param *data, char *extra)
1421 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1422 u16 param;
1423 s32 ret;
1425 if (ar->arWmiReady == false) {
1426 return -EIO;
1429 if (ar->arWlanState == WLAN_DISABLED) {
1430 return -EIO;
1433 param = data->flags & IW_AUTH_INDEX;
1434 ret = 0;
1435 data->value = 0;
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;
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;
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;
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;
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;
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;
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;
1509 break;
1510 case IW_AUTH_WPA_ENABLED:
1511 if (ar->arAuthMode == NONE_AUTH) {
1512 data->value = 0;
1513 } else {
1514 data->value = 1;
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;
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;
1538 return 0;
1542 * SIOCSIWPMKSA
1544 static int
1545 ar6000_ioctl_siwpmksa(struct net_device *dev,
1546 struct iw_request_info *info,
1547 struct iw_point *data, char *extra)
1549 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1550 s32 ret;
1551 int status;
1552 struct iw_pmksa *pmksa;
1554 pmksa = (struct iw_pmksa *)extra;
1556 if (ar->arWmiReady == false) {
1557 return -EIO;
1560 ret = 0;
1561 status = 0;
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);
1574 break;
1575 default:
1576 ret=-1;
1577 break;
1579 if (status) {
1580 ret = -1;
1583 return ret;
1586 #ifdef WAPI_ENABLE
1588 #define PN_INIT 0x5c365c36
1590 static int ar6000_set_wapi_key(struct net_device *dev,
1591 struct iw_request_info *info,
1592 struct iw_point *erq, char *extra)
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};
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;
1613 index--;
1614 if (index < 0 || index > 4) {
1615 return -EIO;
1617 keyData = (u8 *)(ext + 1);
1618 keyLen = erq->length - sizeof(struct iw_encode_ext);
1619 memcpy(wapiKeyRsc, ext->tx_seq, sizeof(wapiKeyRsc));
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;
1627 } else {
1628 keyUsage |= PAIRWISE_USAGE;
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;
1643 return 0;
1646 #endif
1649 * SIOCSIWENCODEEXT
1651 static int
1652 ar6000_ioctl_siwencodeext(struct net_device *dev,
1653 struct iw_request_info *info,
1654 struct iw_point *erq, char *extra)
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 */
1669 if (ar->arWlanState == WLAN_DISABLED) {
1670 return -EIO;
1673 #ifdef USER_KEYS
1674 ar->user_saved_keys.keyOk = false;
1675 #endif /* USER_KEYS */
1677 index = erq->flags & IW_ENCODE_INDEX;
1679 if (index && (((index - 1) < WMI_MIN_KEY_INDEX) ||
1680 ((index - 1) > WMI_MAX_KEY_INDEX)))
1682 return -EIO;
1685 ext = (struct iw_encode_ext *)extra;
1686 if (erq->flags & IW_ENCODE_DISABLED) {
1688 * Encryption disabled
1690 if (index) {
1692 * If key index was specified then clear the specified key
1694 index--;
1695 A_MEMZERO(ar->arWepKeyList[index].arKey,
1696 sizeof(ar->arWepKeyList[index].arKey));
1697 ar->arWepKeyList[index].arKeyLen = 0;
1699 } else {
1701 * Enabling WEP encryption
1703 if (index) {
1704 index--; /* keyindex is off base 1 in iwconfig */
1707 keyUsage = 0;
1708 keyLen = erq->length - sizeof(struct iw_encode_ext);
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;
1719 if (keyLen <= 0) {
1720 return -EIO;
1723 /* key follows iw_encode_ext */
1724 keyData = (u8 *)(ext + 1);
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;
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;
1743 return 0;
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;
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;
1774 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1775 keyUsage |= GROUP_USAGE;
1776 } else {
1777 keyUsage |= PAIRWISE_USAGE;
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));
1786 if (((WPA_PSK_AUTH == ar->arAuthMode) || (WPA2_PSK_AUTH == ar->arAuthMode)) &&
1787 (GROUP_USAGE & keyUsage))
1789 A_UNTIMEOUT(&ar->disconnect_timer);
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;
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));
1814 ar->user_saved_keys.keyOk = true;
1815 #endif /* USER_KEYS */
1819 return 0;
1823 * SIOCGIWENCODEEXT
1825 static int
1826 ar6000_ioctl_giwencodeext(struct net_device *dev,
1827 struct iw_request_info *info,
1828 struct iw_point *erq, char *extra)
1830 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1832 if (ar->arWlanState == WLAN_DISABLED) {
1833 return -EIO;
1836 if (ar->arPairwiseCrypto == NONE_CRYPT) {
1837 erq->length = 0;
1838 erq->flags = IW_ENCODE_DISABLED;
1839 } else {
1840 erq->length = 0;
1843 return 0;
1845 #endif // WIRELESS_EXT >= 18
1847 #if WIRELESS_EXT > 20
1848 static int ar6000_ioctl_siwpower(struct net_device *dev,
1849 struct iw_request_info *info,
1850 union iwreq_data *wrqu, char *extra)
1852 #ifndef ATH6K_CONFIG_OTA_MODE
1853 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1854 WMI_POWER_MODE power_mode;
1856 if (ar->arWmiReady == false) {
1857 return -EIO;
1860 if (ar->arWlanState == WLAN_DISABLED) {
1861 return -EIO;
1864 if (wrqu->power.disabled)
1865 power_mode = MAX_PERF_POWER;
1866 else
1867 power_mode = REC_POWER;
1869 if (wmi_powermode_cmd(ar->arWmi, power_mode) < 0)
1870 return -EIO;
1871 #endif
1872 return 0;
1875 static int ar6000_ioctl_giwpower(struct net_device *dev,
1876 struct iw_request_info *info,
1877 union iwreq_data *wrqu, char *extra)
1879 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
1880 WMI_POWER_MODE power_mode;
1882 if (ar->arWmiReady == false) {
1883 return -EIO;
1886 if (ar->arWlanState == WLAN_DISABLED) {
1887 return -EIO;
1890 power_mode = wmi_get_power_mode_cmd(ar->arWmi);
1892 if (power_mode == MAX_PERF_POWER)
1893 wrqu->power.disabled = 1;
1894 else
1895 wrqu->power.disabled = 0;
1897 return 0;
1899 #endif // WIRELESS_EXT > 20
1902 * SIOCGIWNAME
1905 ar6000_ioctl_giwname(struct net_device *dev,
1906 struct iw_request_info *info,
1907 char *name, char *extra)
1909 u8 capability;
1910 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
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;
1917 if (ar->arWlanState == WLAN_DISABLED) {
1918 return -EIO;
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);
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;
1953 return 0;
1957 * SIOCSIWFREQ
1960 ar6000_ioctl_siwfreq(struct net_device *dev,
1961 struct iw_request_info *info,
1962 struct iw_freq *freq, char *extra)
1964 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
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;
1971 if (ar->arWlanState == WLAN_DISABLED) {
1972 return -EIO;
1976 * We support limiting the channels via wmiconfig.
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.
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;
1995 ar->ap_profile_flag = 1; /* There is a change in profile */
1997 A_PRINTF("channel hint set to %d\n", ar->arChannelHint);
1998 return 0;
2002 * SIOCGIWFREQ
2005 ar6000_ioctl_giwfreq(struct net_device *dev,
2006 struct iw_request_info *info,
2007 struct iw_freq *freq, char *extra)
2009 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
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;
2016 if (ar->arWlanState == WLAN_DISABLED) {
2017 return -EIO;
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;
2028 } else {
2029 if (ar->arConnected != true) {
2030 return -EINVAL;
2031 } else {
2032 freq->m = ar->arBssChannel * 100000;
2036 freq->e = 1;
2038 return 0;
2042 * SIOCSIWMODE
2045 ar6000_ioctl_siwmode(struct net_device *dev,
2046 struct iw_request_info *info,
2047 __u32 *mode, char *extra)
2049 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
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;
2056 if (ar->arWlanState == WLAN_DISABLED) {
2057 return -EIO;
2061 * clear SSID during mode switch in connected state
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;
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;
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.
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;
2101 /* SSID has to be cleared to trigger a profile change while switching
2102 * between STA & IBSS modes having the same SSID
2104 if (ar->arNetworkType != ar->arNextMode) {
2105 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
2106 ar->arSsidLen = 0;
2109 return 0;
2113 * SIOCGIWMODE
2116 ar6000_ioctl_giwmode(struct net_device *dev,
2117 struct iw_request_info *info,
2118 __u32 *mode, char *extra)
2120 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
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;
2127 if (ar->arWlanState == WLAN_DISABLED) {
2128 return -EIO;
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;
2144 return 0;
2148 * SIOCSIWSENS
2151 ar6000_ioctl_siwsens(struct net_device *dev,
2152 struct iw_request_info *info,
2153 struct iw_param *sens, char *extra)
2155 return 0;
2159 * SIOCGIWSENS
2162 ar6000_ioctl_giwsens(struct net_device *dev,
2163 struct iw_request_info *info,
2164 struct iw_param *sens, char *extra)
2166 sens->value = 0;
2167 sens->fixed = 1;
2169 return 0;
2173 * SIOCGIWRANGE
2176 ar6000_ioctl_giwrange(struct net_device *dev,
2177 struct iw_request_info *info,
2178 struct iw_point *data, char *extra)
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;
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;
2189 if (ar->bIsDestroyProgress) {
2190 return -EBUSY;
2193 if (ar->arWmiReady == false) {
2194 return -EIO;
2197 if (down_interruptible(&ar->arSem)) {
2198 return -ERESTARTSYS;
2201 if (ar->bIsDestroyProgress) {
2202 up(&ar->arSem);
2203 return -EBUSY;
2206 ar->arNumChannels = -1;
2207 A_MEMZERO(ar->arChannelList, sizeof (ar->arChannelList));
2209 if (wmi_get_channelList_cmd(ar->arWmi) != 0) {
2210 up(&ar->arSem);
2211 return -EIO;
2214 wait_event_interruptible_timeout(arEvent, ar->arNumChannels != -1, wmitimeout * HZ);
2216 if (signal_pending(current)) {
2217 up(&ar->arSem);
2218 return -EINTR;
2221 data->length = sizeof(struct iw_range);
2222 A_MEMZERO(range, sizeof(struct iw_range));
2224 range->txpower_capa = 0;
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;
2234 range->we_version_compiled = WIRELESS_EXT;
2235 range->we_version_source = 13;
2237 range->retry_capa = IW_RETRY_LIMIT;
2238 range->retry_flags = IW_RETRY_LIMIT;
2239 range->min_retry = 0;
2240 range->max_retry = 255;
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;
2248 * Linux supports max of 32 channels, bail out once you
2249 * reach the max.
2251 if (i == IW_MAX_FREQUENCIES) {
2252 break;
2256 /* Max quality is max field value minus noise floor */
2257 range->max_qual.qual = 0xff - 161;
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.
2266 range->max_qual.level = 0;
2267 range->max_qual.noise = 0;
2269 range->sensitivity = 3;
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 */
2278 range->num_bitrates = 0;
2280 /* estimated maximum TCP throughput values (bps) */
2281 range->throughput = 22000000;
2283 range->min_rts = 0;
2284 range->max_rts = 2347;
2285 range->min_frag = 256;
2286 range->max_frag = 2346;
2288 up(&ar->arSem);
2290 return ret;
2295 * SIOCSIWAP
2296 * This ioctl is used to set the desired bssid for the connect command.
2299 ar6000_ioctl_siwap(struct net_device *dev,
2300 struct iw_request_info *info,
2301 struct sockaddr *ap_addr, char *extra)
2303 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
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;
2310 if (ar->arWlanState == WLAN_DISABLED) {
2311 return -EIO;
2314 if (ap_addr->sa_family != ARPHRD_ETHER) {
2315 return -EIO;
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));
2324 return 0;
2328 * SIOCGIWAP
2331 ar6000_ioctl_giwap(struct net_device *dev,
2332 struct iw_request_info *info,
2333 struct sockaddr *ap_addr, char *extra)
2335 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
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;
2342 if (ar->arWlanState == WLAN_DISABLED) {
2343 return -EIO;
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;
2352 if (ar->arConnected != true) {
2353 return -EINVAL;
2356 memcpy(&ap_addr->sa_data, ar->arBssid, sizeof(ar->arBssid));
2357 ap_addr->sa_family = ARPHRD_ETHER;
2359 return 0;
2362 #if (WIRELESS_EXT >= 18)
2364 * SIOCSIWMLME
2367 ar6000_ioctl_siwmlme(struct net_device *dev,
2368 struct iw_request_info *info,
2369 struct iw_point *data, char *extra)
2371 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
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;
2378 if (ar->bIsDestroyProgress) {
2379 return -EBUSY;
2382 if (ar->arWlanState == WLAN_DISABLED) {
2383 return -EIO;
2386 if (ar->arWmiReady == false) {
2387 return -EIO;
2390 if (down_interruptible(&ar->arSem)) {
2391 return -ERESTARTSYS;
2394 if (data->pointer && data->length == sizeof(struct iw_mlme)) {
2396 u8 arNetworkType;
2397 struct iw_mlme mlme;
2399 if (copy_from_user(&mlme, data->pointer, sizeof(struct iw_mlme)))
2400 return -EIO;
2402 switch (mlme.cmd) {
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)) {
2410 up(&ar->arSem);
2411 return -EINVAL;
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));
2424 break;
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;
2436 up(&ar->arSem);
2437 return 0;
2439 #endif /* WIRELESS_EXT >= 18 */
2442 * SIOCGIWAPLIST
2445 ar6000_ioctl_iwaplist(struct net_device *dev,
2446 struct iw_request_info *info,
2447 struct iw_point *data, char *extra)
2449 return -EIO; /* for now */
2453 * SIOCSIWSCAN
2456 ar6000_ioctl_siwscan(struct net_device *dev,
2457 struct iw_request_info *info,
2458 struct iw_point *data, char *extra)
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;
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;
2471 if (ar->arWmiReady == false) {
2472 return -EIO;
2475 if (ar->arWlanState == WLAN_DISABLED) {
2476 return -EIO;
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"));
2490 if (!ar->arUserBssFilter) {
2491 if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != 0) {
2492 return -EIO;
2496 if (ar->arConnected) {
2497 if (wmi_get_stats_cmd(ar->arWmi) != 0) {
2498 return -EIO;
2502 #ifdef ANDROID_ENV
2503 #if WIRELESS_EXT >= 18
2504 if (data->pointer && (data->length == sizeof(struct iw_scan_req)))
2506 if ((data->flags & IW_SCAN_THIS_ESSID) == IW_SCAN_THIS_ESSID)
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;
2515 else
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;
2524 else
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;
2532 #endif
2533 #endif /* ANDROID_ENV */
2535 if (wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, false, false, \
2536 0, 0, 0, NULL) != 0) {
2537 ret = -EIO;
2540 if (ret == 0) {
2541 ar->scan_triggered = 1;
2544 return ret;
2545 #undef ACT_DWELLTIME_DEFAULT
2546 #undef HOME_TXDRAIN_TIME
2547 #undef SCAN_INT
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.
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.
2564 * NB: various calculations are based on the orinoco/wavelan
2565 * drivers for compatibility
2567 static void
2568 ar6000_set_quality(struct iw_quality *iq, s8 rssi)
2570 if (rssi < 0) {
2571 iq->qual = 0;
2572 } else {
2573 iq->qual = rssi;
2576 /* NB: max is 94 because noise is hardcoded to 161 */
2577 if (iq->qual > 94)
2578 iq->qual = 94;
2580 iq->noise = 161; /* -95dBm */
2581 iq->level = iq->noise + iq->qual;
2582 iq->updated = 7;
2587 ar6000_ioctl_siwcommit(struct net_device *dev,
2588 struct iw_request_info *info,
2589 struct iw_point *data, char *extra)
2591 struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
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;
2598 if (ar->arWmiReady == false) {
2599 return -EIO;
2602 if (ar->arWlanState == WLAN_DISABLED) {
2603 return -EIO;
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));
2612 ar6000_ap_mode_profile_commit(ar);
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.
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;
2624 /* Flush the Tx queues */
2625 ar6000_TxDataCleanup(ar);
2627 /* Start getting pkts from upper stack */
2628 netif_wake_queue(ar->arNetDev);
2631 return 0;
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;\
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*)
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
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,